1 /*
2 
3 Copyright 1991, 1993, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26 
27 Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
28 and Olivetti Research Limited, Cambridge, England.
29 
30                         All Rights Reserved
31 
32 Permission to use, copy, modify, and distribute this software and its
33 documentation for any purpose and without fee is hereby granted,
34 provided that the above copyright notice appear in all copies and that
35 both that copyright notice and this permission notice appear in
36 supporting documentation, and that the names of Digital or Olivetti
37 not be used in advertising or publicity pertaining to distribution of the
38 software without specific, written prior permission.  Digital and Olivetti
39 make no representations about the suitability of this software
40 for any purpose.  It is provided "as is" without express or implied warranty.
41 
42 DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
43 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
44 FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
45 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
46 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
47 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
48 PERFORMANCE OF THIS SOFTWARE.
49 
50 */
51 
52 #ifdef HAVE_DIX_CONFIG_H
53 #include <dix-config.h>
54 #endif
55 
56 #include <string.h>
57 
58 #include <X11/X.h>
59 #include <X11/Xproto.h>
60 #include <X11/Xmd.h>
61 #include "scrnintstr.h"
62 #include "os.h"
63 #include "extnsionst.h"
64 #include "dixstruct.h"
65 #include "pixmapstr.h"
66 #include "resource.h"
67 #include "opaque.h"
68 #include <X11/extensions/syncproto.h>
69 #include "syncsrv.h"
70 #include "syncsdk.h"
71 #include "protocol-versions.h"
72 #include "inputstr.h"
73 
74 #include <stdio.h>
75 #if !defined(WIN32)
76 #include <sys/time.h>
77 #endif
78 
79 #include "extinit.h"
80 
81 /*
82  * Local Global Variables
83  */
84 static int SyncEventBase;
85 static int SyncErrorBase;
86 static RESTYPE RTCounter = 0;
87 static RESTYPE RTAwait;
88 static RESTYPE RTAlarm;
89 static RESTYPE RTAlarmClient;
90 static RESTYPE RTFence;
91 static struct xorg_list SysCounterList;
92 static int SyncNumInvalidCounterWarnings = 0;
93 
94 #define MAX_INVALID_COUNTER_WARNINGS	   5
95 
96 static const char *WARN_INVALID_COUNTER_COMPARE =
97     "Warning: Non-counter XSync object using Counter-only\n"
98     "         comparison.  Result will never be true.\n";
99 
100 static const char *WARN_INVALID_COUNTER_ALARM =
101     "Warning: Non-counter XSync object used in alarm.  This is\n"
102     "         the result of a programming error in the X server.\n";
103 
104 #define IsSystemCounter(pCounter) \
105     (pCounter && (pCounter->sync.client == NULL))
106 
107 /* these are all the alarm attributes that pertain to the alarm's trigger */
108 #define XSyncCAAllTrigger \
109     (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
110 
111 static void SyncComputeBracketValues(SyncCounter *);
112 
113 static void SyncInitServerTime(void);
114 
115 static void SyncInitIdleTime(void);
116 
117 static inline void*
SysCounterGetPrivate(SyncCounter * counter)118 SysCounterGetPrivate(SyncCounter *counter)
119 {
120     BUG_WARN(!IsSystemCounter(counter));
121 
122     return counter->pSysCounterInfo ? counter->pSysCounterInfo->private : NULL;
123 }
124 
125 static Bool
SyncCheckWarnIsCounter(const SyncObject * pSync,const char * warning)126 SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning)
127 {
128     if (pSync && (SYNC_COUNTER != pSync->type)) {
129         if (SyncNumInvalidCounterWarnings++ < MAX_INVALID_COUNTER_WARNINGS) {
130             ErrorF("%s", warning);
131             ErrorF("         Counter type: %d\n", pSync->type);
132         }
133 
134         return FALSE;
135     }
136 
137     return TRUE;
138 }
139 
140 /*  Each counter maintains a simple linked list of triggers that are
141  *  interested in the counter.  The two functions below are used to
142  *  delete and add triggers on this list.
143  */
144 void
SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)145 SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
146 {
147     SyncTriggerList *pCur;
148     SyncTriggerList *pPrev;
149     SyncCounter *pCounter;
150 
151     /* pSync needs to be stored in pTrigger before calling here. */
152 
153     if (!pTrigger->pSync)
154         return;
155 
156     pPrev = NULL;
157     pCur = pTrigger->pSync->pTriglist;
158 
159     while (pCur) {
160         if (pCur->pTrigger == pTrigger) {
161             if (pPrev)
162                 pPrev->next = pCur->next;
163             else
164                 pTrigger->pSync->pTriglist = pCur->next;
165 
166             free(pCur);
167             break;
168         }
169 
170         pPrev = pCur;
171         pCur = pCur->next;
172     }
173 
174     if (SYNC_COUNTER == pTrigger->pSync->type) {
175         pCounter = (SyncCounter *) pTrigger->pSync;
176 
177         if (IsSystemCounter(pCounter))
178             SyncComputeBracketValues(pCounter);
179     }
180     else if (SYNC_FENCE == pTrigger->pSync->type) {
181         SyncFence *pFence = (SyncFence *) pTrigger->pSync;
182 
183         pFence->funcs.DeleteTrigger(pTrigger);
184     }
185 }
186 
187 int
SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)188 SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)
189 {
190     SyncTriggerList *pCur;
191     SyncCounter *pCounter;
192 
193     if (!pTrigger->pSync)
194         return Success;
195 
196     /* don't do anything if it's already there */
197     for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next) {
198         if (pCur->pTrigger == pTrigger)
199             return Success;
200     }
201 
202     if (!(pCur = malloc(sizeof(SyncTriggerList))))
203         return BadAlloc;
204 
205     pCur->pTrigger = pTrigger;
206     pCur->next = pTrigger->pSync->pTriglist;
207     pTrigger->pSync->pTriglist = pCur;
208 
209     if (SYNC_COUNTER == pTrigger->pSync->type) {
210         pCounter = (SyncCounter *) pTrigger->pSync;
211 
212         if (IsSystemCounter(pCounter))
213             SyncComputeBracketValues(pCounter);
214     }
215     else if (SYNC_FENCE == pTrigger->pSync->type) {
216         SyncFence *pFence = (SyncFence *) pTrigger->pSync;
217 
218         pFence->funcs.AddTrigger(pTrigger);
219     }
220 
221     return Success;
222 }
223 
224 /*  Below are five possible functions that can be plugged into
225  *  pTrigger->CheckTrigger for counter sync objects, corresponding to
226  *  the four possible test-types, and the one possible function that
227  *  can be plugged into pTrigger->CheckTrigger for fence sync objects.
228  *  These functions are called after the sync object's state changes
229  *  but are also passed the old state so they can inspect both the old
230  *  and new values.  (PositiveTransition and NegativeTransition need to
231  *  see both pieces of information.)  These functions return the truth
232  *  value of the trigger.
233  *
234  *  All of them include the condition pTrigger->pSync == NULL.
235  *  This is because the spec says that a trigger with a sync value
236  *  of None is always TRUE.
237  */
238 
239 static Bool
SyncCheckTriggerPositiveComparison(SyncTrigger * pTrigger,int64_t oldval)240 SyncCheckTriggerPositiveComparison(SyncTrigger * pTrigger, int64_t oldval)
241 {
242     SyncCounter *pCounter;
243 
244     /* Non-counter sync objects should never get here because they
245      * never trigger this comparison. */
246     if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
247         return FALSE;
248 
249     pCounter = (SyncCounter *) pTrigger->pSync;
250 
251     return pCounter == NULL || pCounter->value >= pTrigger->test_value;
252 }
253 
254 static Bool
SyncCheckTriggerNegativeComparison(SyncTrigger * pTrigger,int64_t oldval)255 SyncCheckTriggerNegativeComparison(SyncTrigger * pTrigger, int64_t oldval)
256 {
257     SyncCounter *pCounter;
258 
259     /* Non-counter sync objects should never get here because they
260      * never trigger this comparison. */
261     if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
262         return FALSE;
263 
264     pCounter = (SyncCounter *) pTrigger->pSync;
265 
266     return pCounter == NULL || pCounter->value <= pTrigger->test_value;
267 }
268 
269 static Bool
SyncCheckTriggerPositiveTransition(SyncTrigger * pTrigger,int64_t oldval)270 SyncCheckTriggerPositiveTransition(SyncTrigger * pTrigger, int64_t oldval)
271 {
272     SyncCounter *pCounter;
273 
274     /* Non-counter sync objects should never get here because they
275      * never trigger this comparison. */
276     if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
277         return FALSE;
278 
279     pCounter = (SyncCounter *) pTrigger->pSync;
280 
281     return (pCounter == NULL ||
282             (oldval < pTrigger->test_value &&
283              pCounter->value >= pTrigger->test_value));
284 }
285 
286 static Bool
SyncCheckTriggerNegativeTransition(SyncTrigger * pTrigger,int64_t oldval)287 SyncCheckTriggerNegativeTransition(SyncTrigger * pTrigger, int64_t oldval)
288 {
289     SyncCounter *pCounter;
290 
291     /* Non-counter sync objects should never get here because they
292      * never trigger this comparison. */
293     if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
294         return FALSE;
295 
296     pCounter = (SyncCounter *) pTrigger->pSync;
297 
298     return (pCounter == NULL ||
299             (oldval > pTrigger->test_value &&
300              pCounter->value <= pTrigger->test_value));
301 }
302 
303 static Bool
SyncCheckTriggerFence(SyncTrigger * pTrigger,int64_t unused)304 SyncCheckTriggerFence(SyncTrigger * pTrigger, int64_t unused)
305 {
306     SyncFence *pFence = (SyncFence *) pTrigger->pSync;
307 
308     (void) unused;
309 
310     return (pFence == NULL || pFence->funcs.CheckTriggered(pFence));
311 }
312 
313 static int
SyncInitTrigger(ClientPtr client,SyncTrigger * pTrigger,XID syncObject,RESTYPE resType,Mask changes)314 SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
315                 RESTYPE resType, Mask changes)
316 {
317     SyncObject *pSync = pTrigger->pSync;
318     SyncCounter *pCounter = NULL;
319     int rc;
320     Bool newSyncObject = FALSE;
321 
322     if (changes & XSyncCACounter) {
323         if (syncObject == None)
324             pSync = NULL;
325         else if (Success != (rc = dixLookupResourceByType((void **) &pSync,
326                                                           syncObject, resType,
327                                                           client,
328                                                           DixReadAccess))) {
329             client->errorValue = syncObject;
330             return rc;
331         }
332         if (pSync != pTrigger->pSync) { /* new counter for trigger */
333             SyncDeleteTriggerFromSyncObject(pTrigger);
334             pTrigger->pSync = pSync;
335             newSyncObject = TRUE;
336         }
337     }
338 
339     /* if system counter, ask it what the current value is */
340 
341     if (pSync && SYNC_COUNTER == pSync->type) {
342         pCounter = (SyncCounter *) pSync;
343 
344         if (IsSystemCounter(pCounter)) {
345             (*pCounter->pSysCounterInfo->QueryValue) ((void *) pCounter,
346                                                       &pCounter->value);
347         }
348     }
349 
350     if (changes & XSyncCAValueType) {
351         if (pTrigger->value_type != XSyncRelative &&
352             pTrigger->value_type != XSyncAbsolute) {
353             client->errorValue = pTrigger->value_type;
354             return BadValue;
355         }
356     }
357 
358     if (changes & XSyncCATestType) {
359 
360         if (pSync && SYNC_FENCE == pSync->type) {
361             pTrigger->CheckTrigger = SyncCheckTriggerFence;
362         }
363         else {
364             /* select appropriate CheckTrigger function */
365 
366             switch (pTrigger->test_type) {
367             case XSyncPositiveTransition:
368                 pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
369                 break;
370             case XSyncNegativeTransition:
371                 pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
372                 break;
373             case XSyncPositiveComparison:
374                 pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
375                 break;
376             case XSyncNegativeComparison:
377                 pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
378                 break;
379             default:
380                 client->errorValue = pTrigger->test_type;
381                 return BadValue;
382             }
383         }
384     }
385 
386     if (changes & (XSyncCAValueType | XSyncCAValue)) {
387         if (pTrigger->value_type == XSyncAbsolute)
388             pTrigger->test_value = pTrigger->wait_value;
389         else {                  /* relative */
390             Bool overflow;
391 
392             if (pCounter == NULL)
393                 return BadMatch;
394 
395             overflow = checked_int64_add(&pTrigger->test_value,
396                                          pCounter->value, pTrigger->wait_value);
397             if (overflow) {
398                 client->errorValue = pTrigger->wait_value >> 32;
399                 return BadValue;
400             }
401         }
402     }
403 
404     /*  we wait until we're sure there are no errors before registering
405      *  a new counter on a trigger
406      */
407     if (newSyncObject) {
408         if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
409             return rc;
410     }
411     else if (pCounter && IsSystemCounter(pCounter)) {
412         SyncComputeBracketValues(pCounter);
413     }
414 
415     return Success;
416 }
417 
418 /*  AlarmNotify events happen in response to actions taken on an Alarm or
419  *  the counter used by the alarm.  AlarmNotify may be sent to multiple
420  *  clients.  The alarm maintains a list of clients interested in events.
421  */
422 static void
SyncSendAlarmNotifyEvents(SyncAlarm * pAlarm)423 SyncSendAlarmNotifyEvents(SyncAlarm * pAlarm)
424 {
425     SyncAlarmClientList *pcl;
426     xSyncAlarmNotifyEvent ane;
427     SyncTrigger *pTrigger = &pAlarm->trigger;
428     SyncCounter *pCounter;
429 
430     if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
431         return;
432 
433     pCounter = (SyncCounter *) pTrigger->pSync;
434 
435     UpdateCurrentTime();
436 
437     ane = (xSyncAlarmNotifyEvent) {
438         .type = SyncEventBase + XSyncAlarmNotify,
439         .kind = XSyncAlarmNotify,
440         .alarm = pAlarm->alarm_id,
441         .alarm_value_hi = pTrigger->test_value >> 32,
442         .alarm_value_lo = pTrigger->test_value,
443         .time = currentTime.milliseconds,
444         .state = pAlarm->state
445     };
446 
447     if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type) {
448         ane.counter_value_hi = pCounter->value >> 32;
449         ane.counter_value_lo = pCounter->value;
450     }
451     else {
452         /* XXX what else can we do if there's no counter? */
453         ane.counter_value_hi = ane.counter_value_lo = 0;
454     }
455 
456     /* send to owner */
457     if (pAlarm->events)
458         WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
459 
460     /* send to other interested clients */
461     for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
462         WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
463 }
464 
465 /*  CounterNotify events only occur in response to an Await.  The events
466  *  go only to the Awaiting client.
467  */
468 static void
SyncSendCounterNotifyEvents(ClientPtr client,SyncAwait ** ppAwait,int num_events)469 SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait ** ppAwait,
470                             int num_events)
471 {
472     xSyncCounterNotifyEvent *pEvents, *pev;
473     int i;
474 
475     if (client->clientGone)
476         return;
477     pev = pEvents = calloc(num_events, sizeof(xSyncCounterNotifyEvent));
478     if (!pEvents)
479         return;
480     UpdateCurrentTime();
481     for (i = 0; i < num_events; i++, ppAwait++, pev++) {
482         SyncTrigger *pTrigger = &(*ppAwait)->trigger;
483 
484         pev->type = SyncEventBase + XSyncCounterNotify;
485         pev->kind = XSyncCounterNotify;
486         pev->counter = pTrigger->pSync->id;
487         pev->wait_value_lo = pTrigger->test_value;
488         pev->wait_value_hi = pTrigger->test_value >> 32;
489         if (SYNC_COUNTER == pTrigger->pSync->type) {
490             SyncCounter *pCounter = (SyncCounter *) pTrigger->pSync;
491 
492             pev->counter_value_lo = pCounter->value;
493             pev->counter_value_hi = pCounter->value >> 32;
494         }
495         else {
496             pev->counter_value_lo = 0;
497             pev->counter_value_hi = 0;
498         }
499 
500         pev->time = currentTime.milliseconds;
501         pev->count = num_events - i - 1;        /* events remaining */
502         pev->destroyed = pTrigger->pSync->beingDestroyed;
503     }
504     /* swapping will be taken care of by this */
505     WriteEventsToClient(client, num_events, (xEvent *) pEvents);
506     free(pEvents);
507 }
508 
509 /* This function is called when an alarm's counter is destroyed.
510  * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
511  */
512 static void
SyncAlarmCounterDestroyed(SyncTrigger * pTrigger)513 SyncAlarmCounterDestroyed(SyncTrigger * pTrigger)
514 {
515     SyncAlarm *pAlarm = (SyncAlarm *) pTrigger;
516 
517     pAlarm->state = XSyncAlarmInactive;
518     SyncSendAlarmNotifyEvents(pAlarm);
519     pTrigger->pSync = NULL;
520 }
521 
522 /*  This function is called when an alarm "goes off."
523  *  It is plugged into pTrigger->TriggerFired (for alarm triggers).
524  */
525 static void
SyncAlarmTriggerFired(SyncTrigger * pTrigger)526 SyncAlarmTriggerFired(SyncTrigger * pTrigger)
527 {
528     SyncAlarm *pAlarm = (SyncAlarm *) pTrigger;
529     SyncCounter *pCounter;
530     int64_t new_test_value;
531 
532     if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
533         return;
534 
535     pCounter = (SyncCounter *) pTrigger->pSync;
536 
537     /* no need to check alarm unless it's active */
538     if (pAlarm->state != XSyncAlarmActive)
539         return;
540 
541     /*  " if the counter value is None, or if the delta is 0 and
542      *    the test-type is PositiveComparison or NegativeComparison,
543      *    no change is made to value (test-value) and the alarm
544      *    state is changed to Inactive before the event is generated."
545      */
546     if (pCounter == NULL || (pAlarm->delta == 0
547                              && (pAlarm->trigger.test_type ==
548                                  XSyncPositiveComparison ||
549                                  pAlarm->trigger.test_type ==
550                                  XSyncNegativeComparison)))
551         pAlarm->state = XSyncAlarmInactive;
552 
553     new_test_value = pAlarm->trigger.test_value;
554 
555     if (pAlarm->state == XSyncAlarmActive) {
556         Bool overflow;
557         int64_t oldvalue;
558         SyncTrigger *paTrigger = &pAlarm->trigger;
559         SyncCounter *paCounter;
560 
561         if (!SyncCheckWarnIsCounter(paTrigger->pSync,
562                                     WARN_INVALID_COUNTER_ALARM))
563             return;
564 
565         paCounter = (SyncCounter *) pTrigger->pSync;
566 
567         /* "The alarm is updated by repeatedly adding delta to the
568          *  value of the trigger and re-initializing it until it
569          *  becomes FALSE."
570          */
571         oldvalue = paTrigger->test_value;
572 
573         /* XXX really should do something smarter here */
574 
575         do {
576             overflow = checked_int64_add(&paTrigger->test_value,
577                                          paTrigger->test_value, pAlarm->delta);
578         } while (!overflow &&
579                  (*paTrigger->CheckTrigger) (paTrigger, paCounter->value));
580 
581         new_test_value = paTrigger->test_value;
582         paTrigger->test_value = oldvalue;
583 
584         /* "If this update would cause value to fall outside the range
585          *  for an INT64...no change is made to value (test-value) and
586          *  the alarm state is changed to Inactive before the event is
587          *  generated."
588          */
589         if (overflow) {
590             new_test_value = oldvalue;
591             pAlarm->state = XSyncAlarmInactive;
592         }
593     }
594     /*  The AlarmNotify event has to have the "new state of the alarm"
595      *  which we can't be sure of until this point.  However, it has
596      *  to have the "old" trigger test value.  That's the reason for
597      *  all the newvalue/oldvalue shuffling above.  After we send the
598      *  events, give the trigger its new test value.
599      */
600     SyncSendAlarmNotifyEvents(pAlarm);
601     pTrigger->test_value = new_test_value;
602 }
603 
604 /*  This function is called when an Await unblocks, either as a result
605  *  of the trigger firing OR the counter being destroyed.
606  *  It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
607  *  (for Await triggers).
608  */
609 static void
SyncAwaitTriggerFired(SyncTrigger * pTrigger)610 SyncAwaitTriggerFired(SyncTrigger * pTrigger)
611 {
612     SyncAwait *pAwait = (SyncAwait *) pTrigger;
613     int numwaits;
614     SyncAwaitUnion *pAwaitUnion;
615     SyncAwait **ppAwait;
616     int num_events = 0;
617 
618     pAwaitUnion = (SyncAwaitUnion *) pAwait->pHeader;
619     numwaits = pAwaitUnion->header.num_waitconditions;
620     ppAwait = xallocarray(numwaits, sizeof(SyncAwait *));
621     if (!ppAwait)
622         goto bail;
623 
624     pAwait = &(pAwaitUnion + 1)->await;
625 
626     /* "When a client is unblocked, all the CounterNotify events for
627      *  the Await request are generated contiguously. If count is 0
628      *  there are no more events to follow for this request. If
629      *  count is n, there are at least n more events to follow."
630      *
631      *  Thus, it is best to find all the counters for which events
632      *  need to be sent first, so that an accurate count field can
633      *  be stored in the events.
634      */
635     for (; numwaits; numwaits--, pAwait++) {
636         int64_t diff;
637         Bool overflow, diffgreater, diffequal;
638 
639         /* "A CounterNotify event with the destroyed flag set to TRUE is
640          *  always generated if the counter for one of the triggers is
641          *  destroyed."
642          */
643         if (pAwait->trigger.pSync->beingDestroyed) {
644             ppAwait[num_events++] = pAwait;
645             continue;
646         }
647 
648         if (SYNC_COUNTER == pAwait->trigger.pSync->type) {
649             SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
650 
651             /* "The difference between the counter and the test value is
652              *  calculated by subtracting the test value from the value of
653              *  the counter."
654              */
655             overflow = checked_int64_subtract(&diff, pCounter->value,
656                                               pAwait->trigger.test_value);
657 
658             /* "If the difference lies outside the range for an INT64, an
659              *  event is not generated."
660              */
661             if (overflow)
662                 continue;
663             diffgreater = diff > pAwait->event_threshold;
664             diffequal = diff == pAwait->event_threshold;
665 
666             /* "If the test-type is PositiveTransition or
667              *  PositiveComparison, a CounterNotify event is generated if
668              *  the difference is at least event-threshold. If the test-type
669              *  is NegativeTransition or NegativeComparison, a CounterNotify
670              *  event is generated if the difference is at most
671              *  event-threshold."
672              */
673 
674             if (((pAwait->trigger.test_type == XSyncPositiveComparison ||
675                   pAwait->trigger.test_type == XSyncPositiveTransition)
676                  && (diffgreater || diffequal))
677                 ||
678                 ((pAwait->trigger.test_type == XSyncNegativeComparison ||
679                   pAwait->trigger.test_type == XSyncNegativeTransition)
680                  && (!diffgreater)      /* less or equal */
681                 )
682                 ) {
683                 ppAwait[num_events++] = pAwait;
684             }
685         }
686     }
687     if (num_events)
688         SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
689                                     num_events);
690     free(ppAwait);
691 
692  bail:
693     /* unblock the client */
694     AttendClient(pAwaitUnion->header.client);
695     /* delete the await */
696     FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
697 }
698 
699 static int64_t
SyncUpdateCounter(SyncCounter * pCounter,int64_t newval)700 SyncUpdateCounter(SyncCounter *pCounter, int64_t newval)
701 {
702     int64_t oldval = pCounter->value;
703     pCounter->value = newval;
704     return oldval;
705 }
706 
707 /*  This function should always be used to change a counter's value so that
708  *  any triggers depending on the counter will be checked.
709  */
710 void
SyncChangeCounter(SyncCounter * pCounter,int64_t newval)711 SyncChangeCounter(SyncCounter * pCounter, int64_t newval)
712 {
713     SyncTriggerList *ptl, *pnext;
714     int64_t oldval;
715 
716     oldval = SyncUpdateCounter(pCounter, newval);
717 
718     /* run through triggers to see if any become true */
719     for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
720         pnext = ptl->next;
721         if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval))
722             (*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
723     }
724 
725     if (IsSystemCounter(pCounter)) {
726         SyncComputeBracketValues(pCounter);
727     }
728 }
729 
730 /* loosely based on dix/events.c/EventSelectForWindow */
731 static Bool
SyncEventSelectForAlarm(SyncAlarm * pAlarm,ClientPtr client,Bool wantevents)732 SyncEventSelectForAlarm(SyncAlarm * pAlarm, ClientPtr client, Bool wantevents)
733 {
734     SyncAlarmClientList *pClients;
735 
736     if (client == pAlarm->client) {     /* alarm owner */
737         pAlarm->events = wantevents;
738         return Success;
739     }
740 
741     /* see if the client is already on the list (has events selected) */
742 
743     for (pClients = pAlarm->pEventClients; pClients; pClients = pClients->next) {
744         if (pClients->client == client) {
745             /* client's presence on the list indicates desire for
746              * events.  If the client doesn't want events, remove it
747              * from the list.  If the client does want events, do
748              * nothing, since it's already got them.
749              */
750             if (!wantevents) {
751                 FreeResource(pClients->delete_id, RT_NONE);
752             }
753             return Success;
754         }
755     }
756 
757     /*  if we get here, this client does not currently have
758      *  events selected on the alarm
759      */
760 
761     if (!wantevents)
762         /* client doesn't want events, and we just discovered that it
763          * doesn't have them, so there's nothing to do.
764          */
765         return Success;
766 
767     /* add new client to pAlarm->pEventClients */
768 
769     pClients = malloc(sizeof(SyncAlarmClientList));
770     if (!pClients)
771         return BadAlloc;
772 
773     /*  register it as a resource so it will be cleaned up
774      *  if the client dies
775      */
776 
777     pClients->delete_id = FakeClientID(client->index);
778 
779     /* link it into list after we know all the allocations succeed */
780     pClients->next = pAlarm->pEventClients;
781     pAlarm->pEventClients = pClients;
782     pClients->client = client;
783 
784     if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
785         return BadAlloc;
786 
787     return Success;
788 }
789 
790 /*
791  * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
792  */
793 static int
SyncChangeAlarmAttributes(ClientPtr client,SyncAlarm * pAlarm,Mask mask,CARD32 * values)794 SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask,
795                           CARD32 *values)
796 {
797     int status;
798     XSyncCounter counter;
799     Mask origmask = mask;
800 
801     counter = pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None;
802 
803     while (mask) {
804         int index2 = lowbit(mask);
805 
806         mask &= ~index2;
807         switch (index2) {
808         case XSyncCACounter:
809             mask &= ~XSyncCACounter;
810             /* sanity check in SyncInitTrigger */
811             counter = *values++;
812             break;
813 
814         case XSyncCAValueType:
815             mask &= ~XSyncCAValueType;
816             /* sanity check in SyncInitTrigger */
817             pAlarm->trigger.value_type = *values++;
818             break;
819 
820         case XSyncCAValue:
821             mask &= ~XSyncCAValue;
822             pAlarm->trigger.wait_value = ((int64_t)values[0] << 32) | values[1];
823             values += 2;
824             break;
825 
826         case XSyncCATestType:
827             mask &= ~XSyncCATestType;
828             /* sanity check in SyncInitTrigger */
829             pAlarm->trigger.test_type = *values++;
830             break;
831 
832         case XSyncCADelta:
833             mask &= ~XSyncCADelta;
834             pAlarm->delta = ((int64_t)values[0] << 32) | values[1];
835             values += 2;
836             break;
837 
838         case XSyncCAEvents:
839             mask &= ~XSyncCAEvents;
840             if ((*values != xTrue) && (*values != xFalse)) {
841                 client->errorValue = *values;
842                 return BadValue;
843             }
844             status = SyncEventSelectForAlarm(pAlarm, client,
845                                              (Bool) (*values++));
846             if (status != Success)
847                 return status;
848             break;
849 
850         default:
851             client->errorValue = mask;
852             return BadValue;
853         }
854     }
855 
856     /* "If the test-type is PositiveComparison or PositiveTransition
857      *  and delta is less than zero, or if the test-type is
858      *  NegativeComparison or NegativeTransition and delta is
859      *  greater than zero, a Match error is generated."
860      */
861     if (origmask & (XSyncCADelta | XSyncCATestType)) {
862         if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
863               (pAlarm->trigger.test_type == XSyncPositiveTransition))
864              && pAlarm->delta < 0)
865             ||
866             (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
867               (pAlarm->trigger.test_type == XSyncNegativeTransition))
868              && pAlarm->delta > 0)
869             ) {
870             return BadMatch;
871         }
872     }
873 
874     /* postpone this until now, when we're sure nothing else can go wrong */
875     if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter,
876                                   origmask & XSyncCAAllTrigger)) != Success)
877         return status;
878 
879     /* XXX spec does not really say to do this - needs clarification */
880     pAlarm->state = XSyncAlarmActive;
881     return Success;
882 }
883 
884 SyncObject *
SyncCreate(ClientPtr client,XID id,unsigned char type)885 SyncCreate(ClientPtr client, XID id, unsigned char type)
886 {
887     SyncObject *pSync;
888     RESTYPE resType;
889 
890     switch (type) {
891     case SYNC_COUNTER:
892         pSync = malloc(sizeof(SyncCounter));
893         resType = RTCounter;
894         break;
895     case SYNC_FENCE:
896         pSync = (SyncObject *) dixAllocateObjectWithPrivates(SyncFence,
897                                                              PRIVATE_SYNC_FENCE);
898         resType = RTFence;
899         break;
900     default:
901         return NULL;
902     }
903 
904     if (!pSync)
905         return NULL;
906 
907     pSync->initialized = FALSE;
908 
909     if (!AddResource(id, resType, (void *) pSync))
910         return NULL;
911 
912     pSync->client = client;
913     pSync->id = id;
914     pSync->pTriglist = NULL;
915     pSync->beingDestroyed = FALSE;
916     pSync->type = type;
917 
918     return pSync;
919 }
920 
921 int
SyncCreateFenceFromFD(ClientPtr client,DrawablePtr pDraw,XID id,int fd,BOOL initially_triggered)922 SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
923 {
924 #ifdef HAVE_XSHMFENCE
925     SyncFence  *pFence;
926     int         status;
927 
928     pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE);
929     if (!pFence)
930         return BadAlloc;
931 
932     status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered);
933     if (status != Success) {
934         FreeResource(pFence->sync.id, RT_NONE);
935         return status;
936     }
937 
938     return Success;
939 #else
940     return BadImplementation;
941 #endif
942 }
943 
944 int
SyncFDFromFence(ClientPtr client,DrawablePtr pDraw,SyncFence * pFence)945 SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
946 {
947 #ifdef HAVE_XSHMFENCE
948     return miSyncFDFromFence(pDraw, pFence);
949 #else
950     return BadImplementation;
951 #endif
952 }
953 
954 static SyncCounter *
SyncCreateCounter(ClientPtr client,XSyncCounter id,int64_t initialvalue)955 SyncCreateCounter(ClientPtr client, XSyncCounter id, int64_t initialvalue)
956 {
957     SyncCounter *pCounter;
958 
959     if (!(pCounter = (SyncCounter *) SyncCreate(client, id, SYNC_COUNTER)))
960         return NULL;
961 
962     pCounter->value = initialvalue;
963     pCounter->pSysCounterInfo = NULL;
964 
965     pCounter->sync.initialized = TRUE;
966 
967     return pCounter;
968 }
969 
970 static int FreeCounter(void *, XID);
971 
972 /*
973  * ***** System Counter utilities
974  */
975 
976 SyncCounter*
SyncCreateSystemCounter(const char * name,int64_t initial,int64_t resolution,SyncCounterType counterType,SyncSystemCounterQueryValue QueryValue,SyncSystemCounterBracketValues BracketValues)977 SyncCreateSystemCounter(const char *name,
978                         int64_t initial,
979                         int64_t resolution,
980                         SyncCounterType counterType,
981                         SyncSystemCounterQueryValue QueryValue,
982                         SyncSystemCounterBracketValues BracketValues
983     )
984 {
985     SyncCounter *pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
986 
987     if (pCounter) {
988         SysCounterInfo *psci;
989 
990         psci = malloc(sizeof(SysCounterInfo));
991         if (!psci) {
992             FreeResource(pCounter->sync.id, RT_NONE);
993             return pCounter;
994         }
995         pCounter->pSysCounterInfo = psci;
996         psci->pCounter = pCounter;
997         psci->name = strdup(name);
998         psci->resolution = resolution;
999         psci->counterType = counterType;
1000         psci->QueryValue = QueryValue;
1001         psci->BracketValues = BracketValues;
1002         psci->private = NULL;
1003         psci->bracket_greater = LLONG_MAX;
1004         psci->bracket_less = LLONG_MIN;
1005         xorg_list_add(&psci->entry, &SysCounterList);
1006     }
1007     return pCounter;
1008 }
1009 
1010 void
SyncDestroySystemCounter(void * pSysCounter)1011 SyncDestroySystemCounter(void *pSysCounter)
1012 {
1013     SyncCounter *pCounter = (SyncCounter *) pSysCounter;
1014 
1015     FreeResource(pCounter->sync.id, RT_NONE);
1016 }
1017 
1018 static void
SyncComputeBracketValues(SyncCounter * pCounter)1019 SyncComputeBracketValues(SyncCounter * pCounter)
1020 {
1021     SyncTriggerList *pCur;
1022     SyncTrigger *pTrigger;
1023     SysCounterInfo *psci;
1024     int64_t *pnewgtval = NULL;
1025     int64_t *pnewltval = NULL;
1026     SyncCounterType ct;
1027 
1028     if (!pCounter)
1029         return;
1030 
1031     psci = pCounter->pSysCounterInfo;
1032     ct = pCounter->pSysCounterInfo->counterType;
1033     if (ct == XSyncCounterNeverChanges)
1034         return;
1035 
1036     psci->bracket_greater = LLONG_MAX;
1037     psci->bracket_less = LLONG_MIN;
1038 
1039     for (pCur = pCounter->sync.pTriglist; pCur; pCur = pCur->next) {
1040         pTrigger = pCur->pTrigger;
1041 
1042         if (pTrigger->test_type == XSyncPositiveComparison &&
1043             ct != XSyncCounterNeverIncreases) {
1044             if (pCounter->value < pTrigger->test_value &&
1045                 pTrigger->test_value < psci->bracket_greater) {
1046                 psci->bracket_greater = pTrigger->test_value;
1047                 pnewgtval = &psci->bracket_greater;
1048             }
1049             else if (pCounter->value > pTrigger->test_value &&
1050                      pTrigger->test_value > psci->bracket_less) {
1051                     psci->bracket_less = pTrigger->test_value;
1052                     pnewltval = &psci->bracket_less;
1053             }
1054         }
1055         else if (pTrigger->test_type == XSyncNegativeComparison &&
1056                  ct != XSyncCounterNeverDecreases) {
1057             if (pCounter->value > pTrigger->test_value &&
1058                 pTrigger->test_value > psci->bracket_less) {
1059                 psci->bracket_less = pTrigger->test_value;
1060                 pnewltval = &psci->bracket_less;
1061             }
1062             else if (pCounter->value < pTrigger->test_value &&
1063                      pTrigger->test_value < psci->bracket_greater) {
1064                     psci->bracket_greater = pTrigger->test_value;
1065                     pnewgtval = &psci->bracket_greater;
1066             }
1067         }
1068         else if (pTrigger->test_type == XSyncNegativeTransition &&
1069                  ct != XSyncCounterNeverIncreases) {
1070             if (pCounter->value >= pTrigger->test_value &&
1071                 pTrigger->test_value > psci->bracket_less) {
1072                     /*
1073                      * If the value is exactly equal to our threshold, we want one
1074                      * more event in the negative direction to ensure we pick up
1075                      * when the value is less than this threshold.
1076                      */
1077                     psci->bracket_less = pTrigger->test_value;
1078                     pnewltval = &psci->bracket_less;
1079             }
1080             else if (pCounter->value < pTrigger->test_value &&
1081                      pTrigger->test_value < psci->bracket_greater) {
1082                     psci->bracket_greater = pTrigger->test_value;
1083                     pnewgtval = &psci->bracket_greater;
1084             }
1085         }
1086         else if (pTrigger->test_type == XSyncPositiveTransition &&
1087                  ct != XSyncCounterNeverDecreases) {
1088             if (pCounter->value <= pTrigger->test_value &&
1089                 pTrigger->test_value < psci->bracket_greater) {
1090                     /*
1091                      * If the value is exactly equal to our threshold, we
1092                      * want one more event in the positive direction to
1093                      * ensure we pick up when the value *exceeds* this
1094                      * threshold.
1095                      */
1096                     psci->bracket_greater = pTrigger->test_value;
1097                     pnewgtval = &psci->bracket_greater;
1098             }
1099             else if (pCounter->value > pTrigger->test_value &&
1100                      pTrigger->test_value > psci->bracket_less) {
1101                     psci->bracket_less = pTrigger->test_value;
1102                     pnewltval = &psci->bracket_less;
1103             }
1104         }
1105     }                           /* end for each trigger */
1106 
1107     (*psci->BracketValues) ((void *) pCounter, pnewltval, pnewgtval);
1108 
1109 }
1110 
1111 /*
1112  * *****  Resource delete functions
1113  */
1114 
1115 /* ARGSUSED */
1116 static int
FreeAlarm(void * addr,XID id)1117 FreeAlarm(void *addr, XID id)
1118 {
1119     SyncAlarm *pAlarm = (SyncAlarm *) addr;
1120 
1121     pAlarm->state = XSyncAlarmDestroyed;
1122 
1123     SyncSendAlarmNotifyEvents(pAlarm);
1124 
1125     /* delete event selections */
1126 
1127     while (pAlarm->pEventClients)
1128         FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
1129 
1130     SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
1131 
1132     free(pAlarm);
1133     return Success;
1134 }
1135 
1136 /*
1137  * ** Cleanup after the destruction of a Counter
1138  */
1139 /* ARGSUSED */
1140 static int
FreeCounter(void * env,XID id)1141 FreeCounter(void *env, XID id)
1142 {
1143     SyncCounter *pCounter = (SyncCounter *) env;
1144 
1145     pCounter->sync.beingDestroyed = TRUE;
1146 
1147     if (pCounter->sync.initialized) {
1148         SyncTriggerList *ptl, *pnext;
1149 
1150         /* tell all the counter's triggers that counter has been destroyed */
1151         for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
1152             (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
1153             pnext = ptl->next;
1154             free(ptl); /* destroy the trigger list as we go */
1155         }
1156         if (IsSystemCounter(pCounter)) {
1157             xorg_list_del(&pCounter->pSysCounterInfo->entry);
1158             free(pCounter->pSysCounterInfo->name);
1159             free(pCounter->pSysCounterInfo->private);
1160             free(pCounter->pSysCounterInfo);
1161         }
1162     }
1163 
1164     free(pCounter);
1165     return Success;
1166 }
1167 
1168 /*
1169  * ** Cleanup after Await
1170  */
1171 /* ARGSUSED */
1172 static int
FreeAwait(void * addr,XID id)1173 FreeAwait(void *addr, XID id)
1174 {
1175     SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
1176     SyncAwait *pAwait;
1177     int numwaits;
1178 
1179     pAwait = &(pAwaitUnion + 1)->await; /* first await on list */
1180 
1181     /* remove triggers from counters */
1182 
1183     for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
1184          numwaits--, pAwait++) {
1185         /* If the counter is being destroyed, FreeCounter will delete
1186          * the trigger list itself, so don't do it here.
1187          */
1188         SyncObject *pSync = pAwait->trigger.pSync;
1189 
1190         if (pSync && !pSync->beingDestroyed)
1191             SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
1192     }
1193     free(pAwaitUnion);
1194     return Success;
1195 }
1196 
1197 /* loosely based on dix/events.c/OtherClientGone */
1198 static int
FreeAlarmClient(void * value,XID id)1199 FreeAlarmClient(void *value, XID id)
1200 {
1201     SyncAlarm *pAlarm = (SyncAlarm *) value;
1202     SyncAlarmClientList *pCur, *pPrev;
1203 
1204     for (pPrev = NULL, pCur = pAlarm->pEventClients;
1205          pCur; pPrev = pCur, pCur = pCur->next) {
1206         if (pCur->delete_id == id) {
1207             if (pPrev)
1208                 pPrev->next = pCur->next;
1209             else
1210                 pAlarm->pEventClients = pCur->next;
1211             free(pCur);
1212             return Success;
1213         }
1214     }
1215     FatalError("alarm client not on event list");
1216  /*NOTREACHED*/}
1217 
1218 /*
1219  * *****  Proc functions
1220  */
1221 
1222 /*
1223  * ** Initialize the extension
1224  */
1225 static int
ProcSyncInitialize(ClientPtr client)1226 ProcSyncInitialize(ClientPtr client)
1227 {
1228     xSyncInitializeReply rep = {
1229         .type = X_Reply,
1230         .sequenceNumber = client->sequence,
1231         .length = 0,
1232         .majorVersion = SERVER_SYNC_MAJOR_VERSION,
1233         .minorVersion = SERVER_SYNC_MINOR_VERSION,
1234     };
1235 
1236     REQUEST_SIZE_MATCH(xSyncInitializeReq);
1237 
1238     if (client->swapped) {
1239         swaps(&rep.sequenceNumber);
1240     }
1241     WriteToClient(client, sizeof(rep), &rep);
1242     return Success;
1243 }
1244 
1245 /*
1246  * ** Get list of system counters available through the extension
1247  */
1248 static int
ProcSyncListSystemCounters(ClientPtr client)1249 ProcSyncListSystemCounters(ClientPtr client)
1250 {
1251     xSyncListSystemCountersReply rep = {
1252         .type = X_Reply,
1253         .sequenceNumber = client->sequence,
1254         .nCounters = 0,
1255     };
1256     SysCounterInfo *psci;
1257     int len = 0;
1258     xSyncSystemCounter *list = NULL, *walklist = NULL;
1259 
1260     REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
1261 
1262     xorg_list_for_each_entry(psci, &SysCounterList, entry) {
1263         /* pad to 4 byte boundary */
1264         len += pad_to_int32(sz_xSyncSystemCounter + strlen(psci->name));
1265         ++rep.nCounters;
1266     }
1267 
1268     if (len) {
1269         walklist = list = malloc(len);
1270         if (!list)
1271             return BadAlloc;
1272     }
1273 
1274     rep.length = bytes_to_int32(len);
1275 
1276     if (client->swapped) {
1277         swaps(&rep.sequenceNumber);
1278         swapl(&rep.length);
1279         swapl(&rep.nCounters);
1280     }
1281 
1282     xorg_list_for_each_entry(psci, &SysCounterList, entry) {
1283         int namelen;
1284         char *pname_in_reply;
1285 
1286         walklist->counter = psci->pCounter->sync.id;
1287         walklist->resolution_hi = psci->resolution >> 32;
1288         walklist->resolution_lo = psci->resolution;
1289         namelen = strlen(psci->name);
1290         walklist->name_length = namelen;
1291 
1292         if (client->swapped) {
1293             swapl(&walklist->counter);
1294             swapl(&walklist->resolution_hi);
1295             swapl(&walklist->resolution_lo);
1296             swaps(&walklist->name_length);
1297         }
1298 
1299         pname_in_reply = ((char *) walklist) + sz_xSyncSystemCounter;
1300         strncpy(pname_in_reply, psci->name, namelen);
1301         walklist = (xSyncSystemCounter *) (((char *) walklist) +
1302                                            pad_to_int32(sz_xSyncSystemCounter +
1303                                                         namelen));
1304     }
1305 
1306     WriteToClient(client, sizeof(rep), &rep);
1307     if (len) {
1308         WriteToClient(client, len, list);
1309         free(list);
1310     }
1311 
1312     return Success;
1313 }
1314 
1315 /*
1316  * ** Set client Priority
1317  */
1318 static int
ProcSyncSetPriority(ClientPtr client)1319 ProcSyncSetPriority(ClientPtr client)
1320 {
1321     REQUEST(xSyncSetPriorityReq);
1322     ClientPtr priorityclient;
1323     int rc;
1324 
1325     REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
1326 
1327     if (stuff->id == None)
1328         priorityclient = client;
1329     else {
1330         rc = dixLookupClient(&priorityclient, stuff->id, client,
1331                              DixSetAttrAccess);
1332         if (rc != Success)
1333             return rc;
1334     }
1335 
1336     if (priorityclient->priority != stuff->priority) {
1337         priorityclient->priority = stuff->priority;
1338 
1339         /*  The following will force the server back into WaitForSomething
1340          *  so that the change in this client's priority is immediately
1341          *  reflected.
1342          */
1343         isItTimeToYield = TRUE;
1344         dispatchException |= DE_PRIORITYCHANGE;
1345     }
1346     return Success;
1347 }
1348 
1349 /*
1350  * ** Get client Priority
1351  */
1352 static int
ProcSyncGetPriority(ClientPtr client)1353 ProcSyncGetPriority(ClientPtr client)
1354 {
1355     REQUEST(xSyncGetPriorityReq);
1356     xSyncGetPriorityReply rep;
1357     ClientPtr priorityclient;
1358     int rc;
1359 
1360     REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
1361 
1362     if (stuff->id == None)
1363         priorityclient = client;
1364     else {
1365         rc = dixLookupClient(&priorityclient, stuff->id, client,
1366                              DixGetAttrAccess);
1367         if (rc != Success)
1368             return rc;
1369     }
1370 
1371     rep = (xSyncGetPriorityReply) {
1372         .type = X_Reply,
1373         .sequenceNumber = client->sequence,
1374         .length = 0,
1375         .priority = priorityclient->priority
1376     };
1377 
1378     if (client->swapped) {
1379         swaps(&rep.sequenceNumber);
1380         swapl(&rep.priority);
1381     }
1382 
1383     WriteToClient(client, sizeof(xSyncGetPriorityReply), &rep);
1384 
1385     return Success;
1386 }
1387 
1388 /*
1389  * ** Create a new counter
1390  */
1391 static int
ProcSyncCreateCounter(ClientPtr client)1392 ProcSyncCreateCounter(ClientPtr client)
1393 {
1394     REQUEST(xSyncCreateCounterReq);
1395     int64_t initial;
1396 
1397     REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
1398 
1399     LEGAL_NEW_RESOURCE(stuff->cid, client);
1400 
1401     initial = ((int64_t)stuff->initial_value_hi << 32) | stuff->initial_value_lo;
1402 
1403     if (!SyncCreateCounter(client, stuff->cid, initial))
1404         return BadAlloc;
1405 
1406     return Success;
1407 }
1408 
1409 /*
1410  * ** Set Counter value
1411  */
1412 static int
ProcSyncSetCounter(ClientPtr client)1413 ProcSyncSetCounter(ClientPtr client)
1414 {
1415     REQUEST(xSyncSetCounterReq);
1416     SyncCounter *pCounter;
1417     int64_t newvalue;
1418     int rc;
1419 
1420     REQUEST_SIZE_MATCH(xSyncSetCounterReq);
1421 
1422     rc = dixLookupResourceByType((void **) &pCounter, stuff->cid, RTCounter,
1423                                  client, DixWriteAccess);
1424     if (rc != Success)
1425         return rc;
1426 
1427     if (IsSystemCounter(pCounter)) {
1428         client->errorValue = stuff->cid;
1429         return BadAccess;
1430     }
1431 
1432     newvalue = ((int64_t)stuff->value_hi << 32) | stuff->value_lo;
1433     SyncChangeCounter(pCounter, newvalue);
1434     return Success;
1435 }
1436 
1437 /*
1438  * ** Change Counter value
1439  */
1440 static int
ProcSyncChangeCounter(ClientPtr client)1441 ProcSyncChangeCounter(ClientPtr client)
1442 {
1443     REQUEST(xSyncChangeCounterReq);
1444     SyncCounter *pCounter;
1445     int64_t newvalue;
1446     Bool overflow;
1447     int rc;
1448 
1449     REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
1450 
1451     rc = dixLookupResourceByType((void **) &pCounter, stuff->cid, RTCounter,
1452                                  client, DixWriteAccess);
1453     if (rc != Success)
1454         return rc;
1455 
1456     if (IsSystemCounter(pCounter)) {
1457         client->errorValue = stuff->cid;
1458         return BadAccess;
1459     }
1460 
1461     newvalue = (int64_t)stuff->value_hi << 32 | stuff->value_lo;
1462     overflow = checked_int64_add(&newvalue, newvalue, pCounter->value);
1463     if (overflow) {
1464         /* XXX 64 bit value can't fit in 32 bits; do the best we can */
1465         client->errorValue = stuff->value_hi;
1466         return BadValue;
1467     }
1468     SyncChangeCounter(pCounter, newvalue);
1469     return Success;
1470 }
1471 
1472 /*
1473  * ** Destroy a counter
1474  */
1475 static int
ProcSyncDestroyCounter(ClientPtr client)1476 ProcSyncDestroyCounter(ClientPtr client)
1477 {
1478     REQUEST(xSyncDestroyCounterReq);
1479     SyncCounter *pCounter;
1480     int rc;
1481 
1482     REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
1483 
1484     rc = dixLookupResourceByType((void **) &pCounter, stuff->counter,
1485                                  RTCounter, client, DixDestroyAccess);
1486     if (rc != Success)
1487         return rc;
1488 
1489     if (IsSystemCounter(pCounter)) {
1490         client->errorValue = stuff->counter;
1491         return BadAccess;
1492     }
1493     FreeResource(pCounter->sync.id, RT_NONE);
1494     return Success;
1495 }
1496 
1497 static SyncAwaitUnion *
SyncAwaitPrologue(ClientPtr client,int items)1498 SyncAwaitPrologue(ClientPtr client, int items)
1499 {
1500     SyncAwaitUnion *pAwaitUnion;
1501 
1502     /*  all the memory for the entire await list is allocated
1503      *  here in one chunk
1504      */
1505     pAwaitUnion = xallocarray(items + 1, sizeof(SyncAwaitUnion));
1506     if (!pAwaitUnion)
1507         return NULL;
1508 
1509     /* first item is the header, remainder are real wait conditions */
1510 
1511     pAwaitUnion->header.delete_id = FakeClientID(client->index);
1512     pAwaitUnion->header.client = client;
1513     pAwaitUnion->header.num_waitconditions = 0;
1514 
1515     if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
1516         return NULL;
1517 
1518     return pAwaitUnion;
1519 }
1520 
1521 static void
SyncAwaitEpilogue(ClientPtr client,int items,SyncAwaitUnion * pAwaitUnion)1522 SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion * pAwaitUnion)
1523 {
1524     SyncAwait *pAwait;
1525     int i;
1526 
1527     IgnoreClient(client);
1528 
1529     /* see if any of the triggers are already true */
1530 
1531     pAwait = &(pAwaitUnion + 1)->await; /* skip over header */
1532     for (i = 0; i < items; i++, pAwait++) {
1533         int64_t value;
1534 
1535         /*  don't have to worry about NULL counters because the request
1536          *  errors before we get here out if they occur
1537          */
1538         switch (pAwait->trigger.pSync->type) {
1539         case SYNC_COUNTER:
1540             value = ((SyncCounter *) pAwait->trigger.pSync)->value;
1541             break;
1542         default:
1543             value = 0;
1544         }
1545 
1546         if ((*pAwait->trigger.CheckTrigger) (&pAwait->trigger, value)) {
1547             (*pAwait->trigger.TriggerFired) (&pAwait->trigger);
1548             break;              /* once is enough */
1549         }
1550     }
1551 }
1552 
1553 /*
1554  * ** Await
1555  */
1556 static int
ProcSyncAwait(ClientPtr client)1557 ProcSyncAwait(ClientPtr client)
1558 {
1559     REQUEST(xSyncAwaitReq);
1560     int len, items;
1561     int i;
1562     xSyncWaitCondition *pProtocolWaitConds;
1563     SyncAwaitUnion *pAwaitUnion;
1564     SyncAwait *pAwait;
1565     int status;
1566 
1567     REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
1568 
1569     len = client->req_len << 2;
1570     len -= sz_xSyncAwaitReq;
1571     items = len / sz_xSyncWaitCondition;
1572 
1573     if (items * sz_xSyncWaitCondition != len) {
1574         return BadLength;
1575     }
1576     if (items == 0) {
1577         client->errorValue = items;     /* XXX protocol change */
1578         return BadValue;
1579     }
1580 
1581     if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
1582         return BadAlloc;
1583 
1584     /* don't need to do any more memory allocation for this request! */
1585 
1586     pProtocolWaitConds = (xSyncWaitCondition *) &stuff[1];
1587 
1588     pAwait = &(pAwaitUnion + 1)->await; /* skip over header */
1589     for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) {
1590         if (pProtocolWaitConds->counter == None) {      /* XXX protocol change */
1591             /*  this should take care of removing any triggers created by
1592              *  this request that have already been registered on sync objects
1593              */
1594             FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1595             client->errorValue = pProtocolWaitConds->counter;
1596             return SyncErrorBase + XSyncBadCounter;
1597         }
1598 
1599         /* sanity checks are in SyncInitTrigger */
1600         pAwait->trigger.pSync = NULL;
1601         pAwait->trigger.value_type = pProtocolWaitConds->value_type;
1602         pAwait->trigger.wait_value =
1603             ((int64_t)pProtocolWaitConds->wait_value_hi << 32) |
1604             pProtocolWaitConds->wait_value_lo;
1605         pAwait->trigger.test_type = pProtocolWaitConds->test_type;
1606 
1607         status = SyncInitTrigger(client, &pAwait->trigger,
1608                                  pProtocolWaitConds->counter, RTCounter,
1609                                  XSyncCAAllTrigger);
1610         if (status != Success) {
1611             /*  this should take care of removing any triggers created by
1612              *  this request that have already been registered on sync objects
1613              */
1614             FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
1615             return status;
1616         }
1617         /* this is not a mistake -- same function works for both cases */
1618         pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
1619         pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
1620         pAwait->event_threshold =
1621             ((int64_t) pProtocolWaitConds->event_threshold_hi << 32) |
1622             pProtocolWaitConds->event_threshold_lo;
1623 
1624         pAwait->pHeader = &pAwaitUnion->header;
1625         pAwaitUnion->header.num_waitconditions++;
1626     }
1627 
1628     SyncAwaitEpilogue(client, items, pAwaitUnion);
1629 
1630     return Success;
1631 }
1632 
1633 /*
1634  * ** Query a counter
1635  */
1636 static int
ProcSyncQueryCounter(ClientPtr client)1637 ProcSyncQueryCounter(ClientPtr client)
1638 {
1639     REQUEST(xSyncQueryCounterReq);
1640     xSyncQueryCounterReply rep;
1641     SyncCounter *pCounter;
1642     int rc;
1643 
1644     REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
1645 
1646     rc = dixLookupResourceByType((void **) &pCounter, stuff->counter,
1647                                  RTCounter, client, DixReadAccess);
1648     if (rc != Success)
1649         return rc;
1650 
1651     /* if system counter, ask it what the current value is */
1652     if (IsSystemCounter(pCounter)) {
1653         (*pCounter->pSysCounterInfo->QueryValue) ((void *) pCounter,
1654                                                   &pCounter->value);
1655     }
1656 
1657     rep = (xSyncQueryCounterReply) {
1658         .type = X_Reply,
1659         .sequenceNumber = client->sequence,
1660         .length = 0,
1661         .value_hi = pCounter->value >> 32,
1662         .value_lo = pCounter->value
1663     };
1664 
1665     if (client->swapped) {
1666         swaps(&rep.sequenceNumber);
1667         swapl(&rep.length);
1668         swapl(&rep.value_hi);
1669         swapl(&rep.value_lo);
1670     }
1671     WriteToClient(client, sizeof(xSyncQueryCounterReply), &rep);
1672     return Success;
1673 }
1674 
1675 /*
1676  * ** Create Alarm
1677  */
1678 static int
ProcSyncCreateAlarm(ClientPtr client)1679 ProcSyncCreateAlarm(ClientPtr client)
1680 {
1681     REQUEST(xSyncCreateAlarmReq);
1682     SyncAlarm *pAlarm;
1683     int status;
1684     unsigned long len, vmask;
1685     SyncTrigger *pTrigger;
1686 
1687     REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
1688 
1689     LEGAL_NEW_RESOURCE(stuff->id, client);
1690 
1691     vmask = stuff->valueMask;
1692     len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
1693     /* the "extra" call to Ones accounts for the presence of 64 bit values */
1694     if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta))))
1695         return BadLength;
1696 
1697     if (!(pAlarm = malloc(sizeof(SyncAlarm)))) {
1698         return BadAlloc;
1699     }
1700 
1701     /* set up defaults */
1702 
1703     pTrigger = &pAlarm->trigger;
1704     pTrigger->pSync = NULL;
1705     pTrigger->value_type = XSyncAbsolute;
1706     pTrigger->wait_value = 0;
1707     pTrigger->test_type = XSyncPositiveComparison;
1708     pTrigger->TriggerFired = SyncAlarmTriggerFired;
1709     pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
1710     status = SyncInitTrigger(client, pTrigger, None, RTCounter,
1711                              XSyncCAAllTrigger);
1712     if (status != Success) {
1713         free(pAlarm);
1714         return status;
1715     }
1716 
1717     pAlarm->client = client;
1718     pAlarm->alarm_id = stuff->id;
1719     pAlarm->delta = 1;
1720     pAlarm->events = TRUE;
1721     pAlarm->state = XSyncAlarmInactive;
1722     pAlarm->pEventClients = NULL;
1723     status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1724                                        (CARD32 *) &stuff[1]);
1725     if (status != Success) {
1726         free(pAlarm);
1727         return status;
1728     }
1729 
1730     if (!AddResource(stuff->id, RTAlarm, pAlarm))
1731         return BadAlloc;
1732 
1733     /*  see if alarm already triggered.  NULL counter will not trigger
1734      *  in CreateAlarm and sets alarm state to Inactive.
1735      */
1736 
1737     if (!pTrigger->pSync) {
1738         pAlarm->state = XSyncAlarmInactive;     /* XXX protocol change */
1739     }
1740     else {
1741         SyncCounter *pCounter;
1742 
1743         if (!SyncCheckWarnIsCounter(pTrigger->pSync,
1744                                     WARN_INVALID_COUNTER_ALARM)) {
1745             FreeResource(stuff->id, RT_NONE);
1746             return BadAlloc;
1747         }
1748 
1749         pCounter = (SyncCounter *) pTrigger->pSync;
1750 
1751         if ((*pTrigger->CheckTrigger) (pTrigger, pCounter->value))
1752             (*pTrigger->TriggerFired) (pTrigger);
1753     }
1754 
1755     return Success;
1756 }
1757 
1758 /*
1759  * ** Change Alarm
1760  */
1761 static int
ProcSyncChangeAlarm(ClientPtr client)1762 ProcSyncChangeAlarm(ClientPtr client)
1763 {
1764     REQUEST(xSyncChangeAlarmReq);
1765     SyncAlarm *pAlarm;
1766     SyncCounter *pCounter = NULL;
1767     long vmask;
1768     int len, status;
1769 
1770     REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
1771 
1772     status = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm,
1773                                      client, DixWriteAccess);
1774     if (status != Success)
1775         return status;
1776 
1777     vmask = stuff->valueMask;
1778     len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
1779     /* the "extra" call to Ones accounts for the presence of 64 bit values */
1780     if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta))))
1781         return BadLength;
1782 
1783     if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
1784                                             (CARD32 *) &stuff[1])) != Success)
1785         return status;
1786 
1787     if (SyncCheckWarnIsCounter(pAlarm->trigger.pSync,
1788                                WARN_INVALID_COUNTER_ALARM))
1789         pCounter = (SyncCounter *) pAlarm->trigger.pSync;
1790 
1791     /*  see if alarm already triggered.  NULL counter WILL trigger
1792      *  in ChangeAlarm.
1793      */
1794 
1795     if (!pCounter ||
1796         (*pAlarm->trigger.CheckTrigger) (&pAlarm->trigger, pCounter->value)) {
1797         (*pAlarm->trigger.TriggerFired) (&pAlarm->trigger);
1798     }
1799     return Success;
1800 }
1801 
1802 static int
ProcSyncQueryAlarm(ClientPtr client)1803 ProcSyncQueryAlarm(ClientPtr client)
1804 {
1805     REQUEST(xSyncQueryAlarmReq);
1806     SyncAlarm *pAlarm;
1807     xSyncQueryAlarmReply rep;
1808     SyncTrigger *pTrigger;
1809     int rc;
1810 
1811     REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
1812 
1813     rc = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm,
1814                                  client, DixReadAccess);
1815     if (rc != Success)
1816         return rc;
1817 
1818     pTrigger = &pAlarm->trigger;
1819     rep = (xSyncQueryAlarmReply) {
1820         .type = X_Reply,
1821         .sequenceNumber = client->sequence,
1822         .length =
1823           bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)),
1824         .counter = (pTrigger->pSync) ? pTrigger->pSync->id : None,
1825 
1826 #if 0  /* XXX unclear what to do, depends on whether relative value-types
1827         * are "consumed" immediately and are considered absolute from then
1828         * on.
1829         */
1830         .value_type = pTrigger->value_type,
1831         .wait_value_hi = pTrigger->wait_value >> 32,
1832         .wait_value_lo = pTrigger->wait_value,
1833 #else
1834         .value_type = XSyncAbsolute,
1835         .wait_value_hi = pTrigger->test_value >> 32,
1836         .wait_value_lo = pTrigger->test_value,
1837 #endif
1838 
1839         .test_type = pTrigger->test_type,
1840         .delta_hi = pAlarm->delta >> 32,
1841         .delta_lo = pAlarm->delta,
1842         .events = pAlarm->events,
1843         .state = pAlarm->state
1844     };
1845 
1846     if (client->swapped) {
1847         swaps(&rep.sequenceNumber);
1848         swapl(&rep.length);
1849         swapl(&rep.counter);
1850         swapl(&rep.wait_value_hi);
1851         swapl(&rep.wait_value_lo);
1852         swapl(&rep.test_type);
1853         swapl(&rep.delta_hi);
1854         swapl(&rep.delta_lo);
1855     }
1856 
1857     WriteToClient(client, sizeof(xSyncQueryAlarmReply), &rep);
1858     return Success;
1859 }
1860 
1861 static int
ProcSyncDestroyAlarm(ClientPtr client)1862 ProcSyncDestroyAlarm(ClientPtr client)
1863 {
1864     SyncAlarm *pAlarm;
1865     int rc;
1866 
1867     REQUEST(xSyncDestroyAlarmReq);
1868 
1869     REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
1870 
1871     rc = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm,
1872                                  client, DixDestroyAccess);
1873     if (rc != Success)
1874         return rc;
1875 
1876     FreeResource(stuff->alarm, RT_NONE);
1877     return Success;
1878 }
1879 
1880 static int
ProcSyncCreateFence(ClientPtr client)1881 ProcSyncCreateFence(ClientPtr client)
1882 {
1883     REQUEST(xSyncCreateFenceReq);
1884     DrawablePtr pDraw;
1885     SyncFence *pFence;
1886     int rc;
1887 
1888     REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
1889 
1890     rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
1891     if (rc != Success)
1892         return rc;
1893 
1894     LEGAL_NEW_RESOURCE(stuff->fid, client);
1895 
1896     if (!(pFence = (SyncFence *) SyncCreate(client, stuff->fid, SYNC_FENCE)))
1897         return BadAlloc;
1898 
1899     miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
1900 
1901     return Success;
1902 }
1903 
1904 static int
FreeFence(void * obj,XID id)1905 FreeFence(void *obj, XID id)
1906 {
1907     SyncFence *pFence = (SyncFence *) obj;
1908 
1909     miSyncDestroyFence(pFence);
1910 
1911     return Success;
1912 }
1913 
1914 int
SyncVerifyFence(SyncFence ** ppSyncFence,XID fid,ClientPtr client,Mask mode)1915 SyncVerifyFence(SyncFence ** ppSyncFence, XID fid, ClientPtr client, Mask mode)
1916 {
1917     int rc = dixLookupResourceByType((void **) ppSyncFence, fid, RTFence,
1918                                      client, mode);
1919 
1920     if (rc != Success)
1921         client->errorValue = fid;
1922 
1923     return rc;
1924 }
1925 
1926 static int
ProcSyncTriggerFence(ClientPtr client)1927 ProcSyncTriggerFence(ClientPtr client)
1928 {
1929     REQUEST(xSyncTriggerFenceReq);
1930     SyncFence *pFence;
1931     int rc;
1932 
1933     REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
1934 
1935     rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence,
1936                                  client, DixWriteAccess);
1937     if (rc != Success)
1938         return rc;
1939 
1940     miSyncTriggerFence(pFence);
1941 
1942     return Success;
1943 }
1944 
1945 static int
ProcSyncResetFence(ClientPtr client)1946 ProcSyncResetFence(ClientPtr client)
1947 {
1948     REQUEST(xSyncResetFenceReq);
1949     SyncFence *pFence;
1950     int rc;
1951 
1952     REQUEST_SIZE_MATCH(xSyncResetFenceReq);
1953 
1954     rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence,
1955                                  client, DixWriteAccess);
1956     if (rc != Success)
1957         return rc;
1958 
1959     if (pFence->funcs.CheckTriggered(pFence) != TRUE)
1960         return BadMatch;
1961 
1962     pFence->funcs.Reset(pFence);
1963 
1964     return Success;
1965 }
1966 
1967 static int
ProcSyncDestroyFence(ClientPtr client)1968 ProcSyncDestroyFence(ClientPtr client)
1969 {
1970     REQUEST(xSyncDestroyFenceReq);
1971     SyncFence *pFence;
1972     int rc;
1973 
1974     REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
1975 
1976     rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence,
1977                                  client, DixDestroyAccess);
1978     if (rc != Success)
1979         return rc;
1980 
1981     FreeResource(stuff->fid, RT_NONE);
1982     return Success;
1983 }
1984 
1985 static int
ProcSyncQueryFence(ClientPtr client)1986 ProcSyncQueryFence(ClientPtr client)
1987 {
1988     REQUEST(xSyncQueryFenceReq);
1989     xSyncQueryFenceReply rep;
1990     SyncFence *pFence;
1991     int rc;
1992 
1993     REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
1994 
1995     rc = dixLookupResourceByType((void **) &pFence, stuff->fid,
1996                                  RTFence, client, DixReadAccess);
1997     if (rc != Success)
1998         return rc;
1999 
2000     rep = (xSyncQueryFenceReply) {
2001         .type = X_Reply,
2002         .sequenceNumber = client->sequence,
2003         .length = 0,
2004 
2005         .triggered = pFence->funcs.CheckTriggered(pFence)
2006     };
2007 
2008     if (client->swapped) {
2009         swaps(&rep.sequenceNumber);
2010         swapl(&rep.length);
2011     }
2012 
2013     WriteToClient(client, sizeof(xSyncQueryFenceReply), &rep);
2014     return Success;
2015 }
2016 
2017 static int
ProcSyncAwaitFence(ClientPtr client)2018 ProcSyncAwaitFence(ClientPtr client)
2019 {
2020     REQUEST(xSyncAwaitFenceReq);
2021     SyncAwaitUnion *pAwaitUnion;
2022     SyncAwait *pAwait;
2023 
2024     /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
2025      * CARD32 in protocol definitions */
2026     CARD32 *pProtocolFences;
2027     int status;
2028     int len;
2029     int items;
2030     int i;
2031 
2032     REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
2033 
2034     len = client->req_len << 2;
2035     len -= sz_xSyncAwaitFenceReq;
2036     items = len / sizeof(CARD32);
2037 
2038     if (items * sizeof(CARD32) != len) {
2039         return BadLength;
2040     }
2041     if (items == 0) {
2042         client->errorValue = items;
2043         return BadValue;
2044     }
2045 
2046     if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
2047         return BadAlloc;
2048 
2049     /* don't need to do any more memory allocation for this request! */
2050 
2051     pProtocolFences = (CARD32 *) &stuff[1];
2052 
2053     pAwait = &(pAwaitUnion + 1)->await; /* skip over header */
2054     for (i = 0; i < items; i++, pProtocolFences++, pAwait++) {
2055         if (*pProtocolFences == None) {
2056             /*  this should take care of removing any triggers created by
2057              *  this request that have already been registered on sync objects
2058              */
2059             FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
2060             client->errorValue = *pProtocolFences;
2061             return SyncErrorBase + XSyncBadFence;
2062         }
2063 
2064         pAwait->trigger.pSync = NULL;
2065         /* Provide acceptable values for these unused fields to
2066          * satisfy SyncInitTrigger's validation logic
2067          */
2068         pAwait->trigger.value_type = XSyncAbsolute;
2069         pAwait->trigger.wait_value = 0;
2070         pAwait->trigger.test_type = 0;
2071 
2072         status = SyncInitTrigger(client, &pAwait->trigger,
2073                                  *pProtocolFences, RTFence, XSyncCAAllTrigger);
2074         if (status != Success) {
2075             /*  this should take care of removing any triggers created by
2076              *  this request that have already been registered on sync objects
2077              */
2078             FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
2079             return status;
2080         }
2081         /* this is not a mistake -- same function works for both cases */
2082         pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
2083         pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
2084         /* event_threshold is unused for fence syncs */
2085         pAwait->event_threshold = 0;
2086         pAwait->pHeader = &pAwaitUnion->header;
2087         pAwaitUnion->header.num_waitconditions++;
2088     }
2089 
2090     SyncAwaitEpilogue(client, items, pAwaitUnion);
2091 
2092     return Success;
2093 }
2094 
2095 /*
2096  * ** Given an extension request, call the appropriate request procedure
2097  */
2098 static int
ProcSyncDispatch(ClientPtr client)2099 ProcSyncDispatch(ClientPtr client)
2100 {
2101     REQUEST(xReq);
2102 
2103     switch (stuff->data) {
2104     case X_SyncInitialize:
2105         return ProcSyncInitialize(client);
2106     case X_SyncListSystemCounters:
2107         return ProcSyncListSystemCounters(client);
2108     case X_SyncCreateCounter:
2109         return ProcSyncCreateCounter(client);
2110     case X_SyncSetCounter:
2111         return ProcSyncSetCounter(client);
2112     case X_SyncChangeCounter:
2113         return ProcSyncChangeCounter(client);
2114     case X_SyncQueryCounter:
2115         return ProcSyncQueryCounter(client);
2116     case X_SyncDestroyCounter:
2117         return ProcSyncDestroyCounter(client);
2118     case X_SyncAwait:
2119         return ProcSyncAwait(client);
2120     case X_SyncCreateAlarm:
2121         return ProcSyncCreateAlarm(client);
2122     case X_SyncChangeAlarm:
2123         return ProcSyncChangeAlarm(client);
2124     case X_SyncQueryAlarm:
2125         return ProcSyncQueryAlarm(client);
2126     case X_SyncDestroyAlarm:
2127         return ProcSyncDestroyAlarm(client);
2128     case X_SyncSetPriority:
2129         return ProcSyncSetPriority(client);
2130     case X_SyncGetPriority:
2131         return ProcSyncGetPriority(client);
2132     case X_SyncCreateFence:
2133         return ProcSyncCreateFence(client);
2134     case X_SyncTriggerFence:
2135         return ProcSyncTriggerFence(client);
2136     case X_SyncResetFence:
2137         return ProcSyncResetFence(client);
2138     case X_SyncDestroyFence:
2139         return ProcSyncDestroyFence(client);
2140     case X_SyncQueryFence:
2141         return ProcSyncQueryFence(client);
2142     case X_SyncAwaitFence:
2143         return ProcSyncAwaitFence(client);
2144     default:
2145         return BadRequest;
2146     }
2147 }
2148 
2149 /*
2150  * Boring Swapping stuff ...
2151  */
2152 
2153 static int _X_COLD
SProcSyncInitialize(ClientPtr client)2154 SProcSyncInitialize(ClientPtr client)
2155 {
2156     REQUEST(xSyncInitializeReq);
2157     swaps(&stuff->length);
2158     REQUEST_SIZE_MATCH(xSyncInitializeReq);
2159 
2160     return ProcSyncInitialize(client);
2161 }
2162 
2163 static int _X_COLD
SProcSyncListSystemCounters(ClientPtr client)2164 SProcSyncListSystemCounters(ClientPtr client)
2165 {
2166     REQUEST(xSyncListSystemCountersReq);
2167     swaps(&stuff->length);
2168     REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
2169 
2170     return ProcSyncListSystemCounters(client);
2171 }
2172 
2173 static int _X_COLD
SProcSyncCreateCounter(ClientPtr client)2174 SProcSyncCreateCounter(ClientPtr client)
2175 {
2176     REQUEST(xSyncCreateCounterReq);
2177     swaps(&stuff->length);
2178     REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
2179     swapl(&stuff->cid);
2180     swapl(&stuff->initial_value_lo);
2181     swapl(&stuff->initial_value_hi);
2182 
2183     return ProcSyncCreateCounter(client);
2184 }
2185 
2186 static int _X_COLD
SProcSyncSetCounter(ClientPtr client)2187 SProcSyncSetCounter(ClientPtr client)
2188 {
2189     REQUEST(xSyncSetCounterReq);
2190     swaps(&stuff->length);
2191     REQUEST_SIZE_MATCH(xSyncSetCounterReq);
2192     swapl(&stuff->cid);
2193     swapl(&stuff->value_lo);
2194     swapl(&stuff->value_hi);
2195 
2196     return ProcSyncSetCounter(client);
2197 }
2198 
2199 static int _X_COLD
SProcSyncChangeCounter(ClientPtr client)2200 SProcSyncChangeCounter(ClientPtr client)
2201 {
2202     REQUEST(xSyncChangeCounterReq);
2203     swaps(&stuff->length);
2204     REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
2205     swapl(&stuff->cid);
2206     swapl(&stuff->value_lo);
2207     swapl(&stuff->value_hi);
2208 
2209     return ProcSyncChangeCounter(client);
2210 }
2211 
2212 static int _X_COLD
SProcSyncQueryCounter(ClientPtr client)2213 SProcSyncQueryCounter(ClientPtr client)
2214 {
2215     REQUEST(xSyncQueryCounterReq);
2216     swaps(&stuff->length);
2217     REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
2218     swapl(&stuff->counter);
2219 
2220     return ProcSyncQueryCounter(client);
2221 }
2222 
2223 static int _X_COLD
SProcSyncDestroyCounter(ClientPtr client)2224 SProcSyncDestroyCounter(ClientPtr client)
2225 {
2226     REQUEST(xSyncDestroyCounterReq);
2227     swaps(&stuff->length);
2228     REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
2229     swapl(&stuff->counter);
2230 
2231     return ProcSyncDestroyCounter(client);
2232 }
2233 
2234 static int _X_COLD
SProcSyncAwait(ClientPtr client)2235 SProcSyncAwait(ClientPtr client)
2236 {
2237     REQUEST(xSyncAwaitReq);
2238     swaps(&stuff->length);
2239     REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
2240     SwapRestL(stuff);
2241 
2242     return ProcSyncAwait(client);
2243 }
2244 
2245 static int _X_COLD
SProcSyncCreateAlarm(ClientPtr client)2246 SProcSyncCreateAlarm(ClientPtr client)
2247 {
2248     REQUEST(xSyncCreateAlarmReq);
2249     swaps(&stuff->length);
2250     REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
2251     swapl(&stuff->id);
2252     swapl(&stuff->valueMask);
2253     SwapRestL(stuff);
2254 
2255     return ProcSyncCreateAlarm(client);
2256 }
2257 
2258 static int _X_COLD
SProcSyncChangeAlarm(ClientPtr client)2259 SProcSyncChangeAlarm(ClientPtr client)
2260 {
2261     REQUEST(xSyncChangeAlarmReq);
2262     swaps(&stuff->length);
2263     REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
2264     swapl(&stuff->alarm);
2265     swapl(&stuff->valueMask);
2266     SwapRestL(stuff);
2267     return ProcSyncChangeAlarm(client);
2268 }
2269 
2270 static int _X_COLD
SProcSyncQueryAlarm(ClientPtr client)2271 SProcSyncQueryAlarm(ClientPtr client)
2272 {
2273     REQUEST(xSyncQueryAlarmReq);
2274     swaps(&stuff->length);
2275     REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
2276     swapl(&stuff->alarm);
2277 
2278     return ProcSyncQueryAlarm(client);
2279 }
2280 
2281 static int _X_COLD
SProcSyncDestroyAlarm(ClientPtr client)2282 SProcSyncDestroyAlarm(ClientPtr client)
2283 {
2284     REQUEST(xSyncDestroyAlarmReq);
2285     swaps(&stuff->length);
2286     REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
2287     swapl(&stuff->alarm);
2288 
2289     return ProcSyncDestroyAlarm(client);
2290 }
2291 
2292 static int _X_COLD
SProcSyncSetPriority(ClientPtr client)2293 SProcSyncSetPriority(ClientPtr client)
2294 {
2295     REQUEST(xSyncSetPriorityReq);
2296     swaps(&stuff->length);
2297     REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
2298     swapl(&stuff->id);
2299     swapl(&stuff->priority);
2300 
2301     return ProcSyncSetPriority(client);
2302 }
2303 
2304 static int _X_COLD
SProcSyncGetPriority(ClientPtr client)2305 SProcSyncGetPriority(ClientPtr client)
2306 {
2307     REQUEST(xSyncGetPriorityReq);
2308     swaps(&stuff->length);
2309     REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
2310     swapl(&stuff->id);
2311 
2312     return ProcSyncGetPriority(client);
2313 }
2314 
2315 static int _X_COLD
SProcSyncCreateFence(ClientPtr client)2316 SProcSyncCreateFence(ClientPtr client)
2317 {
2318     REQUEST(xSyncCreateFenceReq);
2319     swaps(&stuff->length);
2320     REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
2321     swapl(&stuff->fid);
2322 
2323     return ProcSyncCreateFence(client);
2324 }
2325 
2326 static int _X_COLD
SProcSyncTriggerFence(ClientPtr client)2327 SProcSyncTriggerFence(ClientPtr client)
2328 {
2329     REQUEST(xSyncTriggerFenceReq);
2330     swaps(&stuff->length);
2331     REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
2332     swapl(&stuff->fid);
2333 
2334     return ProcSyncTriggerFence(client);
2335 }
2336 
2337 static int _X_COLD
SProcSyncResetFence(ClientPtr client)2338 SProcSyncResetFence(ClientPtr client)
2339 {
2340     REQUEST(xSyncResetFenceReq);
2341     swaps(&stuff->length);
2342     REQUEST_SIZE_MATCH(xSyncResetFenceReq);
2343     swapl(&stuff->fid);
2344 
2345     return ProcSyncResetFence(client);
2346 }
2347 
2348 static int _X_COLD
SProcSyncDestroyFence(ClientPtr client)2349 SProcSyncDestroyFence(ClientPtr client)
2350 {
2351     REQUEST(xSyncDestroyFenceReq);
2352     swaps(&stuff->length);
2353     REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
2354     swapl(&stuff->fid);
2355 
2356     return ProcSyncDestroyFence(client);
2357 }
2358 
2359 static int _X_COLD
SProcSyncQueryFence(ClientPtr client)2360 SProcSyncQueryFence(ClientPtr client)
2361 {
2362     REQUEST(xSyncQueryFenceReq);
2363     swaps(&stuff->length);
2364     REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
2365     swapl(&stuff->fid);
2366 
2367     return ProcSyncQueryFence(client);
2368 }
2369 
2370 static int _X_COLD
SProcSyncAwaitFence(ClientPtr client)2371 SProcSyncAwaitFence(ClientPtr client)
2372 {
2373     REQUEST(xSyncAwaitFenceReq);
2374     swaps(&stuff->length);
2375     REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
2376     SwapRestL(stuff);
2377 
2378     return ProcSyncAwaitFence(client);
2379 }
2380 
2381 static int _X_COLD
SProcSyncDispatch(ClientPtr client)2382 SProcSyncDispatch(ClientPtr client)
2383 {
2384     REQUEST(xReq);
2385 
2386     switch (stuff->data) {
2387     case X_SyncInitialize:
2388         return SProcSyncInitialize(client);
2389     case X_SyncListSystemCounters:
2390         return SProcSyncListSystemCounters(client);
2391     case X_SyncCreateCounter:
2392         return SProcSyncCreateCounter(client);
2393     case X_SyncSetCounter:
2394         return SProcSyncSetCounter(client);
2395     case X_SyncChangeCounter:
2396         return SProcSyncChangeCounter(client);
2397     case X_SyncQueryCounter:
2398         return SProcSyncQueryCounter(client);
2399     case X_SyncDestroyCounter:
2400         return SProcSyncDestroyCounter(client);
2401     case X_SyncAwait:
2402         return SProcSyncAwait(client);
2403     case X_SyncCreateAlarm:
2404         return SProcSyncCreateAlarm(client);
2405     case X_SyncChangeAlarm:
2406         return SProcSyncChangeAlarm(client);
2407     case X_SyncQueryAlarm:
2408         return SProcSyncQueryAlarm(client);
2409     case X_SyncDestroyAlarm:
2410         return SProcSyncDestroyAlarm(client);
2411     case X_SyncSetPriority:
2412         return SProcSyncSetPriority(client);
2413     case X_SyncGetPriority:
2414         return SProcSyncGetPriority(client);
2415     case X_SyncCreateFence:
2416         return SProcSyncCreateFence(client);
2417     case X_SyncTriggerFence:
2418         return SProcSyncTriggerFence(client);
2419     case X_SyncResetFence:
2420         return SProcSyncResetFence(client);
2421     case X_SyncDestroyFence:
2422         return SProcSyncDestroyFence(client);
2423     case X_SyncQueryFence:
2424         return SProcSyncQueryFence(client);
2425     case X_SyncAwaitFence:
2426         return SProcSyncAwaitFence(client);
2427     default:
2428         return BadRequest;
2429     }
2430 }
2431 
2432 /*
2433  * Event Swapping
2434  */
2435 
2436 static void _X_COLD
SCounterNotifyEvent(xSyncCounterNotifyEvent * from,xSyncCounterNotifyEvent * to)2437 SCounterNotifyEvent(xSyncCounterNotifyEvent * from,
2438                     xSyncCounterNotifyEvent * to)
2439 {
2440     to->type = from->type;
2441     to->kind = from->kind;
2442     cpswaps(from->sequenceNumber, to->sequenceNumber);
2443     cpswapl(from->counter, to->counter);
2444     cpswapl(from->wait_value_lo, to->wait_value_lo);
2445     cpswapl(from->wait_value_hi, to->wait_value_hi);
2446     cpswapl(from->counter_value_lo, to->counter_value_lo);
2447     cpswapl(from->counter_value_hi, to->counter_value_hi);
2448     cpswapl(from->time, to->time);
2449     cpswaps(from->count, to->count);
2450     to->destroyed = from->destroyed;
2451 }
2452 
2453 static void _X_COLD
SAlarmNotifyEvent(xSyncAlarmNotifyEvent * from,xSyncAlarmNotifyEvent * to)2454 SAlarmNotifyEvent(xSyncAlarmNotifyEvent * from, xSyncAlarmNotifyEvent * to)
2455 {
2456     to->type = from->type;
2457     to->kind = from->kind;
2458     cpswaps(from->sequenceNumber, to->sequenceNumber);
2459     cpswapl(from->alarm, to->alarm);
2460     cpswapl(from->counter_value_lo, to->counter_value_lo);
2461     cpswapl(from->counter_value_hi, to->counter_value_hi);
2462     cpswapl(from->alarm_value_lo, to->alarm_value_lo);
2463     cpswapl(from->alarm_value_hi, to->alarm_value_hi);
2464     cpswapl(from->time, to->time);
2465     to->state = from->state;
2466 }
2467 
2468 /*
2469  * ** Close everything down. ** This is fairly simple for now.
2470  */
2471 /* ARGSUSED */
2472 static void
SyncResetProc(ExtensionEntry * extEntry)2473 SyncResetProc(ExtensionEntry * extEntry)
2474 {
2475     RTCounter = 0;
2476 }
2477 
2478 /*
2479  * ** Initialise the extension.
2480  */
2481 void
SyncExtensionInit(void)2482 SyncExtensionInit(void)
2483 {
2484     ExtensionEntry *extEntry;
2485     int s;
2486 
2487     for (s = 0; s < screenInfo.numScreens; s++)
2488         miSyncSetup(screenInfo.screens[s]);
2489 
2490     RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
2491     xorg_list_init(&SysCounterList);
2492     RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
2493     RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
2494     RTFence = CreateNewResourceType(FreeFence, "SyncFence");
2495     if (RTAwait)
2496         RTAwait |= RC_NEVERRETAIN;
2497     RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
2498     if (RTAlarmClient)
2499         RTAlarmClient |= RC_NEVERRETAIN;
2500 
2501     if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
2502         RTAlarmClient == 0 ||
2503         (extEntry = AddExtension(SYNC_NAME,
2504                                  XSyncNumberEvents, XSyncNumberErrors,
2505                                  ProcSyncDispatch, SProcSyncDispatch,
2506                                  SyncResetProc, StandardMinorOpcode)) == NULL) {
2507         ErrorF("Sync Extension %d.%d failed to Initialise\n",
2508                SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2509         return;
2510     }
2511 
2512     SyncEventBase = extEntry->eventBase;
2513     SyncErrorBase = extEntry->errorBase;
2514     EventSwapVector[SyncEventBase + XSyncCounterNotify] =
2515         (EventSwapPtr) SCounterNotifyEvent;
2516     EventSwapVector[SyncEventBase + XSyncAlarmNotify] =
2517         (EventSwapPtr) SAlarmNotifyEvent;
2518 
2519     SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
2520     SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
2521     SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
2522 
2523     /*
2524      * Although SERVERTIME is implemented by the OS layer, we initialise it
2525      * here because doing it in OsInit() is too early. The resource database
2526      * is not initialised when OsInit() is called. This is just about OK
2527      * because there is always a servertime counter.
2528      */
2529     SyncInitServerTime();
2530     SyncInitIdleTime();
2531 
2532 #ifdef DEBUG
2533     fprintf(stderr, "Sync Extension %d.%d\n",
2534             SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
2535 #endif
2536 }
2537 
2538 /*
2539  * ***** SERVERTIME implementation - should go in its own file in OS directory?
2540  */
2541 
2542 static void *ServertimeCounter;
2543 static int64_t Now;
2544 static int64_t *pnext_time;
2545 
GetTime(void)2546 static void GetTime(void)
2547 {
2548     unsigned long millis = GetTimeInMillis();
2549     unsigned long maxis = Now >> 32;
2550 
2551     if (millis < (Now & 0xffffffff))
2552         maxis++;
2553 
2554     Now = ((int64_t)maxis << 32) | millis;
2555 }
2556 
2557 /*
2558 *** Server Block Handler
2559 *** code inspired by multibuffer extension (now deprecated)
2560  */
2561 /*ARGSUSED*/ static void
ServertimeBlockHandler(void * env,void * wt)2562 ServertimeBlockHandler(void *env, void *wt)
2563 {
2564     unsigned long timeout;
2565 
2566     if (pnext_time) {
2567         GetTime();
2568 
2569         if (Now >= *pnext_time) {
2570             timeout = 0;
2571         }
2572         else {
2573             timeout = *pnext_time - Now;
2574         }
2575         AdjustWaitForDelay(wt, timeout);        /* os/utils.c */
2576     }
2577 }
2578 
2579 /*
2580 *** Wakeup Handler
2581  */
2582 /*ARGSUSED*/ static void
ServertimeWakeupHandler(void * env,int rc)2583 ServertimeWakeupHandler(void *env, int rc)
2584 {
2585     if (pnext_time) {
2586         GetTime();
2587 
2588         if (Now >= *pnext_time) {
2589             SyncChangeCounter(ServertimeCounter, Now);
2590         }
2591     }
2592 }
2593 
2594 static void
ServertimeQueryValue(void * pCounter,int64_t * pValue_return)2595 ServertimeQueryValue(void *pCounter, int64_t *pValue_return)
2596 {
2597     GetTime();
2598     *pValue_return = Now;
2599 }
2600 
2601 static void
ServertimeBracketValues(void * pCounter,int64_t * pbracket_less,int64_t * pbracket_greater)2602 ServertimeBracketValues(void *pCounter, int64_t *pbracket_less,
2603                         int64_t *pbracket_greater)
2604 {
2605     if (!pnext_time && pbracket_greater) {
2606         RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
2607                                        ServertimeWakeupHandler, NULL);
2608     }
2609     else if (pnext_time && !pbracket_greater) {
2610         RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
2611                                      ServertimeWakeupHandler, NULL);
2612     }
2613     pnext_time = pbracket_greater;
2614 }
2615 
2616 static void
SyncInitServerTime(void)2617 SyncInitServerTime(void)
2618 {
2619     int64_t resolution = 4;
2620 
2621     Now = GetTimeInMillis();
2622     ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
2623                                                 XSyncCounterNeverDecreases,
2624                                                 ServertimeQueryValue,
2625                                                 ServertimeBracketValues);
2626     pnext_time = NULL;
2627 }
2628 
2629 /*
2630  * IDLETIME implementation
2631  */
2632 
2633 typedef struct {
2634     int64_t *value_less;
2635     int64_t *value_greater;
2636     int deviceid;
2637 } IdleCounterPriv;
2638 
2639 static void
IdleTimeQueryValue(void * pCounter,int64_t * pValue_return)2640 IdleTimeQueryValue(void *pCounter, int64_t *pValue_return)
2641 {
2642     int deviceid;
2643     CARD32 idle;
2644 
2645     if (pCounter) {
2646         SyncCounter *counter = pCounter;
2647         IdleCounterPriv *priv = SysCounterGetPrivate(counter);
2648         deviceid = priv->deviceid;
2649     }
2650     else
2651         deviceid = XIAllDevices;
2652     idle = GetTimeInMillis() - LastEventTime(deviceid).milliseconds;
2653     *pValue_return = idle;
2654 }
2655 
2656 static void
IdleTimeBlockHandler(void * pCounter,void * wt)2657 IdleTimeBlockHandler(void *pCounter, void *wt)
2658 {
2659     SyncCounter *counter = pCounter;
2660     IdleCounterPriv *priv = SysCounterGetPrivate(counter);
2661     int64_t *less = priv->value_less;
2662     int64_t *greater = priv->value_greater;
2663     int64_t idle, old_idle;
2664     SyncTriggerList *list = counter->sync.pTriglist;
2665     SyncTrigger *trig;
2666 
2667     if (!less && !greater)
2668         return;
2669 
2670     old_idle = counter->value;
2671     IdleTimeQueryValue(counter, &idle);
2672     counter->value = idle;      /* push, so CheckTrigger works */
2673 
2674     /**
2675      * There's an indefinite amount of time between ProcessInputEvents()
2676      * where the idle time is reset and the time we actually get here. idle
2677      * may be past the lower bracket if we dawdled with the events, so
2678      * check for whether we did reset and bomb out of select immediately.
2679      */
2680     if (less && idle > *less &&
2681         LastEventTimeWasReset(priv->deviceid)) {
2682         AdjustWaitForDelay(wt, 0);
2683     } else if (less && idle <= *less) {
2684         /*
2685          * We've been idle for less than the threshold value, and someone
2686          * wants to know about that, but now we need to know whether they
2687          * want level or edge trigger.  Check the trigger list against the
2688          * current idle time, and if any succeed, bomb out of select()
2689          * immediately so we can reschedule.
2690          */
2691 
2692         for (list = counter->sync.pTriglist; list; list = list->next) {
2693             trig = list->pTrigger;
2694             if (trig->CheckTrigger(trig, old_idle)) {
2695                 AdjustWaitForDelay(wt, 0);
2696                 break;
2697             }
2698         }
2699         /*
2700          * We've been called exactly on the idle time, but we have a
2701          * NegativeTransition trigger which requires a transition from an
2702          * idle time greater than this.  Schedule a wakeup for the next
2703          * millisecond so we won't miss a transition.
2704          */
2705         if (idle == *less)
2706             AdjustWaitForDelay(wt, 1);
2707     }
2708     else if (greater) {
2709         /*
2710          * There's a threshold in the positive direction.  If we've been
2711          * idle less than it, schedule a wakeup for sometime in the future.
2712          * If we've been idle more than it, and someone wants to know about
2713          * that level-triggered, schedule an immediate wakeup.
2714          */
2715 
2716         if (idle < *greater) {
2717             AdjustWaitForDelay(wt, *greater - idle);
2718         }
2719         else {
2720             for (list = counter->sync.pTriglist; list;
2721                  list = list->next) {
2722                 trig = list->pTrigger;
2723                 if (trig->CheckTrigger(trig, old_idle)) {
2724                     AdjustWaitForDelay(wt, 0);
2725                     break;
2726                 }
2727             }
2728         }
2729     }
2730 
2731     counter->value = old_idle;  /* pop */
2732 }
2733 
2734 static void
IdleTimeCheckBrackets(SyncCounter * counter,int64_t idle,int64_t * less,int64_t * greater)2735 IdleTimeCheckBrackets(SyncCounter *counter, int64_t idle,
2736                       int64_t *less, int64_t *greater)
2737 {
2738     if ((greater && idle >= *greater) ||
2739         (less && idle <= *less)) {
2740         SyncChangeCounter(counter, idle);
2741     }
2742     else
2743         SyncUpdateCounter(counter, idle);
2744 }
2745 
2746 static void
IdleTimeWakeupHandler(void * pCounter,int rc)2747 IdleTimeWakeupHandler(void *pCounter, int rc)
2748 {
2749     SyncCounter *counter = pCounter;
2750     IdleCounterPriv *priv = SysCounterGetPrivate(counter);
2751     int64_t *less = priv->value_less;
2752     int64_t *greater = priv->value_greater;
2753     int64_t idle;
2754 
2755     if (!less && !greater)
2756         return;
2757 
2758     IdleTimeQueryValue(pCounter, &idle);
2759 
2760     /*
2761       There is no guarantee for the WakeupHandler to be called within a specific
2762       timeframe. Idletime may go to 0, but by the time we get here, it may be
2763       non-zero and alarms for a pos. transition on 0 won't get triggered.
2764       https://bugs.freedesktop.org/show_bug.cgi?id=70476
2765       */
2766     if (LastEventTimeWasReset(priv->deviceid)) {
2767         LastEventTimeToggleResetFlag(priv->deviceid, FALSE);
2768         if (idle != 0) {
2769             IdleTimeCheckBrackets(counter, 0, less, greater);
2770             less = priv->value_less;
2771             greater = priv->value_greater;
2772         }
2773     }
2774 
2775     IdleTimeCheckBrackets(counter, idle, less, greater);
2776 }
2777 
2778 static void
IdleTimeBracketValues(void * pCounter,int64_t * pbracket_less,int64_t * pbracket_greater)2779 IdleTimeBracketValues(void *pCounter, int64_t *pbracket_less,
2780                       int64_t *pbracket_greater)
2781 {
2782     SyncCounter *counter = pCounter;
2783     IdleCounterPriv *priv = SysCounterGetPrivate(counter);
2784     int64_t *less = priv->value_less;
2785     int64_t *greater = priv->value_greater;
2786     Bool registered = (less || greater);
2787 
2788     if (registered && !pbracket_less && !pbracket_greater) {
2789         RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
2790                                      IdleTimeWakeupHandler, pCounter);
2791     }
2792     else if (!registered && (pbracket_less || pbracket_greater)) {
2793         /* Reset flag must be zero so we don't force a idle timer reset on
2794            the first wakeup */
2795         LastEventTimeToggleResetAll(FALSE);
2796         RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
2797                                        IdleTimeWakeupHandler, pCounter);
2798     }
2799 
2800     priv->value_greater = pbracket_greater;
2801     priv->value_less = pbracket_less;
2802 }
2803 
2804 static SyncCounter*
init_system_idle_counter(const char * name,int deviceid)2805 init_system_idle_counter(const char *name, int deviceid)
2806 {
2807     int64_t resolution = 4;
2808     int64_t idle;
2809     SyncCounter *idle_time_counter;
2810 
2811     IdleTimeQueryValue(NULL, &idle);
2812 
2813     idle_time_counter = SyncCreateSystemCounter(name, idle, resolution,
2814                                                 XSyncCounterUnrestricted,
2815                                                 IdleTimeQueryValue,
2816                                                 IdleTimeBracketValues);
2817 
2818     if (idle_time_counter != NULL) {
2819         IdleCounterPriv *priv = malloc(sizeof(IdleCounterPriv));
2820 
2821         priv->value_less = priv->value_greater = NULL;
2822         priv->deviceid = deviceid;
2823 
2824         idle_time_counter->pSysCounterInfo->private = priv;
2825     }
2826 
2827     return idle_time_counter;
2828 }
2829 
2830 static void
SyncInitIdleTime(void)2831 SyncInitIdleTime(void)
2832 {
2833     init_system_idle_counter("IDLETIME", XIAllDevices);
2834 }
2835 
2836 SyncCounter*
SyncInitDeviceIdleTime(DeviceIntPtr dev)2837 SyncInitDeviceIdleTime(DeviceIntPtr dev)
2838 {
2839     char timer_name[64];
2840     sprintf(timer_name, "DEVICEIDLETIME %d", dev->id);
2841 
2842     return init_system_idle_counter(timer_name, dev->id);
2843 }
2844 
SyncRemoveDeviceIdleTime(SyncCounter * counter)2845 void SyncRemoveDeviceIdleTime(SyncCounter *counter)
2846 {
2847     /* FreeAllResources() frees all system counters before the devices are
2848        shut down, check if there are any left before freeing the device's
2849        counter */
2850     if (counter && !xorg_list_is_empty(&SysCounterList))
2851         xorg_list_del(&counter->pSysCounterInfo->entry);
2852 }
2853