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