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