1
/* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
4
Copyright 1991, 1993, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of The Open Group shall
24
not be used in advertising or otherwise to promote the sale, use or
25
other dealings in this Software without prior written authorization
29
Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
30
and Olivetti Research Limited, Cambridge, England.
34
Permission to use, copy, modify, and distribute this software and its
35
documentation for any purpose and without fee is hereby granted,
36
provided that the above copyright notice appear in all copies and that
37
both that copyright notice and this permission notice appear in
38
supporting documentation, and that the names of Digital or Olivetti
39
not be used in advertising or publicity pertaining to distribution of the
40
software without specific, written prior permission. Digital and Olivetti
41
make no representations about the suitability of this software
42
for any purpose. It is provided "as is" without express or implied warranty.
44
DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
45
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
46
FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
47
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
48
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
49
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
50
PERFORMANCE OF THIS SOFTWARE.
53
/* $XFree86: xc/programs/Xserver/Xext/sync.c,v 3.13 2003/09/02 18:19:01 tsi Exp $ */
57
#ifdef HAVE_DIX_CONFIG_H
58
#include <dix-config.h>
62
#include <X11/Xproto.h>
66
#include "extnsionst.h"
67
#include "dixstruct.h"
71
#include <X11/extensions/sync.h>
72
#include <X11/extensions/syncstr.h>
75
#include "xf86_ansic.h"
78
#if !defined(WIN32) && !defined(Lynx)
86
* Local Global Variables
88
static int SyncEventBase;
89
static int SyncErrorBase;
90
static RESTYPE RTCounter = 0;
91
static RESTYPE RTAwait;
92
static RESTYPE RTAlarm;
93
static RESTYPE RTAlarmClient;
94
static int SyncNumSystemCounters = 0;
95
static SyncCounter **SysCounterList = NULL;
97
#define IsSystemCounter(pCounter) \
98
(pCounter && (pCounter->client == NULL))
100
/* these are all the alarm attributes that pertain to the alarm's trigger */
101
#define XSyncCAAllTrigger \
102
(XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
123
ServertimeBracketValues(
124
pointer /* pCounter */,
125
CARD64 * /* pbracket_less */,
126
CARD64 * /* pbracket_greater */
130
ServertimeQueryValue(
131
pointer /* pCounter */,
132
CARD64 * /* pValue_return */
136
ServertimeWakeupHandler(
139
pointer /* LastSelectMask */
144
ClientPtr /* client */,
145
SyncTrigger * /* pTrigger */,
146
XSyncCounter /* counter */,
152
xSyncAlarmNotifyEvent * /* from */,
153
xSyncAlarmNotifyEvent * /* to */
158
xSyncCounterNotifyEvent * /* from */,
159
xSyncCounterNotifyEvent * /* to */
163
ServertimeBlockHandler(
165
struct timeval ** /* wt */,
166
pointer /* LastSelectMask */
170
SyncAddTriggerToCounter(
171
SyncTrigger * /* pTrigger */
175
SyncAlarmCounterDestroyed(
176
SyncTrigger * /* pTrigger */
180
SyncAlarmTriggerFired(
181
SyncTrigger * /* pTrigger */
185
SyncAwaitTriggerFired(
186
SyncTrigger * /* pTrigger */
190
SyncChangeAlarmAttributes(
191
ClientPtr /* client */,
192
SyncAlarm * /* pAlarm */,
194
CARD32 * /* values */
198
SyncCheckTriggerNegativeComparison(
199
SyncTrigger * /* pTrigger */,
204
SyncCheckTriggerNegativeTransition(
205
SyncTrigger * /* pTrigger */,
210
SyncCheckTriggerPositiveComparison(
211
SyncTrigger * /* pTrigger */,
216
SyncCheckTriggerPositiveTransition(
217
SyncTrigger * /* pTrigger */,
223
ClientPtr /* client */,
224
XSyncCounter /* id */,
225
CARD64 /* initialvalue */
228
static void SyncComputeBracketValues(
229
SyncCounter * /* pCounter */,
234
SyncDeleteTriggerFromCounter(
235
SyncTrigger * /* pTrigger */
239
SyncEventSelectForAlarm(
240
SyncAlarm * /* pAlarm */,
241
ClientPtr /* client */,
242
Bool /* wantevents */
252
ExtensionEntry * /* extEntry */
256
SyncSendAlarmNotifyEvents(
257
SyncAlarm * /* pAlarm */
261
SyncSendCounterNotifyEvents(
262
ClientPtr /* client */,
263
SyncAwait ** /* ppAwait */,
267
static DISPATCH_PROC(ProcSyncAwait);
268
static DISPATCH_PROC(ProcSyncChangeAlarm);
269
static DISPATCH_PROC(ProcSyncChangeCounter);
270
static DISPATCH_PROC(ProcSyncCreateAlarm);
271
static DISPATCH_PROC(ProcSyncCreateCounter);
272
static DISPATCH_PROC(ProcSyncDestroyAlarm);
273
static DISPATCH_PROC(ProcSyncDestroyCounter);
274
static DISPATCH_PROC(ProcSyncDispatch);
275
static DISPATCH_PROC(ProcSyncGetPriority);
276
static DISPATCH_PROC(ProcSyncInitialize);
277
static DISPATCH_PROC(ProcSyncListSystemCounters);
278
static DISPATCH_PROC(ProcSyncQueryAlarm);
279
static DISPATCH_PROC(ProcSyncQueryCounter);
280
static DISPATCH_PROC(ProcSyncSetCounter);
281
static DISPATCH_PROC(ProcSyncSetPriority);
282
static DISPATCH_PROC(SProcSyncAwait);
283
static DISPATCH_PROC(SProcSyncChangeAlarm);
284
static DISPATCH_PROC(SProcSyncChangeCounter);
285
static DISPATCH_PROC(SProcSyncCreateAlarm);
286
static DISPATCH_PROC(SProcSyncCreateCounter);
287
static DISPATCH_PROC(SProcSyncDestroyAlarm);
288
static DISPATCH_PROC(SProcSyncDestroyCounter);
289
static DISPATCH_PROC(SProcSyncDispatch);
290
static DISPATCH_PROC(SProcSyncGetPriority);
291
static DISPATCH_PROC(SProcSyncInitialize);
292
static DISPATCH_PROC(SProcSyncListSystemCounters);
293
static DISPATCH_PROC(SProcSyncQueryAlarm);
294
static DISPATCH_PROC(SProcSyncQueryCounter);
295
static DISPATCH_PROC(SProcSyncSetCounter);
296
static DISPATCH_PROC(SProcSyncSetPriority);
298
/* Each counter maintains a simple linked list of triggers that are
299
* interested in the counter. The two functions below are used to
300
* delete and add triggers on this list.
303
SyncDeleteTriggerFromCounter(pTrigger)
304
SyncTrigger *pTrigger;
306
SyncTriggerList *pCur, *pPrev = NULL;
308
/* pCounter needs to be stored in pTrigger before calling here. */
310
if (!pTrigger->pCounter)
313
for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
315
if (pCur->pTrigger == pTrigger)
318
pPrev->next = pCur->next;
320
pTrigger->pCounter->pTriglist = pCur->next;
326
if (IsSystemCounter(pTrigger->pCounter))
327
SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
332
SyncAddTriggerToCounter(pTrigger)
333
SyncTrigger *pTrigger;
335
SyncTriggerList *pCur;
337
if (!pTrigger->pCounter)
340
/* don't do anything if it's already there */
341
for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
343
if (pCur->pTrigger == pTrigger)
347
if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
350
pCur->pTrigger = pTrigger;
351
pCur->next = pTrigger->pCounter->pTriglist;
352
pTrigger->pCounter->pTriglist = pCur;
354
if (IsSystemCounter(pTrigger->pCounter))
355
SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
361
/* Below are four possible functions that can be plugged into
362
* pTrigger->CheckTrigger, corresponding to the four possible
363
* test-types. These functions are called after the counter's
364
* value changes but are also passed the old counter value
365
* so they can inspect both the old and new values.
366
* (PositiveTransition and NegativeTransition need to see both
367
* pieces of information.) These functions return the truth value
370
* All of them include the condition pTrigger->pCounter == NULL.
371
* This is because the spec says that a trigger with a counter value
372
* of None is always TRUE.
376
SyncCheckTriggerPositiveComparison(pTrigger, oldval)
377
SyncTrigger *pTrigger;
380
return (pTrigger->pCounter == NULL ||
381
XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
382
pTrigger->test_value));
386
SyncCheckTriggerNegativeComparison(pTrigger, oldval)
387
SyncTrigger *pTrigger;
390
return (pTrigger->pCounter == NULL ||
391
XSyncValueLessOrEqual(pTrigger->pCounter->value,
392
pTrigger->test_value));
396
SyncCheckTriggerPositiveTransition(pTrigger, oldval)
397
SyncTrigger *pTrigger;
400
return (pTrigger->pCounter == NULL ||
401
(XSyncValueLessThan(oldval, pTrigger->test_value) &&
402
XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
403
pTrigger->test_value)));
407
SyncCheckTriggerNegativeTransition(pTrigger, oldval)
408
SyncTrigger *pTrigger;
411
return (pTrigger->pCounter == NULL ||
412
(XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
413
XSyncValueLessOrEqual(pTrigger->pCounter->value,
414
pTrigger->test_value)));
420
SyncInitTrigger(client, pTrigger, counter, changes)
421
ClientPtr client; /* so we can set errorValue */
422
SyncTrigger *pTrigger;
423
XSyncCounter counter;
426
SyncCounter *pCounter = pTrigger->pCounter;
428
Bool newcounter = FALSE;
430
if (changes & XSyncCACounter)
434
else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
435
client, counter, RTCounter, SecurityReadAccess)))
437
client->errorValue = counter;
438
return SyncErrorBase + XSyncBadCounter;
440
if (pCounter != pTrigger->pCounter)
441
{ /* new counter for trigger */
442
SyncDeleteTriggerFromCounter(pTrigger);
443
pTrigger->pCounter = pCounter;
448
/* if system counter, ask it what the current value is */
450
if (IsSystemCounter(pCounter))
452
(*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
456
if (changes & XSyncCAValueType)
458
if (pTrigger->value_type != XSyncRelative &&
459
pTrigger->value_type != XSyncAbsolute)
461
client->errorValue = pTrigger->value_type;
466
if (changes & XSyncCATestType)
468
if (pTrigger->test_type != XSyncPositiveTransition &&
469
pTrigger->test_type != XSyncNegativeTransition &&
470
pTrigger->test_type != XSyncPositiveComparison &&
471
pTrigger->test_type != XSyncNegativeComparison)
473
client->errorValue = pTrigger->test_type;
476
/* select appropriate CheckTrigger function */
478
switch (pTrigger->test_type)
480
case XSyncPositiveTransition:
481
pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
483
case XSyncNegativeTransition:
484
pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
486
case XSyncPositiveComparison:
487
pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
489
case XSyncNegativeComparison:
490
pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
495
if (changes & (XSyncCAValueType | XSyncCAValue))
497
if (pTrigger->value_type == XSyncAbsolute)
498
pTrigger->test_value = pTrigger->wait_value;
502
if (pCounter == NULL)
505
XSyncValueAdd(&pTrigger->test_value, pCounter->value,
506
pTrigger->wait_value, &overflow);
509
client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
515
/* we wait until we're sure there are no errors before registering
516
* a new counter on a trigger
520
if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
523
else if (IsSystemCounter(pCounter))
525
SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
531
/* AlarmNotify events happen in response to actions taken on an Alarm or
532
* the counter used by the alarm. AlarmNotify may be sent to multiple
533
* clients. The alarm maintains a list of clients interested in events.
536
SyncSendAlarmNotifyEvents(pAlarm)
539
SyncAlarmClientList *pcl;
540
xSyncAlarmNotifyEvent ane;
541
SyncTrigger *pTrigger = &pAlarm->trigger;
545
ane.type = SyncEventBase + XSyncAlarmNotify;
546
ane.kind = XSyncAlarmNotify;
547
ane.sequenceNumber = pAlarm->client->sequence;
548
ane.alarm = pAlarm->alarm_id;
549
if (pTrigger->pCounter)
551
ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
552
ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
555
{ /* XXX what else can we do if there's no counter? */
556
ane.counter_value_hi = ane.counter_value_lo = 0;
559
ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
560
ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
561
ane.time = currentTime.milliseconds;
562
ane.state = pAlarm->state;
565
if (pAlarm->events && !pAlarm->client->clientGone)
566
WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
568
/* send to other interested clients */
569
for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
571
if (!pAlarm->client->clientGone)
573
ane.sequenceNumber = pcl->client->sequence;
574
WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
580
/* CounterNotify events only occur in response to an Await. The events
581
* go only to the Awaiting client.
584
SyncSendCounterNotifyEvents(client, ppAwait, num_events)
589
xSyncCounterNotifyEvent *pEvents, *pev;
592
if (client->clientGone)
594
pev = pEvents = (xSyncCounterNotifyEvent *)
595
ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
599
for (i = 0; i < num_events; i++, ppAwait++, pev++)
601
SyncTrigger *pTrigger = &(*ppAwait)->trigger;
602
pev->type = SyncEventBase + XSyncCounterNotify;
603
pev->kind = XSyncCounterNotify;
604
pev->sequenceNumber = client->sequence;
605
pev->counter = pTrigger->pCounter->id;
606
pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
607
pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
608
pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
609
pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
610
pev->time = currentTime.milliseconds;
611
pev->count = num_events - i - 1; /* events remaining */
612
pev->destroyed = pTrigger->pCounter->beingDestroyed;
614
/* swapping will be taken care of by this */
615
WriteEventsToClient(client, num_events, (xEvent *)pEvents);
616
DEALLOCATE_LOCAL(pEvents);
620
/* This function is called when an alarm's counter is destroyed.
621
* It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
624
SyncAlarmCounterDestroyed(pTrigger)
625
SyncTrigger *pTrigger;
627
SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
629
pAlarm->state = XSyncAlarmInactive;
630
SyncSendAlarmNotifyEvents(pAlarm);
631
pTrigger->pCounter = NULL;
635
/* This function is called when an alarm "goes off."
636
* It is plugged into pTrigger->TriggerFired (for alarm triggers).
639
SyncAlarmTriggerFired(pTrigger)
640
SyncTrigger *pTrigger;
642
SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
643
CARD64 new_test_value;
645
/* no need to check alarm unless it's active */
646
if (pAlarm->state != XSyncAlarmActive)
649
/* " if the counter value is None, or if the delta is 0 and
650
* the test-type is PositiveComparison or NegativeComparison,
651
* no change is made to value (test-value) and the alarm
652
* state is changed to Inactive before the event is generated."
654
if (pAlarm->trigger.pCounter == NULL
655
|| (XSyncValueIsZero(pAlarm->delta)
656
&& (pAlarm->trigger.test_type == XSyncPositiveComparison
657
|| pAlarm->trigger.test_type == XSyncNegativeComparison)))
658
pAlarm->state = XSyncAlarmInactive;
660
new_test_value = pAlarm->trigger.test_value;
662
if (pAlarm->state == XSyncAlarmActive)
666
SyncTrigger *paTrigger = &pAlarm->trigger;
668
/* "The alarm is updated by repeatedly adding delta to the
669
* value of the trigger and re-initializing it until it
672
oldvalue = paTrigger->test_value;
674
/* XXX really should do something smarter here */
678
XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
679
pAlarm->delta, &overflow);
680
} while (!overflow &&
681
(*paTrigger->CheckTrigger)(paTrigger,
682
paTrigger->pCounter->value));
684
new_test_value = paTrigger->test_value;
685
paTrigger->test_value = oldvalue;
687
/* "If this update would cause value to fall outside the range
688
* for an INT64...no change is made to value (test-value) and
689
* the alarm state is changed to Inactive before the event is
694
new_test_value = oldvalue;
695
pAlarm->state = XSyncAlarmInactive;
698
/* The AlarmNotify event has to have the "new state of the alarm"
699
* which we can't be sure of until this point. However, it has
700
* to have the "old" trigger test value. That's the reason for
701
* all the newvalue/oldvalue shuffling above. After we send the
702
* events, give the trigger its new test value.
704
SyncSendAlarmNotifyEvents(pAlarm);
705
pTrigger->test_value = new_test_value;
709
/* This function is called when an Await unblocks, either as a result
710
* of the trigger firing OR the counter being destroyed.
711
* It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
712
* (for Await triggers).
715
SyncAwaitTriggerFired(pTrigger)
716
SyncTrigger *pTrigger;
718
SyncAwait *pAwait = (SyncAwait *)pTrigger;
720
SyncAwaitUnion *pAwaitUnion;
724
pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
725
numwaits = pAwaitUnion->header.num_waitconditions;
726
ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
730
pAwait = &(pAwaitUnion+1)->await;
732
/* "When a client is unblocked, all the CounterNotify events for
733
* the Await request are generated contiguously. If count is 0
734
* there are no more events to follow for this request. If
735
* count is n, there are at least n more events to follow."
737
* Thus, it is best to find all the counters for which events
738
* need to be sent first, so that an accurate count field can
739
* be stored in the events.
741
for ( ; numwaits; numwaits--, pAwait++)
744
Bool overflow, diffgreater, diffequal;
746
/* "A CounterNotify event with the destroyed flag set to TRUE is
747
* always generated if the counter for one of the triggers is
750
if (pAwait->trigger.pCounter->beingDestroyed)
752
ppAwait[num_events++] = pAwait;
756
/* "The difference between the counter and the test value is
757
* calculated by subtracting the test value from the value of
760
XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
761
pAwait->trigger.test_value, &overflow);
763
/* "If the difference lies outside the range for an INT64, an
764
* event is not generated."
768
diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
769
diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
771
/* "If the test-type is PositiveTransition or
772
* PositiveComparison, a CounterNotify event is generated if
773
* the difference is at least event-threshold. If the test-type
774
* is NegativeTransition or NegativeComparison, a CounterNotify
775
* event is generated if the difference is at most
779
if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
780
pAwait->trigger.test_type == XSyncPositiveTransition)
781
&& (diffgreater || diffequal))
783
((pAwait->trigger.test_type == XSyncNegativeComparison ||
784
pAwait->trigger.test_type == XSyncNegativeTransition)
785
&& (!diffgreater) /* less or equal */
789
ppAwait[num_events++] = pAwait;
793
SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
795
DEALLOCATE_LOCAL(ppAwait);
798
/* unblock the client */
799
AttendClient(pAwaitUnion->header.client);
800
/* delete the await */
801
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
805
/* This function should always be used to change a counter's value so that
806
* any triggers depending on the counter will be checked.
809
SyncChangeCounter(pCounter, newval)
810
SyncCounter *pCounter;
813
SyncTriggerList *ptl, *pnext;
816
oldval = pCounter->value;
817
pCounter->value = newval;
819
/* run through triggers to see if any become true */
820
for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
823
if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
824
(*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
827
if (IsSystemCounter(pCounter))
829
SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
834
/* loosely based on dix/events.c/EventSelectForWindow */
836
SyncEventSelectForAlarm(pAlarm, client, wantevents)
841
SyncAlarmClientList *pClients;
843
if (client == pAlarm->client) /* alarm owner */
845
pAlarm->events = wantevents;
849
/* see if the client is already on the list (has events selected) */
851
for (pClients = pAlarm->pEventClients; pClients;
852
pClients = pClients->next)
854
if (pClients->client == client)
856
/* client's presence on the list indicates desire for
857
* events. If the client doesn't want events, remove it
858
* from the list. If the client does want events, do
859
* nothing, since it's already got them.
863
FreeResource(pClients->delete_id, RT_NONE);
869
/* if we get here, this client does not currently have
870
* events selected on the alarm
874
/* client doesn't want events, and we just discovered that it
875
* doesn't have them, so there's nothing to do.
879
/* add new client to pAlarm->pEventClients */
881
pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
885
/* register it as a resource so it will be cleaned up
889
pClients->delete_id = FakeClientID(client->index);
890
if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
896
/* link it into list after we know all the allocations succeed */
898
pClients->next = pAlarm->pEventClients;
899
pAlarm->pEventClients = pClients;
900
pClients->client = client;
905
* ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
908
SyncChangeAlarmAttributes(client, pAlarm, mask, values)
915
XSyncCounter counter;
916
Mask origmask = mask;
918
counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
922
int index2 = lowbit(mask);
927
mask &= ~XSyncCACounter;
928
/* sanity check in SyncInitTrigger */
932
case XSyncCAValueType:
933
mask &= ~XSyncCAValueType;
934
/* sanity check in SyncInitTrigger */
935
pAlarm->trigger.value_type = *values++;
939
mask &= ~XSyncCAValue;
940
XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
944
case XSyncCATestType:
945
mask &= ~XSyncCATestType;
946
/* sanity check in SyncInitTrigger */
947
pAlarm->trigger.test_type = *values++;
951
mask &= ~XSyncCADelta;
952
XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
957
mask &= ~XSyncCAEvents;
958
if ((*values != xTrue) && (*values != xFalse))
960
client->errorValue = *values;
963
status = SyncEventSelectForAlarm(pAlarm, client,
965
if (status != Success)
970
client->errorValue = mask;
975
/* "If the test-type is PositiveComparison or PositiveTransition
976
* and delta is less than zero, or if the test-type is
977
* NegativeComparison or NegativeTransition and delta is
978
* greater than zero, a Match error is generated."
980
if (origmask & (XSyncCADelta|XSyncCATestType))
983
XSyncIntToValue(&zero, 0);
984
if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
985
(pAlarm->trigger.test_type == XSyncPositiveTransition))
986
&& XSyncValueLessThan(pAlarm->delta, zero))
988
(((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
989
(pAlarm->trigger.test_type == XSyncNegativeTransition))
990
&& XSyncValueGreaterThan(pAlarm->delta, zero))
997
/* postpone this until now, when we're sure nothing else can go wrong */
998
if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
999
origmask & XSyncCAAllTrigger)) != Success)
1002
/* XXX spec does not really say to do this - needs clarification */
1003
pAlarm->state = XSyncAlarmActive;
1008
static SyncCounter *
1009
SyncCreateCounter(client, id, initialvalue)
1012
CARD64 initialvalue;
1014
SyncCounter *pCounter;
1016
if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
1017
return (SyncCounter *)NULL;
1019
if (!AddResource(id, RTCounter, (pointer) pCounter))
1021
xfree((pointer) pCounter);
1022
return (SyncCounter *)NULL;
1025
pCounter->client = client;
1027
pCounter->value = initialvalue;
1028
pCounter->pTriglist = NULL;
1029
pCounter->beingDestroyed = FALSE;
1030
pCounter->pSysCounterInfo = NULL;
1034
static int FreeCounter(
1040
* ***** System Counter utilities
1044
SyncCreateSystemCounter(name, initial, resolution, counterType,
1045
QueryValue, BracketValues)
1049
SyncCounterType counterType;
1050
void (*QueryValue) (
1051
pointer /* pCounter */,
1052
CARD64 * /* pValue_return */);
1053
void (*BracketValues) (
1054
pointer /* pCounter */,
1055
CARD64 * /* pbracket_less */,
1056
CARD64 * /* pbracket_greater */);
1058
SyncCounter *pCounter;
1060
SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
1061
(SyncNumSystemCounters+1)*sizeof(SyncCounter *));
1062
if (!SysCounterList)
1063
return (pointer)NULL;
1065
/* this function may be called before SYNC has been initialized, so we
1066
* have to make sure RTCounter is created.
1070
RTCounter = CreateNewResourceType(FreeCounter);
1073
return (pointer)NULL;
1077
pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
1081
SysCounterInfo *psci;
1083
psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
1086
FreeResource(pCounter->id, RT_NONE);
1087
return (pointer) pCounter;
1089
pCounter->pSysCounterInfo = psci;
1091
psci->resolution = resolution;
1092
psci->counterType = counterType;
1093
psci->QueryValue = QueryValue;
1094
psci->BracketValues = BracketValues;
1095
XSyncMaxValue(&psci->bracket_greater);
1096
XSyncMinValue(&psci->bracket_less);
1097
SysCounterList[SyncNumSystemCounters++] = pCounter;
1099
return (pointer) pCounter;
1103
SyncDestroySystemCounter(pSysCounter)
1104
pointer pSysCounter;
1106
SyncCounter *pCounter = (SyncCounter *)pSysCounter;
1107
FreeResource(pCounter->id, RT_NONE);
1111
SyncComputeBracketValues(pCounter, startOver)
1112
SyncCounter *pCounter;
1115
SyncTriggerList *pCur;
1116
SyncTrigger *pTrigger;
1117
SysCounterInfo *psci = pCounter->pSysCounterInfo;
1118
CARD64 *pnewgtval = NULL;
1119
CARD64 *pnewltval = NULL;
1125
ct = pCounter->pSysCounterInfo->counterType;
1126
if (ct == XSyncCounterNeverChanges)
1131
XSyncMaxValue(&psci->bracket_greater);
1132
XSyncMinValue(&psci->bracket_less);
1135
for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
1137
pTrigger = pCur->pTrigger;
1139
if (pTrigger->test_type == XSyncPositiveComparison &&
1140
ct != XSyncCounterNeverIncreases)
1142
if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
1143
XSyncValueLessThan(pTrigger->test_value,
1144
psci->bracket_greater))
1146
psci->bracket_greater = pTrigger->test_value;
1147
pnewgtval = &psci->bracket_greater;
1150
else if (pTrigger->test_type == XSyncNegativeComparison &&
1151
ct != XSyncCounterNeverDecreases)
1153
if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
1154
XSyncValueGreaterThan(pTrigger->test_value,
1155
psci->bracket_less))
1157
psci->bracket_less = pTrigger->test_value;
1158
pnewltval = &psci->bracket_less;
1161
else if ( (pTrigger->test_type == XSyncPositiveTransition &&
1162
ct != XSyncCounterNeverIncreases)
1164
(pTrigger->test_type == XSyncNegativeTransition &&
1165
ct != XSyncCounterNeverDecreases)
1168
if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
1170
if (XSyncValueLessThan(pTrigger->test_value,
1171
psci->bracket_greater))
1173
psci->bracket_greater = pTrigger->test_value;
1174
pnewgtval = &psci->bracket_greater;
1177
if (XSyncValueGreaterThan(pTrigger->test_value,
1178
psci->bracket_less))
1180
psci->bracket_less = pTrigger->test_value;
1181
pnewltval = &psci->bracket_less;
1185
} /* end for each trigger */
1187
if (pnewgtval || pnewltval)
1189
(*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
1194
* ***** Resource delete functions
1203
SyncAlarm *pAlarm = (SyncAlarm *) addr;
1205
pAlarm->state = XSyncAlarmDestroyed;
1207
SyncSendAlarmNotifyEvents(pAlarm);
1209
/* delete event selections */
1211
while (pAlarm->pEventClients)
1212
FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
1214
SyncDeleteTriggerFromCounter(&pAlarm->trigger);
1222
* ** Cleanup after the destruction of a Counter
1226
FreeCounter(env, id)
1230
SyncCounter *pCounter = (SyncCounter *) env;
1231
SyncTriggerList *ptl, *pnext;
1233
pCounter->beingDestroyed = TRUE;
1234
/* tell all the counter's triggers that the counter has been destroyed */
1235
for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
1237
(*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
1239
xfree(ptl); /* destroy the trigger list as we go */
1241
if (IsSystemCounter(pCounter))
1245
xfree(pCounter->pSysCounterInfo);
1247
/* find the counter in the list of system counters and remove it */
1251
for (i = 0; i < SyncNumSystemCounters; i++)
1253
if (SysCounterList[i] == pCounter)
1259
if (found < (SyncNumSystemCounters-1))
1261
for (i = found; i < SyncNumSystemCounters-1; i++)
1263
SysCounterList[i] = SysCounterList[i+1];
1267
SyncNumSystemCounters--;
1274
* ** Cleanup after Await
1282
SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
1286
pAwait = &(pAwaitUnion+1)->await; /* first await on list */
1288
/* remove triggers from counters */
1290
for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
1291
numwaits--, pAwait++)
1293
/* If the counter is being destroyed, FreeCounter will delete
1294
* the trigger list itself, so don't do it here.
1296
SyncCounter *pCounter = pAwait->trigger.pCounter;
1297
if (pCounter && !pCounter->beingDestroyed)
1298
SyncDeleteTriggerFromCounter(&pAwait->trigger);
1304
/* loosely based on dix/events.c/OtherClientGone */
1306
FreeAlarmClient(value, id)
1307
pointer value; /* must conform to DeleteType */
1310
SyncAlarm *pAlarm = (SyncAlarm *)value;
1311
SyncAlarmClientList *pCur, *pPrev;
1313
for (pPrev = NULL, pCur = pAlarm->pEventClients;
1315
pPrev = pCur, pCur = pCur->next)
1317
if (pCur->delete_id == id)
1320
pPrev->next = pCur->next;
1322
pAlarm->pEventClients = pCur->next;
1327
FatalError("alarm client not on event list");
1333
* ***** Proc functions
1338
* ** Initialize the extension
1341
ProcSyncInitialize(client)
1344
xSyncInitializeReply rep;
1347
REQUEST_SIZE_MATCH(xSyncInitializeReq);
1350
rep.sequenceNumber = client->sequence;
1351
rep.majorVersion = SYNC_MAJOR_VERSION;
1352
rep.minorVersion = SYNC_MINOR_VERSION;
1355
if (client->swapped)
1357
swaps(&rep.sequenceNumber, n);
1359
WriteToClient(client, sizeof(rep), (char *) &rep);
1360
return (client->noClientException);
1364
* ** Get list of system counters available through the extension
1367
ProcSyncListSystemCounters(client)
1370
xSyncListSystemCountersReply rep;
1372
xSyncSystemCounter *list = NULL, *walklist = NULL;
1374
REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
1377
rep.sequenceNumber = client->sequence;
1378
rep.nCounters = SyncNumSystemCounters;
1380
for (i = len = 0; i < SyncNumSystemCounters; i++)
1382
char *name = SysCounterList[i]->pSysCounterInfo->name;
1383
/* pad to 4 byte boundary */
1384
len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
1389
walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
1394
rep.length = len >> 2;
1396
if (client->swapped)
1399
swaps(&rep.sequenceNumber, n);
1400
swapl(&rep.length, n);
1401
swapl(&rep.nCounters, n);
1404
for (i = 0; i < SyncNumSystemCounters; i++)
1407
char *pname_in_reply;
1408
SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
1410
walklist->counter = SysCounterList[i]->id;
1411
walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
1412
walklist->resolution_lo = XSyncValueLow32(psci->resolution);
1413
namelen = strlen(psci->name);
1414
walklist->name_length = namelen;
1416
if (client->swapped)
1419
swapl(&walklist->counter, n);
1420
swapl(&walklist->resolution_hi, n);
1421
swapl(&walklist->resolution_lo, n);
1422
swaps(&walklist->name_length, n);
1425
pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
1426
strncpy(pname_in_reply, psci->name, namelen);
1427
walklist = (xSyncSystemCounter *) (((char *)walklist) +
1428
((sz_xSyncSystemCounter + namelen + 3) & ~3));
1431
WriteToClient(client, sizeof(rep), (char *) &rep);
1434
WriteToClient(client, len, (char *) list);
1435
DEALLOCATE_LOCAL(list);
1438
return (client->noClientException);
1442
* ** Set client Priority
1445
ProcSyncSetPriority(client)
1448
REQUEST(xSyncSetPriorityReq);
1449
ClientPtr priorityclient;
1451
REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
1453
if (stuff->id == None)
1454
priorityclient = client;
1455
else if (!(priorityclient = LookupClient(stuff->id, client)))
1457
client->errorValue = stuff->id;
1461
if (priorityclient->priority != stuff->priority)
1463
priorityclient->priority = stuff->priority;
1465
/* The following will force the server back into WaitForSomething
1466
* so that the change in this client's priority is immediately
1469
isItTimeToYield = TRUE;
1470
dispatchException |= DE_PRIORITYCHANGE;
1476
* ** Get client Priority
1479
ProcSyncGetPriority(client)
1482
REQUEST(xSyncGetPriorityReq);
1483
xSyncGetPriorityReply rep;
1484
ClientPtr priorityclient;
1486
REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
1488
if (stuff->id == None)
1489
priorityclient = client;
1490
else if (!(priorityclient = LookupClient(stuff->id, client)))
1492
client->errorValue = stuff->id;
1498
rep.sequenceNumber = client->sequence;
1499
rep.priority = priorityclient->priority;
1501
if (client->swapped)
1504
swaps(&rep.sequenceNumber, n);
1505
swapl(&rep.priority, n);
1508
WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
1510
return (client->noClientException);
1514
* ** Create a new counter
1517
ProcSyncCreateCounter(client)
1520
REQUEST(xSyncCreateCounterReq);
1523
REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
1525
LEGAL_NEW_RESOURCE(stuff->cid, client);
1527
XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
1528
if (!SyncCreateCounter(client, stuff->cid, initial))
1531
return (client->noClientException);
1535
* ** Set Counter value
1538
ProcSyncSetCounter(client)
1541
REQUEST(xSyncSetCounterReq);
1542
SyncCounter *pCounter;
1545
REQUEST_SIZE_MATCH(xSyncSetCounterReq);
1547
pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
1548
RTCounter, SecurityWriteAccess);
1549
if (pCounter == NULL)
1551
client->errorValue = stuff->cid;
1552
return SyncErrorBase + XSyncBadCounter;
1555
if (IsSystemCounter(pCounter))
1557
client->errorValue = stuff->cid;
1561
XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
1562
SyncChangeCounter(pCounter, newvalue);
1567
* ** Change Counter value
1570
ProcSyncChangeCounter(client)
1573
REQUEST(xSyncChangeCounterReq);
1574
SyncCounter *pCounter;
1578
REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
1580
pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
1581
RTCounter, SecurityWriteAccess);
1582
if (pCounter == NULL)
1584
client->errorValue = stuff->cid;
1585
return SyncErrorBase + XSyncBadCounter;
1588
if (IsSystemCounter(pCounter))
1590
client->errorValue = stuff->cid;
1594
XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
1595
XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
1598
/* XXX 64 bit value can't fit in 32 bits; do the best we can */
1599
client->errorValue = stuff->value_hi;
1602
SyncChangeCounter(pCounter, newvalue);
1607
* ** Destroy a counter
1610
ProcSyncDestroyCounter(client)
1613
REQUEST(xSyncDestroyCounterReq);
1614
SyncCounter *pCounter;
1616
REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
1618
pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
1619
RTCounter, SecurityDestroyAccess);
1620
if (pCounter == NULL)
1622
client->errorValue = stuff->counter;
1623
return SyncErrorBase + XSyncBadCounter;
1625
if (IsSystemCounter(pCounter))
1627
client->errorValue = stuff->counter;
1630
FreeResource(pCounter->id, RT_NONE);
1639
ProcSyncAwait(client)
1642
REQUEST(xSyncAwaitReq);
1645
xSyncWaitCondition *pProtocolWaitConds;
1646
SyncAwaitUnion *pAwaitUnion;
1650
REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
1652
len = client->req_len << 2;
1653
len -= sz_xSyncAwaitReq;
1654
items = len / sz_xSyncWaitCondition;
1656
if (items * sz_xSyncWaitCondition != len)
1662
client->errorValue = items; /* XXX protocol change */
1666
pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
1668
/* all the memory for the entire await list is allocated
1671
pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
1675
/* first item is the header, remainder are real wait conditions */
1677
pAwaitUnion->header.delete_id = FakeClientID(client->index);
1678
if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
1684
/* don't need to do any more memory allocation for this request! */
1686
pAwaitUnion->header.client = client;
1687
pAwaitUnion->header.num_waitconditions = 0;
1689
pAwait = &(pAwaitUnion+1)->await; /* skip over header */
1690
for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
1692
if (pProtocolWaitConds->counter == None) /* XXX protocol change */
1694
/* this should take care of removing any triggers created by
1695
* this request that have already been registered on counters
1697
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1698
client->errorValue = pProtocolWaitConds->counter;
1699
return SyncErrorBase + XSyncBadCounter;
1702
/* sanity checks are in SyncInitTrigger */
1703
pAwait->trigger.pCounter = NULL;
1704
pAwait->trigger.value_type = pProtocolWaitConds->value_type;
1705
XSyncIntsToValue(&pAwait->trigger.wait_value,
1706
pProtocolWaitConds->wait_value_lo,
1707
pProtocolWaitConds->wait_value_hi);
1708
pAwait->trigger.test_type = pProtocolWaitConds->test_type;
1710
status = SyncInitTrigger(client, &pAwait->trigger,
1711
pProtocolWaitConds->counter, XSyncCAAllTrigger);
1712
if (status != Success)
1714
/* this should take care of removing any triggers created by
1715
* this request that have already been registered on counters
1717
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1720
/* this is not a mistake -- same function works for both cases */
1721
pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
1722
pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
1723
XSyncIntsToValue(&pAwait->event_threshold,
1724
pProtocolWaitConds->event_threshold_lo,
1725
pProtocolWaitConds->event_threshold_hi);
1726
pAwait->pHeader = &pAwaitUnion->header;
1727
pAwaitUnion->header.num_waitconditions++;
1730
IgnoreClient(client);
1732
/* see if any of the triggers are already true */
1734
pAwait = &(pAwaitUnion+1)->await; /* skip over header */
1735
for (i = 0; i < items; i++, pAwait++)
1737
/* don't have to worry about NULL counters because the request
1738
* errors before we get here out if they occur
1740
if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
1741
pAwait->trigger.pCounter->value))
1743
(*pAwait->trigger.TriggerFired)(&pAwait->trigger);
1744
break; /* once is enough */
1752
* ** Query a counter
1755
ProcSyncQueryCounter(client)
1758
REQUEST(xSyncQueryCounterReq);
1759
xSyncQueryCounterReply rep;
1760
SyncCounter *pCounter;
1762
REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
1764
pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
1765
RTCounter, SecurityReadAccess);
1766
if (pCounter == NULL)
1768
client->errorValue = stuff->counter;
1769
return SyncErrorBase + XSyncBadCounter;
1774
rep.sequenceNumber = client->sequence;
1776
/* if system counter, ask it what the current value is */
1778
if (IsSystemCounter(pCounter))
1780
(*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
1784
rep.value_hi = XSyncValueHigh32(pCounter->value);
1785
rep.value_lo = XSyncValueLow32(pCounter->value);
1786
if (client->swapped)
1789
swaps(&rep.sequenceNumber, n);
1790
swapl(&rep.length, n);
1791
swapl(&rep.value_hi, n);
1792
swapl(&rep.value_lo, n);
1794
WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
1795
return (client->noClientException);
1803
ProcSyncCreateAlarm(client)
1806
REQUEST(xSyncCreateAlarmReq);
1809
unsigned long len, vmask;
1810
SyncTrigger *pTrigger;
1812
REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
1814
LEGAL_NEW_RESOURCE(stuff->id, client);
1816
vmask = stuff->valueMask;
1817
len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
1818
/* the "extra" call to Ones accounts for the presence of 64 bit values */
1819
if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
1822
if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
1827
/* set up defaults */
1829
pTrigger = &pAlarm->trigger;
1830
pTrigger->pCounter = NULL;
1831
pTrigger->value_type = XSyncAbsolute;
1832
XSyncIntToValue(&pTrigger->wait_value, 0L);
1833
pTrigger->test_type = XSyncPositiveComparison;
1834
pTrigger->TriggerFired = SyncAlarmTriggerFired;
1835
pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
1836
status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
1837
if (status != Success)
1843
pAlarm->client = client;
1844
pAlarm->alarm_id = stuff->id;
1845
XSyncIntToValue(&pAlarm->delta, 1L);
1846
pAlarm->events = TRUE;
1847
pAlarm->state = XSyncAlarmInactive;
1848
pAlarm->pEventClients = NULL;
1849
status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1850
(CARD32 *)&stuff[1]);
1851
if (status != Success)
1857
if (!AddResource(stuff->id, RTAlarm, pAlarm))
1863
/* see if alarm already triggered. NULL counter will not trigger
1864
* in CreateAlarm and sets alarm state to Inactive.
1867
if (!pTrigger->pCounter)
1869
pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
1871
else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
1873
(*pTrigger->TriggerFired)(pTrigger);
1883
ProcSyncChangeAlarm(client)
1886
REQUEST(xSyncChangeAlarmReq);
1891
REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
1893
if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1894
RTAlarm, SecurityWriteAccess)))
1896
client->errorValue = stuff->alarm;
1897
return SyncErrorBase + XSyncBadAlarm;
1900
vmask = stuff->valueMask;
1901
len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
1902
/* the "extra" call to Ones accounts for the presence of 64 bit values */
1903
if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
1906
if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1907
(CARD32 *)&stuff[1])) != Success)
1910
/* see if alarm already triggered. NULL counter WILL trigger
1914
if (!pAlarm->trigger.pCounter ||
1915
(*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
1916
pAlarm->trigger.pCounter->value))
1918
(*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
1924
ProcSyncQueryAlarm(client)
1927
REQUEST(xSyncQueryAlarmReq);
1929
xSyncQueryAlarmReply rep;
1930
SyncTrigger *pTrigger;
1932
REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
1934
pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1935
RTAlarm, SecurityReadAccess);
1938
client->errorValue = stuff->alarm;
1939
return (SyncErrorBase + XSyncBadAlarm);
1943
rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2;
1944
rep.sequenceNumber = client->sequence;
1946
pTrigger = &pAlarm->trigger;
1947
rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None;
1949
#if 0 /* XXX unclear what to do, depends on whether relative value-types
1950
* are "consumed" immediately and are considered absolute from then
1953
rep.value_type = pTrigger->value_type;
1954
rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
1955
rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
1957
rep.value_type = XSyncAbsolute;
1958
rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
1959
rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
1962
rep.test_type = pTrigger->test_type;
1963
rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
1964
rep.delta_lo = XSyncValueLow32(pAlarm->delta);
1965
rep.events = pAlarm->events;
1966
rep.state = pAlarm->state;
1968
if (client->swapped)
1971
swaps(&rep.sequenceNumber, n);
1972
swapl(&rep.length, n);
1973
swapl(&rep.counter, n);
1974
swapl(&rep.wait_value_hi, n);
1975
swapl(&rep.wait_value_lo, n);
1976
swapl(&rep.test_type, n);
1977
swapl(&rep.delta_hi, n);
1978
swapl(&rep.delta_lo, n);
1981
WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
1982
return (client->noClientException);
1987
ProcSyncDestroyAlarm(client)
1990
REQUEST(xSyncDestroyAlarmReq);
1992
REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
1994
if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1995
RTAlarm, SecurityDestroyAccess)))
1997
client->errorValue = stuff->alarm;
1998
return SyncErrorBase + XSyncBadAlarm;
2001
FreeResource(stuff->alarm, RT_NONE);
2002
return (client->noClientException);
2006
* ** Given an extension request, call the appropriate request procedure
2009
ProcSyncDispatch(client)
2014
switch (stuff->data)
2017
case X_SyncInitialize:
2018
return ProcSyncInitialize(client);
2019
case X_SyncListSystemCounters:
2020
return ProcSyncListSystemCounters(client);
2021
case X_SyncCreateCounter:
2022
return ProcSyncCreateCounter(client);
2023
case X_SyncSetCounter:
2024
return ProcSyncSetCounter(client);
2025
case X_SyncChangeCounter:
2026
return ProcSyncChangeCounter(client);
2027
case X_SyncQueryCounter:
2028
return ProcSyncQueryCounter(client);
2029
case X_SyncDestroyCounter:
2030
return ProcSyncDestroyCounter(client);
2032
return ProcSyncAwait(client);
2033
case X_SyncCreateAlarm:
2034
return ProcSyncCreateAlarm(client);
2035
case X_SyncChangeAlarm:
2036
return ProcSyncChangeAlarm(client);
2037
case X_SyncQueryAlarm:
2038
return ProcSyncQueryAlarm(client);
2039
case X_SyncDestroyAlarm:
2040
return ProcSyncDestroyAlarm(client);
2041
case X_SyncSetPriority:
2042
return ProcSyncSetPriority(client);
2043
case X_SyncGetPriority:
2044
return ProcSyncGetPriority(client);
2051
* Boring Swapping stuff ...
2055
SProcSyncInitialize(client)
2058
REQUEST(xSyncInitializeReq);
2061
swaps(&stuff->length, n);
2062
REQUEST_SIZE_MATCH (xSyncInitializeReq);
2064
return ProcSyncInitialize(client);
2068
SProcSyncListSystemCounters(client)
2071
REQUEST(xSyncListSystemCountersReq);
2074
swaps(&stuff->length, n);
2075
REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
2077
return ProcSyncListSystemCounters(client);
2081
SProcSyncCreateCounter(client)
2084
REQUEST(xSyncCreateCounterReq);
2087
swaps(&stuff->length, n);
2088
REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
2089
swapl(&stuff->cid, n);
2090
swapl(&stuff->initial_value_lo, n);
2091
swapl(&stuff->initial_value_hi, n);
2093
return ProcSyncCreateCounter(client);
2097
SProcSyncSetCounter(client)
2100
REQUEST(xSyncSetCounterReq);
2103
swaps(&stuff->length, n);
2104
REQUEST_SIZE_MATCH (xSyncSetCounterReq);
2105
swapl(&stuff->cid, n);
2106
swapl(&stuff->value_lo, n);
2107
swapl(&stuff->value_hi, n);
2109
return ProcSyncSetCounter(client);
2113
SProcSyncChangeCounter(client)
2116
REQUEST(xSyncChangeCounterReq);
2119
swaps(&stuff->length, n);
2120
REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
2121
swapl(&stuff->cid, n);
2122
swapl(&stuff->value_lo, n);
2123
swapl(&stuff->value_hi, n);
2125
return ProcSyncChangeCounter(client);
2129
SProcSyncQueryCounter(client)
2132
REQUEST(xSyncQueryCounterReq);
2135
swaps(&stuff->length, n);
2136
REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
2137
swapl(&stuff->counter, n);
2139
return ProcSyncQueryCounter(client);
2143
SProcSyncDestroyCounter(client)
2146
REQUEST(xSyncDestroyCounterReq);
2149
swaps(&stuff->length, n);
2150
REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
2151
swapl(&stuff->counter, n);
2153
return ProcSyncDestroyCounter(client);
2157
SProcSyncAwait(client)
2160
REQUEST(xSyncAwaitReq);
2163
swaps(&stuff->length, n);
2164
REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
2167
return ProcSyncAwait(client);
2172
SProcSyncCreateAlarm(client)
2175
REQUEST(xSyncCreateAlarmReq);
2178
swaps(&stuff->length, n);
2179
REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
2180
swapl(&stuff->id, n);
2181
swapl(&stuff->valueMask, n);
2184
return ProcSyncCreateAlarm(client);
2188
SProcSyncChangeAlarm(client)
2191
REQUEST(xSyncChangeAlarmReq);
2194
swaps(&stuff->length, n);
2195
REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
2196
swapl(&stuff->alarm, n);
2197
swapl(&stuff->valueMask, n);
2199
return ProcSyncChangeAlarm(client);
2203
SProcSyncQueryAlarm(client)
2206
REQUEST(xSyncQueryAlarmReq);
2209
swaps(&stuff->length, n);
2210
REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
2211
swapl(&stuff->alarm, n);
2213
return ProcSyncQueryAlarm(client);
2217
SProcSyncDestroyAlarm(client)
2220
REQUEST(xSyncDestroyAlarmReq);
2223
swaps(&stuff->length, n);
2224
REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
2225
swapl(&stuff->alarm, n);
2227
return ProcSyncDestroyAlarm(client);
2231
SProcSyncSetPriority(client)
2234
REQUEST(xSyncSetPriorityReq);
2237
swaps(&stuff->length, n);
2238
REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
2239
swapl(&stuff->id, n);
2240
swapl(&stuff->priority, n);
2242
return ProcSyncSetPriority(client);
2246
SProcSyncGetPriority(client)
2249
REQUEST(xSyncGetPriorityReq);
2252
swaps(&stuff->length, n);
2253
REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
2254
swapl(&stuff->id, n);
2256
return ProcSyncGetPriority(client);
2261
SProcSyncDispatch(client)
2266
switch (stuff->data)
2268
case X_SyncInitialize:
2269
return SProcSyncInitialize(client);
2270
case X_SyncListSystemCounters:
2271
return SProcSyncListSystemCounters(client);
2272
case X_SyncCreateCounter:
2273
return SProcSyncCreateCounter(client);
2274
case X_SyncSetCounter:
2275
return SProcSyncSetCounter(client);
2276
case X_SyncChangeCounter:
2277
return SProcSyncChangeCounter(client);
2278
case X_SyncQueryCounter:
2279
return SProcSyncQueryCounter(client);
2280
case X_SyncDestroyCounter:
2281
return SProcSyncDestroyCounter(client);
2283
return SProcSyncAwait(client);
2284
case X_SyncCreateAlarm:
2285
return SProcSyncCreateAlarm(client);
2286
case X_SyncChangeAlarm:
2287
return SProcSyncChangeAlarm(client);
2288
case X_SyncQueryAlarm:
2289
return SProcSyncQueryAlarm(client);
2290
case X_SyncDestroyAlarm:
2291
return SProcSyncDestroyAlarm(client);
2292
case X_SyncSetPriority:
2293
return SProcSyncSetPriority(client);
2294
case X_SyncGetPriority:
2295
return SProcSyncGetPriority(client);
2306
SCounterNotifyEvent(from, to)
2307
xSyncCounterNotifyEvent *from, *to;
2309
to->type = from->type;
2310
to->kind = from->kind;
2311
cpswaps(from->sequenceNumber, to->sequenceNumber);
2312
cpswapl(from->counter, to->counter);
2313
cpswapl(from->wait_value_lo, to->wait_value_lo);
2314
cpswapl(from->wait_value_hi, to->wait_value_hi);
2315
cpswapl(from->counter_value_lo, to->counter_value_lo);
2316
cpswapl(from->counter_value_hi, to->counter_value_hi);
2317
cpswapl(from->time, to->time);
2318
cpswaps(from->count, to->count);
2319
to->destroyed = from->destroyed;
2324
SAlarmNotifyEvent(from, to)
2325
xSyncAlarmNotifyEvent *from, *to;
2327
to->type = from->type;
2328
to->kind = from->kind;
2329
cpswaps(from->sequenceNumber, to->sequenceNumber);
2330
cpswapl(from->alarm, to->alarm);
2331
cpswapl(from->counter_value_lo, to->counter_value_lo);
2332
cpswapl(from->counter_value_hi, to->counter_value_hi);
2333
cpswapl(from->alarm_value_lo, to->alarm_value_lo);
2334
cpswapl(from->alarm_value_hi, to->alarm_value_hi);
2335
cpswapl(from->time, to->time);
2336
to->state = from->state;
2340
* ** Close everything down. ** This is fairly simple for now.
2344
SyncResetProc(extEntry)
2345
ExtensionEntry *extEntry;
2347
xfree(SysCounterList);
2348
SysCounterList = NULL;
2354
* ** Initialise the extension.
2357
SyncExtensionInit(INITARGS)
2359
ExtensionEntry *extEntry;
2363
RTCounter = CreateNewResourceType(FreeCounter);
2365
RTAlarm = CreateNewResourceType(FreeAlarm);
2366
RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN;
2367
RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN;
2369
if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
2370
RTAlarmClient == 0 ||
2371
(extEntry = AddExtension(SYNC_NAME,
2372
XSyncNumberEvents, XSyncNumberErrors,
2373
ProcSyncDispatch, SProcSyncDispatch,
2375
StandardMinorOpcode)) == NULL)
2377
ErrorF("Sync Extension %d.%d failed to Initialise\n",
2378
SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2382
SyncEventBase = extEntry->eventBase;
2383
SyncErrorBase = extEntry->errorBase;
2384
EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
2385
EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
2388
* Although SERVERTIME is implemented by the OS layer, we initialise it
2389
* here because doing it in OsInit() is too early. The resource database
2390
* is not initialised when OsInit() is called. This is just about OK
2391
* because there is always a servertime counter.
2393
SyncInitServerTime();
2396
fprintf(stderr, "Sync Extension %d.%d\n",
2397
SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2403
* ***** SERVERTIME implementation - should go in its own file in OS directory?
2408
static pointer ServertimeCounter;
2409
static XSyncValue Now;
2410
static XSyncValue *pnext_time;
2414
unsigned long millis = GetTimeInMillis();\
2415
unsigned long maxis = XSyncValueHigh32(Now);\
2416
if (millis < XSyncValueLow32(Now)) maxis++;\
2417
XSyncIntsToValue(&Now, millis, maxis);\
2421
*** Server Block Handler
2422
*** code inspired by multibuffer extension
2425
static void ServertimeBlockHandler(env, wt, LastSelectMask)
2427
struct timeval **wt;
2428
pointer LastSelectMask;
2431
unsigned long timeout;
2437
if (XSyncValueGreaterOrEqual(Now, *pnext_time))
2444
XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
2446
timeout = XSyncValueLow32(delay);
2448
AdjustWaitForDelay(wt, timeout); /* os/utils.c */
2456
static void ServertimeWakeupHandler(env, rc, LastSelectMask)
2459
pointer LastSelectMask;
2465
if (XSyncValueGreaterOrEqual(Now, *pnext_time))
2467
SyncChangeCounter(ServertimeCounter, Now);
2473
ServertimeQueryValue(pCounter, pValue_return)
2475
CARD64 *pValue_return;
2478
*pValue_return = Now;
2482
ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater)
2484
CARD64 *pbracket_less;
2485
CARD64 *pbracket_greater;
2487
if (!pnext_time && pbracket_greater)
2489
RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
2490
ServertimeWakeupHandler,
2493
else if (pnext_time && !pbracket_greater)
2495
RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
2496
ServertimeWakeupHandler,
2499
pnext_time = pbracket_greater;
2503
SyncInitServerTime()
2507
XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
2508
XSyncIntToValue(&resolution, 4);
2509
ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
2510
XSyncCounterNeverDecreases,
2511
ServertimeQueryValue, ServertimeBracketValues);