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