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