]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/Xext/sync.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / Xext / sync.c
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
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
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
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
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
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
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 
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
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
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
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
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
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
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
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 
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 *
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 
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
1145 SyncDestroySystemCounter(pSysCounter)
1146     pointer pSysCounter;
1147 {
1148     SyncCounter *pCounter = (SyncCounter *)pSysCounter;
1149     FreeResource(pCounter->id, RT_NONE);
1150 }
1151
1152 static void
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
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
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
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
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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*/
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*/
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
2517 ServertimeQueryValue(pCounter, pValue_return)
2518     pointer pCounter;
2519     CARD64 *pValue_return;
2520 {
2521     GetTime();
2522     *pValue_return = Now;
2523 }
2524
2525 static void
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
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 }