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 $ */
3 /*
4 
5 Copyright (c) 1991, 1993  X Consortium
6 
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:
14 
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17 
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.
25 
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.
30 
31 
32 Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
33 and Olivetti Research Limited, Cambridge, England.
34 
35                         All Rights Reserved
36 
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.
46 
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.
54 
55 */
56 
57 #define NEED_REPLIES
58 #define NEED_EVENTS
59 #include <stdio.h>
60 #include "X.h"
61 #include "Xproto.h"
62 #include "Xmd.h"
63 #include "misc.h"
64 #include "os.h"
65 #include "extnsionst.h"
66 #include "dixstruct.h"
67 #include "resource.h"
68 #include "opaque.h"
69 #define _SYNC_SERVER
70 #include "sync.h"
71 #include "syncstr.h"
72 
73 /*
74  * Local Global Variables
75  */
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;
85 
86 #define IsSystemCounter(pCounter) \
87     (pCounter && (pCounter->client == NULL))
88 
89 /* these are all the alarm attributes that pertain to the alarm's trigger */
90 #define XSyncCAAllTrigger \
91     (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
92 
93 static int
94 FreeAlarm(
95 #if NeedFunctionPrototypes
96     pointer /* addr */,
97     XID /* id */
98 #endif
99 );
100 
101 static int
102 FreeAlarmClient(
103 #if NeedFunctionPrototypes
104     pointer /* value */,
105     XID /* id */
106 #endif
107 );
108 
109 static int
110 FreeAwait(
111 #if NeedFunctionPrototypes
112     pointer /* addr */,
113     XID /* id */
114 #endif
115 );
116 
117 static void
118 ServertimeBracketValues(
119 #if NeedFunctionPrototypes
120     pointer /* pCounter */,
121     CARD64 * /* pbracket_less */,
122     CARD64 * /* pbracket_greater */
123 #endif
124 );
125 
126 static void
127 ServertimeQueryValue(
128 #if NeedFunctionPrototypes
129     pointer /* pCounter */,
130     CARD64 * /* pValue_return */
131 #endif
132 );
133 
134 static void
135 ServertimeWakeupHandler(
136 #if NeedFunctionPrototypes
137     pointer /* env */,
138     int /* rc */,
139     pointer /* LastSelectMask */
140 #endif
141 );
142 
143 static int
144 SyncInitTrigger(
145 #if NeedFunctionPrototypes
146     ClientPtr /* client */,
147     SyncTrigger * /* pTrigger */,
148     XSyncCounter /* counter */,
149     Mask /* changes */
150 #endif
151 );
152 
153 static void
154 SAlarmNotifyEvent(
155 #if NeedFunctionPrototypes
156     xSyncAlarmNotifyEvent * /* from */,
157     xSyncAlarmNotifyEvent * /* to */
158 #endif
159 );
160 
161 static void
162 SCounterNotifyEvent(
163 #if NeedFunctionPrototypes
164     xSyncCounterNotifyEvent * /* from */,
165     xSyncCounterNotifyEvent * /* to */
166 #endif
167 );
168 
169 static void
170 ServertimeBlockHandler(
171 #if NeedFunctionPrototypes
172     pointer  /* env */,
173     struct timeval ** /* wt */,
174     pointer  /* LastSelectMask */
175 #endif
176 );
177 
178 static int
179 SyncAddTriggerToCounter(
180 #if NeedFunctionPrototypes
181     SyncTrigger * /* pTrigger */
182 #endif
183 );
184 
185 extern void
186 SyncAlarmCounterDestroyed(
187 #if NeedFunctionPrototypes
188     SyncTrigger * /* pTrigger */
189 #endif
190 );
191 
192 static void
193 SyncAlarmTriggerFired(
194 #if NeedFunctionPrototypes
195     SyncTrigger * /* pTrigger */
196 #endif
197 );
198 
199 static void
200 SyncAwaitTriggerFired(
201 #if NeedFunctionPrototypes
202     SyncTrigger * /* pTrigger */
203 #endif
204 );
205 
206 static int
207 SyncChangeAlarmAttributes(
208 #if NeedFunctionPrototypes
209     ClientPtr /* client */,
210     SyncAlarm * /* pAlarm */,
211     Mask /* mask */,
212     CARD32 * /* values */
213 #endif
214 );
215 
216 static Bool
217 SyncCheckTriggerNegativeComparison(
218 #if NeedFunctionPrototypes
219     SyncTrigger * /* pTrigger */,
220     CARD64 /* oldval */
221 #endif
222 );
223 
224 static Bool
225 SyncCheckTriggerNegativeTransition(
226 #if NeedFunctionPrototypes
227     SyncTrigger * /* pTrigger */,
228     CARD64 /* oldval */
229 #endif
230 );
231 
232 static Bool
233 SyncCheckTriggerPositiveComparison(
234 #if NeedFunctionPrototypes
235     SyncTrigger * /* pTrigger */,
236     CARD64 /* oldval */
237 #endif
238 );
239 
240 static Bool
241 SyncCheckTriggerPositiveTransition(
242 #if NeedFunctionPrototypes
243     SyncTrigger * /* pTrigger */,
244     CARD64 /* oldval */
245 #endif
246 );
247 
248 static SyncCounter *
249 SyncCreateCounter(
250 #if NeedFunctionPrototypes
251     ClientPtr /* client */,
252     XSyncCounter /* id */,
253     CARD64 /* initialvalue */
254 #endif
255 );
256 
257 static void SyncComputeBracketValues(
258 #if NeedFunctionPrototypes
259     SyncCounter * /* pCounter */,
260     Bool /* startOver */
261 #endif
262 );
263 
264 static void
265 SyncDeleteTriggerFromCounter(
266 #if NeedFunctionPrototypes
267     SyncTrigger * /* pTrigger */
268 #endif
269 );
270 
271 static Bool
272 SyncEventSelectForAlarm(
273 #if NeedFunctionPrototypes
274     SyncAlarm * /* pAlarm */,
275     ClientPtr /* client */,
276     Bool /* wantevents */
277 #endif
278 );
279 
280 static void
281 SyncInitServerTime(
282 #if NeedFunctionPrototypes
283     void
284 #endif
285 );
286 
287 static void
288 SyncResetProc(
289 #if NeedFunctionPrototypes
290     ExtensionEntry * /* extEntry */
291 #endif
292 );
293 
294 static void
295 SyncSendAlarmNotifyEvents(
296 #if NeedFunctionPrototypes
297     SyncAlarm * /* pAlarm */
298 #endif
299 );
300 
301 static void
302 SyncSendCounterNotifyEvents(
303 #if NeedFunctionPrototypes
304     ClientPtr /* client */,
305     SyncAwait ** /* ppAwait */,
306     int /* num_events */
307 #endif
308 );
309 
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);
342 
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.
346  */
347 static void
SyncDeleteTriggerFromCounter(pTrigger)348 SyncDeleteTriggerFromCounter(pTrigger)
349     SyncTrigger *pTrigger;
350 {
351     SyncTriggerList *pCur, *pPrev = NULL;
352 
353     /* pCounter needs to be stored in pTrigger before calling here. */
354 
355     if (!pTrigger->pCounter)
356 	return;
357 
358     for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
359     {
360 	if (pCur->pTrigger == pTrigger)
361 	{
362 	    if (pPrev)
363 		pPrev->next = pCur->next;
364 	    else
365 		pTrigger->pCounter->pTriglist = pCur->next;
366 	    xfree(pCur);
367 	    break;
368 	}
369     }
370 
371     if (IsSystemCounter(pTrigger->pCounter))
372 	SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
373 }
374 
375 
376 static int
SyncAddTriggerToCounter(pTrigger)377 SyncAddTriggerToCounter(pTrigger)
378     SyncTrigger *pTrigger;
379 {
380     SyncTriggerList *pCur;
381 
382     if (!pTrigger->pCounter)
383 	return Success;
384 
385     /* don't do anything if it's already there */
386     for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
387     {
388 	if (pCur->pTrigger == pTrigger)
389 	    return Success;
390     }
391 
392     if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
393 	return BadAlloc;
394 
395     pCur->pTrigger = pTrigger;
396     pCur->next = pTrigger->pCounter->pTriglist;
397     pTrigger->pCounter->pTriglist = pCur;
398 
399     if (IsSystemCounter(pTrigger->pCounter))
400 	SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
401 
402     return Success;
403 }
404 
405 
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
413  *  of the trigger.
414  *
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.
418  */
419 
420 static Bool
SyncCheckTriggerPositiveComparison(pTrigger,oldval)421 SyncCheckTriggerPositiveComparison(pTrigger, oldval)
422     SyncTrigger *pTrigger;
423     CARD64	oldval;
424 {
425     return (pTrigger->pCounter == NULL ||
426 	    XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
427 				     pTrigger->test_value));
428 }
429 
430 static Bool
SyncCheckTriggerNegativeComparison(pTrigger,oldval)431 SyncCheckTriggerNegativeComparison(pTrigger, oldval)
432     SyncTrigger *pTrigger;
433     CARD64	oldval;
434 {
435     return (pTrigger->pCounter == NULL ||
436 	    XSyncValueLessOrEqual(pTrigger->pCounter->value,
437 				  pTrigger->test_value));
438 }
439 
440 static Bool
SyncCheckTriggerPositiveTransition(pTrigger,oldval)441 SyncCheckTriggerPositiveTransition(pTrigger, oldval)
442     SyncTrigger *pTrigger;
443     CARD64	oldval;
444 {
445     return (pTrigger->pCounter == NULL ||
446 	    (XSyncValueLessThan(oldval, pTrigger->test_value) &&
447 	     XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
448 				      pTrigger->test_value)));
449 }
450 
451 static Bool
SyncCheckTriggerNegativeTransition(pTrigger,oldval)452 SyncCheckTriggerNegativeTransition(pTrigger, oldval)
453     SyncTrigger *pTrigger;
454     CARD64	oldval;
455 {
456     return (pTrigger->pCounter == NULL ||
457 	    (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
458 	     XSyncValueLessOrEqual(pTrigger->pCounter->value,
459 				   pTrigger->test_value)));
460 }
461 
462 
463 
464 static int
SyncInitTrigger(client,pTrigger,counter,changes)465 SyncInitTrigger(client, pTrigger, counter, changes)
466     ClientPtr	     client;    /* so we can set errorValue */
467     SyncTrigger      *pTrigger;
468     XSyncCounter     counter;
469     Mask	     changes;
470 {
471     SyncCounter *pCounter = pTrigger->pCounter;
472     int		status;
473     Bool	newcounter = FALSE;
474 
475     if (changes & XSyncCACounter)
476     {
477 	if (counter == None)
478 	    pCounter = NULL;
479 	else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
480 			client, counter, RTCounter, SecurityReadAccess)))
481 	{
482 	    client->errorValue = counter;
483 	    return SyncErrorBase + XSyncBadCounter;
484 	}
485 	if (pCounter != pTrigger->pCounter)
486 	{ /* new counter for trigger */
487 	    SyncDeleteTriggerFromCounter(pTrigger);
488 	    pTrigger->pCounter = pCounter;
489 	    newcounter = TRUE;
490 	}
491     }
492 
493     /* if system counter, ask it what the current value is */
494 
495     if (IsSystemCounter(pCounter))
496     {
497 	(*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
498 						  &pCounter->value);
499     }
500 
501     if (changes & XSyncCAValueType)
502     {
503 	if (pTrigger->value_type != XSyncRelative &&
504 	    pTrigger->value_type != XSyncAbsolute)
505 	{
506 	    client->errorValue = pTrigger->value_type;
507 	    return BadValue;
508 	}
509     }
510 
511     if (changes & XSyncCATestType)
512     {
513 	if (pTrigger->test_type != XSyncPositiveTransition &&
514 	    pTrigger->test_type != XSyncNegativeTransition &&
515 	    pTrigger->test_type != XSyncPositiveComparison &&
516 	    pTrigger->test_type != XSyncNegativeComparison)
517 	{
518 	    client->errorValue = pTrigger->test_type;
519 	    return BadValue;
520 	}
521 	/* select appropriate CheckTrigger function */
522 
523 	switch (pTrigger->test_type)
524 	{
525         case XSyncPositiveTransition:
526 	    pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
527 	    break;
528         case XSyncNegativeTransition:
529 	    pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
530 	    break;
531         case XSyncPositiveComparison:
532 	    pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
533 	    break;
534         case XSyncNegativeComparison:
535 	    pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
536 	    break;
537 	}
538     }
539 
540     if (changes & (XSyncCAValueType | XSyncCAValue))
541     {
542 	if (pTrigger->value_type == XSyncAbsolute)
543 	    pTrigger->test_value = pTrigger->wait_value;
544 	else /* relative */
545 	{
546 	    Bool overflow;
547 	    if (pCounter == NULL)
548 		return BadMatch;
549 
550 	    XSyncValueAdd(&pTrigger->test_value, pCounter->value,
551 			  pTrigger->wait_value, &overflow);
552 	    if (overflow)
553 	    {
554 		client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
555 		return BadValue;
556 	    }
557 	}
558     }
559 
560     /*  we wait until we're sure there are no errors before registering
561      *  a new counter on a trigger
562      */
563     if (newcounter)
564     {
565 	if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
566 	    return status;
567     }
568     else if (IsSystemCounter(pCounter))
569     {
570 	SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
571     }
572 
573     return Success;
574 }
575 
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.
579  */
580 static void
SyncSendAlarmNotifyEvents(pAlarm)581 SyncSendAlarmNotifyEvents(pAlarm)
582     SyncAlarm *pAlarm;
583 {
584     SyncAlarmClientList *pcl;
585     xSyncAlarmNotifyEvent ane;
586     SyncTrigger *pTrigger = &pAlarm->trigger;
587 
588     UpdateCurrentTime();
589 
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)
595     {
596 	ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
597 	ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
598     }
599     else
600     { /* XXX what else can we do if there's no counter? */
601 	ane.counter_value_hi = ane.counter_value_lo = 0;
602     }
603 
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;
608 
609     /* send to owner */
610     if (pAlarm->events && !pAlarm->client->clientGone)
611 	WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
612 
613     /* send to other interested clients */
614     for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
615     {
616 	if (!pAlarm->client->clientGone)
617 	{
618 	    ane.sequenceNumber = pcl->client->sequence;
619 	    WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
620 	}
621     }
622 }
623 
624 
625 /*  CounterNotify events only occur in response to an Await.  The events
626  *  go only to the Awaiting client.
627  */
628 static void
SyncSendCounterNotifyEvents(client,ppAwait,num_events)629 SyncSendCounterNotifyEvents(client, ppAwait, num_events)
630     ClientPtr client;
631     SyncAwait **ppAwait;
632     int num_events;
633 {
634     xSyncCounterNotifyEvent *pEvents, *pev;
635     int i;
636 
637     if (client->clientGone)
638 	return;
639     pev = pEvents = (xSyncCounterNotifyEvent *)
640 		 ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
641     if (!pEvents)
642 	return;
643     UpdateCurrentTime();
644     for (i = 0; i < num_events; i++, ppAwait++, pev++)
645     {
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;
658     }
659     /* swapping will be taken care of by this */
660     WriteEventsToClient(client, num_events, (xEvent *)pEvents);
661     DEALLOCATE_LOCAL(pEvents);
662 }
663 
664 
665 /* This function is called when an alarm's counter is destroyed.
666  * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
667  */
668 void
SyncAlarmCounterDestroyed(pTrigger)669 SyncAlarmCounterDestroyed(pTrigger)
670     SyncTrigger *pTrigger;
671 {
672     SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
673 
674     pAlarm->state = XSyncAlarmInactive;
675     SyncSendAlarmNotifyEvents(pAlarm);
676     pTrigger->pCounter = NULL;
677 }
678 
679 
680 /*  This function is called when an alarm "goes off."
681  *  It is plugged into pTrigger->TriggerFired (for alarm triggers).
682  */
683 static void
SyncAlarmTriggerFired(pTrigger)684 SyncAlarmTriggerFired(pTrigger)
685     SyncTrigger *pTrigger;
686 {
687     SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
688     CARD64 new_test_value;
689 
690     /* no need to check alarm unless it's active */
691     if (pAlarm->state != XSyncAlarmActive)
692 	return;
693 
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."
698      */
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;
704 
705     new_test_value = pAlarm->trigger.test_value;
706 
707     if (pAlarm->state == XSyncAlarmActive)
708     {
709 	Bool overflow;
710 	CARD64 oldvalue;
711 	SyncTrigger *paTrigger = &pAlarm->trigger;
712 
713 	/* "The alarm is updated by repeatedly adding delta to the
714 	 *  value of the trigger and re-initializing it until it
715 	 *  becomes FALSE."
716 	 */
717 	oldvalue = paTrigger->test_value;
718 
719 	/* XXX really should do something smarter here */
720 
721 	do
722 	{
723 	    XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
724 			  pAlarm->delta, &overflow);
725 	} while (!overflow &&
726 	      (*paTrigger->CheckTrigger)(paTrigger,
727 					paTrigger->pCounter->value));
728 
729 	new_test_value = paTrigger->test_value;
730 	paTrigger->test_value = oldvalue;
731 
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
735 	 *  generated."
736 	 */
737 	if (overflow)
738 	{
739 	    new_test_value = oldvalue;
740 	    pAlarm->state = XSyncAlarmInactive;
741 	}
742     }
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.
748      */
749     SyncSendAlarmNotifyEvents(pAlarm);
750     pTrigger->test_value = new_test_value;
751 }
752 
753 
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).
758  */
759 static void
SyncAwaitTriggerFired(pTrigger)760 SyncAwaitTriggerFired(pTrigger)
761     SyncTrigger *pTrigger;
762 {
763     SyncAwait *pAwait = (SyncAwait *)pTrigger;
764     int numwaits;
765     SyncAwaitUnion *pAwaitUnion;
766     SyncAwait **ppAwait;
767     int num_events = 0;
768 
769     pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
770     numwaits = pAwaitUnion->header.num_waitconditions;
771     ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
772     if (!ppAwait)
773 	goto bail;
774 
775     pAwait = &(pAwaitUnion+1)->await;
776 
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."
781      *
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.
785      */
786     for ( ; numwaits; numwaits--, pAwait++)
787     {
788 	CARD64 diff;
789 	Bool overflow, diffgreater, diffequal;
790 
791 	/* "A CounterNotify event with the destroyed flag set to TRUE is
792 	 *  always generated if the counter for one of the triggers is
793 	 *  destroyed."
794 	 */
795 	if (pAwait->trigger.pCounter->beingDestroyed)
796 	{
797 	    ppAwait[num_events++] = pAwait;
798 	    continue;
799 	}
800 
801 	/* "The difference between the counter and the test value is
802 	 *  calculated by subtracting the test value from the value of
803 	 *  the counter."
804 	 */
805 	XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
806 			   pAwait->trigger.test_value, &overflow);
807 
808 	/* "If the difference lies outside the range for an INT64, an
809 	 *  event is not generated."
810 	 */
811 	if (overflow)
812 	    continue;
813 	diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
814 	diffequal   = XSyncValueEqual(diff, pAwait->event_threshold);
815 
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
821 	 *  event-threshold."
822 	 */
823 
824 	if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
825 	       pAwait->trigger.test_type == XSyncPositiveTransition)
826 	       && (diffgreater || diffequal))
827 	     ||
828 	     ((pAwait->trigger.test_type == XSyncNegativeComparison ||
829 	       pAwait->trigger.test_type == XSyncNegativeTransition)
830 	      && (!diffgreater) /* less or equal */
831 	      )
832 	   )
833 	{
834 	    ppAwait[num_events++] = pAwait;
835 	}
836     }
837     if (num_events)
838 	SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
839 				    num_events);
840     DEALLOCATE_LOCAL(ppAwait);
841 
842 bail:
843     /* unblock the client */
844     AttendClient(pAwaitUnion->header.client);
845     /* delete the await */
846     FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
847 }
848 
849 
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.
852  */
853 void
SyncChangeCounter(pCounter,newval)854 SyncChangeCounter(pCounter, newval)
855     SyncCounter    *pCounter;
856     CARD64         newval;
857 {
858     SyncTriggerList       *ptl, *pnext;
859     CARD64 oldval;
860 
861     oldval = pCounter->value;
862     pCounter->value = newval;
863 
864     /* run through triggers to see if any become true */
865     for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
866     {
867 	pnext = ptl->next;
868 	if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
869 	    (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
870     }
871 
872     if (IsSystemCounter(pCounter))
873     {
874 	SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
875     }
876 }
877 
878 
879 /* loosely based on dix/events.c/EventSelectForWindow */
880 static Bool
SyncEventSelectForAlarm(pAlarm,client,wantevents)881 SyncEventSelectForAlarm(pAlarm, client, wantevents)
882     SyncAlarm *pAlarm;
883     ClientPtr client;
884     Bool      wantevents;
885 {
886     SyncAlarmClientList *pClients;
887 
888     if (client == pAlarm->client) /* alarm owner */
889     {
890 	pAlarm->events = wantevents;
891 	return Success;
892     }
893 
894     /* see if the client is already on the list (has events selected) */
895 
896     for (pClients = pAlarm->pEventClients; pClients;
897 	 pClients = pClients->next)
898     {
899 	if (pClients->client == client)
900 	{
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.
905 	     */
906 	    if (!wantevents)
907 	    {
908 		FreeResource(pClients->delete_id, RT_NONE);
909 	    }
910 	    return Success;
911 	}
912     }
913 
914     /*  if we get here, this client does not currently have
915      *  events selected on the alarm
916      */
917 
918     if (!wantevents)
919 	/* client doesn't want events, and we just discovered that it
920 	 * doesn't have them, so there's nothing to do.
921 	 */
922 	return Success;
923 
924     /* add new client to pAlarm->pEventClients */
925 
926     pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
927     if (!pClients)
928 	return BadAlloc;
929 
930     /*  register it as a resource so it will be cleaned up
931      *  if the client dies
932      */
933 
934     pClients->delete_id = FakeClientID(client->index);
935     if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
936     {
937 	xfree(pClients);
938 	return BadAlloc;
939     }
940 
941     /* link it into list after we know all the allocations succeed */
942 
943     pClients->next = pAlarm->pEventClients;
944     pAlarm->pEventClients = pClients;
945     pClients->client = client;
946     return Success;
947 }
948 
949 /*
950  * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
951  */
952 static int
SyncChangeAlarmAttributes(client,pAlarm,mask,values)953 SyncChangeAlarmAttributes(client, pAlarm, mask, values)
954     ClientPtr       client;
955     SyncAlarm      *pAlarm;
956     Mask	    mask;
957     CARD32	    *values;
958 {
959     int		   status;
960     XSyncCounter   counter;
961     Mask	   origmask = mask;
962 
963     counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
964 
965     while (mask)
966     {
967 	int    index2 = lowbit(mask);
968 	mask &= ~index2;
969 	switch (index2)
970 	{
971 	  case XSyncCACounter:
972 	    mask &= ~XSyncCACounter;
973 	    /* sanity check in SyncInitTrigger */
974 	    counter = *values++;
975 	    break;
976 
977 	  case XSyncCAValueType:
978 	    mask &= ~XSyncCAValueType;
979 	    /* sanity check in SyncInitTrigger */
980 	    pAlarm->trigger.value_type = *values++;
981 	    break;
982 
983 	  case XSyncCAValue:
984 	    mask &= ~XSyncCAValue;
985 	    XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
986 	    values += 2;
987 	    break;
988 
989 	  case XSyncCATestType:
990 	    mask &= ~XSyncCATestType;
991 	    /* sanity check in SyncInitTrigger */
992 	    pAlarm->trigger.test_type = *values++;
993 	    break;
994 
995 	  case XSyncCADelta:
996 	    mask &= ~XSyncCADelta;
997 	    XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
998 	    values += 2;
999 	    break;
1000 
1001 	  case XSyncCAEvents:
1002 	    mask &= ~XSyncCAEvents;
1003 	    if ((*values != xTrue) && (*values != xFalse))
1004 	    {
1005 		client->errorValue = *values;
1006 		return BadValue;
1007 	    }
1008 	    status = SyncEventSelectForAlarm(pAlarm, client,
1009 					     (Bool)(*values++));
1010 	    if (status != Success)
1011 		return status;
1012 	    break;
1013 
1014 	  default:
1015 	    client->errorValue = mask;
1016 	    return BadValue;
1017 	}
1018     }
1019 
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."
1024      */
1025     if (origmask & (XSyncCADelta|XSyncCATestType))
1026     {
1027 	CARD64 zero;
1028 	XSyncIntToValue(&zero, 0);
1029 	if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
1030 	      (pAlarm->trigger.test_type == XSyncPositiveTransition))
1031 	     && XSyncValueLessThan(pAlarm->delta, zero))
1032 	    ||
1033 	    (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
1034 	      (pAlarm->trigger.test_type == XSyncNegativeTransition))
1035 	     && XSyncValueGreaterThan(pAlarm->delta, zero))
1036 	   )
1037 	{
1038 	    return BadMatch;
1039 	}
1040     }
1041 
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)
1045 	return status;
1046 
1047     /* XXX spec does not really say to do this - needs clarification */
1048     pAlarm->state = XSyncAlarmActive;
1049     return Success;
1050 }
1051 
1052 
1053 static SyncCounter *
SyncCreateCounter(client,id,initialvalue)1054 SyncCreateCounter(client, id, initialvalue)
1055     ClientPtr	client;
1056     XSyncCounter id;
1057     CARD64      initialvalue;
1058 {
1059     SyncCounter *pCounter;
1060 
1061     if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
1062 	return (SyncCounter *)NULL;
1063 
1064     if (!AddResource(id, RTCounter, (pointer) pCounter))
1065     {
1066 	xfree((pointer) pCounter);
1067 	return (SyncCounter *)NULL;
1068     }
1069 
1070     pCounter->client = client;
1071     pCounter->id = id;
1072     pCounter->value = initialvalue;
1073     pCounter->pTriglist = NULL;
1074     pCounter->beingDestroyed = FALSE;
1075     pCounter->pSysCounterInfo = NULL;
1076     return pCounter;
1077 }
1078 
1079 static int FreeCounter(
1080 #if NeedFunctionPrototypes
1081     pointer /*env*/,
1082     XID     /*id*/
1083 #endif
1084 );
1085 
1086 /*
1087  * ***** System Counter utilities
1088  */
1089 
1090 pointer
SyncCreateSystemCounter(name,initial,resolution,counterType,QueryValue,BracketValues)1091 SyncCreateSystemCounter(name, initial, resolution, counterType,
1092 			QueryValue, BracketValues)
1093     char           *name;
1094     CARD64          initial;
1095     CARD64          resolution;
1096     SyncCounterType counterType;
1097     void            (*QueryValue) ();
1098     void            (*BracketValues) ();
1099 {
1100     SyncCounter    *pCounter;
1101 
1102     SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
1103 			    (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
1104     if (!SysCounterList)
1105 	return (pointer)NULL;
1106 
1107     /* this function may be called before SYNC has been initialized, so we
1108      * have to make sure RTCounter is created.
1109      */
1110     if (RTCounter == 0)
1111     {
1112 	RTCounter = CreateNewResourceType(FreeCounter);
1113 	if (RTCounter == 0)
1114 	{
1115 	    return (pointer)NULL;
1116 	}
1117     }
1118 
1119     pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
1120 
1121     if (pCounter)
1122     {
1123 	SysCounterInfo *psci;
1124 
1125 	psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
1126 	if (!psci)
1127 	{
1128 	    FreeResource(pCounter->id, RT_NONE);
1129 	    return (pointer) pCounter;
1130 	}
1131 	pCounter->pSysCounterInfo = psci;
1132 	psci->name = name;
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;
1140     }
1141     return (pointer) pCounter;
1142 }
1143 
1144 void
SyncDestroySystemCounter(pSysCounter)1145 SyncDestroySystemCounter(pSysCounter)
1146     pointer pSysCounter;
1147 {
1148     SyncCounter *pCounter = (SyncCounter *)pSysCounter;
1149     FreeResource(pCounter->id, RT_NONE);
1150 }
1151 
1152 static void
SyncComputeBracketValues(pCounter,startOver)1153 SyncComputeBracketValues(pCounter, startOver)
1154     SyncCounter *pCounter;
1155     Bool startOver;
1156 {
1157     SyncTriggerList *pCur;
1158     SyncTrigger *pTrigger;
1159     SysCounterInfo *psci = pCounter->pSysCounterInfo;
1160     CARD64 *pnewgtval = NULL;
1161     CARD64 *pnewltval = NULL;
1162     SyncCounterType ct;
1163 
1164     if (!pCounter)
1165 	return;
1166 
1167     ct = pCounter->pSysCounterInfo->counterType;
1168     if (ct == XSyncCounterNeverChanges)
1169 	return;
1170 
1171     if (startOver)
1172     {
1173 	XSyncMaxValue(&psci->bracket_greater);
1174 	XSyncMinValue(&psci->bracket_less);
1175     }
1176 
1177     for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
1178     {
1179 	pTrigger = pCur->pTrigger;
1180 
1181         if (pTrigger->test_type == XSyncPositiveComparison &&
1182 	    ct != XSyncCounterNeverIncreases)
1183 	{
1184 	    if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
1185 		XSyncValueLessThan(pTrigger->test_value,
1186 				   psci->bracket_greater))
1187 	    {
1188 		psci->bracket_greater = pTrigger->test_value;
1189 		pnewgtval = &psci->bracket_greater;
1190 	    }
1191 	}
1192 	else if (pTrigger->test_type == XSyncNegativeComparison &&
1193 		 ct != XSyncCounterNeverDecreases)
1194 	{
1195 	    if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
1196 		XSyncValueGreaterThan(pTrigger->test_value,
1197 				      psci->bracket_less))
1198 	    {
1199 		psci->bracket_less = pTrigger->test_value;
1200 		pnewltval = &psci->bracket_less;
1201 	    }
1202 	}
1203 	else if ( (pTrigger->test_type == XSyncPositiveTransition &&
1204 		   ct != XSyncCounterNeverIncreases)
1205 		 ||
1206 		 (pTrigger->test_type == XSyncNegativeTransition &&
1207 		  ct != XSyncCounterNeverDecreases)
1208 		 )
1209 	{
1210 	    if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
1211 	    {
1212 		if (XSyncValueLessThan(pTrigger->test_value,
1213 				       psci->bracket_greater))
1214 		{
1215 		    psci->bracket_greater = pTrigger->test_value;
1216 		    pnewgtval = &psci->bracket_greater;
1217 		}
1218 		else
1219 		if (XSyncValueGreaterThan(pTrigger->test_value,
1220 					  psci->bracket_less))
1221 		{
1222 		    psci->bracket_less = pTrigger->test_value;
1223 		    pnewltval = &psci->bracket_less;
1224 		}
1225 	    }
1226 	}
1227     } /* end for each trigger */
1228 
1229     if (pnewgtval || pnewltval)
1230     {
1231 	(*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
1232     }
1233 }
1234 
1235 /*
1236  * *****  Resource delete functions
1237  */
1238 
1239 /* ARGSUSED */
1240 static int
FreeAlarm(addr,id)1241 FreeAlarm(addr, id)
1242     pointer         addr;
1243     XID             id;
1244 {
1245     SyncAlarm      *pAlarm = (SyncAlarm *) addr;
1246 
1247     pAlarm->state = XSyncAlarmDestroyed;
1248 
1249     SyncSendAlarmNotifyEvents(pAlarm);
1250 
1251     /* delete event selections */
1252 
1253     while (pAlarm->pEventClients)
1254 	FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
1255 
1256     SyncDeleteTriggerFromCounter(&pAlarm->trigger);
1257 
1258     xfree(pAlarm);
1259     return Success;
1260 }
1261 
1262 
1263 /*
1264  * ** Cleanup after the destruction of a Counter
1265  */
1266 /* ARGSUSED */
1267 static int
FreeCounter(env,id)1268 FreeCounter(env, id)
1269     pointer         env;
1270     XID             id;
1271 {
1272     SyncCounter     *pCounter = (SyncCounter *) env;
1273     SyncTriggerList *ptl, *pnext;
1274 
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)
1278     {
1279 	(*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
1280 	pnext = ptl->next;
1281 	xfree(ptl); /* destroy the trigger list as we go */
1282     }
1283     if (IsSystemCounter(pCounter))
1284     {
1285 	int i, found = 0;
1286 
1287 	xfree(pCounter->pSysCounterInfo);
1288 
1289 	/* find the counter in the list of system counters and remove it */
1290 
1291 	if (SysCounterList)
1292 	{
1293 	    for (i = 0; i < SyncNumSystemCounters; i++)
1294 	    {
1295 		if (SysCounterList[i] == pCounter)
1296 		{
1297 		    found = i;
1298 		    break;
1299 		}
1300 	    }
1301 	    if (found < (SyncNumSystemCounters-1))
1302 	    {
1303 		for (i = found; i < SyncNumSystemCounters-1; i++)
1304 		{
1305 		    SysCounterList[i] = SysCounterList[i+1];
1306 		}
1307 	    }
1308 	}
1309 	SyncNumSystemCounters--;
1310     }
1311     xfree(pCounter);
1312     return Success;
1313 }
1314 
1315 /*
1316  * ** Cleanup after Await
1317  */
1318 /* ARGSUSED */
1319 static int
FreeAwait(addr,id)1320 FreeAwait(addr, id)
1321     pointer         addr;
1322     XID             id;
1323 {
1324     SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
1325     SyncAwait *pAwait;
1326     int numwaits;
1327 
1328     pAwait = &(pAwaitUnion+1)->await; /* first await on list */
1329 
1330     /* remove triggers from counters */
1331 
1332     for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
1333 	 numwaits--, pAwait++)
1334     {
1335 	/* If the counter is being destroyed, FreeCounter will delete
1336 	 * the trigger list itself, so don't do it here.
1337 	 */
1338 	SyncCounter *pCounter = pAwait->trigger.pCounter;
1339 	if (pCounter && !pCounter->beingDestroyed)
1340 	    SyncDeleteTriggerFromCounter(&pAwait->trigger);
1341     }
1342     xfree(pAwaitUnion);
1343     return Success;
1344 }
1345 
1346 /* loosely based on dix/events.c/OtherClientGone */
1347 static int
FreeAlarmClient(value,id)1348 FreeAlarmClient(value, id)
1349     pointer value; /* must conform to DeleteType */
1350     XID   id;
1351 {
1352     SyncAlarm *pAlarm = (SyncAlarm *)value;
1353     SyncAlarmClientList *pCur, *pPrev;
1354 
1355     for (pPrev = NULL, pCur = pAlarm->pEventClients;
1356 	 pCur;
1357 	 pPrev = pCur, pCur = pCur->next)
1358     {
1359 	if (pCur->delete_id == id)
1360 	{
1361 	    if (pPrev)
1362 		pPrev->next = pCur->next;
1363 	    else
1364 		pAlarm->pEventClients = pCur->next;
1365 	    xfree(pCur);
1366 	    return(Success);
1367 	}
1368     }
1369     FatalError("alarm client not on event list");
1370     /*NOTREACHED*/
1371 }
1372 
1373 
1374 /*
1375  * *****  Proc functions
1376  */
1377 
1378 
1379 /*
1380  * ** Initialize the extension
1381  */
1382 static int
ProcSyncInitialize(client)1383 ProcSyncInitialize(client)
1384     ClientPtr       client;
1385 {
1386     xSyncInitializeReply  rep;
1387     int   n;
1388 
1389     REQUEST_SIZE_MATCH(xSyncInitializeReq);
1390 
1391     rep.type = X_Reply;
1392     rep.sequenceNumber = client->sequence;
1393     rep.majorVersion = SYNC_MAJOR_VERSION;
1394     rep.minorVersion = SYNC_MINOR_VERSION;
1395     rep.length = 0;
1396 
1397     if (client->swapped)
1398     {
1399 	swaps(&rep.sequenceNumber, n);
1400     }
1401     WriteToClient(client, sizeof(rep), (char *) &rep);
1402     return (client->noClientException);
1403 }
1404 
1405 /*
1406  * ** Get list of system counters available through the extension
1407  */
1408 static int
ProcSyncListSystemCounters(client)1409 ProcSyncListSystemCounters(client)
1410     ClientPtr       client;
1411 {
1412     xSyncListSystemCountersReply  rep;
1413     int i, len;
1414     xSyncSystemCounter *list, *walklist;
1415 
1416     REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
1417 
1418     rep.type = X_Reply;
1419     rep.sequenceNumber = client->sequence;
1420     rep.nCounters = SyncNumSystemCounters;
1421 
1422     for (i = len = 0; i < SyncNumSystemCounters; i++)
1423     {
1424 	char *name = SysCounterList[i]->pSysCounterInfo->name;
1425 	/* pad to 4 byte boundary */
1426 	len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
1427     }
1428 
1429     if (len)
1430     {
1431 	walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
1432 	if (!list)
1433 	    return BadAlloc;
1434     }
1435 
1436     rep.length = len >> 2;
1437 
1438     if (client->swapped)
1439     {
1440 	register char n;
1441 	swaps(&rep.sequenceNumber, n);
1442 	swapl(&rep.length, n);
1443 	swapl(&rep.nCounters, n);
1444     }
1445 
1446     for (i = 0; i < SyncNumSystemCounters; i++)
1447     {
1448 	int namelen;
1449 	char *pname_in_reply;
1450 	SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
1451 
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;
1457 
1458 	if (client->swapped)
1459 	{
1460 	    register char n;
1461 	    swapl(&walklist->counter, n);
1462 	    swapl(&walklist->resolution_hi, n);
1463 	    swapl(&walklist->resolution_lo, n);
1464 	    swaps(&walklist->name_length, n);
1465 	}
1466 
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));
1471     }
1472 
1473     WriteToClient(client, sizeof(rep), (char *) &rep);
1474     if (len)
1475     {
1476 	WriteToClient(client, len, (char *) list);
1477 	DEALLOCATE_LOCAL(list);
1478     }
1479 
1480     return (client->noClientException);
1481 }
1482 
1483 /*
1484  * ** Set client Priority
1485  */
1486 static int
ProcSyncSetPriority(client)1487 ProcSyncSetPriority(client)
1488     ClientPtr       client;
1489 {
1490     REQUEST(xSyncSetPriorityReq);
1491     ClientPtr priorityclient;
1492 
1493     REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
1494 
1495     if (stuff->id == None)
1496 	priorityclient = client;
1497     else if (!(priorityclient = LookupClient(stuff->id, client)))
1498     {
1499 	client->errorValue = stuff->id;
1500 	return BadMatch;
1501     }
1502 
1503     if (priorityclient->priority != stuff->priority)
1504     {
1505 	priorityclient->priority = stuff->priority;
1506 
1507 	/*  The following will force the server back into WaitForSomething
1508 	 *  so that the change in this client's priority is immediately
1509 	 *  reflected.
1510 	 */
1511 	isItTimeToYield = TRUE;
1512 	dispatchException |= DE_PRIORITYCHANGE;
1513     }
1514     return Success;
1515 }
1516 
1517 /*
1518  * ** Get client Priority
1519  */
1520 static int
ProcSyncGetPriority(client)1521 ProcSyncGetPriority(client)
1522     ClientPtr       client;
1523 {
1524     REQUEST(xSyncGetPriorityReq);
1525     xSyncGetPriorityReply rep;
1526     ClientPtr priorityclient;
1527 
1528     REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
1529 
1530     if (stuff->id == None)
1531 	priorityclient = client;
1532     else if (!(priorityclient = LookupClient(stuff->id, client)))
1533     {
1534 	client->errorValue = stuff->id;
1535 	return BadMatch;
1536     }
1537 
1538     rep.type = X_Reply;
1539     rep.length = 0;
1540     rep.sequenceNumber = client->sequence;
1541     rep.priority = priorityclient->priority;
1542 
1543     if (client->swapped)
1544     {
1545 	register char n;
1546 	swaps(&rep.sequenceNumber, n);
1547 	swapl(&rep.priority, n);
1548     }
1549 
1550     WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
1551 
1552     return (client->noClientException);
1553 }
1554 
1555 /*
1556  * ** Create a new counter
1557  */
1558 static int
ProcSyncCreateCounter(client)1559 ProcSyncCreateCounter(client)
1560     ClientPtr       client;
1561 {
1562     REQUEST(xSyncCreateCounterReq);
1563     CARD64          initial;
1564 
1565     REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
1566 
1567     LEGAL_NEW_RESOURCE(stuff->cid, client);
1568 
1569     XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
1570     if (!SyncCreateCounter(client, stuff->cid, initial))
1571 	return BadAlloc;
1572 
1573     return (client->noClientException);
1574 }
1575 
1576 /*
1577  * ** Set Counter value
1578  */
1579 static int
ProcSyncSetCounter(client)1580 ProcSyncSetCounter(client)
1581     ClientPtr       client;
1582 {
1583     REQUEST(xSyncSetCounterReq);
1584     SyncCounter    *pCounter;
1585     CARD64	   newvalue;
1586 
1587     pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
1588 					   RTCounter, SecurityWriteAccess);
1589     if (pCounter == NULL)
1590     {
1591 	client->errorValue = stuff->cid;
1592 	return SyncErrorBase + XSyncBadCounter;
1593     }
1594 
1595     if (IsSystemCounter(pCounter))
1596     {
1597 	client->errorValue = stuff->cid;
1598 	return BadAccess;
1599     }
1600 
1601     XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
1602     SyncChangeCounter(pCounter, newvalue);
1603     return Success;
1604 }
1605 
1606 /*
1607  * ** Change Counter value
1608  */
1609 static int
ProcSyncChangeCounter(client)1610 ProcSyncChangeCounter(client)
1611     ClientPtr       client;
1612 {
1613     REQUEST(xSyncChangeCounterReq);
1614     SyncCounter    *pCounter;
1615     CARD64          newvalue;
1616     Bool	    overflow;
1617 
1618     REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
1619 
1620     pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
1621 					    RTCounter, SecurityWriteAccess);
1622     if (pCounter == NULL)
1623     {
1624 	client->errorValue = stuff->cid;
1625 	return SyncErrorBase + XSyncBadCounter;
1626     }
1627 
1628     if (IsSystemCounter(pCounter))
1629     {
1630 	client->errorValue = stuff->cid;
1631 	return BadAccess;
1632     }
1633 
1634     XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
1635     XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
1636     if (overflow)
1637     {
1638 	/* XXX 64 bit value can't fit in 32 bits; do the best we can */
1639 	client->errorValue = stuff->value_hi;
1640 	return BadValue;
1641     }
1642     SyncChangeCounter(pCounter, newvalue);
1643     return Success;
1644 }
1645 
1646 /*
1647  * ** Destroy a counter
1648  */
1649 static int
ProcSyncDestroyCounter(client)1650 ProcSyncDestroyCounter(client)
1651     ClientPtr       client;
1652 {
1653     REQUEST(xSyncDestroyCounterReq);
1654     SyncCounter    *pCounter;
1655 
1656     REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
1657 
1658     pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
1659 					   RTCounter, SecurityDestroyAccess);
1660     if (pCounter == NULL)
1661     {
1662 	client->errorValue = stuff->counter;
1663 	return SyncErrorBase + XSyncBadCounter;
1664     }
1665     if (IsSystemCounter(pCounter))
1666     {
1667 	client->errorValue = stuff->counter;
1668 	return BadAccess;
1669     }
1670     FreeResource(pCounter->id, RT_NONE);
1671     return Success;
1672 }
1673 
1674 
1675 /*
1676  * ** Await
1677  */
1678 static int
ProcSyncAwait(client)1679 ProcSyncAwait(client)
1680     ClientPtr       client;
1681 {
1682     REQUEST(xSyncAwaitReq);
1683     int             len, items;
1684     int             i;
1685     xSyncWaitCondition *pProtocolWaitConds;
1686     SyncAwaitUnion *pAwaitUnion;
1687     SyncAwait	   *pAwait;
1688     int		   status;
1689 
1690     REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
1691 
1692     len = client->req_len << 2;
1693     len -= sz_xSyncAwaitReq;
1694     items = len / sz_xSyncWaitCondition;
1695 
1696     if (items * sz_xSyncWaitCondition != len)
1697     {
1698 	return BadLength;
1699     }
1700     if (items == 0)
1701     {
1702 	client->errorValue = items; /* XXX protocol change */
1703 	return BadValue;
1704     }
1705 
1706     pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
1707 
1708     /*  all the memory for the entire await list is allocated
1709      *  here in one chunk
1710      */
1711     pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
1712     if (!pAwaitUnion)
1713 	return BadAlloc;
1714 
1715     /* first item is the header, remainder are real wait conditions */
1716 
1717     pAwaitUnion->header.delete_id = FakeClientID(client->index);
1718     if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
1719     {
1720 	xfree(pAwaitUnion);
1721 	return BadAlloc;
1722     }
1723 
1724     /* don't need to do any more memory allocation for this request! */
1725 
1726     pAwaitUnion->header.client = client;
1727     pAwaitUnion->header.num_waitconditions = 0;
1728 
1729     pAwait = &(pAwaitUnion+1)->await; /* skip over header */
1730     for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
1731     {
1732 	if (pProtocolWaitConds->counter == None) /* XXX protocol change */
1733 	{
1734 	    /*  this should take care of removing any triggers created by
1735 	     *  this request that have already been registered on counters
1736 	     */
1737 	    FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1738 	    client->errorValue = pProtocolWaitConds->counter;
1739 	    return SyncErrorBase + XSyncBadCounter;
1740 	}
1741 
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;
1749 
1750 	status = SyncInitTrigger(client, &pAwait->trigger,
1751 			 pProtocolWaitConds->counter, XSyncCAAllTrigger);
1752 	if (status != Success)
1753 	{
1754 	    /*  this should take care of removing any triggers created by
1755 	     *  this request that have already been registered on counters
1756 	     */
1757 	    FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1758 	    return status;
1759 	}
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++;
1768     }
1769 
1770     IgnoreClient(client);
1771 
1772     /* see if any of the triggers are already true */
1773 
1774     pAwait = &(pAwaitUnion+1)->await; /* skip over header */
1775     for (i = 0; i < items; i++, pAwait++)
1776     {
1777 	/*  don't have to worry about NULL counters because the request
1778 	 *  errors before we get here out if they occur
1779 	 */
1780 	if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
1781 					    pAwait->trigger.pCounter->value))
1782 	{
1783 	    (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
1784 	    break; /* once is enough */
1785 	}
1786     }
1787     return Success;
1788 }
1789 
1790 
1791 /*
1792  * ** Query a counter
1793  */
1794 static int
ProcSyncQueryCounter(client)1795 ProcSyncQueryCounter(client)
1796     ClientPtr       client;
1797 {
1798     REQUEST(xSyncQueryCounterReq);
1799     xSyncQueryCounterReply rep;
1800     SyncCounter    *pCounter;
1801 
1802     REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
1803 
1804     pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
1805 					    RTCounter, SecurityReadAccess);
1806     if (pCounter == NULL)
1807     {
1808 	client->errorValue = stuff->counter;
1809 	return SyncErrorBase + XSyncBadCounter;
1810     }
1811 
1812     rep.type = X_Reply;
1813     rep.length = 0;
1814     rep.sequenceNumber = client->sequence;
1815 
1816     /* if system counter, ask it what the current value is */
1817 
1818     if (IsSystemCounter(pCounter))
1819     {
1820 	(*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
1821 						  &pCounter->value);
1822     }
1823 
1824     rep.value_hi = XSyncValueHigh32(pCounter->value);
1825     rep.value_lo = XSyncValueLow32(pCounter->value);
1826     if (client->swapped)
1827     {
1828 	register char n;
1829 	swaps(&rep.sequenceNumber, n);
1830 	swapl(&rep.length, n);
1831 	swapl(&rep.value_hi, n);
1832 	swapl(&rep.value_lo, n);
1833     }
1834     WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
1835     return (client->noClientException);
1836 }
1837 
1838 
1839 /*
1840  * ** Create Alarm
1841  */
1842 static int
ProcSyncCreateAlarm(client)1843 ProcSyncCreateAlarm(client)
1844     ClientPtr       client;
1845 {
1846     REQUEST(xSyncCreateAlarmReq);
1847     SyncAlarm      *pAlarm;
1848     int             status;
1849     unsigned long   len, vmask;
1850     SyncTrigger	    *pTrigger;
1851 
1852     REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
1853 
1854     LEGAL_NEW_RESOURCE(stuff->id, client);
1855 
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))))
1860 	return BadLength;
1861 
1862     if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
1863     {
1864 	return BadAlloc;
1865     }
1866 
1867     /* set up defaults */
1868 
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)
1878     {
1879 	xfree(pAlarm);
1880 	return status;
1881     }
1882 
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)
1892     {
1893 	xfree(pAlarm);
1894 	return status;
1895     }
1896 
1897     if (!AddResource(stuff->id, RTAlarm, pAlarm))
1898     {
1899 	xfree(pAlarm);
1900 	return BadAlloc;
1901     }
1902 
1903     /*  see if alarm already triggered.  NULL counter will not trigger
1904      *  in CreateAlarm and sets alarm state to Inactive.
1905      */
1906 
1907     if (!pTrigger->pCounter)
1908     {
1909 	pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
1910     }
1911     else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
1912     {
1913 	(*pTrigger->TriggerFired)(pTrigger);
1914     }
1915 
1916     return Success;
1917 }
1918 
1919 /*
1920  * ** Change Alarm
1921  */
1922 static int
ProcSyncChangeAlarm(client)1923 ProcSyncChangeAlarm(client)
1924     ClientPtr       client;
1925 {
1926     REQUEST(xSyncChangeAlarmReq);
1927     SyncAlarm   *pAlarm;
1928     long        vmask;
1929     int         len, status;
1930 
1931     REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
1932 
1933     if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1934 					      RTAlarm, SecurityWriteAccess)))
1935     {
1936 	client->errorValue = stuff->alarm;
1937 	return SyncErrorBase + XSyncBadAlarm;
1938     }
1939 
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))))
1944 	return BadLength;
1945 
1946     if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1947 					    (CARD32 *)&stuff[1])) != Success)
1948 	return status;
1949 
1950     /*  see if alarm already triggered.  NULL counter WILL trigger
1951      *  in ChangeAlarm.
1952      */
1953 
1954     if (!pAlarm->trigger.pCounter ||
1955 	(*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
1956 					pAlarm->trigger.pCounter->value))
1957     {
1958 	(*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
1959     }
1960     return Success;
1961 }
1962 
1963 static int
ProcSyncQueryAlarm(client)1964 ProcSyncQueryAlarm(client)
1965     ClientPtr       client;
1966 {
1967     REQUEST(xSyncQueryAlarmReq);
1968     SyncAlarm      *pAlarm;
1969     xSyncQueryAlarmReply rep;
1970     SyncTrigger    *pTrigger;
1971 
1972     REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
1973 
1974     pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
1975 						RTAlarm, SecurityReadAccess);
1976     if (!pAlarm)
1977     {
1978 	client->errorValue = stuff->alarm;
1979 	return (SyncErrorBase + XSyncBadAlarm);
1980     }
1981 
1982     rep.type = X_Reply;
1983     rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2;
1984     rep.sequenceNumber = client->sequence;
1985 
1986     pTrigger = &pAlarm->trigger;
1987     rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None;
1988 
1989 #if 0 /* XXX unclear what to do, depends on whether relative value-types
1990        * are "consumed" immediately and are considered absolute from then
1991        * on.
1992        */
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);
1996 #else
1997     rep.value_type = XSyncAbsolute;
1998     rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
1999     rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
2000 #endif
2001 
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;
2007 
2008     if (client->swapped)
2009     {
2010 	register char n;
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);
2019     }
2020 
2021     WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
2022     return (client->noClientException);
2023 }
2024 
2025 
2026 static int
ProcSyncDestroyAlarm(client)2027 ProcSyncDestroyAlarm(client)
2028     ClientPtr       client;
2029 {
2030     SyncAlarm      *pAlarm;
2031     REQUEST(xSyncDestroyAlarmReq);
2032 
2033     REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
2034 
2035     if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
2036 					      RTAlarm, SecurityDestroyAccess)))
2037     {
2038 	client->errorValue = stuff->alarm;
2039 	return SyncErrorBase + XSyncBadAlarm;
2040     }
2041 
2042     FreeResource(stuff->alarm, RT_NONE);
2043     return (client->noClientException);
2044 }
2045 
2046 /*
2047  * ** Given an extension request, call the appropriate request procedure
2048  */
2049 static int
ProcSyncDispatch(client)2050 ProcSyncDispatch(client)
2051     ClientPtr       client;
2052 {
2053     REQUEST(xReq);
2054 
2055     switch (stuff->data)
2056     {
2057 
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);
2072       case X_SyncAwait:
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);
2086       default:
2087 	return BadRequest;
2088     }
2089 }
2090 
2091 /*
2092  * Boring Swapping stuff ...
2093  */
2094 
2095 static int
SProcSyncInitialize(client)2096 SProcSyncInitialize(client)
2097     ClientPtr       client;
2098 {
2099     REQUEST(xSyncInitializeReq);
2100     register char   n;
2101 
2102     swaps(&stuff->length, n);
2103     REQUEST_SIZE_MATCH (xSyncInitializeReq);
2104 
2105     return ProcSyncInitialize(client);
2106 }
2107 
2108 static int
SProcSyncListSystemCounters(client)2109 SProcSyncListSystemCounters(client)
2110     ClientPtr       client;
2111 {
2112     REQUEST(xSyncListSystemCountersReq);
2113     register char   n;
2114 
2115     swaps(&stuff->length, n);
2116     REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
2117 
2118     return ProcSyncListSystemCounters(client);
2119 }
2120 
2121 static int
SProcSyncCreateCounter(client)2122 SProcSyncCreateCounter(client)
2123     ClientPtr       client;
2124 {
2125     REQUEST(xSyncCreateCounterReq);
2126     register char   n;
2127 
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);
2133 
2134     return ProcSyncCreateCounter(client);
2135 }
2136 
2137 static int
SProcSyncSetCounter(client)2138 SProcSyncSetCounter(client)
2139     ClientPtr       client;
2140 {
2141     REQUEST(xSyncSetCounterReq);
2142     register char   n;
2143 
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);
2149 
2150     return ProcSyncSetCounter(client);
2151 }
2152 
2153 static int
SProcSyncChangeCounter(client)2154 SProcSyncChangeCounter(client)
2155     ClientPtr       client;
2156 {
2157     REQUEST(xSyncChangeCounterReq);
2158     register char   n;
2159 
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);
2165 
2166     return ProcSyncChangeCounter(client);
2167 }
2168 
2169 static int
SProcSyncQueryCounter(client)2170 SProcSyncQueryCounter(client)
2171     ClientPtr       client;
2172 {
2173     REQUEST(xSyncQueryCounterReq);
2174     register char   n;
2175 
2176     swaps(&stuff->length, n);
2177     REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
2178     swapl(&stuff->counter, n);
2179 
2180     return ProcSyncQueryCounter(client);
2181 }
2182 
2183 static int
SProcSyncDestroyCounter(client)2184 SProcSyncDestroyCounter(client)
2185     ClientPtr       client;
2186 {
2187     REQUEST(xSyncDestroyCounterReq);
2188     register char   n;
2189 
2190     swaps(&stuff->length, n);
2191     REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
2192     swapl(&stuff->counter, n);
2193 
2194     return ProcSyncDestroyCounter(client);
2195 }
2196 
2197 static int
SProcSyncAwait(client)2198 SProcSyncAwait(client)
2199     ClientPtr       client;
2200 {
2201     REQUEST(xSyncAwaitReq);
2202     register char   n;
2203 
2204     swaps(&stuff->length, n);
2205     REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
2206     SwapRestL(stuff);
2207 
2208     return ProcSyncAwait(client);
2209 }
2210 
2211 
2212 static int
SProcSyncCreateAlarm(client)2213 SProcSyncCreateAlarm(client)
2214     ClientPtr       client;
2215 {
2216     REQUEST(xSyncCreateAlarmReq);
2217     register char   n;
2218 
2219     swaps(&stuff->length, n);
2220     REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
2221     swapl(&stuff->id, n);
2222     swapl(&stuff->valueMask, n);
2223     SwapRestL(stuff);
2224 
2225     return ProcSyncCreateAlarm(client);
2226 }
2227 
2228 static int
SProcSyncChangeAlarm(client)2229 SProcSyncChangeAlarm(client)
2230     ClientPtr       client;
2231 {
2232     REQUEST(xSyncChangeAlarmReq);
2233     register char   n;
2234 
2235     swaps(&stuff->length, n);
2236     REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
2237     swapl(&stuff->alarm, n);
2238     swapl(&stuff->valueMask, n);
2239     SwapRestL(stuff);
2240     return ProcSyncChangeAlarm(client);
2241 }
2242 
2243 static int
SProcSyncQueryAlarm(client)2244 SProcSyncQueryAlarm(client)
2245     ClientPtr       client;
2246 {
2247     REQUEST(xSyncQueryAlarmReq);
2248     register char   n;
2249 
2250     swaps(&stuff->length, n);
2251     REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
2252     swapl(&stuff->alarm, n);
2253 
2254     return ProcSyncQueryAlarm(client);
2255 }
2256 
2257 static int
SProcSyncDestroyAlarm(client)2258 SProcSyncDestroyAlarm(client)
2259     ClientPtr       client;
2260 {
2261     REQUEST(xSyncDestroyAlarmReq);
2262     register char   n;
2263 
2264     swaps(&stuff->length, n);
2265     REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
2266     swapl(&stuff->alarm, n);
2267 
2268     return ProcSyncDestroyAlarm(client);
2269 }
2270 
2271 static int
SProcSyncSetPriority(client)2272 SProcSyncSetPriority(client)
2273     ClientPtr       client;
2274 {
2275     REQUEST(xSyncSetPriorityReq);
2276     register char   n;
2277 
2278     swaps(&stuff->length, n);
2279     REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
2280     swapl(&stuff->id, n);
2281     swapl(&stuff->priority, n);
2282 
2283     return ProcSyncSetPriority(client);
2284 }
2285 
2286 static int
SProcSyncGetPriority(client)2287 SProcSyncGetPriority(client)
2288     ClientPtr       client;
2289 {
2290     REQUEST(xSyncGetPriorityReq);
2291     register char   n;
2292 
2293     swaps(&stuff->length, n);
2294     REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
2295     swapl(&stuff->id, n);
2296 
2297     return ProcSyncGetPriority(client);
2298 }
2299 
2300 
2301 static int
SProcSyncDispatch(client)2302 SProcSyncDispatch(client)
2303     ClientPtr       client;
2304 {
2305     REQUEST(xReq);
2306 
2307     switch (stuff->data)
2308     {
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);
2323       case X_SyncAwait:
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);
2337       default:
2338 	return BadRequest;
2339     }
2340 }
2341 
2342 /*
2343  * Event Swapping
2344  */
2345 
2346 static void
SCounterNotifyEvent(from,to)2347 SCounterNotifyEvent(from, to)
2348     xSyncCounterNotifyEvent *from, *to;
2349 {
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;
2361 }
2362 
2363 
2364 static void
SAlarmNotifyEvent(from,to)2365 SAlarmNotifyEvent(from, to)
2366     xSyncAlarmNotifyEvent *from, *to;
2367 {
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;
2378 }
2379 
2380 /*
2381  * ** Close everything down. ** This is fairly simple for now.
2382  */
2383 /* ARGSUSED */
2384 static void
SyncResetProc(extEntry)2385 SyncResetProc(extEntry)
2386     ExtensionEntry *extEntry;
2387 {
2388     xfree(SysCounterList);
2389     SysCounterList = NULL;
2390     RTCounter = 0;
2391 }
2392 
2393 
2394 /*
2395  * ** Initialise the extension.
2396  */
2397 void
SyncExtensionInit()2398 SyncExtensionInit()
2399 {
2400     ExtensionEntry *extEntry;
2401 
2402     if (RTCounter == 0)
2403     {
2404 	RTCounter = CreateNewResourceType(FreeCounter);
2405     }
2406     RTAlarm = CreateNewResourceType(FreeAlarm);
2407     RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN;
2408     RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN;
2409 
2410     if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
2411 	RTAlarmClient == 0 ||
2412 	(extEntry = AddExtension(SYNC_NAME,
2413 				 XSyncNumberEvents, XSyncNumberErrors,
2414 				 ProcSyncDispatch, SProcSyncDispatch,
2415 				 SyncResetProc,
2416 				 StandardMinorOpcode)) == NULL)
2417     {
2418 	ErrorF("Sync Extension %d.%d failed to Initialise\n",
2419 		SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2420 	return;
2421     }
2422 
2423     SyncReqCode = extEntry->base;
2424     SyncEventBase = extEntry->eventBase;
2425     SyncErrorBase = extEntry->errorBase;
2426     EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
2427     EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
2428 
2429     /*
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.
2434      */
2435     SyncInitServerTime();
2436 
2437 #ifdef DEBUG
2438     fprintf(stderr, "Sync Extension %d.%d\n",
2439 	    SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2440 #endif
2441 }
2442 
2443 
2444 /*
2445  * ***** SERVERTIME implementation - should go in its own file in OS directory?
2446  */
2447 
2448 
2449 #if !defined(WIN32) && !defined(MINIX) && !defined(Lynx)
2450 #include <sys/time.h>
2451 #endif
2452 
2453 static pointer ServertimeCounter;
2454 static XSyncValue Now;
2455 static XSyncValue *pnext_time;
2456 
2457 #define GetTime()\
2458 {\
2459     unsigned long millis = GetTimeInMillis();\
2460     unsigned long maxis = XSyncValueHigh32(Now);\
2461     if (millis < XSyncValueLow32(Now)) maxis++;\
2462     XSyncIntsToValue(&Now, millis, maxis);\
2463 }
2464 
2465 /*
2466 *** Server Block Handler
2467 *** code inspired by multibuffer extension
2468  */
2469 /*ARGSUSED*/
ServertimeBlockHandler(env,wt,LastSelectMask)2470 static void ServertimeBlockHandler(env, wt, LastSelectMask)
2471 pointer env;
2472 struct timeval **wt;
2473 pointer LastSelectMask;
2474 {
2475     XSyncValue delay;
2476     unsigned long timeout;
2477 
2478     if (pnext_time)
2479     {
2480         GetTime();
2481 
2482         if (XSyncValueGreaterOrEqual(Now, *pnext_time))
2483 	{
2484             timeout = 0;
2485         }
2486 	else
2487 	{
2488 	    Bool overflow;
2489             XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
2490             timeout = XSyncValueLow32(delay);
2491         }
2492         AdjustWaitForDelay(wt, timeout); /* os/utils.c */
2493     }
2494 }
2495 
2496 /*
2497 *** Wakeup Handler
2498  */
2499 /*ARGSUSED*/
ServertimeWakeupHandler(env,rc,LastSelectMask)2500 static void ServertimeWakeupHandler(env, rc, LastSelectMask)
2501 pointer env;
2502 int rc;
2503 pointer LastSelectMask;
2504 {
2505     if (pnext_time)
2506     {
2507         GetTime();
2508 
2509         if (XSyncValueGreaterOrEqual(Now, *pnext_time))
2510 	{
2511             SyncChangeCounter(ServertimeCounter, Now);
2512         }
2513     }
2514 }
2515 
2516 static void
ServertimeQueryValue(pCounter,pValue_return)2517 ServertimeQueryValue(pCounter, pValue_return)
2518     pointer pCounter;
2519     CARD64 *pValue_return;
2520 {
2521     GetTime();
2522     *pValue_return = Now;
2523 }
2524 
2525 static void
ServertimeBracketValues(pCounter,pbracket_less,pbracket_greater)2526 ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater)
2527     pointer pCounter;
2528     CARD64 *pbracket_less;
2529     CARD64 *pbracket_greater;
2530 {
2531     if (!pnext_time && pbracket_greater)
2532     {
2533 	RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
2534 				       ServertimeWakeupHandler,
2535 				       NULL);
2536     }
2537     else if (pnext_time && !pbracket_greater)
2538     {
2539 	RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
2540 				     ServertimeWakeupHandler,
2541 				     NULL);
2542     }
2543     pnext_time = pbracket_greater;
2544 }
2545 
2546 static void
SyncInitServerTime()2547 SyncInitServerTime()
2548 {
2549     CARD64 resolution;
2550 
2551     XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
2552     XSyncIntToValue(&resolution, 4);
2553     ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
2554 			    XSyncCounterNeverDecreases,
2555 			    ServertimeQueryValue, ServertimeBracketValues);
2556     pnext_time = NULL;
2557 }
2558