#define NEED_REPLIES
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "Xmd.h"
#include "misc.h"
#include "os.h"
#include "extnsionst.h"
#include "dixstruct.h"
#include "resource.h"
#include "opaque.h"
#define _SYNC_SERVER
#include "sync.h"
#include "syncstr.h"
#ifdef EXTMODULE
#include "xf86_ansic.h"
#else
#include <stdio.h>
#if !defined(WIN32) && !defined(Lynx)
#include <sys/time.h>
#endif
#endif
#include "modinit.h"
static int SyncEventBase;
static int SyncErrorBase;
static RESTYPE RTCounter = 0;
static RESTYPE RTAwait;
static RESTYPE RTAlarm;
static RESTYPE RTAlarmClient;
static int SyncNumSystemCounters = 0;
static SyncCounter **SysCounterList = NULL;
#define IsSystemCounter(pCounter) \
(pCounter && (pCounter->client == NULL))
#define XSyncCAAllTrigger \
(XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
static int
FreeAlarm(
pointer ,
XID
);
static int
FreeAlarmClient(
pointer ,
XID
);
static int
FreeAwait(
pointer ,
XID
);
static void
ServertimeBracketValues(
pointer ,
CARD64 * ,
CARD64 *
);
static void
ServertimeQueryValue(
pointer ,
CARD64 *
);
static void
ServertimeWakeupHandler(
pointer ,
int ,
pointer
);
static int
SyncInitTrigger(
ClientPtr ,
SyncTrigger * ,
XSyncCounter ,
Mask
);
static void
SAlarmNotifyEvent(
xSyncAlarmNotifyEvent * ,
xSyncAlarmNotifyEvent *
);
static void
SCounterNotifyEvent(
xSyncCounterNotifyEvent * ,
xSyncCounterNotifyEvent *
);
static void
ServertimeBlockHandler(
pointer ,
struct timeval ** ,
pointer
);
static int
SyncAddTriggerToCounter(
SyncTrigger *
);
extern void
SyncAlarmCounterDestroyed(
SyncTrigger *
);
static void
SyncAlarmTriggerFired(
SyncTrigger *
);
static void
SyncAwaitTriggerFired(
SyncTrigger *
);
static int
SyncChangeAlarmAttributes(
ClientPtr ,
SyncAlarm * ,
Mask ,
CARD32 *
);
static Bool
SyncCheckTriggerNegativeComparison(
SyncTrigger * ,
CARD64
);
static Bool
SyncCheckTriggerNegativeTransition(
SyncTrigger * ,
CARD64
);
static Bool
SyncCheckTriggerPositiveComparison(
SyncTrigger * ,
CARD64
);
static Bool
SyncCheckTriggerPositiveTransition(
SyncTrigger * ,
CARD64
);
static SyncCounter *
SyncCreateCounter(
ClientPtr ,
XSyncCounter ,
CARD64
);
static void SyncComputeBracketValues(
SyncCounter * ,
Bool
);
static void
SyncDeleteTriggerFromCounter(
SyncTrigger *
);
static Bool
SyncEventSelectForAlarm(
SyncAlarm * ,
ClientPtr ,
Bool
);
static void
SyncInitServerTime(
void
);
static void
SyncResetProc(
ExtensionEntry *
);
static void
SyncSendAlarmNotifyEvents(
SyncAlarm *
);
static void
SyncSendCounterNotifyEvents(
ClientPtr ,
SyncAwait ** ,
int
);
static DISPATCH_PROC(ProcSyncAwait);
static DISPATCH_PROC(ProcSyncChangeAlarm);
static DISPATCH_PROC(ProcSyncChangeCounter);
static DISPATCH_PROC(ProcSyncCreateAlarm);
static DISPATCH_PROC(ProcSyncCreateCounter);
static DISPATCH_PROC(ProcSyncDestroyAlarm);
static DISPATCH_PROC(ProcSyncDestroyCounter);
static DISPATCH_PROC(ProcSyncDispatch);
static DISPATCH_PROC(ProcSyncGetPriority);
static DISPATCH_PROC(ProcSyncInitialize);
static DISPATCH_PROC(ProcSyncListSystemCounters);
static DISPATCH_PROC(ProcSyncQueryAlarm);
static DISPATCH_PROC(ProcSyncQueryCounter);
static DISPATCH_PROC(ProcSyncSetCounter);
static DISPATCH_PROC(ProcSyncSetPriority);
static DISPATCH_PROC(SProcSyncAwait);
static DISPATCH_PROC(SProcSyncChangeAlarm);
static DISPATCH_PROC(SProcSyncChangeCounter);
static DISPATCH_PROC(SProcSyncCreateAlarm);
static DISPATCH_PROC(SProcSyncCreateCounter);
static DISPATCH_PROC(SProcSyncDestroyAlarm);
static DISPATCH_PROC(SProcSyncDestroyCounter);
static DISPATCH_PROC(SProcSyncDispatch);
static DISPATCH_PROC(SProcSyncGetPriority);
static DISPATCH_PROC(SProcSyncInitialize);
static DISPATCH_PROC(SProcSyncListSystemCounters);
static DISPATCH_PROC(SProcSyncQueryAlarm);
static DISPATCH_PROC(SProcSyncQueryCounter);
static DISPATCH_PROC(SProcSyncSetCounter);
static DISPATCH_PROC(SProcSyncSetPriority);
static void
SyncDeleteTriggerFromCounter(pTrigger)
SyncTrigger *pTrigger;
{
SyncTriggerList *pCur, *pPrev = NULL;
if (!pTrigger->pCounter)
return;
for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
{
if (pCur->pTrigger == pTrigger)
{
if (pPrev)
pPrev->next = pCur->next;
else
pTrigger->pCounter->pTriglist = pCur->next;
xfree(pCur);
break;
}
}
if (IsSystemCounter(pTrigger->pCounter))
SyncComputeBracketValues(pTrigger->pCounter, TRUE);
}
static int
SyncAddTriggerToCounter(pTrigger)
SyncTrigger *pTrigger;
{
SyncTriggerList *pCur;
if (!pTrigger->pCounter)
return Success;
for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
{
if (pCur->pTrigger == pTrigger)
return Success;
}
if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
return BadAlloc;
pCur->pTrigger = pTrigger;
pCur->next = pTrigger->pCounter->pTriglist;
pTrigger->pCounter->pTriglist = pCur;
if (IsSystemCounter(pTrigger->pCounter))
SyncComputeBracketValues(pTrigger->pCounter, TRUE);
return Success;
}
static Bool
SyncCheckTriggerPositiveComparison(pTrigger, oldval)
SyncTrigger *pTrigger;
CARD64 oldval;
{
return (pTrigger->pCounter == NULL ||
XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
pTrigger->test_value));
}
static Bool
SyncCheckTriggerNegativeComparison(pTrigger, oldval)
SyncTrigger *pTrigger;
CARD64 oldval;
{
return (pTrigger->pCounter == NULL ||
XSyncValueLessOrEqual(pTrigger->pCounter->value,
pTrigger->test_value));
}
static Bool
SyncCheckTriggerPositiveTransition(pTrigger, oldval)
SyncTrigger *pTrigger;
CARD64 oldval;
{
return (pTrigger->pCounter == NULL ||
(XSyncValueLessThan(oldval, pTrigger->test_value) &&
XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
pTrigger->test_value)));
}
static Bool
SyncCheckTriggerNegativeTransition(pTrigger, oldval)
SyncTrigger *pTrigger;
CARD64 oldval;
{
return (pTrigger->pCounter == NULL ||
(XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
XSyncValueLessOrEqual(pTrigger->pCounter->value,
pTrigger->test_value)));
}
static int
SyncInitTrigger(client, pTrigger, counter, changes)
ClientPtr client;
SyncTrigger *pTrigger;
XSyncCounter counter;
Mask changes;
{
SyncCounter *pCounter = pTrigger->pCounter;
int status;
Bool newcounter = FALSE;
if (changes & XSyncCACounter)
{
if (counter == None)
pCounter = NULL;
else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
client, counter, RTCounter, SecurityReadAccess)))
{
client->errorValue = counter;
return SyncErrorBase + XSyncBadCounter;
}
if (pCounter != pTrigger->pCounter)
{
SyncDeleteTriggerFromCounter(pTrigger);
pTrigger->pCounter = pCounter;
newcounter = TRUE;
}
}
if (IsSystemCounter(pCounter))
{
(*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
&pCounter->value);
}
if (changes & XSyncCAValueType)
{
if (pTrigger->value_type != XSyncRelative &&
pTrigger->value_type != XSyncAbsolute)
{
client->errorValue = pTrigger->value_type;
return BadValue;
}
}
if (changes & XSyncCATestType)
{
if (pTrigger->test_type != XSyncPositiveTransition &&
pTrigger->test_type != XSyncNegativeTransition &&
pTrigger->test_type != XSyncPositiveComparison &&
pTrigger->test_type != XSyncNegativeComparison)
{
client->errorValue = pTrigger->test_type;
return BadValue;
}
switch (pTrigger->test_type)
{
case XSyncPositiveTransition:
pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
break;
case XSyncNegativeTransition:
pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
break;
case XSyncPositiveComparison:
pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
break;
case XSyncNegativeComparison:
pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
break;
}
}
if (changes & (XSyncCAValueType | XSyncCAValue))
{
if (pTrigger->value_type == XSyncAbsolute)
pTrigger->test_value = pTrigger->wait_value;
else
{
Bool overflow;
if (pCounter == NULL)
return BadMatch;
XSyncValueAdd(&pTrigger->test_value, pCounter->value,
pTrigger->wait_value, &overflow);
if (overflow)
{
client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
return BadValue;
}
}
}
if (newcounter)
{
if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
return status;
}
else if (IsSystemCounter(pCounter))
{
SyncComputeBracketValues(pCounter, TRUE);
}
return Success;
}
static void
SyncSendAlarmNotifyEvents(pAlarm)
SyncAlarm *pAlarm;
{
SyncAlarmClientList *pcl;
xSyncAlarmNotifyEvent ane;
SyncTrigger *pTrigger = &pAlarm->trigger;
UpdateCurrentTime();
ane.type = SyncEventBase + XSyncAlarmNotify;
ane.kind = XSyncAlarmNotify;
ane.sequenceNumber = pAlarm->client->sequence;
ane.alarm = pAlarm->alarm_id;
if (pTrigger->pCounter)
{
ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
}
else
{
ane.counter_value_hi = ane.counter_value_lo = 0;
}
ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
ane.time = currentTime.milliseconds;
ane.state = pAlarm->state;
if (pAlarm->events && !pAlarm->client->clientGone)
WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
{
if (!pAlarm->client->clientGone)
{
ane.sequenceNumber = pcl->client->sequence;
WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
}
}
}
static void
SyncSendCounterNotifyEvents(client, ppAwait, num_events)
ClientPtr client;
SyncAwait **ppAwait;
int num_events;
{
xSyncCounterNotifyEvent *pEvents, *pev;
int i;
if (client->clientGone)
return;
pev = pEvents = (xSyncCounterNotifyEvent *)
ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
if (!pEvents)
return;
UpdateCurrentTime();
for (i = 0; i < num_events; i++, ppAwait++, pev++)
{
SyncTrigger *pTrigger = &(*ppAwait)->trigger;
pev->type = SyncEventBase + XSyncCounterNotify;
pev->kind = XSyncCounterNotify;
pev->sequenceNumber = client->sequence;
pev->counter = pTrigger->pCounter->id;
pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
pev->time = currentTime.milliseconds;
pev->count = num_events - i - 1;
pev->destroyed = pTrigger->pCounter->beingDestroyed;
}
WriteEventsToClient(client, num_events, (xEvent *)pEvents);
DEALLOCATE_LOCAL(pEvents);
}
void
SyncAlarmCounterDestroyed(pTrigger)
SyncTrigger *pTrigger;
{
SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
pAlarm->state = XSyncAlarmInactive;
SyncSendAlarmNotifyEvents(pAlarm);
pTrigger->pCounter = NULL;
}
static void
SyncAlarmTriggerFired(pTrigger)
SyncTrigger *pTrigger;
{
SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
CARD64 new_test_value;
if (pAlarm->state != XSyncAlarmActive)
return;
if (pAlarm->trigger.pCounter == NULL
|| (XSyncValueIsZero(pAlarm->delta)
&& (pAlarm->trigger.test_type == XSyncPositiveComparison
|| pAlarm->trigger.test_type == XSyncNegativeComparison)))
pAlarm->state = XSyncAlarmInactive;
new_test_value = pAlarm->trigger.test_value;
if (pAlarm->state == XSyncAlarmActive)
{
Bool overflow;
CARD64 oldvalue;
SyncTrigger *paTrigger = &pAlarm->trigger;
oldvalue = paTrigger->test_value;
do
{
XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
pAlarm->delta, &overflow);
} while (!overflow &&
(*paTrigger->CheckTrigger)(paTrigger,
paTrigger->pCounter->value));
new_test_value = paTrigger->test_value;
paTrigger->test_value = oldvalue;
if (overflow)
{
new_test_value = oldvalue;
pAlarm->state = XSyncAlarmInactive;
}
}
SyncSendAlarmNotifyEvents(pAlarm);
pTrigger->test_value = new_test_value;
}
static void
SyncAwaitTriggerFired(pTrigger)
SyncTrigger *pTrigger;
{
SyncAwait *pAwait = (SyncAwait *)pTrigger;
int numwaits;
SyncAwaitUnion *pAwaitUnion;
SyncAwait **ppAwait;
int num_events = 0;
pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
numwaits = pAwaitUnion->header.num_waitconditions;
ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
if (!ppAwait)
goto bail;
pAwait = &(pAwaitUnion+1)->await;
for ( ; numwaits; numwaits--, pAwait++)
{
CARD64 diff;
Bool overflow, diffgreater, diffequal;
if (pAwait->trigger.pCounter->beingDestroyed)
{
ppAwait[num_events++] = pAwait;
continue;
}
XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
pAwait->trigger.test_value, &overflow);
if (overflow)
continue;
diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
pAwait->trigger.test_type == XSyncPositiveTransition)
&& (diffgreater || diffequal))
||
((pAwait->trigger.test_type == XSyncNegativeComparison ||
pAwait->trigger.test_type == XSyncNegativeTransition)
&& (!diffgreater)
)
)
{
ppAwait[num_events++] = pAwait;
}
}
if (num_events)
SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
num_events);
DEALLOCATE_LOCAL(ppAwait);
bail:
AttendClient(pAwaitUnion->header.client);
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
}
void
SyncChangeCounter(pCounter, newval)
SyncCounter *pCounter;
CARD64 newval;
{
SyncTriggerList *ptl, *pnext;
CARD64 oldval;
oldval = pCounter->value;
pCounter->value = newval;
for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
{
pnext = ptl->next;
if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
(*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
}
if (IsSystemCounter(pCounter))
{
SyncComputeBracketValues(pCounter, FALSE);
}
}
static Bool
SyncEventSelectForAlarm(pAlarm, client, wantevents)
SyncAlarm *pAlarm;
ClientPtr client;
Bool wantevents;
{
SyncAlarmClientList *pClients;
if (client == pAlarm->client)
{
pAlarm->events = wantevents;
return Success;
}
for (pClients = pAlarm->pEventClients; pClients;
pClients = pClients->next)
{
if (pClients->client == client)
{
if (!wantevents)
{
FreeResource(pClients->delete_id, RT_NONE);
}
return Success;
}
}
if (!wantevents)
return Success;
pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
if (!pClients)
return BadAlloc;
pClients->delete_id = FakeClientID(client->index);
if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
{
xfree(pClients);
return BadAlloc;
}
pClients->next = pAlarm->pEventClients;
pAlarm->pEventClients = pClients;
pClients->client = client;
return Success;
}
static int
SyncChangeAlarmAttributes(client, pAlarm, mask, values)
ClientPtr client;
SyncAlarm *pAlarm;
Mask mask;
CARD32 *values;
{
int status;
XSyncCounter counter;
Mask origmask = mask;
counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
while (mask)
{
int index2 = lowbit(mask);
mask &= ~index2;
switch (index2)
{
case XSyncCACounter:
mask &= ~XSyncCACounter;
counter = *values++;
break;
case XSyncCAValueType:
mask &= ~XSyncCAValueType;
pAlarm->trigger.value_type = *values++;
break;
case XSyncCAValue:
mask &= ~XSyncCAValue;
XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
values += 2;
break;
case XSyncCATestType:
mask &= ~XSyncCATestType;
pAlarm->trigger.test_type = *values++;
break;
case XSyncCADelta:
mask &= ~XSyncCADelta;
XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
values += 2;
break;
case XSyncCAEvents:
mask &= ~XSyncCAEvents;
if ((*values != xTrue) && (*values != xFalse))
{
client->errorValue = *values;
return BadValue;
}
status = SyncEventSelectForAlarm(pAlarm, client,
(Bool)(*values++));
if (status != Success)
return status;
break;
default:
client->errorValue = mask;
return BadValue;
}
}
if (origmask & (XSyncCADelta|XSyncCATestType))
{
CARD64 zero;
XSyncIntToValue(&zero, 0);
if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
(pAlarm->trigger.test_type == XSyncPositiveTransition))
&& XSyncValueLessThan(pAlarm->delta, zero))
||
(((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
(pAlarm->trigger.test_type == XSyncNegativeTransition))
&& XSyncValueGreaterThan(pAlarm->delta, zero))
)
{
return BadMatch;
}
}
if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
origmask & XSyncCAAllTrigger)) != Success)
return status;
pAlarm->state = XSyncAlarmActive;
return Success;
}
static SyncCounter *
SyncCreateCounter(client, id, initialvalue)
ClientPtr client;
XSyncCounter id;
CARD64 initialvalue;
{
SyncCounter *pCounter;
if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
return (SyncCounter *)NULL;
if (!AddResource(id, RTCounter, (pointer) pCounter))
{
xfree((pointer) pCounter);
return (SyncCounter *)NULL;
}
pCounter->client = client;
pCounter->id = id;
pCounter->value = initialvalue;
pCounter->pTriglist = NULL;
pCounter->beingDestroyed = FALSE;
pCounter->pSysCounterInfo = NULL;
return pCounter;
}
static int FreeCounter(
pointer ,
XID
);
pointer
SyncCreateSystemCounter(name, initial, resolution, counterType,
QueryValue, BracketValues)
char *name;
CARD64 initial;
CARD64 resolution;
SyncCounterType counterType;
void (*QueryValue) (
pointer ,
CARD64 * );
void (*BracketValues) (
pointer ,
CARD64 * ,
CARD64 * );
{
SyncCounter *pCounter;
SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
(SyncNumSystemCounters+1)*sizeof(SyncCounter *));
if (!SysCounterList)
return (pointer)NULL;
if (RTCounter == 0)
{
RTCounter = CreateNewResourceType(FreeCounter);
if (RTCounter == 0)
{
return (pointer)NULL;
}
}
pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
if (pCounter)
{
SysCounterInfo *psci;
psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
if (!psci)
{
FreeResource(pCounter->id, RT_NONE);
return (pointer) pCounter;
}
pCounter->pSysCounterInfo = psci;
psci->name = name;
psci->resolution = resolution;
psci->counterType = counterType;
psci->QueryValue = QueryValue;
psci->BracketValues = BracketValues;
XSyncMaxValue(&psci->bracket_greater);
XSyncMinValue(&psci->bracket_less);
SysCounterList[SyncNumSystemCounters++] = pCounter;
}
return (pointer) pCounter;
}
void
SyncDestroySystemCounter(pSysCounter)
pointer pSysCounter;
{
SyncCounter *pCounter = (SyncCounter *)pSysCounter;
FreeResource(pCounter->id, RT_NONE);
}
static void
SyncComputeBracketValues(pCounter, startOver)
SyncCounter *pCounter;
Bool startOver;
{
SyncTriggerList *pCur;
SyncTrigger *pTrigger;
SysCounterInfo *psci = pCounter->pSysCounterInfo;
CARD64 *pnewgtval = NULL;
CARD64 *pnewltval = NULL;
SyncCounterType ct;
if (!pCounter)
return;
ct = pCounter->pSysCounterInfo->counterType;
if (ct == XSyncCounterNeverChanges)
return;
if (startOver)
{
XSyncMaxValue(&psci->bracket_greater);
XSyncMinValue(&psci->bracket_less);
}
for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
{
pTrigger = pCur->pTrigger;
if (pTrigger->test_type == XSyncPositiveComparison &&
ct != XSyncCounterNeverIncreases)
{
if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
XSyncValueLessThan(pTrigger->test_value,
psci->bracket_greater))
{
psci->bracket_greater = pTrigger->test_value;
pnewgtval = &psci->bracket_greater;
}
}
else if (pTrigger->test_type == XSyncNegativeComparison &&
ct != XSyncCounterNeverDecreases)
{
if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
XSyncValueGreaterThan(pTrigger->test_value,
psci->bracket_less))
{
psci->bracket_less = pTrigger->test_value;
pnewltval = &psci->bracket_less;
}
}
else if ( (pTrigger->test_type == XSyncPositiveTransition &&
ct != XSyncCounterNeverIncreases)
||
(pTrigger->test_type == XSyncNegativeTransition &&
ct != XSyncCounterNeverDecreases)
)
{
if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
{
if (XSyncValueLessThan(pTrigger->test_value,
psci->bracket_greater))
{
psci->bracket_greater = pTrigger->test_value;
pnewgtval = &psci->bracket_greater;
}
else
if (XSyncValueGreaterThan(pTrigger->test_value,
psci->bracket_less))
{
psci->bracket_less = pTrigger->test_value;
pnewltval = &psci->bracket_less;
}
}
}
}
if (pnewgtval || pnewltval)
{
(*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
}
}
static int
FreeAlarm(addr, id)
pointer addr;
XID id;
{
SyncAlarm *pAlarm = (SyncAlarm *) addr;
pAlarm->state = XSyncAlarmDestroyed;
SyncSendAlarmNotifyEvents(pAlarm);
while (pAlarm->pEventClients)
FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
SyncDeleteTriggerFromCounter(&pAlarm->trigger);
xfree(pAlarm);
return Success;
}
static int
FreeCounter(env, id)
pointer env;
XID id;
{
SyncCounter *pCounter = (SyncCounter *) env;
SyncTriggerList *ptl, *pnext;
pCounter->beingDestroyed = TRUE;
for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
{
(*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
pnext = ptl->next;
xfree(ptl);
}
if (IsSystemCounter(pCounter))
{
int i, found = 0;
xfree(pCounter->pSysCounterInfo);
if (SysCounterList)
{
for (i = 0; i < SyncNumSystemCounters; i++)
{
if (SysCounterList[i] == pCounter)
{
found = i;
break;
}
}
if (found < (SyncNumSystemCounters-1))
{
for (i = found; i < SyncNumSystemCounters-1; i++)
{
SysCounterList[i] = SysCounterList[i+1];
}
}
}
SyncNumSystemCounters--;
}
xfree(pCounter);
return Success;
}
static int
FreeAwait(addr, id)
pointer addr;
XID id;
{
SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
SyncAwait *pAwait;
int numwaits;
pAwait = &(pAwaitUnion+1)->await;
for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
numwaits--, pAwait++)
{
SyncCounter *pCounter = pAwait->trigger.pCounter;
if (pCounter && !pCounter->beingDestroyed)
SyncDeleteTriggerFromCounter(&pAwait->trigger);
}
xfree(pAwaitUnion);
return Success;
}
static int
FreeAlarmClient(value, id)
pointer value;
XID id;
{
SyncAlarm *pAlarm = (SyncAlarm *)value;
SyncAlarmClientList *pCur, *pPrev;
for (pPrev = NULL, pCur = pAlarm->pEventClients;
pCur;
pPrev = pCur, pCur = pCur->next)
{
if (pCur->delete_id == id)
{
if (pPrev)
pPrev->next = pCur->next;
else
pAlarm->pEventClients = pCur->next;
xfree(pCur);
return(Success);
}
}
FatalError("alarm client not on event list");
}
static int
ProcSyncInitialize(client)
ClientPtr client;
{
xSyncInitializeReply rep;
int n;
REQUEST_SIZE_MATCH(xSyncInitializeReq);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.majorVersion = SYNC_MAJOR_VERSION;
rep.minorVersion = SYNC_MINOR_VERSION;
rep.length = 0;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
}
WriteToClient(client, sizeof(rep), (char *) &rep);
return (client->noClientException);
}
static int
ProcSyncListSystemCounters(client)
ClientPtr client;
{
xSyncListSystemCountersReply rep;
int i, len;
xSyncSystemCounter *list = NULL, *walklist = NULL;
REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.nCounters = SyncNumSystemCounters;
for (i = len = 0; i < SyncNumSystemCounters; i++)
{
char *name = SysCounterList[i]->pSysCounterInfo->name;
len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
}
if (len)
{
walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
if (!list)
return BadAlloc;
}
rep.length = len >> 2;
if (client->swapped)
{
register char n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.nCounters, n);
}
for (i = 0; i < SyncNumSystemCounters; i++)
{
int namelen;
char *pname_in_reply;
SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
walklist->counter = SysCounterList[i]->id;
walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
walklist->resolution_lo = XSyncValueLow32(psci->resolution);
namelen = strlen(psci->name);
walklist->name_length = namelen;
if (client->swapped)
{
register char n;
swapl(&walklist->counter, n);
swapl(&walklist->resolution_hi, n);
swapl(&walklist->resolution_lo, n);
swaps(&walklist->name_length, n);
}
pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
strncpy(pname_in_reply, psci->name, namelen);
walklist = (xSyncSystemCounter *) (((char *)walklist) +
((sz_xSyncSystemCounter + namelen + 3) & ~3));
}
WriteToClient(client, sizeof(rep), (char *) &rep);
if (len)
{
WriteToClient(client, len, (char *) list);
DEALLOCATE_LOCAL(list);
}
return (client->noClientException);
}
static int
ProcSyncSetPriority(client)
ClientPtr client;
{
REQUEST(xSyncSetPriorityReq);
ClientPtr priorityclient;
REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
if (stuff->id == None)
priorityclient = client;
else if (!(priorityclient = LookupClient(stuff->id, client)))
{
client->errorValue = stuff->id;
return BadMatch;
}
if (priorityclient->priority != stuff->priority)
{
priorityclient->priority = stuff->priority;
isItTimeToYield = TRUE;
dispatchException |= DE_PRIORITYCHANGE;
}
return Success;
}
static int
ProcSyncGetPriority(client)
ClientPtr client;
{
REQUEST(xSyncGetPriorityReq);
xSyncGetPriorityReply rep;
ClientPtr priorityclient;
REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
if (stuff->id == None)
priorityclient = client;
else if (!(priorityclient = LookupClient(stuff->id, client)))
{
client->errorValue = stuff->id;
return BadMatch;
}
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.priority = priorityclient->priority;
if (client->swapped)
{
register char n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.priority, n);
}
WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
return (client->noClientException);
}
static int
ProcSyncCreateCounter(client)
ClientPtr client;
{
REQUEST(xSyncCreateCounterReq);
CARD64 initial;
REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
LEGAL_NEW_RESOURCE(stuff->cid, client);
XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
if (!SyncCreateCounter(client, stuff->cid, initial))
return BadAlloc;
return (client->noClientException);
}
static int
ProcSyncSetCounter(client)
ClientPtr client;
{
REQUEST(xSyncSetCounterReq);
SyncCounter *pCounter;
CARD64 newvalue;
REQUEST_SIZE_MATCH(xSyncSetCounterReq);
pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
RTCounter, SecurityWriteAccess);
if (pCounter == NULL)
{
client->errorValue = stuff->cid;
return SyncErrorBase + XSyncBadCounter;
}
if (IsSystemCounter(pCounter))
{
client->errorValue = stuff->cid;
return BadAccess;
}
XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
SyncChangeCounter(pCounter, newvalue);
return Success;
}
static int
ProcSyncChangeCounter(client)
ClientPtr client;
{
REQUEST(xSyncChangeCounterReq);
SyncCounter *pCounter;
CARD64 newvalue;
Bool overflow;
REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
RTCounter, SecurityWriteAccess);
if (pCounter == NULL)
{
client->errorValue = stuff->cid;
return SyncErrorBase + XSyncBadCounter;
}
if (IsSystemCounter(pCounter))
{
client->errorValue = stuff->cid;
return BadAccess;
}
XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
if (overflow)
{
client->errorValue = stuff->value_hi;
return BadValue;
}
SyncChangeCounter(pCounter, newvalue);
return Success;
}
static int
ProcSyncDestroyCounter(client)
ClientPtr client;
{
REQUEST(xSyncDestroyCounterReq);
SyncCounter *pCounter;
REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
RTCounter, SecurityDestroyAccess);
if (pCounter == NULL)
{
client->errorValue = stuff->counter;
return SyncErrorBase + XSyncBadCounter;
}
if (IsSystemCounter(pCounter))
{
client->errorValue = stuff->counter;
return BadAccess;
}
FreeResource(pCounter->id, RT_NONE);
return Success;
}
static int
ProcSyncAwait(client)
ClientPtr client;
{
REQUEST(xSyncAwaitReq);
int len, items;
int i;
xSyncWaitCondition *pProtocolWaitConds;
SyncAwaitUnion *pAwaitUnion;
SyncAwait *pAwait;
int status;
REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
len = client->req_len << 2;
len -= sz_xSyncAwaitReq;
items = len / sz_xSyncWaitCondition;
if (items * sz_xSyncWaitCondition != len)
{
return BadLength;
}
if (items == 0)
{
client->errorValue = items;
return BadValue;
}
pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
if (!pAwaitUnion)
return BadAlloc;
pAwaitUnion->header.delete_id = FakeClientID(client->index);
if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
{
xfree(pAwaitUnion);
return BadAlloc;
}
pAwaitUnion->header.client = client;
pAwaitUnion->header.num_waitconditions = 0;
pAwait = &(pAwaitUnion+1)->await;
for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
{
if (pProtocolWaitConds->counter == None)
{
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
client->errorValue = pProtocolWaitConds->counter;
return SyncErrorBase + XSyncBadCounter;
}
pAwait->trigger.pCounter = NULL;
pAwait->trigger.value_type = pProtocolWaitConds->value_type;
XSyncIntsToValue(&pAwait->trigger.wait_value,
pProtocolWaitConds->wait_value_lo,
pProtocolWaitConds->wait_value_hi);
pAwait->trigger.test_type = pProtocolWaitConds->test_type;
status = SyncInitTrigger(client, &pAwait->trigger,
pProtocolWaitConds->counter, XSyncCAAllTrigger);
if (status != Success)
{
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
return status;
}
pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
XSyncIntsToValue(&pAwait->event_threshold,
pProtocolWaitConds->event_threshold_lo,
pProtocolWaitConds->event_threshold_hi);
pAwait->pHeader = &pAwaitUnion->header;
pAwaitUnion->header.num_waitconditions++;
}
IgnoreClient(client);
pAwait = &(pAwaitUnion+1)->await;
for (i = 0; i < items; i++, pAwait++)
{
if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
pAwait->trigger.pCounter->value))
{
(*pAwait->trigger.TriggerFired)(&pAwait->trigger);
break;
}
}
return Success;
}
static int
ProcSyncQueryCounter(client)
ClientPtr client;
{
REQUEST(xSyncQueryCounterReq);
xSyncQueryCounterReply rep;
SyncCounter *pCounter;
REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
RTCounter, SecurityReadAccess);
if (pCounter == NULL)
{
client->errorValue = stuff->counter;
return SyncErrorBase + XSyncBadCounter;
}
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
if (IsSystemCounter(pCounter))
{
(*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
&pCounter->value);
}
rep.value_hi = XSyncValueHigh32(pCounter->value);
rep.value_lo = XSyncValueLow32(pCounter->value);
if (client->swapped)
{
register char n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.value_hi, n);
swapl(&rep.value_lo, n);
}
WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
return (client->noClientException);
}
static int
ProcSyncCreateAlarm(client)
ClientPtr client;
{
REQUEST(xSyncCreateAlarmReq);
SyncAlarm *pAlarm;
int status;
unsigned long len, vmask;
SyncTrigger *pTrigger;
REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
LEGAL_NEW_RESOURCE(stuff->id, client);
vmask = stuff->valueMask;
len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
return BadLength;
if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
{
return BadAlloc;
}
pTrigger = &pAlarm->trigger;
pTrigger->pCounter = NULL;
pTrigger->value_type = XSyncAbsolute;
XSyncIntToValue(&pTrigger->wait_value, 0L);
pTrigger->test_type = XSyncPositiveComparison;
pTrigger->TriggerFired = SyncAlarmTriggerFired;
pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
if (status != Success)
{
xfree(pAlarm);
return status;
}
pAlarm->client = client;
pAlarm->alarm_id = stuff->id;
XSyncIntToValue(&pAlarm->delta, 1L);
pAlarm->events = TRUE;
pAlarm->state = XSyncAlarmInactive;
pAlarm->pEventClients = NULL;
status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
(CARD32 *)&stuff[1]);
if (status != Success)
{
xfree(pAlarm);
return status;
}
if (!AddResource(stuff->id, RTAlarm, pAlarm))
{
xfree(pAlarm);
return BadAlloc;
}
if (!pTrigger->pCounter)
{
pAlarm->state = XSyncAlarmInactive;
}
else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
{
(*pTrigger->TriggerFired)(pTrigger);
}
return Success;
}
static int
ProcSyncChangeAlarm(client)
ClientPtr client;
{
REQUEST(xSyncChangeAlarmReq);
SyncAlarm *pAlarm;
long vmask;
int len, status;
REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
RTAlarm, SecurityWriteAccess)))
{
client->errorValue = stuff->alarm;
return SyncErrorBase + XSyncBadAlarm;
}
vmask = stuff->valueMask;
len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
return BadLength;
if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
(CARD32 *)&stuff[1])) != Success)
return status;
if (!pAlarm->trigger.pCounter ||
(*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
pAlarm->trigger.pCounter->value))
{
(*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
}
return Success;
}
static int
ProcSyncQueryAlarm(client)
ClientPtr client;
{
REQUEST(xSyncQueryAlarmReq);
SyncAlarm *pAlarm;
xSyncQueryAlarmReply rep;
SyncTrigger *pTrigger;
REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
RTAlarm, SecurityReadAccess);
if (!pAlarm)
{
client->errorValue = stuff->alarm;
return (SyncErrorBase + XSyncBadAlarm);
}
rep.type = X_Reply;
rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2;
rep.sequenceNumber = client->sequence;
pTrigger = &pAlarm->trigger;
rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None;
#if 0
rep.value_type = pTrigger->value_type;
rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
#else
rep.value_type = XSyncAbsolute;
rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
#endif
rep.test_type = pTrigger->test_type;
rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
rep.delta_lo = XSyncValueLow32(pAlarm->delta);
rep.events = pAlarm->events;
rep.state = pAlarm->state;
if (client->swapped)
{
register char n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.counter, n);
swapl(&rep.wait_value_hi, n);
swapl(&rep.wait_value_lo, n);
swapl(&rep.test_type, n);
swapl(&rep.delta_hi, n);
swapl(&rep.delta_lo, n);
}
WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
return (client->noClientException);
}
static int
ProcSyncDestroyAlarm(client)
ClientPtr client;
{
REQUEST(xSyncDestroyAlarmReq);
REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
RTAlarm, SecurityDestroyAccess)))
{
client->errorValue = stuff->alarm;
return SyncErrorBase + XSyncBadAlarm;
}
FreeResource(stuff->alarm, RT_NONE);
return (client->noClientException);
}
static int
ProcSyncDispatch(client)
ClientPtr client;
{
REQUEST(xReq);
switch (stuff->data)
{
case X_SyncInitialize:
return ProcSyncInitialize(client);
case X_SyncListSystemCounters:
return ProcSyncListSystemCounters(client);
case X_SyncCreateCounter:
return ProcSyncCreateCounter(client);
case X_SyncSetCounter:
return ProcSyncSetCounter(client);
case X_SyncChangeCounter:
return ProcSyncChangeCounter(client);
case X_SyncQueryCounter:
return ProcSyncQueryCounter(client);
case X_SyncDestroyCounter:
return ProcSyncDestroyCounter(client);
case X_SyncAwait:
return ProcSyncAwait(client);
case X_SyncCreateAlarm:
return ProcSyncCreateAlarm(client);
case X_SyncChangeAlarm:
return ProcSyncChangeAlarm(client);
case X_SyncQueryAlarm:
return ProcSyncQueryAlarm(client);
case X_SyncDestroyAlarm:
return ProcSyncDestroyAlarm(client);
case X_SyncSetPriority:
return ProcSyncSetPriority(client);
case X_SyncGetPriority:
return ProcSyncGetPriority(client);
default:
return BadRequest;
}
}
static int
SProcSyncInitialize(client)
ClientPtr client;
{
REQUEST(xSyncInitializeReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncInitializeReq);
return ProcSyncInitialize(client);
}
static int
SProcSyncListSystemCounters(client)
ClientPtr client;
{
REQUEST(xSyncListSystemCountersReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
return ProcSyncListSystemCounters(client);
}
static int
SProcSyncCreateCounter(client)
ClientPtr client;
{
REQUEST(xSyncCreateCounterReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
swapl(&stuff->cid, n);
swapl(&stuff->initial_value_lo, n);
swapl(&stuff->initial_value_hi, n);
return ProcSyncCreateCounter(client);
}
static int
SProcSyncSetCounter(client)
ClientPtr client;
{
REQUEST(xSyncSetCounterReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncSetCounterReq);
swapl(&stuff->cid, n);
swapl(&stuff->value_lo, n);
swapl(&stuff->value_hi, n);
return ProcSyncSetCounter(client);
}
static int
SProcSyncChangeCounter(client)
ClientPtr client;
{
REQUEST(xSyncChangeCounterReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
swapl(&stuff->cid, n);
swapl(&stuff->value_lo, n);
swapl(&stuff->value_hi, n);
return ProcSyncChangeCounter(client);
}
static int
SProcSyncQueryCounter(client)
ClientPtr client;
{
REQUEST(xSyncQueryCounterReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
swapl(&stuff->counter, n);
return ProcSyncQueryCounter(client);
}
static int
SProcSyncDestroyCounter(client)
ClientPtr client;
{
REQUEST(xSyncDestroyCounterReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
swapl(&stuff->counter, n);
return ProcSyncDestroyCounter(client);
}
static int
SProcSyncAwait(client)
ClientPtr client;
{
REQUEST(xSyncAwaitReq);
register char n;
swaps(&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
SwapRestL(stuff);
return ProcSyncAwait(client);
}
static int
SProcSyncCreateAlarm(client)
ClientPtr client;
{
REQUEST(xSyncCreateAlarmReq);
register char n;
swaps(&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
swapl(&stuff->id, n);
swapl(&stuff->valueMask, n);
SwapRestL(stuff);
return ProcSyncCreateAlarm(client);
}
static int
SProcSyncChangeAlarm(client)
ClientPtr client;
{
REQUEST(xSyncChangeAlarmReq);
register char n;
swaps(&stuff->length, n);
REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
swapl(&stuff->alarm, n);
swapl(&stuff->valueMask, n);
SwapRestL(stuff);
return ProcSyncChangeAlarm(client);
}
static int
SProcSyncQueryAlarm(client)
ClientPtr client;
{
REQUEST(xSyncQueryAlarmReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
swapl(&stuff->alarm, n);
return ProcSyncQueryAlarm(client);
}
static int
SProcSyncDestroyAlarm(client)
ClientPtr client;
{
REQUEST(xSyncDestroyAlarmReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
swapl(&stuff->alarm, n);
return ProcSyncDestroyAlarm(client);
}
static int
SProcSyncSetPriority(client)
ClientPtr client;
{
REQUEST(xSyncSetPriorityReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
swapl(&stuff->id, n);
swapl(&stuff->priority, n);
return ProcSyncSetPriority(client);
}
static int
SProcSyncGetPriority(client)
ClientPtr client;
{
REQUEST(xSyncGetPriorityReq);
register char n;
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
swapl(&stuff->id, n);
return ProcSyncGetPriority(client);
}
static int
SProcSyncDispatch(client)
ClientPtr client;
{
REQUEST(xReq);
switch (stuff->data)
{
case X_SyncInitialize:
return SProcSyncInitialize(client);
case X_SyncListSystemCounters:
return SProcSyncListSystemCounters(client);
case X_SyncCreateCounter:
return SProcSyncCreateCounter(client);
case X_SyncSetCounter:
return SProcSyncSetCounter(client);
case X_SyncChangeCounter:
return SProcSyncChangeCounter(client);
case X_SyncQueryCounter:
return SProcSyncQueryCounter(client);
case X_SyncDestroyCounter:
return SProcSyncDestroyCounter(client);
case X_SyncAwait:
return SProcSyncAwait(client);
case X_SyncCreateAlarm:
return SProcSyncCreateAlarm(client);
case X_SyncChangeAlarm:
return SProcSyncChangeAlarm(client);
case X_SyncQueryAlarm:
return SProcSyncQueryAlarm(client);
case X_SyncDestroyAlarm:
return SProcSyncDestroyAlarm(client);
case X_SyncSetPriority:
return SProcSyncSetPriority(client);
case X_SyncGetPriority:
return SProcSyncGetPriority(client);
default:
return BadRequest;
}
}
static void
SCounterNotifyEvent(from, to)
xSyncCounterNotifyEvent *from, *to;
{
to->type = from->type;
to->kind = from->kind;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->counter, to->counter);
cpswapl(from->wait_value_lo, to->wait_value_lo);
cpswapl(from->wait_value_hi, to->wait_value_hi);
cpswapl(from->counter_value_lo, to->counter_value_lo);
cpswapl(from->counter_value_hi, to->counter_value_hi);
cpswapl(from->time, to->time);
cpswaps(from->count, to->count);
to->destroyed = from->destroyed;
}
static void
SAlarmNotifyEvent(from, to)
xSyncAlarmNotifyEvent *from, *to;
{
to->type = from->type;
to->kind = from->kind;
cpswaps(from->sequenceNumber, to->sequenceNumber);
cpswapl(from->alarm, to->alarm);
cpswapl(from->counter_value_lo, to->counter_value_lo);
cpswapl(from->counter_value_hi, to->counter_value_hi);
cpswapl(from->alarm_value_lo, to->alarm_value_lo);
cpswapl(from->alarm_value_hi, to->alarm_value_hi);
cpswapl(from->time, to->time);
to->state = from->state;
}
static void
SyncResetProc(extEntry)
ExtensionEntry *extEntry;
{
xfree(SysCounterList);
SysCounterList = NULL;
RTCounter = 0;
}
void
SyncExtensionInit(INITARGS)
{
ExtensionEntry *extEntry;
if (RTCounter == 0)
{
RTCounter = CreateNewResourceType(FreeCounter);
}
RTAlarm = CreateNewResourceType(FreeAlarm);
RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN;
RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN;
if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
RTAlarmClient == 0 ||
(extEntry = AddExtension(SYNC_NAME,
XSyncNumberEvents, XSyncNumberErrors,
ProcSyncDispatch, SProcSyncDispatch,
SyncResetProc,
StandardMinorOpcode)) == NULL)
{
ErrorF("Sync Extension %d.%d failed to Initialise\n",
SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
return;
}
SyncEventBase = extEntry->eventBase;
SyncErrorBase = extEntry->errorBase;
EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
SyncInitServerTime();
#ifdef DEBUG
fprintf(stderr, "Sync Extension %d.%d\n",
SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
#endif
}
static pointer ServertimeCounter;
static XSyncValue Now;
static XSyncValue *pnext_time;
#define GetTime()\
{\
unsigned long millis = GetTimeInMillis();\
unsigned long maxis = XSyncValueHigh32(Now);\
if (millis < XSyncValueLow32(Now)) maxis++;\
XSyncIntsToValue(&Now, millis, maxis);\
}
static void ServertimeBlockHandler(env, wt, LastSelectMask)
pointer env;
struct timeval **wt;
pointer LastSelectMask;
{
XSyncValue delay;
unsigned long timeout;
if (pnext_time)
{
GetTime();
if (XSyncValueGreaterOrEqual(Now, *pnext_time))
{
timeout = 0;
}
else
{
Bool overflow;
XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
(void)overflow;
timeout = XSyncValueLow32(delay);
}
AdjustWaitForDelay(wt, timeout);
}
}
static void ServertimeWakeupHandler(env, rc, LastSelectMask)
pointer env;
int rc;
pointer LastSelectMask;
{
if (pnext_time)
{
GetTime();
if (XSyncValueGreaterOrEqual(Now, *pnext_time))
{
SyncChangeCounter(ServertimeCounter, Now);
}
}
}
static void
ServertimeQueryValue(pCounter, pValue_return)
pointer pCounter;
CARD64 *pValue_return;
{
GetTime();
*pValue_return = Now;
}
static void
ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater)
pointer pCounter;
CARD64 *pbracket_less;
CARD64 *pbracket_greater;
{
if (!pnext_time && pbracket_greater)
{
RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
ServertimeWakeupHandler,
NULL);
}
else if (pnext_time && !pbracket_greater)
{
RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
ServertimeWakeupHandler,
NULL);
}
pnext_time = pbracket_greater;
}
static void
SyncInitServerTime()
{
CARD64 resolution;
XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
XSyncIntToValue(&resolution, 4);
ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
XSyncCounterNeverDecreases,
ServertimeQueryValue, ServertimeBracketValues);
pnext_time = NULL;
}