xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

sync.c (83286B)


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