1 /* $XConsortium: sync.c /main/13 1996/12/16 16:51:55 rws $ */
2 /* $XFree86: xc/programs/Xserver/Xext/sync.c,v 3.3 1997/01/18 06:53:00 dawes Exp $ */
5 Copyright (c) 1991, 1993 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
32 Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
33 and Olivetti Research Limited, Cambridge, England.
37 Permission to use, copy, modify, and distribute this software and its
38 documentation for any purpose and without fee is hereby granted,
39 provided that the above copyright notice appear in all copies and that
40 both that copyright notice and this permission notice appear in
41 supporting documentation, and that the names of Digital or Olivetti
42 not be used in advertising or publicity pertaining to distribution of the
43 software without specific, written prior permission. Digital and Olivetti
44 make no representations about the suitability of this software
45 for any purpose. It is provided "as is" without express or implied warranty.
47 DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
48 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
49 FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
50 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
51 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
52 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
53 PERFORMANCE OF THIS SOFTWARE.
65 #include "extnsionst.h"
66 #include "dixstruct.h"
74 * Local Global Variables
76 static int SyncReqCode;
77 static int SyncEventBase;
78 static int SyncErrorBase;
79 static RESTYPE RTCounter = 0;
80 static RESTYPE RTAwait;
81 static RESTYPE RTAlarm;
82 static RESTYPE RTAlarmClient;
83 static int SyncNumSystemCounters = 0;
84 static SyncCounter **SysCounterList = NULL;
86 #define IsSystemCounter(pCounter) \
87 (pCounter && (pCounter->client == NULL))
89 /* these are all the alarm attributes that pertain to the alarm's trigger */
90 #define XSyncCAAllTrigger \
91 (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
95 #if NeedFunctionPrototypes
103 #if NeedFunctionPrototypes
111 #if NeedFunctionPrototypes
118 ServertimeBracketValues(
119 #if NeedFunctionPrototypes
120 pointer /* pCounter */,
121 CARD64 * /* pbracket_less */,
122 CARD64 * /* pbracket_greater */
127 ServertimeQueryValue(
128 #if NeedFunctionPrototypes
129 pointer /* pCounter */,
130 CARD64 * /* pValue_return */
135 ServertimeWakeupHandler(
136 #if NeedFunctionPrototypes
139 pointer /* LastSelectMask */
145 #if NeedFunctionPrototypes
146 ClientPtr /* client */,
147 SyncTrigger * /* pTrigger */,
148 XSyncCounter /* counter */,
155 #if NeedFunctionPrototypes
156 xSyncAlarmNotifyEvent * /* from */,
157 xSyncAlarmNotifyEvent * /* to */
163 #if NeedFunctionPrototypes
164 xSyncCounterNotifyEvent * /* from */,
165 xSyncCounterNotifyEvent * /* to */
170 ServertimeBlockHandler(
171 #if NeedFunctionPrototypes
173 struct timeval ** /* wt */,
174 pointer /* LastSelectMask */
179 SyncAddTriggerToCounter(
180 #if NeedFunctionPrototypes
181 SyncTrigger * /* pTrigger */
186 SyncAlarmCounterDestroyed(
187 #if NeedFunctionPrototypes
188 SyncTrigger * /* pTrigger */
193 SyncAlarmTriggerFired(
194 #if NeedFunctionPrototypes
195 SyncTrigger * /* pTrigger */
200 SyncAwaitTriggerFired(
201 #if NeedFunctionPrototypes
202 SyncTrigger * /* pTrigger */
207 SyncChangeAlarmAttributes(
208 #if NeedFunctionPrototypes
209 ClientPtr /* client */,
210 SyncAlarm * /* pAlarm */,
212 CARD32 * /* values */
217 SyncCheckTriggerNegativeComparison(
218 #if NeedFunctionPrototypes
219 SyncTrigger * /* pTrigger */,
225 SyncCheckTriggerNegativeTransition(
226 #if NeedFunctionPrototypes
227 SyncTrigger * /* pTrigger */,
233 SyncCheckTriggerPositiveComparison(
234 #if NeedFunctionPrototypes
235 SyncTrigger * /* pTrigger */,
241 SyncCheckTriggerPositiveTransition(
242 #if NeedFunctionPrototypes
243 SyncTrigger * /* pTrigger */,
250 #if NeedFunctionPrototypes
251 ClientPtr /* client */,
252 XSyncCounter /* id */,
253 CARD64 /* initialvalue */
257 static void SyncComputeBracketValues(
258 #if NeedFunctionPrototypes
259 SyncCounter * /* pCounter */,
265 SyncDeleteTriggerFromCounter(
266 #if NeedFunctionPrototypes
267 SyncTrigger * /* pTrigger */
272 SyncEventSelectForAlarm(
273 #if NeedFunctionPrototypes
274 SyncAlarm * /* pAlarm */,
275 ClientPtr /* client */,
276 Bool /* wantevents */
282 #if NeedFunctionPrototypes
289 #if NeedFunctionPrototypes
290 ExtensionEntry * /* extEntry */
295 SyncSendAlarmNotifyEvents(
296 #if NeedFunctionPrototypes
297 SyncAlarm * /* pAlarm */
302 SyncSendCounterNotifyEvents(
303 #if NeedFunctionPrototypes
304 ClientPtr /* client */,
305 SyncAwait ** /* ppAwait */,
310 static DISPATCH_PROC(ProcSyncAwait);
311 static DISPATCH_PROC(ProcSyncChangeAlarm);
312 static DISPATCH_PROC(ProcSyncChangeCounter);
313 static DISPATCH_PROC(ProcSyncCreateAlarm);
314 static DISPATCH_PROC(ProcSyncCreateCounter);
315 static DISPATCH_PROC(ProcSyncDestroyAlarm);
316 static DISPATCH_PROC(ProcSyncDestroyCounter);
317 static DISPATCH_PROC(ProcSyncDispatch);
318 static DISPATCH_PROC(ProcSyncGetPriority);
319 static DISPATCH_PROC(ProcSyncInitialize);
320 static DISPATCH_PROC(ProcSyncListSystemCounters);
321 static DISPATCH_PROC(ProcSyncListSystemCounters);
322 static DISPATCH_PROC(ProcSyncQueryAlarm);
323 static DISPATCH_PROC(ProcSyncQueryCounter);
324 static DISPATCH_PROC(ProcSyncSetCounter);
325 static DISPATCH_PROC(ProcSyncSetPriority);
326 static DISPATCH_PROC(SProcSyncAwait);
327 static DISPATCH_PROC(SProcSyncChangeAlarm);
328 static DISPATCH_PROC(SProcSyncChangeCounter);
329 static DISPATCH_PROC(SProcSyncCreateAlarm);
330 static DISPATCH_PROC(SProcSyncCreateCounter);
331 static DISPATCH_PROC(SProcSyncDestroyAlarm);
332 static DISPATCH_PROC(SProcSyncDestroyCounter);
333 static DISPATCH_PROC(SProcSyncDispatch);
334 static DISPATCH_PROC(SProcSyncDispatch);
335 static DISPATCH_PROC(SProcSyncGetPriority);
336 static DISPATCH_PROC(SProcSyncInitialize);
337 static DISPATCH_PROC(SProcSyncListSystemCounters);
338 static DISPATCH_PROC(SProcSyncQueryAlarm);
339 static DISPATCH_PROC(SProcSyncQueryCounter);
340 static DISPATCH_PROC(SProcSyncSetCounter);
341 static DISPATCH_PROC(SProcSyncSetPriority);
343 /* Each counter maintains a simple linked list of triggers that are
344 * interested in the counter. The two functions below are used to
345 * delete and add triggers on this list.
348 SyncDeleteTriggerFromCounter(pTrigger)
349 SyncTrigger *pTrigger;
351 SyncTriggerList *pCur, *pPrev = NULL;
353 /* pCounter needs to be stored in pTrigger before calling here. */
355 if (!pTrigger->pCounter)
358 for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
360 if (pCur->pTrigger == pTrigger)
363 pPrev->next = pCur->next;
365 pTrigger->pCounter->pTriglist = pCur->next;
371 if (IsSystemCounter(pTrigger->pCounter))
372 SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
377 SyncAddTriggerToCounter(pTrigger)
378 SyncTrigger *pTrigger;
380 SyncTriggerList *pCur;
382 if (!pTrigger->pCounter)
385 /* don't do anything if it's already there */
386 for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
388 if (pCur->pTrigger == pTrigger)
392 if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
395 pCur->pTrigger = pTrigger;
396 pCur->next = pTrigger->pCounter->pTriglist;
397 pTrigger->pCounter->pTriglist = pCur;
399 if (IsSystemCounter(pTrigger->pCounter))
400 SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
406 /* Below are four possible functions that can be plugged into
407 * pTrigger->CheckTrigger, corresponding to the four possible
408 * test-types. These functions are called after the counter's
409 * value changes but are also passed the old counter value
410 * so they can inspect both the old and new values.
411 * (PositiveTransition and NegativeTransition need to see both
412 * pieces of information.) These functions return the truth value
415 * All of them include the condition pTrigger->pCounter == NULL.
416 * This is because the spec says that a trigger with a counter value
417 * of None is always TRUE.
421 SyncCheckTriggerPositiveComparison(pTrigger, oldval)
422 SyncTrigger *pTrigger;
425 return (pTrigger->pCounter == NULL ||
426 XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
427 pTrigger->test_value));
431 SyncCheckTriggerNegativeComparison(pTrigger, oldval)
432 SyncTrigger *pTrigger;
435 return (pTrigger->pCounter == NULL ||
436 XSyncValueLessOrEqual(pTrigger->pCounter->value,
437 pTrigger->test_value));
441 SyncCheckTriggerPositiveTransition(pTrigger, oldval)
442 SyncTrigger *pTrigger;
445 return (pTrigger->pCounter == NULL ||
446 (XSyncValueLessThan(oldval, pTrigger->test_value) &&
447 XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
448 pTrigger->test_value)));
452 SyncCheckTriggerNegativeTransition(pTrigger, oldval)
453 SyncTrigger *pTrigger;
456 return (pTrigger->pCounter == NULL ||
457 (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
458 XSyncValueLessOrEqual(pTrigger->pCounter->value,
459 pTrigger->test_value)));
465 SyncInitTrigger(client, pTrigger, counter, changes)
466 ClientPtr client; /* so we can set errorValue */
467 SyncTrigger *pTrigger;
468 XSyncCounter counter;
471 SyncCounter *pCounter = pTrigger->pCounter;
473 Bool newcounter = FALSE;
475 if (changes & XSyncCACounter)
479 else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
480 client, counter, RTCounter, SecurityReadAccess)))
482 client->errorValue = counter;
483 return SyncErrorBase + XSyncBadCounter;
485 if (pCounter != pTrigger->pCounter)
486 { /* new counter for trigger */
487 SyncDeleteTriggerFromCounter(pTrigger);
488 pTrigger->pCounter = pCounter;
493 /* if system counter, ask it what the current value is */
495 if (IsSystemCounter(pCounter))
497 (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
501 if (changes & XSyncCAValueType)
503 if (pTrigger->value_type != XSyncRelative &&
504 pTrigger->value_type != XSyncAbsolute)
506 client->errorValue = pTrigger->value_type;
511 if (changes & XSyncCATestType)
513 if (pTrigger->test_type != XSyncPositiveTransition &&
514 pTrigger->test_type != XSyncNegativeTransition &&
515 pTrigger->test_type != XSyncPositiveComparison &&
516 pTrigger->test_type != XSyncNegativeComparison)
518 client->errorValue = pTrigger->test_type;
521 /* select appropriate CheckTrigger function */
523 switch (pTrigger->test_type)
525 case XSyncPositiveTransition:
526 pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
528 case XSyncNegativeTransition:
529 pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
531 case XSyncPositiveComparison:
532 pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
534 case XSyncNegativeComparison:
535 pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
540 if (changes & (XSyncCAValueType | XSyncCAValue))
542 if (pTrigger->value_type == XSyncAbsolute)
543 pTrigger->test_value = pTrigger->wait_value;
547 if (pCounter == NULL)
550 XSyncValueAdd(&pTrigger->test_value, pCounter->value,
551 pTrigger->wait_value, &overflow);
554 client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
560 /* we wait until we're sure there are no errors before registering
561 * a new counter on a trigger
565 if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
568 else if (IsSystemCounter(pCounter))
570 SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
576 /* AlarmNotify events happen in response to actions taken on an Alarm or
577 * the counter used by the alarm. AlarmNotify may be sent to multiple
578 * clients. The alarm maintains a list of clients interested in events.
581 SyncSendAlarmNotifyEvents(pAlarm)
584 SyncAlarmClientList *pcl;
585 xSyncAlarmNotifyEvent ane;
586 SyncTrigger *pTrigger = &pAlarm->trigger;
590 ane.type = SyncEventBase + XSyncAlarmNotify;
591 ane.kind = XSyncAlarmNotify;
592 ane.sequenceNumber = pAlarm->client->sequence;
593 ane.alarm = pAlarm->alarm_id;
594 if (pTrigger->pCounter)
596 ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
597 ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
600 { /* XXX what else can we do if there's no counter? */
601 ane.counter_value_hi = ane.counter_value_lo = 0;
604 ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
605 ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
606 ane.time = currentTime.milliseconds;
607 ane.state = pAlarm->state;
610 if (pAlarm->events && !pAlarm->client->clientGone)
611 WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
613 /* send to other interested clients */
614 for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
616 if (!pAlarm->client->clientGone)
618 ane.sequenceNumber = pcl->client->sequence;
619 WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
625 /* CounterNotify events only occur in response to an Await. The events
626 * go only to the Awaiting client.
629 SyncSendCounterNotifyEvents(client, ppAwait, num_events)
634 xSyncCounterNotifyEvent *pEvents, *pev;
637 if (client->clientGone)
639 pev = pEvents = (xSyncCounterNotifyEvent *)
640 ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
644 for (i = 0; i < num_events; i++, ppAwait++, pev++)
646 SyncTrigger *pTrigger = &(*ppAwait)->trigger;
647 pev->type = SyncEventBase + XSyncCounterNotify;
648 pev->kind = XSyncCounterNotify;
649 pev->sequenceNumber = client->sequence;
650 pev->counter = pTrigger->pCounter->id;
651 pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
652 pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
653 pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
654 pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
655 pev->time = currentTime.milliseconds;
656 pev->count = num_events - i - 1; /* events remaining */
657 pev->destroyed = pTrigger->pCounter->beingDestroyed;
659 /* swapping will be taken care of by this */
660 WriteEventsToClient(client, num_events, (xEvent *)pEvents);
661 DEALLOCATE_LOCAL(pEvents);
665 /* This function is called when an alarm's counter is destroyed.
666 * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
669 SyncAlarmCounterDestroyed(pTrigger)
670 SyncTrigger *pTrigger;
672 SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
674 pAlarm->state = XSyncAlarmInactive;
675 SyncSendAlarmNotifyEvents(pAlarm);
676 pTrigger->pCounter = NULL;
680 /* This function is called when an alarm "goes off."
681 * It is plugged into pTrigger->TriggerFired (for alarm triggers).
684 SyncAlarmTriggerFired(pTrigger)
685 SyncTrigger *pTrigger;
687 SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
688 CARD64 new_test_value;
690 /* no need to check alarm unless it's active */
691 if (pAlarm->state != XSyncAlarmActive)
694 /* " if the counter value is None, or if the delta is 0 and
695 * the test-type is PositiveComparison or NegativeComparison,
696 * no change is made to value (test-value) and the alarm
697 * state is changed to Inactive before the event is generated."
699 if (pAlarm->trigger.pCounter == NULL
700 || (XSyncValueIsZero(pAlarm->delta)
701 && (pAlarm->trigger.test_type == XSyncPositiveComparison
702 || pAlarm->trigger.test_type == XSyncNegativeComparison)))
703 pAlarm->state = XSyncAlarmInactive;
705 new_test_value = pAlarm->trigger.test_value;
707 if (pAlarm->state == XSyncAlarmActive)
711 SyncTrigger *paTrigger = &pAlarm->trigger;
713 /* "The alarm is updated by repeatedly adding delta to the
714 * value of the trigger and re-initializing it until it
717 oldvalue = paTrigger->test_value;
719 /* XXX really should do something smarter here */
723 XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
724 pAlarm->delta, &overflow);
725 } while (!overflow &&
726 (*paTrigger->CheckTrigger)(paTrigger,
727 paTrigger->pCounter->value));
729 new_test_value = paTrigger->test_value;
730 paTrigger->test_value = oldvalue;
732 /* "If this update would cause value to fall outside the range
733 * for an INT64...no change is made to value (test-value) and
734 * the alarm state is changed to Inactive before the event is
739 new_test_value = oldvalue;
740 pAlarm->state = XSyncAlarmInactive;
743 /* The AlarmNotify event has to have the "new state of the alarm"
744 * which we can't be sure of until this point. However, it has
745 * to have the "old" trigger test value. That's the reason for
746 * all the newvalue/oldvalue shuffling above. After we send the
747 * events, give the trigger its new test value.
749 SyncSendAlarmNotifyEvents(pAlarm);
750 pTrigger->test_value = new_test_value;
754 /* This function is called when an Await unblocks, either as a result
755 * of the trigger firing OR the counter being destroyed.
756 * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
757 * (for Await triggers).
760 SyncAwaitTriggerFired(pTrigger)
761 SyncTrigger *pTrigger;
763 SyncAwait *pAwait = (SyncAwait *)pTrigger;
765 SyncAwaitUnion *pAwaitUnion;
769 pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
770 numwaits = pAwaitUnion->header.num_waitconditions;
771 ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
775 pAwait = &(pAwaitUnion+1)->await;
777 /* "When a client is unblocked, all the CounterNotify events for
778 * the Await request are generated contiguously. If count is 0
779 * there are no more events to follow for this request. If
780 * count is n, there are at least n more events to follow."
782 * Thus, it is best to find all the counters for which events
783 * need to be sent first, so that an accurate count field can
784 * be stored in the events.
786 for ( ; numwaits; numwaits--, pAwait++)
789 Bool overflow, diffgreater, diffequal;
791 /* "A CounterNotify event with the destroyed flag set to TRUE is
792 * always generated if the counter for one of the triggers is
795 if (pAwait->trigger.pCounter->beingDestroyed)
797 ppAwait[num_events++] = pAwait;
801 /* "The difference between the counter and the test value is
802 * calculated by subtracting the test value from the value of
805 XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
806 pAwait->trigger.test_value, &overflow);
808 /* "If the difference lies outside the range for an INT64, an
809 * event is not generated."
813 diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
814 diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
816 /* "If the test-type is PositiveTransition or
817 * PositiveComparison, a CounterNotify event is generated if
818 * the difference is at least event-threshold. If the test-type
819 * is NegativeTransition or NegativeComparison, a CounterNotify
820 * event is generated if the difference is at most
824 if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
825 pAwait->trigger.test_type == XSyncPositiveTransition)
826 && (diffgreater || diffequal))
828 ((pAwait->trigger.test_type == XSyncNegativeComparison ||
829 pAwait->trigger.test_type == XSyncNegativeTransition)
830 && (!diffgreater) /* less or equal */
834 ppAwait[num_events++] = pAwait;
838 SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
840 DEALLOCATE_LOCAL(ppAwait);
843 /* unblock the client */
844 AttendClient(pAwaitUnion->header.client);
845 /* delete the await */
846 FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
850 /* This function should always be used to change a counter's value so that
851 * any triggers depending on the counter will be checked.
854 SyncChangeCounter(pCounter, newval)
855 SyncCounter *pCounter;
858 SyncTriggerList *ptl, *pnext;
861 oldval = pCounter->value;
862 pCounter->value = newval;
864 /* run through triggers to see if any become true */
865 for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
868 if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
869 (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
872 if (IsSystemCounter(pCounter))
874 SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
879 /* loosely based on dix/events.c/EventSelectForWindow */
881 SyncEventSelectForAlarm(pAlarm, client, wantevents)
886 SyncAlarmClientList *pClients;
888 if (client == pAlarm->client) /* alarm owner */
890 pAlarm->events = wantevents;
894 /* see if the client is already on the list (has events selected) */
896 for (pClients = pAlarm->pEventClients; pClients;
897 pClients = pClients->next)
899 if (pClients->client == client)
901 /* client's presence on the list indicates desire for
902 * events. If the client doesn't want events, remove it
903 * from the list. If the client does want events, do
904 * nothing, since it's already got them.
908 FreeResource(pClients->delete_id, RT_NONE);
914 /* if we get here, this client does not currently have
915 * events selected on the alarm
919 /* client doesn't want events, and we just discovered that it
920 * doesn't have them, so there's nothing to do.
924 /* add new client to pAlarm->pEventClients */
926 pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
930 /* register it as a resource so it will be cleaned up
934 pClients->delete_id = FakeClientID(client->index);
935 if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
941 /* link it into list after we know all the allocations succeed */
943 pClients->next = pAlarm->pEventClients;
944 pAlarm->pEventClients = pClients;
945 pClients->client = client;
950 * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
953 SyncChangeAlarmAttributes(client, pAlarm, mask, values)
960 XSyncCounter counter;
961 Mask origmask = mask;
963 counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
967 int index2 = lowbit(mask);
972 mask &= ~XSyncCACounter;
973 /* sanity check in SyncInitTrigger */
977 case XSyncCAValueType:
978 mask &= ~XSyncCAValueType;
979 /* sanity check in SyncInitTrigger */
980 pAlarm->trigger.value_type = *values++;
984 mask &= ~XSyncCAValue;
985 XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
989 case XSyncCATestType:
990 mask &= ~XSyncCATestType;
991 /* sanity check in SyncInitTrigger */
992 pAlarm->trigger.test_type = *values++;
996 mask &= ~XSyncCADelta;
997 XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
1002 mask &= ~XSyncCAEvents;
1003 if ((*values != xTrue) && (*values != xFalse))
1005 client->errorValue = *values;
1008 status = SyncEventSelectForAlarm(pAlarm, client,
1010 if (status != Success)
1015 client->errorValue = mask;
1020 /* "If the test-type is PositiveComparison or PositiveTransition
1021 * and delta is less than zero, or if the test-type is
1022 * NegativeComparison or NegativeTransition and delta is
1023 * greater than zero, a Match error is generated."
1025 if (origmask & (XSyncCADelta|XSyncCATestType))
1028 XSyncIntToValue(&zero, 0);
1029 if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
1030 (pAlarm->trigger.test_type == XSyncPositiveTransition))
1031 && XSyncValueLessThan(pAlarm->delta, zero))
1033 (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
1034 (pAlarm->trigger.test_type == XSyncNegativeTransition))
1035 && XSyncValueGreaterThan(pAlarm->delta, zero))
1042 /* postpone this until now, when we're sure nothing else can go wrong */
1043 if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
1044 origmask & XSyncCAAllTrigger)) != Success)
1047 /* XXX spec does not really say to do this - needs clarification */
1048 pAlarm->state = XSyncAlarmActive;
1053 static SyncCounter *
1054 SyncCreateCounter(client, id, initialvalue)
1057 CARD64 initialvalue;
1059 SyncCounter *pCounter;
1061 if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
1062 return (SyncCounter *)NULL;
1064 if (!AddResource(id, RTCounter, (pointer) pCounter))
1066 xfree((pointer) pCounter);
1067 return (SyncCounter *)NULL;
1070 pCounter->client = client;
1072 pCounter->value = initialvalue;
1073 pCounter->pTriglist = NULL;
1074 pCounter->beingDestroyed = FALSE;
1075 pCounter->pSysCounterInfo = NULL;
1079 static int FreeCounter(
1080 #if NeedFunctionPrototypes
1087 * ***** System Counter utilities
1091 SyncCreateSystemCounter(name, initial, resolution, counterType,
1092 QueryValue, BracketValues)
1096 SyncCounterType counterType;
1097 void (*QueryValue) ();
1098 void (*BracketValues) ();
1100 SyncCounter *pCounter;
1102 SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
1103 (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
1104 if (!SysCounterList)
1105 return (pointer)NULL;
1107 /* this function may be called before SYNC has been initialized, so we
1108 * have to make sure RTCounter is created.
1112 RTCounter = CreateNewResourceType(FreeCounter);
1115 return (pointer)NULL;
1119 pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
1123 SysCounterInfo *psci;
1125 psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
1128 FreeResource(pCounter->id, RT_NONE);
1129 return (pointer) pCounter;
1131 pCounter->pSysCounterInfo = psci;
1133 psci->resolution = resolution;
1134 psci->counterType = counterType;
1135 psci->QueryValue = QueryValue;
1136 psci->BracketValues = BracketValues;
1137 XSyncMaxValue(&psci->bracket_greater);
1138 XSyncMinValue(&psci->bracket_less);
1139 SysCounterList[SyncNumSystemCounters++] = pCounter;
1141 return (pointer) pCounter;
1145 SyncDestroySystemCounter(pSysCounter)
1146 pointer pSysCounter;
1148 SyncCounter *pCounter = (SyncCounter *)pSysCounter;
1149 FreeResource(pCounter->id, RT_NONE);
1153 SyncComputeBracketValues(pCounter, startOver)
1154 SyncCounter *pCounter;
1157 SyncTriggerList *pCur;
1158 SyncTrigger *pTrigger;
1159 SysCounterInfo *psci = pCounter->pSysCounterInfo;
1160 CARD64 *pnewgtval = NULL;
1161 CARD64 *pnewltval = NULL;
1167 ct = pCounter->pSysCounterInfo->counterType;
1168 if (ct == XSyncCounterNeverChanges)
1173 XSyncMaxValue(&psci->bracket_greater);
1174 XSyncMinValue(&psci->bracket_less);
1177 for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
1179 pTrigger = pCur->pTrigger;
1181 if (pTrigger->test_type == XSyncPositiveComparison &&
1182 ct != XSyncCounterNeverIncreases)
1184 if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
1185 XSyncValueLessThan(pTrigger->test_value,
1186 psci->bracket_greater))
1188 psci->bracket_greater = pTrigger->test_value;
1189 pnewgtval = &psci->bracket_greater;
1192 else if (pTrigger->test_type == XSyncNegativeComparison &&
1193 ct != XSyncCounterNeverDecreases)
1195 if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
1196 XSyncValueGreaterThan(pTrigger->test_value,
1197 psci->bracket_less))
1199 psci->bracket_less = pTrigger->test_value;
1200 pnewltval = &psci->bracket_less;
1203 else if ( (pTrigger->test_type == XSyncPositiveTransition &&
1204 ct != XSyncCounterNeverIncreases)
1206 (pTrigger->test_type == XSyncNegativeTransition &&
1207 ct != XSyncCounterNeverDecreases)
1210 if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
1212 if (XSyncValueLessThan(pTrigger->test_value,
1213 psci->bracket_greater))
1215 psci->bracket_greater = pTrigger->test_value;
1216 pnewgtval = &psci->bracket_greater;
1219 if (XSyncValueGreaterThan(pTrigger->test_value,
1220 psci->bracket_less))
1222 psci->bracket_less = pTrigger->test_value;
1223 pnewltval = &psci->bracket_less;
1227 } /* end for each trigger */
1229 if (pnewgtval || pnewltval)
1231 (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
1236 * ***** Resource delete functions
1245 SyncAlarm *pAlarm = (SyncAlarm *) addr;
1247 pAlarm->state = XSyncAlarmDestroyed;
1249 SyncSendAlarmNotifyEvents(pAlarm);
1251 /* delete event selections */
1253 while (pAlarm->pEventClients)
1254 FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
1256 SyncDeleteTriggerFromCounter(&pAlarm->trigger);
1264 * ** Cleanup after the destruction of a Counter
1268 FreeCounter(env, id)
1272 SyncCounter *pCounter = (SyncCounter *) env;
1273 SyncTriggerList *ptl, *pnext;
1275 pCounter->beingDestroyed = TRUE;
1276 /* tell all the counter's triggers that the counter has been destroyed */
1277 for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
1279 (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
1281 xfree(ptl); /* destroy the trigger list as we go */
1283 if (IsSystemCounter(pCounter))
1287 xfree(pCounter->pSysCounterInfo);
1289 /* find the counter in the list of system counters and remove it */
1293 for (i = 0; i < SyncNumSystemCounters; i++)
1295 if (SysCounterList[i] == pCounter)
1301 if (found < (SyncNumSystemCounters-1))
1303 for (i = found; i < SyncNumSystemCounters-1; i++)
1305 SysCounterList[i] = SysCounterList[i+1];
1309 SyncNumSystemCounters--;
1316 * ** Cleanup after Await
1324 SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
1328 pAwait = &(pAwaitUnion+1)->await; /* first await on list */
1330 /* remove triggers from counters */
1332 for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
1333 numwaits--, pAwait++)
1335 /* If the counter is being destroyed, FreeCounter will delete
1336 * the trigger list itself, so don't do it here.
1338 SyncCounter *pCounter = pAwait->trigger.pCounter;
1339 if (pCounter && !pCounter->beingDestroyed)
1340 SyncDeleteTriggerFromCounter(&pAwait->trigger);
1346 /* loosely based on dix/events.c/OtherClientGone */
1348 FreeAlarmClient(value, id)
1349 pointer value; /* must conform to DeleteType */
1352 SyncAlarm *pAlarm = (SyncAlarm *)value;
1353 SyncAlarmClientList *pCur, *pPrev;
1355 for (pPrev = NULL, pCur = pAlarm->pEventClients;
1357 pPrev = pCur, pCur = pCur->next)
1359 if (pCur->delete_id == id)
1362 pPrev->next = pCur->next;
1364 pAlarm->pEventClients = pCur->next;
1369 FatalError("alarm client not on event list");
1375 * ***** Proc functions
1380 * ** Initialize the extension
1383 ProcSyncInitialize(client)
1386 xSyncInitializeReply rep;
1389 REQUEST_SIZE_MATCH(xSyncInitializeReq);
1392 rep.sequenceNumber = client->sequence;
1393 rep.majorVersion = SYNC_MAJOR_VERSION;
1394 rep.minorVersion = SYNC_MINOR_VERSION;
1397 if (client->swapped)
1399 swaps(&rep.sequenceNumber, n);
1401 WriteToClient(client, sizeof(rep), (char *) &rep);
1402 return (client->noClientException);
1406 * ** Get list of system counters available through the extension
1409 ProcSyncListSystemCounters(client)
1412 xSyncListSystemCountersReply rep;
1414 xSyncSystemCounter *list, *walklist;
1416 REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
1419 rep.sequenceNumber = client->sequence;
1420 rep.nCounters = SyncNumSystemCounters;
1422 for (i = len = 0; i < SyncNumSystemCounters; i++)
1424 char *name = SysCounterList[i]->pSysCounterInfo->name;
1425 /* pad to 4 byte boundary */
1426 len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
1431 walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
1436 rep.length = len >> 2;
1438 if (client->swapped)
1441 swaps(&rep.sequenceNumber, n);
1442 swapl(&rep.length, n);
1443 swapl(&rep.nCounters, n);
1446 for (i = 0; i < SyncNumSystemCounters; i++)
1449 char *pname_in_reply;
1450 SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
1452 walklist->counter = SysCounterList[i]->id;
1453 walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
1454 walklist->resolution_lo = XSyncValueLow32(psci->resolution);
1455 namelen = strlen(psci->name);
1456 walklist->name_length = namelen;
1458 if (client->swapped)
1461 swapl(&walklist->counter, n);
1462 swapl(&walklist->resolution_hi, n);
1463 swapl(&walklist->resolution_lo, n);
1464 swaps(&walklist->name_length, n);
1467 pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
1468 strncpy(pname_in_reply, psci->name, namelen);
1469 walklist = (xSyncSystemCounter *) (((char *)walklist) +
1470 ((sz_xSyncSystemCounter + namelen + 3) & ~3));
1473 WriteToClient(client, sizeof(rep), (char *) &rep);
1476 WriteToClient(client, len, (char *) list);
1477 DEALLOCATE_LOCAL(list);
1480 return (client->noClientException);
1484 * ** Set client Priority
1487 ProcSyncSetPriority(client)
1490 REQUEST(xSyncSetPriorityReq);
1491 ClientPtr priorityclient;
1493 REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
1495 if (stuff->id == None)
1496 priorityclient = client;
1497 else if (!(priorityclient = LookupClient(stuff->id, client)))
1499 client->errorValue = stuff->id;
1503 if (priorityclient->priority != stuff->priority)
1505 priorityclient->priority = stuff->priority;
1507 /* The following will force the server back into WaitForSomething
1508 * so that the change in this client's priority is immediately
1511 isItTimeToYield = TRUE;
1512 dispatchException |= DE_PRIORITYCHANGE;
1518 * ** Get client Priority
1521 ProcSyncGetPriority(client)
1524 REQUEST(xSyncGetPriorityReq);
1525 xSyncGetPriorityReply rep;
1526 ClientPtr priorityclient;
1528 REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
1530 if (stuff->id == None)
1531 priorityclient = client;
1532 else if (!(priorityclient = LookupClient(stuff->id, client)))
1534 client->errorValue = stuff->id;
1540 rep.sequenceNumber = client->sequence;
1541 rep.priority = priorityclient->priority;
1543 if (client->swapped)
1546 swaps(&rep.sequenceNumber, n);
1547 swapl(&rep.priority, n);
1550 WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
1552 return (client->noClientException);
1556 * ** Create a new counter
1559 ProcSyncCreateCounter(client)
1562 REQUEST(xSyncCreateCounterReq);
1565 REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
1567 LEGAL_NEW_RESOURCE(stuff->cid, client);
1569 XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
1570 if (!SyncCreateCounter(client, stuff->cid, initial))
1573 return (client->noClientException);
1577 * ** Set Counter value
1580 ProcSyncSetCounter(client)
1583 REQUEST(xSyncSetCounterReq);
1584 SyncCounter *pCounter;
1587 pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
1588 RTCounter, SecurityWriteAccess);
1589 if (pCounter == NULL)
1591 client->errorValue = stuff->cid;
1592 return SyncErrorBase + XSyncBadCounter;
1595 if (IsSystemCounter(pCounter))
1597 client->errorValue = stuff->cid;
1601 XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
1602 SyncChangeCounter(pCounter, newvalue);
1607 * ** Change Counter value
1610 ProcSyncChangeCounter(client)
1613 REQUEST(xSyncChangeCounterReq);
1614 SyncCounter *pCounter;
1618 REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
1620 pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
1621 RTCounter, SecurityWriteAccess);
1622 if (pCounter == NULL)
1624 client->errorValue = stuff->cid;
1625 return SyncErrorBase + XSyncBadCounter;
1628 if (IsSystemCounter(pCounter))
1630 client->errorValue = stuff->cid;
1634 XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
1635 XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
1638 /* XXX 64 bit value can't fit in 32 bits; do the best we can */
1639 client->errorValue = stuff->value_hi;
1642 SyncChangeCounter(pCounter, newvalue);
1647 * ** Destroy a counter
1650 ProcSyncDestroyCounter(client)
1653 REQUEST(xSyncDestroyCounterReq);
1654 SyncCounter *pCounter;
1656 REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
1658 pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
1659 RTCounter, SecurityDestroyAccess);
1660 if (pCounter == NULL)
1662 client->errorValue = stuff->counter;
1663 return SyncErrorBase + XSyncBadCounter;
1665 if (IsSystemCounter(pCounter))
1667 client->errorValue = stuff->counter;
1670 FreeResource(pCounter->id, RT_NONE);
1679 ProcSyncAwait(client)
1682 REQUEST(xSyncAwaitReq);
1685 xSyncWaitCondition *pProtocolWaitConds;
1686 SyncAwaitUnion *pAwaitUnion;
1690 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
1692 len = client->req_len << 2;
1693 len -= sz_xSyncAwaitReq;
1694 items = len / sz_xSyncWaitCondition;
1696 if (items * sz_xSyncWaitCondition != len)
1702 client->errorValue = items; /* XXX protocol change */
1706 pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
1708 /* all the memory for the entire await list is allocated
1711 pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
1715 /* first item is the header, remainder are real wait conditions */
1717 pAwaitUnion->header.delete_id = FakeClientID(client->index);
1718 if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
1724 /* don't need to do any more memory allocation for this request! */
1726 pAwaitUnion->header.client = client;
1727 pAwaitUnion->header.num_waitconditions = 0;
1729 pAwait = &(pAwaitUnion+1)->await; /* skip over header */
1730 for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
1732 if (pProtocolWaitConds->counter == None) /* XXX protocol change */
1734 /* this should take care of removing any triggers created by
1735 * this request that have already been registered on counters
1737 FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1738 client->errorValue = pProtocolWaitConds->counter;
1739 return SyncErrorBase + XSyncBadCounter;
1742 /* sanity checks are in SyncInitTrigger */
1743 pAwait->trigger.pCounter = NULL;
1744 pAwait->trigger.value_type = pProtocolWaitConds->value_type;
1745 XSyncIntsToValue(&pAwait->trigger.wait_value,
1746 pProtocolWaitConds->wait_value_lo,
1747 pProtocolWaitConds->wait_value_hi);
1748 pAwait->trigger.test_type = pProtocolWaitConds->test_type;
1750 status = SyncInitTrigger(client, &pAwait->trigger,
1751 pProtocolWaitConds->counter, XSyncCAAllTrigger);
1752 if (status != Success)
1754 /* this should take care of removing any triggers created by
1755 * this request that have already been registered on counters
1757 FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1760 /* this is not a mistake -- same function works for both cases */
1761 pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
1762 pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
1763 XSyncIntsToValue(&pAwait->event_threshold,
1764 pProtocolWaitConds->event_threshold_lo,
1765 pProtocolWaitConds->event_threshold_hi);
1766 pAwait->pHeader = &pAwaitUnion->header;
1767 pAwaitUnion->header.num_waitconditions++;
1770 IgnoreClient(client);
1772 /* see if any of the triggers are already true */
1774 pAwait = &(pAwaitUnion+1)->await; /* skip over header */
1775 for (i = 0; i < items; i++, pAwait++)
1777 /* don't have to worry about NULL counters because the request
1778 * errors before we get here out if they occur
1780 if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
1781 pAwait->trigger.pCounter->value))
1783 (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
1784 break; /* once is enough */
1792 * ** Query a counter
1795 ProcSyncQueryCounter(client)
1798 REQUEST(xSyncQueryCounterReq);
1799 xSyncQueryCounterReply rep;
1800 SyncCounter *pCounter;
1802 REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
1804 pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
1805 RTCounter, SecurityReadAccess);
1806 if (pCounter == NULL)
1808 client->errorValue = stuff->counter;
1809 return SyncErrorBase + XSyncBadCounter;
1814 rep.sequenceNumber = client->sequence;
1816 /* if system counter, ask it what the current value is */
1818 if (IsSystemCounter(pCounter))
1820 (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
1824 rep.value_hi = XSyncValueHigh32(pCounter->value);
1825 rep.value_lo = XSyncValueLow32(pCounter->value);
1826 if (client->swapped)
1829 swaps(&rep.sequenceNumber, n);
1830 swapl(&rep.length, n);
1831 swapl(&rep.value_hi, n);
1832 swapl(&rep.value_lo, n);
1834 WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
1835 return (client->noClientException);
1843 ProcSyncCreateAlarm(client)
1846 REQUEST(xSyncCreateAlarmReq);
1849 unsigned long len, vmask;
1850 SyncTrigger *pTrigger;
1852 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
1854 LEGAL_NEW_RESOURCE(stuff->id, client);
1856 vmask = stuff->valueMask;
1857 len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
1858 /* the "extra" call to Ones accounts for the presence of 64 bit values */
1859 if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
1862 if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
1867 /* set up defaults */
1869 pTrigger = &pAlarm->trigger;
1870 pTrigger->pCounter = NULL;
1871 pTrigger->value_type = XSyncAbsolute;
1872 XSyncIntToValue(&pTrigger->wait_value, 0L);
1873 pTrigger->test_type = XSyncPositiveComparison;
1874 pTrigger->TriggerFired = SyncAlarmTriggerFired;
1875 pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
1876 status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
1877 if (status != Success)
1883 pAlarm->client = client;
1884 pAlarm->alarm_id = stuff->id;
1885 XSyncIntToValue(&pAlarm->delta, 1L);
1886 pAlarm->events = TRUE;
1887 pAlarm->state = XSyncAlarmInactive;
1888 pAlarm->pEventClients = NULL;
1889 status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1890 (CARD32 *)&stuff[1]);
1891 if (status != Success)
1897 if (!AddResource(stuff->id, RTAlarm, pAlarm))
1903 /* see if alarm already triggered. NULL counter will not trigger
1904 * in CreateAlarm and sets alarm state to Inactive.
1907 if (!pTrigger->pCounter)
1909 pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
1911 else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
1913 (*pTrigger->TriggerFired)(pTrigger);
1923 ProcSyncChangeAlarm(client)
1926 REQUEST(xSyncChangeAlarmReq);
1931 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
1933 if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1934 RTAlarm, SecurityWriteAccess)))
1936 client->errorValue = stuff->alarm;
1937 return SyncErrorBase + XSyncBadAlarm;
1940 vmask = stuff->valueMask;
1941 len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
1942 /* the "extra" call to Ones accounts for the presence of 64 bit values */
1943 if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
1946 if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1947 (CARD32 *)&stuff[1])) != Success)
1950 /* see if alarm already triggered. NULL counter WILL trigger
1954 if (!pAlarm->trigger.pCounter ||
1955 (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
1956 pAlarm->trigger.pCounter->value))
1958 (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
1964 ProcSyncQueryAlarm(client)
1967 REQUEST(xSyncQueryAlarmReq);
1969 xSyncQueryAlarmReply rep;
1970 SyncTrigger *pTrigger;
1972 REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
1974 pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1975 RTAlarm, SecurityReadAccess);
1978 client->errorValue = stuff->alarm;
1979 return (SyncErrorBase + XSyncBadAlarm);
1983 rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2;
1984 rep.sequenceNumber = client->sequence;
1986 pTrigger = &pAlarm->trigger;
1987 rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None;
1989 #if 0 /* XXX unclear what to do, depends on whether relative value-types
1990 * are "consumed" immediately and are considered absolute from then
1993 rep.value_type = pTrigger->value_type;
1994 rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
1995 rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
1997 rep.value_type = XSyncAbsolute;
1998 rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
1999 rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
2002 rep.test_type = pTrigger->test_type;
2003 rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
2004 rep.delta_lo = XSyncValueLow32(pAlarm->delta);
2005 rep.events = pAlarm->events;
2006 rep.state = pAlarm->state;
2008 if (client->swapped)
2011 swaps(&rep.sequenceNumber, n);
2012 swapl(&rep.length, n);
2013 swapl(&rep.counter, n);
2014 swapl(&rep.wait_value_hi, n);
2015 swapl(&rep.wait_value_lo, n);
2016 swapl(&rep.test_type, n);
2017 swapl(&rep.delta_hi, n);
2018 swapl(&rep.delta_lo, n);
2021 WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
2022 return (client->noClientException);
2027 ProcSyncDestroyAlarm(client)
2031 REQUEST(xSyncDestroyAlarmReq);
2033 REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
2035 if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
2036 RTAlarm, SecurityDestroyAccess)))
2038 client->errorValue = stuff->alarm;
2039 return SyncErrorBase + XSyncBadAlarm;
2042 FreeResource(stuff->alarm, RT_NONE);
2043 return (client->noClientException);
2047 * ** Given an extension request, call the appropriate request procedure
2050 ProcSyncDispatch(client)
2055 switch (stuff->data)
2058 case X_SyncInitialize:
2059 return ProcSyncInitialize(client);
2060 case X_SyncListSystemCounters:
2061 return ProcSyncListSystemCounters(client);
2062 case X_SyncCreateCounter:
2063 return ProcSyncCreateCounter(client);
2064 case X_SyncSetCounter:
2065 return ProcSyncSetCounter(client);
2066 case X_SyncChangeCounter:
2067 return ProcSyncChangeCounter(client);
2068 case X_SyncQueryCounter:
2069 return ProcSyncQueryCounter(client);
2070 case X_SyncDestroyCounter:
2071 return ProcSyncDestroyCounter(client);
2073 return ProcSyncAwait(client);
2074 case X_SyncCreateAlarm:
2075 return ProcSyncCreateAlarm(client);
2076 case X_SyncChangeAlarm:
2077 return ProcSyncChangeAlarm(client);
2078 case X_SyncQueryAlarm:
2079 return ProcSyncQueryAlarm(client);
2080 case X_SyncDestroyAlarm:
2081 return ProcSyncDestroyAlarm(client);
2082 case X_SyncSetPriority:
2083 return ProcSyncSetPriority(client);
2084 case X_SyncGetPriority:
2085 return ProcSyncGetPriority(client);
2092 * Boring Swapping stuff ...
2096 SProcSyncInitialize(client)
2099 REQUEST(xSyncInitializeReq);
2102 swaps(&stuff->length, n);
2103 REQUEST_SIZE_MATCH (xSyncInitializeReq);
2105 return ProcSyncInitialize(client);
2109 SProcSyncListSystemCounters(client)
2112 REQUEST(xSyncListSystemCountersReq);
2115 swaps(&stuff->length, n);
2116 REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
2118 return ProcSyncListSystemCounters(client);
2122 SProcSyncCreateCounter(client)
2125 REQUEST(xSyncCreateCounterReq);
2128 swaps(&stuff->length, n);
2129 REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
2130 swapl(&stuff->cid, n);
2131 swapl(&stuff->initial_value_lo, n);
2132 swapl(&stuff->initial_value_hi, n);
2134 return ProcSyncCreateCounter(client);
2138 SProcSyncSetCounter(client)
2141 REQUEST(xSyncSetCounterReq);
2144 swaps(&stuff->length, n);
2145 REQUEST_SIZE_MATCH (xSyncSetCounterReq);
2146 swapl(&stuff->cid, n);
2147 swapl(&stuff->value_lo, n);
2148 swapl(&stuff->value_hi, n);
2150 return ProcSyncSetCounter(client);
2154 SProcSyncChangeCounter(client)
2157 REQUEST(xSyncChangeCounterReq);
2160 swaps(&stuff->length, n);
2161 REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
2162 swapl(&stuff->cid, n);
2163 swapl(&stuff->value_lo, n);
2164 swapl(&stuff->value_hi, n);
2166 return ProcSyncChangeCounter(client);
2170 SProcSyncQueryCounter(client)
2173 REQUEST(xSyncQueryCounterReq);
2176 swaps(&stuff->length, n);
2177 REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
2178 swapl(&stuff->counter, n);
2180 return ProcSyncQueryCounter(client);
2184 SProcSyncDestroyCounter(client)
2187 REQUEST(xSyncDestroyCounterReq);
2190 swaps(&stuff->length, n);
2191 REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
2192 swapl(&stuff->counter, n);
2194 return ProcSyncDestroyCounter(client);
2198 SProcSyncAwait(client)
2201 REQUEST(xSyncAwaitReq);
2204 swaps(&stuff->length, n);
2205 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
2208 return ProcSyncAwait(client);
2213 SProcSyncCreateAlarm(client)
2216 REQUEST(xSyncCreateAlarmReq);
2219 swaps(&stuff->length, n);
2220 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
2221 swapl(&stuff->id, n);
2222 swapl(&stuff->valueMask, n);
2225 return ProcSyncCreateAlarm(client);
2229 SProcSyncChangeAlarm(client)
2232 REQUEST(xSyncChangeAlarmReq);
2235 swaps(&stuff->length, n);
2236 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
2237 swapl(&stuff->alarm, n);
2238 swapl(&stuff->valueMask, n);
2240 return ProcSyncChangeAlarm(client);
2244 SProcSyncQueryAlarm(client)
2247 REQUEST(xSyncQueryAlarmReq);
2250 swaps(&stuff->length, n);
2251 REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
2252 swapl(&stuff->alarm, n);
2254 return ProcSyncQueryAlarm(client);
2258 SProcSyncDestroyAlarm(client)
2261 REQUEST(xSyncDestroyAlarmReq);
2264 swaps(&stuff->length, n);
2265 REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
2266 swapl(&stuff->alarm, n);
2268 return ProcSyncDestroyAlarm(client);
2272 SProcSyncSetPriority(client)
2275 REQUEST(xSyncSetPriorityReq);
2278 swaps(&stuff->length, n);
2279 REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
2280 swapl(&stuff->id, n);
2281 swapl(&stuff->priority, n);
2283 return ProcSyncSetPriority(client);
2287 SProcSyncGetPriority(client)
2290 REQUEST(xSyncGetPriorityReq);
2293 swaps(&stuff->length, n);
2294 REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
2295 swapl(&stuff->id, n);
2297 return ProcSyncGetPriority(client);
2302 SProcSyncDispatch(client)
2307 switch (stuff->data)
2309 case X_SyncInitialize:
2310 return SProcSyncInitialize(client);
2311 case X_SyncListSystemCounters:
2312 return SProcSyncListSystemCounters(client);
2313 case X_SyncCreateCounter:
2314 return SProcSyncCreateCounter(client);
2315 case X_SyncSetCounter:
2316 return SProcSyncSetCounter(client);
2317 case X_SyncChangeCounter:
2318 return SProcSyncChangeCounter(client);
2319 case X_SyncQueryCounter:
2320 return SProcSyncQueryCounter(client);
2321 case X_SyncDestroyCounter:
2322 return SProcSyncDestroyCounter(client);
2324 return SProcSyncAwait(client);
2325 case X_SyncCreateAlarm:
2326 return SProcSyncCreateAlarm(client);
2327 case X_SyncChangeAlarm:
2328 return SProcSyncChangeAlarm(client);
2329 case X_SyncQueryAlarm:
2330 return SProcSyncQueryAlarm(client);
2331 case X_SyncDestroyAlarm:
2332 return SProcSyncDestroyAlarm(client);
2333 case X_SyncSetPriority:
2334 return SProcSyncSetPriority(client);
2335 case X_SyncGetPriority:
2336 return SProcSyncGetPriority(client);
2347 SCounterNotifyEvent(from, to)
2348 xSyncCounterNotifyEvent *from, *to;
2350 to->type = from->type;
2351 to->kind = from->kind;
2352 cpswaps(from->sequenceNumber, to->sequenceNumber);
2353 cpswapl(from->counter, to->counter);
2354 cpswapl(from->wait_value_lo, to->wait_value_lo);
2355 cpswapl(from->wait_value_hi, to->wait_value_hi);
2356 cpswapl(from->counter_value_lo, to->counter_value_lo);
2357 cpswapl(from->counter_value_hi, to->counter_value_hi);
2358 cpswapl(from->time, to->time);
2359 cpswaps(from->count, to->count);
2360 to->destroyed = from->destroyed;
2365 SAlarmNotifyEvent(from, to)
2366 xSyncAlarmNotifyEvent *from, *to;
2368 to->type = from->type;
2369 to->kind = from->kind;
2370 cpswaps(from->sequenceNumber, to->sequenceNumber);
2371 cpswapl(from->alarm, to->alarm);
2372 cpswapl(from->counter_value_lo, to->counter_value_lo);
2373 cpswapl(from->counter_value_hi, to->counter_value_hi);
2374 cpswapl(from->alarm_value_lo, to->alarm_value_lo);
2375 cpswapl(from->alarm_value_hi, to->alarm_value_hi);
2376 cpswapl(from->time, to->time);
2377 to->state = from->state;
2381 * ** Close everything down. ** This is fairly simple for now.
2385 SyncResetProc(extEntry)
2386 ExtensionEntry *extEntry;
2388 xfree(SysCounterList);
2389 SysCounterList = NULL;
2395 * ** Initialise the extension.
2400 ExtensionEntry *extEntry;
2404 RTCounter = CreateNewResourceType(FreeCounter);
2406 RTAlarm = CreateNewResourceType(FreeAlarm);
2407 RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN;
2408 RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN;
2410 if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
2411 RTAlarmClient == 0 ||
2412 (extEntry = AddExtension(SYNC_NAME,
2413 XSyncNumberEvents, XSyncNumberErrors,
2414 ProcSyncDispatch, SProcSyncDispatch,
2416 StandardMinorOpcode)) == NULL)
2418 ErrorF("Sync Extension %d.%d failed to Initialise\n",
2419 SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2423 SyncReqCode = extEntry->base;
2424 SyncEventBase = extEntry->eventBase;
2425 SyncErrorBase = extEntry->errorBase;
2426 EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
2427 EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
2430 * Although SERVERTIME is implemented by the OS layer, we initialise it
2431 * here because doing it in OsInit() is too early. The resource database
2432 * is not initialised when OsInit() is called. This is just about OK
2433 * because there is always a servertime counter.
2435 SyncInitServerTime();
2438 fprintf(stderr, "Sync Extension %d.%d\n",
2439 SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2445 * ***** SERVERTIME implementation - should go in its own file in OS directory?
2449 #if !defined(WIN32) && !defined(MINIX) && !defined(Lynx)
2450 #include <sys/time.h>
2453 static pointer ServertimeCounter;
2454 static XSyncValue Now;
2455 static XSyncValue *pnext_time;
2459 unsigned long millis = GetTimeInMillis();\
2460 unsigned long maxis = XSyncValueHigh32(Now);\
2461 if (millis < XSyncValueLow32(Now)) maxis++;\
2462 XSyncIntsToValue(&Now, millis, maxis);\
2466 *** Server Block Handler
2467 *** code inspired by multibuffer extension
2470 static void ServertimeBlockHandler(env, wt, LastSelectMask)
2472 struct timeval **wt;
2473 pointer LastSelectMask;
2476 unsigned long timeout;
2482 if (XSyncValueGreaterOrEqual(Now, *pnext_time))
2489 XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
2490 timeout = XSyncValueLow32(delay);
2492 AdjustWaitForDelay(wt, timeout); /* os/utils.c */
2500 static void ServertimeWakeupHandler(env, rc, LastSelectMask)
2503 pointer LastSelectMask;
2509 if (XSyncValueGreaterOrEqual(Now, *pnext_time))
2511 SyncChangeCounter(ServertimeCounter, Now);
2517 ServertimeQueryValue(pCounter, pValue_return)
2519 CARD64 *pValue_return;
2522 *pValue_return = Now;
2526 ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater)
2528 CARD64 *pbracket_less;
2529 CARD64 *pbracket_greater;
2531 if (!pnext_time && pbracket_greater)
2533 RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
2534 ServertimeWakeupHandler,
2537 else if (pnext_time && !pbracket_greater)
2539 RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
2540 ServertimeWakeupHandler,
2543 pnext_time = pbracket_greater;
2547 SyncInitServerTime()
2551 XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
2552 XSyncIntToValue(&resolution, 4);
2553 ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
2554 XSyncCounterNeverDecreases,
2555 ServertimeQueryValue, ServertimeBracketValues);