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