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