3 Copyright 1991, 1993, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
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.
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
27 Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
28 and Olivetti Research Limited, Cambridge, England.
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.
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.
52 #ifdef HAVE_DIX_CONFIG_H
53 #include <dix-config.h>
59 #include <X11/Xproto.h>
61 #include "scrnintstr.h"
63 #include "extnsionst.h"
64 #include "dixstruct.h"
65 #include "pixmapstr.h"
68 #include <X11/extensions/syncproto.h>
71 #include "protocol-versions.h"
82 * Local Global Variables
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;
94 #define MAX_INVALID_COUNTER_WARNINGS 5
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";
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";
104 #define IsSystemCounter(pCounter) \
105 (pCounter && (pCounter->sync.client == NULL))
107 /* these are all the alarm attributes that pertain to the alarm's trigger */
108 #define XSyncCAAllTrigger \
109 (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
111 static void SyncComputeBracketValues(SyncCounter
*);
113 static void SyncInitServerTime(void);
115 static void SyncInitIdleTime(void);
118 SysCounterGetPrivate(SyncCounter
*counter
)
120 BUG_WARN(!IsSystemCounter(counter
));
122 return counter
->pSysCounterInfo
? counter
->pSysCounterInfo
->private : NULL
;
126 SyncCheckWarnIsCounter(const SyncObject
* pSync
, const char *warning
)
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
);
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.
145 SyncDeleteTriggerFromSyncObject(SyncTrigger
* pTrigger
)
147 SyncTriggerList
*pCur
;
148 SyncTriggerList
*pPrev
;
149 SyncCounter
*pCounter
;
151 /* pSync needs to be stored in pTrigger before calling here. */
153 if (!pTrigger
->pSync
)
157 pCur
= pTrigger
->pSync
->pTriglist
;
160 if (pCur
->pTrigger
== pTrigger
) {
162 pPrev
->next
= pCur
->next
;
164 pTrigger
->pSync
->pTriglist
= pCur
->next
;
174 if (SYNC_COUNTER
== pTrigger
->pSync
->type
) {
175 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
177 if (IsSystemCounter(pCounter
))
178 SyncComputeBracketValues(pCounter
);
180 else if (SYNC_FENCE
== pTrigger
->pSync
->type
) {
181 SyncFence
*pFence
= (SyncFence
*) pTrigger
->pSync
;
183 pFence
->funcs
.DeleteTrigger(pTrigger
);
188 SyncAddTriggerToSyncObject(SyncTrigger
* pTrigger
)
190 SyncTriggerList
*pCur
;
191 SyncCounter
*pCounter
;
193 if (!pTrigger
->pSync
)
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
)
202 if (!(pCur
= malloc(sizeof(SyncTriggerList
))))
205 pCur
->pTrigger
= pTrigger
;
206 pCur
->next
= pTrigger
->pSync
->pTriglist
;
207 pTrigger
->pSync
->pTriglist
= pCur
;
209 if (SYNC_COUNTER
== pTrigger
->pSync
->type
) {
210 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
212 if (IsSystemCounter(pCounter
))
213 SyncComputeBracketValues(pCounter
);
215 else if (SYNC_FENCE
== pTrigger
->pSync
->type
) {
216 SyncFence
*pFence
= (SyncFence
*) pTrigger
->pSync
;
218 pFence
->funcs
.AddTrigger(pTrigger
);
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.
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.
240 SyncCheckTriggerPositiveComparison(SyncTrigger
* pTrigger
, CARD64 oldval
)
242 SyncCounter
*pCounter
;
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
))
249 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
251 return (pCounter
== NULL
||
252 XSyncValueGreaterOrEqual(pCounter
->value
, pTrigger
->test_value
));
256 SyncCheckTriggerNegativeComparison(SyncTrigger
* pTrigger
, CARD64 oldval
)
258 SyncCounter
*pCounter
;
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
))
265 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
267 return (pCounter
== NULL
||
268 XSyncValueLessOrEqual(pCounter
->value
, pTrigger
->test_value
));
272 SyncCheckTriggerPositiveTransition(SyncTrigger
* pTrigger
, CARD64 oldval
)
274 SyncCounter
*pCounter
;
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
))
281 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
283 return (pCounter
== NULL
||
284 (XSyncValueLessThan(oldval
, pTrigger
->test_value
) &&
285 XSyncValueGreaterOrEqual(pCounter
->value
, pTrigger
->test_value
)));
289 SyncCheckTriggerNegativeTransition(SyncTrigger
* pTrigger
, CARD64 oldval
)
291 SyncCounter
*pCounter
;
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
))
298 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
300 return (pCounter
== NULL
||
301 (XSyncValueGreaterThan(oldval
, pTrigger
->test_value
) &&
302 XSyncValueLessOrEqual(pCounter
->value
, pTrigger
->test_value
)));
306 SyncCheckTriggerFence(SyncTrigger
* pTrigger
, CARD64 unused
)
308 SyncFence
*pFence
= (SyncFence
*) pTrigger
->pSync
;
312 return (pFence
== NULL
|| pFence
->funcs
.CheckTriggered(pFence
));
316 SyncInitTrigger(ClientPtr client
, SyncTrigger
* pTrigger
, XID syncObject
,
317 RESTYPE resType
, Mask changes
)
319 SyncObject
*pSync
= pTrigger
->pSync
;
320 SyncCounter
*pCounter
= NULL
;
322 Bool newSyncObject
= FALSE
;
324 if (changes
& XSyncCACounter
) {
325 if (syncObject
== None
)
327 else if (Success
!= (rc
= dixLookupResourceByType((pointer
*) &pSync
,
331 client
->errorValue
= syncObject
;
334 if (pSync
!= pTrigger
->pSync
) { /* new counter for trigger */
335 SyncDeleteTriggerFromSyncObject(pTrigger
);
336 pTrigger
->pSync
= pSync
;
337 newSyncObject
= TRUE
;
341 /* if system counter, ask it what the current value is */
343 if (pSync
&& SYNC_COUNTER
== pSync
->type
) {
344 pCounter
= (SyncCounter
*) pSync
;
346 if (IsSystemCounter(pCounter
)) {
347 (*pCounter
->pSysCounterInfo
->QueryValue
) ((pointer
) pCounter
,
352 if (changes
& XSyncCAValueType
) {
353 if (pTrigger
->value_type
!= XSyncRelative
&&
354 pTrigger
->value_type
!= XSyncAbsolute
) {
355 client
->errorValue
= pTrigger
->value_type
;
360 if (changes
& XSyncCATestType
) {
362 if (pSync
&& SYNC_FENCE
== pSync
->type
) {
363 pTrigger
->CheckTrigger
= SyncCheckTriggerFence
;
366 /* select appropriate CheckTrigger function */
368 switch (pTrigger
->test_type
) {
369 case XSyncPositiveTransition
:
370 pTrigger
->CheckTrigger
= SyncCheckTriggerPositiveTransition
;
372 case XSyncNegativeTransition
:
373 pTrigger
->CheckTrigger
= SyncCheckTriggerNegativeTransition
;
375 case XSyncPositiveComparison
:
376 pTrigger
->CheckTrigger
= SyncCheckTriggerPositiveComparison
;
378 case XSyncNegativeComparison
:
379 pTrigger
->CheckTrigger
= SyncCheckTriggerNegativeComparison
;
382 client
->errorValue
= pTrigger
->test_type
;
388 if (changes
& (XSyncCAValueType
| XSyncCAValue
)) {
389 if (pTrigger
->value_type
== XSyncAbsolute
)
390 pTrigger
->test_value
= pTrigger
->wait_value
;
391 else { /* relative */
395 if (pCounter
== NULL
)
398 XSyncValueAdd(&pTrigger
->test_value
, pCounter
->value
,
399 pTrigger
->wait_value
, &overflow
);
401 client
->errorValue
= XSyncValueHigh32(pTrigger
->wait_value
);
407 /* we wait until we're sure there are no errors before registering
408 * a new counter on a trigger
411 if ((rc
= SyncAddTriggerToSyncObject(pTrigger
)) != Success
)
414 else if (pCounter
&& IsSystemCounter(pCounter
)) {
415 SyncComputeBracketValues(pCounter
);
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.
426 SyncSendAlarmNotifyEvents(SyncAlarm
* pAlarm
)
428 SyncAlarmClientList
*pcl
;
429 xSyncAlarmNotifyEvent ane
;
430 SyncTrigger
*pTrigger
= &pAlarm
->trigger
;
431 SyncCounter
*pCounter
;
433 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_ALARM
))
436 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
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
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
);
455 /* XXX what else can we do if there's no counter? */
456 ane
.counter_value_hi
= ane
.counter_value_lo
= 0;
461 WriteEventsToClient(pAlarm
->client
, 1, (xEvent
*) &ane
);
463 /* send to other interested clients */
464 for (pcl
= pAlarm
->pEventClients
; pcl
; pcl
= pcl
->next
)
465 WriteEventsToClient(pcl
->client
, 1, (xEvent
*) &ane
);
468 /* CounterNotify events only occur in response to an Await. The events
469 * go only to the Awaiting client.
472 SyncSendCounterNotifyEvents(ClientPtr client
, SyncAwait
** ppAwait
,
475 xSyncCounterNotifyEvent
*pEvents
, *pev
;
478 if (client
->clientGone
)
480 pev
= pEvents
= calloc(num_events
, sizeof(xSyncCounterNotifyEvent
));
484 for (i
= 0; i
< num_events
; i
++, ppAwait
++, pev
++) {
485 SyncTrigger
*pTrigger
= &(*ppAwait
)->trigger
;
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
;
495 pev
->counter_value_lo
= XSyncValueLow32(pCounter
->value
);
496 pev
->counter_value_hi
= XSyncValueHigh32(pCounter
->value
);
499 pev
->counter_value_lo
= 0;
500 pev
->counter_value_hi
= 0;
503 pev
->time
= currentTime
.milliseconds
;
504 pev
->count
= num_events
- i
- 1; /* events remaining */
505 pev
->destroyed
= pTrigger
->pSync
->beingDestroyed
;
507 /* swapping will be taken care of by this */
508 WriteEventsToClient(client
, num_events
, (xEvent
*) pEvents
);
512 /* This function is called when an alarm's counter is destroyed.
513 * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
516 SyncAlarmCounterDestroyed(SyncTrigger
* pTrigger
)
518 SyncAlarm
*pAlarm
= (SyncAlarm
*) pTrigger
;
520 pAlarm
->state
= XSyncAlarmInactive
;
521 SyncSendAlarmNotifyEvents(pAlarm
);
522 pTrigger
->pSync
= NULL
;
525 /* This function is called when an alarm "goes off."
526 * It is plugged into pTrigger->TriggerFired (for alarm triggers).
529 SyncAlarmTriggerFired(SyncTrigger
* pTrigger
)
531 SyncAlarm
*pAlarm
= (SyncAlarm
*) pTrigger
;
532 SyncCounter
*pCounter
;
533 CARD64 new_test_value
;
535 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_ALARM
))
538 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
540 /* no need to check alarm unless it's active */
541 if (pAlarm
->state
!= XSyncAlarmActive
)
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."
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
;
556 new_test_value
= pAlarm
->trigger
.test_value
;
558 if (pAlarm
->state
== XSyncAlarmActive
) {
561 SyncTrigger
*paTrigger
= &pAlarm
->trigger
;
562 SyncCounter
*paCounter
;
564 if (!SyncCheckWarnIsCounter(paTrigger
->pSync
,
565 WARN_INVALID_COUNTER_ALARM
))
568 paCounter
= (SyncCounter
*) pTrigger
->pSync
;
570 /* "The alarm is updated by repeatedly adding delta to the
571 * value of the trigger and re-initializing it until it
574 oldvalue
= paTrigger
->test_value
;
576 /* XXX really should do something smarter here */
579 XSyncValueAdd(&paTrigger
->test_value
, paTrigger
->test_value
,
580 pAlarm
->delta
, &overflow
);
581 } while (!overflow
&&
582 (*paTrigger
->CheckTrigger
) (paTrigger
, paCounter
->value
));
584 new_test_value
= paTrigger
->test_value
;
585 paTrigger
->test_value
= oldvalue
;
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
593 new_test_value
= oldvalue
;
594 pAlarm
->state
= XSyncAlarmInactive
;
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.
603 SyncSendAlarmNotifyEvents(pAlarm
);
604 pTrigger
->test_value
= new_test_value
;
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).
613 SyncAwaitTriggerFired(SyncTrigger
* pTrigger
)
615 SyncAwait
*pAwait
= (SyncAwait
*) pTrigger
;
617 SyncAwaitUnion
*pAwaitUnion
;
621 pAwaitUnion
= (SyncAwaitUnion
*) pAwait
->pHeader
;
622 numwaits
= pAwaitUnion
->header
.num_waitconditions
;
623 ppAwait
= malloc(numwaits
* sizeof(SyncAwait
*));
627 pAwait
= &(pAwaitUnion
+ 1)->await
;
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."
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.
638 for (; numwaits
; numwaits
--, pAwait
++) {
640 Bool overflow
, diffgreater
, diffequal
;
642 /* "A CounterNotify event with the destroyed flag set to TRUE is
643 * always generated if the counter for one of the triggers is
646 if (pAwait
->trigger
.pSync
->beingDestroyed
) {
647 ppAwait
[num_events
++] = pAwait
;
651 if (SYNC_COUNTER
== pAwait
->trigger
.pSync
->type
) {
652 SyncCounter
*pCounter
= (SyncCounter
*) pAwait
->trigger
.pSync
;
654 /* "The difference between the counter and the test value is
655 * calculated by subtracting the test value from the value of
658 XSyncValueSubtract(&diff
, pCounter
->value
,
659 pAwait
->trigger
.test_value
, &overflow
);
661 /* "If the difference lies outside the range for an INT64, an
662 * event is not generated."
666 diffgreater
= XSyncValueGreaterThan(diff
, pAwait
->event_threshold
);
667 diffequal
= XSyncValueEqual(diff
, pAwait
->event_threshold
);
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
677 if (((pAwait
->trigger
.test_type
== XSyncPositiveComparison
||
678 pAwait
->trigger
.test_type
== XSyncPositiveTransition
)
679 && (diffgreater
|| diffequal
))
681 ((pAwait
->trigger
.test_type
== XSyncNegativeComparison
||
682 pAwait
->trigger
.test_type
== XSyncNegativeTransition
)
683 && (!diffgreater
) /* less or equal */
686 ppAwait
[num_events
++] = pAwait
;
691 SyncSendCounterNotifyEvents(pAwaitUnion
->header
.client
, ppAwait
,
696 /* unblock the client */
697 AttendClient(pAwaitUnion
->header
.client
);
698 /* delete the await */
699 FreeResource(pAwaitUnion
->header
.delete_id
, RT_NONE
);
703 SyncUpdateCounter(SyncCounter
*pCounter
, CARD64 newval
)
705 CARD64 oldval
= pCounter
->value
;
706 pCounter
->value
= newval
;
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.
714 SyncChangeCounter(SyncCounter
* pCounter
, CARD64 newval
)
716 SyncTriggerList
*ptl
, *pnext
;
719 oldval
= SyncUpdateCounter(pCounter
, newval
);
721 /* run through triggers to see if any become true */
722 for (ptl
= pCounter
->sync
.pTriglist
; ptl
; ptl
= pnext
) {
724 if ((*ptl
->pTrigger
->CheckTrigger
) (ptl
->pTrigger
, oldval
))
725 (*ptl
->pTrigger
->TriggerFired
) (ptl
->pTrigger
);
728 if (IsSystemCounter(pCounter
)) {
729 SyncComputeBracketValues(pCounter
);
733 /* loosely based on dix/events.c/EventSelectForWindow */
735 SyncEventSelectForAlarm(SyncAlarm
* pAlarm
, ClientPtr client
, Bool wantevents
)
737 SyncAlarmClientList
*pClients
;
739 if (client
== pAlarm
->client
) { /* alarm owner */
740 pAlarm
->events
= wantevents
;
744 /* see if the client is already on the list (has events selected) */
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.
754 FreeResource(pClients
->delete_id
, RT_NONE
);
760 /* if we get here, this client does not currently have
761 * events selected on the alarm
765 /* client doesn't want events, and we just discovered that it
766 * doesn't have them, so there's nothing to do.
770 /* add new client to pAlarm->pEventClients */
772 pClients
= malloc(sizeof(SyncAlarmClientList
));
776 /* register it as a resource so it will be cleaned up
780 pClients
->delete_id
= FakeClientID(client
->index
);
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
;
787 if (!AddResource(pClients
->delete_id
, RTAlarmClient
, pAlarm
))
794 * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
797 SyncChangeAlarmAttributes(ClientPtr client
, SyncAlarm
* pAlarm
, Mask mask
,
801 XSyncCounter counter
;
802 Mask origmask
= mask
;
804 counter
= pAlarm
->trigger
.pSync
? pAlarm
->trigger
.pSync
->id
: None
;
807 int index2
= lowbit(mask
);
812 mask
&= ~XSyncCACounter
;
813 /* sanity check in SyncInitTrigger */
817 case XSyncCAValueType
:
818 mask
&= ~XSyncCAValueType
;
819 /* sanity check in SyncInitTrigger */
820 pAlarm
->trigger
.value_type
= *values
++;
824 mask
&= ~XSyncCAValue
;
825 XSyncIntsToValue(&pAlarm
->trigger
.wait_value
, values
[1], values
[0]);
829 case XSyncCATestType
:
830 mask
&= ~XSyncCATestType
;
831 /* sanity check in SyncInitTrigger */
832 pAlarm
->trigger
.test_type
= *values
++;
836 mask
&= ~XSyncCADelta
;
837 XSyncIntsToValue(&pAlarm
->delta
, values
[1], values
[0]);
842 mask
&= ~XSyncCAEvents
;
843 if ((*values
!= xTrue
) && (*values
!= xFalse
)) {
844 client
->errorValue
= *values
;
847 status
= SyncEventSelectForAlarm(pAlarm
, client
,
849 if (status
!= Success
)
854 client
->errorValue
= mask
;
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."
864 if (origmask
& (XSyncCADelta
| XSyncCATestType
)) {
867 XSyncIntToValue(&zero
, 0);
868 if ((((pAlarm
->trigger
.test_type
== XSyncPositiveComparison
) ||
869 (pAlarm
->trigger
.test_type
== XSyncPositiveTransition
))
870 && XSyncValueLessThan(pAlarm
->delta
, zero
))
872 (((pAlarm
->trigger
.test_type
== XSyncNegativeComparison
) ||
873 (pAlarm
->trigger
.test_type
== XSyncNegativeTransition
))
874 && XSyncValueGreaterThan(pAlarm
->delta
, zero
))
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
)
885 /* XXX spec does not really say to do this - needs clarification */
886 pAlarm
->state
= XSyncAlarmActive
;
891 SyncCreate(ClientPtr client
, XID id
, unsigned char type
)
897 pSync
= malloc(sizeof(SyncCounter
));
900 pSync
= (SyncObject
*) dixAllocateObjectWithPrivates(SyncFence
,
910 pSync
->client
= client
;
912 pSync
->pTriglist
= NULL
;
913 pSync
->beingDestroyed
= FALSE
;
920 SyncCreateFenceFromFD(ClientPtr client
, DrawablePtr pDraw
, XID id
, int fd
, BOOL initially_triggered
)
926 pFence
= (SyncFence
*) SyncCreate(client
, id
, SYNC_FENCE
);
930 status
= miSyncInitFenceFromFD(pDraw
, pFence
, fd
, initially_triggered
);
931 if (status
!= Success
) {
932 dixFreeObjectWithPrivates(pFence
, PRIVATE_SYNC_FENCE
);
936 if (!AddResource(id
, RTFence
, (pointer
) pFence
))
941 return BadImplementation
;
946 SyncFDFromFence(ClientPtr client
, DrawablePtr pDraw
, SyncFence
*pFence
)
949 return miSyncFDFromFence(pDraw
, pFence
);
951 return BadImplementation
;
956 SyncCreateCounter(ClientPtr client
, XSyncCounter id
, CARD64 initialvalue
)
958 SyncCounter
*pCounter
;
960 if (!(pCounter
= (SyncCounter
*) SyncCreate(client
, id
, SYNC_COUNTER
)))
963 pCounter
->value
= initialvalue
;
964 pCounter
->pSysCounterInfo
= NULL
;
966 if (!AddResource(id
, RTCounter
, (pointer
) pCounter
))
972 static int FreeCounter(void *, XID
);
975 * ***** System Counter utilities
979 SyncCreateSystemCounter(const char *name
,
982 SyncCounterType counterType
,
983 SyncSystemCounterQueryValue QueryValue
,
984 SyncSystemCounterBracketValues BracketValues
987 SyncCounter
*pCounter
;
989 /* this function may be called before SYNC has been initialized, so we
990 * have to make sure RTCounter is created.
992 if (RTCounter
== 0) {
993 RTCounter
= CreateNewResourceType(FreeCounter
, "SyncCounter");
994 if (RTCounter
== 0) {
997 xorg_list_init(&SysCounterList
);
1000 pCounter
= SyncCreateCounter(NULL
, FakeClientID(0), initial
);
1003 SysCounterInfo
*psci
;
1005 psci
= malloc(sizeof(SysCounterInfo
));
1007 FreeResource(pCounter
->sync
.id
, RT_NONE
);
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
);
1026 SyncDestroySystemCounter(pointer pSysCounter
)
1028 SyncCounter
*pCounter
= (SyncCounter
*) pSysCounter
;
1030 FreeResource(pCounter
->sync
.id
, RT_NONE
);
1034 SyncComputeBracketValues(SyncCounter
* pCounter
)
1036 SyncTriggerList
*pCur
;
1037 SyncTrigger
*pTrigger
;
1038 SysCounterInfo
*psci
;
1039 CARD64
*pnewgtval
= NULL
;
1040 CARD64
*pnewltval
= NULL
;
1046 psci
= pCounter
->pSysCounterInfo
;
1047 ct
= pCounter
->pSysCounterInfo
->counterType
;
1048 if (ct
== XSyncCounterNeverChanges
)
1051 XSyncMaxValue(&psci
->bracket_greater
);
1052 XSyncMinValue(&psci
->bracket_less
);
1054 for (pCur
= pCounter
->sync
.pTriglist
; pCur
; pCur
= pCur
->next
) {
1055 pTrigger
= pCur
->pTrigger
;
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
;
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
;
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
;
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
;
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
)) {
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.
1094 psci
->bracket_less
= pTrigger
->test_value
;
1095 pnewltval
= &psci
->bracket_less
;
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
;
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
)) {
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
1113 psci
->bracket_greater
= pTrigger
->test_value
;
1114 pnewgtval
= &psci
->bracket_greater
;
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
;
1122 } /* end for each trigger */
1124 (*psci
->BracketValues
) ((pointer
) pCounter
, pnewltval
, pnewgtval
);
1129 * ***** Resource delete functions
1134 FreeAlarm(void *addr
, XID id
)
1136 SyncAlarm
*pAlarm
= (SyncAlarm
*) addr
;
1138 pAlarm
->state
= XSyncAlarmDestroyed
;
1140 SyncSendAlarmNotifyEvents(pAlarm
);
1142 /* delete event selections */
1144 while (pAlarm
->pEventClients
)
1145 FreeResource(pAlarm
->pEventClients
->delete_id
, RT_NONE
);
1147 SyncDeleteTriggerFromSyncObject(&pAlarm
->trigger
);
1154 * ** Cleanup after the destruction of a Counter
1158 FreeCounter(void *env
, XID id
)
1160 SyncCounter
*pCounter
= (SyncCounter
*) env
;
1161 SyncTriggerList
*ptl
, *pnext
;
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
);
1168 free(ptl
); /* destroy the trigger list as we go */
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
);
1181 * ** Cleanup after Await
1185 FreeAwait(void *addr
, XID id
)
1187 SyncAwaitUnion
*pAwaitUnion
= (SyncAwaitUnion
*) addr
;
1191 pAwait
= &(pAwaitUnion
+ 1)->await
; /* first await on list */
1193 /* remove triggers from counters */
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.
1200 SyncObject
*pSync
= pAwait
->trigger
.pSync
;
1202 if (pSync
&& !pSync
->beingDestroyed
)
1203 SyncDeleteTriggerFromSyncObject(&pAwait
->trigger
);
1209 /* loosely based on dix/events.c/OtherClientGone */
1211 FreeAlarmClient(void *value
, XID id
)
1213 SyncAlarm
*pAlarm
= (SyncAlarm
*) value
;
1214 SyncAlarmClientList
*pCur
, *pPrev
;
1216 for (pPrev
= NULL
, pCur
= pAlarm
->pEventClients
;
1217 pCur
; pPrev
= pCur
, pCur
= pCur
->next
) {
1218 if (pCur
->delete_id
== id
) {
1220 pPrev
->next
= pCur
->next
;
1222 pAlarm
->pEventClients
= pCur
->next
;
1227 FatalError("alarm client not on event list");
1231 * ***** Proc functions
1235 * ** Initialize the extension
1238 ProcSyncInitialize(ClientPtr client
)
1240 xSyncInitializeReply rep
= {
1242 .sequenceNumber
= client
->sequence
,
1244 .majorVersion
= SERVER_SYNC_MAJOR_VERSION
,
1245 .minorVersion
= SERVER_SYNC_MINOR_VERSION
,
1248 REQUEST_SIZE_MATCH(xSyncInitializeReq
);
1250 if (client
->swapped
) {
1251 swaps(&rep
.sequenceNumber
);
1253 WriteToClient(client
, sizeof(rep
), &rep
);
1258 * ** Get list of system counters available through the extension
1261 ProcSyncListSystemCounters(ClientPtr client
)
1263 xSyncListSystemCountersReply rep
= {
1265 .sequenceNumber
= client
->sequence
,
1268 SysCounterInfo
*psci
;
1270 xSyncSystemCounter
*list
= NULL
, *walklist
= NULL
;
1272 REQUEST_SIZE_MATCH(xSyncListSystemCountersReq
);
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
));
1281 walklist
= list
= malloc(len
);
1286 rep
.length
= bytes_to_int32(len
);
1288 if (client
->swapped
) {
1289 swaps(&rep
.sequenceNumber
);
1291 swapl(&rep
.nCounters
);
1294 xorg_list_for_each_entry(psci
, &SysCounterList
, entry
) {
1296 char *pname_in_reply
;
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
;
1304 if (client
->swapped
) {
1305 swapl(&walklist
->counter
);
1306 swapl(&walklist
->resolution_hi
);
1307 swapl(&walklist
->resolution_lo
);
1308 swaps(&walklist
->name_length
);
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
+
1318 WriteToClient(client
, sizeof(rep
), &rep
);
1320 WriteToClient(client
, len
, list
);
1328 * ** Set client Priority
1331 ProcSyncSetPriority(ClientPtr client
)
1333 REQUEST(xSyncSetPriorityReq
);
1334 ClientPtr priorityclient
;
1337 REQUEST_SIZE_MATCH(xSyncSetPriorityReq
);
1339 if (stuff
->id
== None
)
1340 priorityclient
= client
;
1342 rc
= dixLookupClient(&priorityclient
, stuff
->id
, client
,
1348 if (priorityclient
->priority
!= stuff
->priority
) {
1349 priorityclient
->priority
= stuff
->priority
;
1351 /* The following will force the server back into WaitForSomething
1352 * so that the change in this client's priority is immediately
1355 isItTimeToYield
= TRUE
;
1356 dispatchException
|= DE_PRIORITYCHANGE
;
1362 * ** Get client Priority
1365 ProcSyncGetPriority(ClientPtr client
)
1367 REQUEST(xSyncGetPriorityReq
);
1368 xSyncGetPriorityReply rep
;
1369 ClientPtr priorityclient
;
1372 REQUEST_SIZE_MATCH(xSyncGetPriorityReq
);
1374 if (stuff
->id
== None
)
1375 priorityclient
= client
;
1377 rc
= dixLookupClient(&priorityclient
, stuff
->id
, client
,
1383 rep
= (xSyncGetPriorityReply
) {
1385 .sequenceNumber
= client
->sequence
,
1387 .priority
= priorityclient
->priority
1390 if (client
->swapped
) {
1391 swaps(&rep
.sequenceNumber
);
1392 swapl(&rep
.priority
);
1395 WriteToClient(client
, sizeof(xSyncGetPriorityReply
), &rep
);
1401 * ** Create a new counter
1404 ProcSyncCreateCounter(ClientPtr client
)
1406 REQUEST(xSyncCreateCounterReq
);
1409 REQUEST_SIZE_MATCH(xSyncCreateCounterReq
);
1411 LEGAL_NEW_RESOURCE(stuff
->cid
, client
);
1413 XSyncIntsToValue(&initial
, stuff
->initial_value_lo
,
1414 stuff
->initial_value_hi
);
1415 if (!SyncCreateCounter(client
, stuff
->cid
, initial
))
1422 * ** Set Counter value
1425 ProcSyncSetCounter(ClientPtr client
)
1427 REQUEST(xSyncSetCounterReq
);
1428 SyncCounter
*pCounter
;
1432 REQUEST_SIZE_MATCH(xSyncSetCounterReq
);
1434 rc
= dixLookupResourceByType((pointer
*) &pCounter
, stuff
->cid
, RTCounter
,
1435 client
, DixWriteAccess
);
1439 if (IsSystemCounter(pCounter
)) {
1440 client
->errorValue
= stuff
->cid
;
1444 XSyncIntsToValue(&newvalue
, stuff
->value_lo
, stuff
->value_hi
);
1445 SyncChangeCounter(pCounter
, newvalue
);
1450 * ** Change Counter value
1453 ProcSyncChangeCounter(ClientPtr client
)
1455 REQUEST(xSyncChangeCounterReq
);
1456 SyncCounter
*pCounter
;
1461 REQUEST_SIZE_MATCH(xSyncChangeCounterReq
);
1463 rc
= dixLookupResourceByType((pointer
*) &pCounter
, stuff
->cid
, RTCounter
,
1464 client
, DixWriteAccess
);
1468 if (IsSystemCounter(pCounter
)) {
1469 client
->errorValue
= stuff
->cid
;
1473 XSyncIntsToValue(&newvalue
, stuff
->value_lo
, stuff
->value_hi
);
1474 XSyncValueAdd(&newvalue
, pCounter
->value
, newvalue
, &overflow
);
1476 /* XXX 64 bit value can't fit in 32 bits; do the best we can */
1477 client
->errorValue
= stuff
->value_hi
;
1480 SyncChangeCounter(pCounter
, newvalue
);
1485 * ** Destroy a counter
1488 ProcSyncDestroyCounter(ClientPtr client
)
1490 REQUEST(xSyncDestroyCounterReq
);
1491 SyncCounter
*pCounter
;
1494 REQUEST_SIZE_MATCH(xSyncDestroyCounterReq
);
1496 rc
= dixLookupResourceByType((pointer
*) &pCounter
, stuff
->counter
,
1497 RTCounter
, client
, DixDestroyAccess
);
1501 if (IsSystemCounter(pCounter
)) {
1502 client
->errorValue
= stuff
->counter
;
1505 FreeResource(pCounter
->sync
.id
, RT_NONE
);
1509 static SyncAwaitUnion
*
1510 SyncAwaitPrologue(ClientPtr client
, int items
)
1512 SyncAwaitUnion
*pAwaitUnion
;
1514 /* all the memory for the entire await list is allocated
1517 pAwaitUnion
= malloc((items
+ 1) * sizeof(SyncAwaitUnion
));
1521 /* first item is the header, remainder are real wait conditions */
1523 pAwaitUnion
->header
.delete_id
= FakeClientID(client
->index
);
1524 pAwaitUnion
->header
.client
= client
;
1525 pAwaitUnion
->header
.num_waitconditions
= 0;
1527 if (!AddResource(pAwaitUnion
->header
.delete_id
, RTAwait
, pAwaitUnion
))
1534 SyncAwaitEpilogue(ClientPtr client
, int items
, SyncAwaitUnion
* pAwaitUnion
)
1539 IgnoreClient(client
);
1541 /* see if any of the triggers are already true */
1543 pAwait
= &(pAwaitUnion
+ 1)->await
; /* skip over header */
1544 for (i
= 0; i
< items
; i
++, pAwait
++) {
1547 /* don't have to worry about NULL counters because the request
1548 * errors before we get here out if they occur
1550 switch (pAwait
->trigger
.pSync
->type
) {
1552 value
= ((SyncCounter
*) pAwait
->trigger
.pSync
)->value
;
1555 XSyncIntToValue(&value
, 0);
1558 if ((*pAwait
->trigger
.CheckTrigger
) (&pAwait
->trigger
, value
)) {
1559 (*pAwait
->trigger
.TriggerFired
) (&pAwait
->trigger
);
1560 break; /* once is enough */
1569 ProcSyncAwait(ClientPtr client
)
1571 REQUEST(xSyncAwaitReq
);
1574 xSyncWaitCondition
*pProtocolWaitConds
;
1575 SyncAwaitUnion
*pAwaitUnion
;
1579 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq
);
1581 len
= client
->req_len
<< 2;
1582 len
-= sz_xSyncAwaitReq
;
1583 items
= len
/ sz_xSyncWaitCondition
;
1585 if (items
* sz_xSyncWaitCondition
!= len
) {
1589 client
->errorValue
= items
; /* XXX protocol change */
1593 if (!(pAwaitUnion
= SyncAwaitPrologue(client
, items
)))
1596 /* don't need to do any more memory allocation for this request! */
1598 pProtocolWaitConds
= (xSyncWaitCondition
*) &stuff
[1];
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
1606 FreeResource(pAwaitUnion
->header
.delete_id
, RT_NONE
);
1607 client
->errorValue
= pProtocolWaitConds
->counter
;
1608 return SyncErrorBase
+ XSyncBadCounter
;
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
;
1619 status
= SyncInitTrigger(client
, &pAwait
->trigger
,
1620 pProtocolWaitConds
->counter
, RTCounter
,
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
1626 FreeResource(pAwaitUnion
->header
.delete_id
, RT_NONE
);
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
++;
1639 SyncAwaitEpilogue(client
, items
, pAwaitUnion
);
1645 * ** Query a counter
1648 ProcSyncQueryCounter(ClientPtr client
)
1650 REQUEST(xSyncQueryCounterReq
);
1651 xSyncQueryCounterReply rep
;
1652 SyncCounter
*pCounter
;
1655 REQUEST_SIZE_MATCH(xSyncQueryCounterReq
);
1657 rc
= dixLookupResourceByType((pointer
*) &pCounter
, stuff
->counter
,
1658 RTCounter
, client
, DixReadAccess
);
1662 /* if system counter, ask it what the current value is */
1663 if (IsSystemCounter(pCounter
)) {
1664 (*pCounter
->pSysCounterInfo
->QueryValue
) ((pointer
) pCounter
,
1668 rep
= (xSyncQueryCounterReply
) {
1670 .sequenceNumber
= client
->sequence
,
1672 .value_hi
= XSyncValueHigh32(pCounter
->value
),
1673 .value_lo
= XSyncValueLow32(pCounter
->value
)
1676 if (client
->swapped
) {
1677 swaps(&rep
.sequenceNumber
);
1679 swapl(&rep
.value_hi
);
1680 swapl(&rep
.value_lo
);
1682 WriteToClient(client
, sizeof(xSyncQueryCounterReply
), &rep
);
1690 ProcSyncCreateAlarm(ClientPtr client
)
1692 REQUEST(xSyncCreateAlarmReq
);
1695 unsigned long len
, vmask
;
1696 SyncTrigger
*pTrigger
;
1698 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq
);
1700 LEGAL_NEW_RESOURCE(stuff
->id
, client
);
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
))))
1708 if (!(pAlarm
= malloc(sizeof(SyncAlarm
)))) {
1712 /* set up defaults */
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
,
1723 if (status
!= Success
) {
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
) {
1741 if (!AddResource(stuff
->id
, RTAlarm
, pAlarm
))
1744 /* see if alarm already triggered. NULL counter will not trigger
1745 * in CreateAlarm and sets alarm state to Inactive.
1748 if (!pTrigger
->pSync
) {
1749 pAlarm
->state
= XSyncAlarmInactive
; /* XXX protocol change */
1752 SyncCounter
*pCounter
;
1754 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
,
1755 WARN_INVALID_COUNTER_ALARM
)) {
1756 FreeResource(stuff
->id
, RT_NONE
);
1760 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
1762 if ((*pTrigger
->CheckTrigger
) (pTrigger
, pCounter
->value
))
1763 (*pTrigger
->TriggerFired
) (pTrigger
);
1773 ProcSyncChangeAlarm(ClientPtr client
)
1775 REQUEST(xSyncChangeAlarmReq
);
1777 SyncCounter
*pCounter
= NULL
;
1781 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq
);
1783 status
= dixLookupResourceByType((pointer
*) &pAlarm
, stuff
->alarm
, RTAlarm
,
1784 client
, DixWriteAccess
);
1785 if (status
!= Success
)
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
))))
1794 if ((status
= SyncChangeAlarmAttributes(client
, pAlarm
, vmask
,
1795 (CARD32
*) &stuff
[1])) != Success
)
1798 if (SyncCheckWarnIsCounter(pAlarm
->trigger
.pSync
,
1799 WARN_INVALID_COUNTER_ALARM
))
1800 pCounter
= (SyncCounter
*) pAlarm
->trigger
.pSync
;
1802 /* see if alarm already triggered. NULL counter WILL trigger
1807 (*pAlarm
->trigger
.CheckTrigger
) (&pAlarm
->trigger
, pCounter
->value
)) {
1808 (*pAlarm
->trigger
.TriggerFired
) (&pAlarm
->trigger
);
1814 ProcSyncQueryAlarm(ClientPtr client
)
1816 REQUEST(xSyncQueryAlarmReq
);
1818 xSyncQueryAlarmReply rep
;
1819 SyncTrigger
*pTrigger
;
1822 REQUEST_SIZE_MATCH(xSyncQueryAlarmReq
);
1824 rc
= dixLookupResourceByType((pointer
*) &pAlarm
, stuff
->alarm
, RTAlarm
,
1825 client
, DixReadAccess
);
1829 pTrigger
= &pAlarm
->trigger
;
1830 rep
= (xSyncQueryAlarmReply
) {
1832 .sequenceNumber
= client
->sequence
,
1834 bytes_to_int32(sizeof(xSyncQueryAlarmReply
) - sizeof(xGenericReply
)),
1835 .counter
= (pTrigger
->pSync
) ? pTrigger
->pSync
->id
: None
,
1837 #if 0 /* XXX unclear what to do, depends on whether relative value-types
1838 * are "consumed" immediately and are considered absolute from then
1841 .value_type
= pTrigger
->value_type
,
1842 .wait_value_hi
= XSyncValueHigh32(pTrigger
->wait_value
),
1843 .wait_value_lo
= XSyncValueLow32(pTrigger
->wait_value
),
1845 .value_type
= XSyncAbsolute
,
1846 .wait_value_hi
= XSyncValueHigh32(pTrigger
->test_value
),
1847 .wait_value_lo
= XSyncValueLow32(pTrigger
->test_value
),
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
1857 if (client
->swapped
) {
1858 swaps(&rep
.sequenceNumber
);
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
);
1868 WriteToClient(client
, sizeof(xSyncQueryAlarmReply
), &rep
);
1873 ProcSyncDestroyAlarm(ClientPtr client
)
1878 REQUEST(xSyncDestroyAlarmReq
);
1880 REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq
);
1882 rc
= dixLookupResourceByType((pointer
*) &pAlarm
, stuff
->alarm
, RTAlarm
,
1883 client
, DixDestroyAccess
);
1887 FreeResource(stuff
->alarm
, RT_NONE
);
1892 ProcSyncCreateFence(ClientPtr client
)
1894 REQUEST(xSyncCreateFenceReq
);
1899 REQUEST_SIZE_MATCH(xSyncCreateFenceReq
);
1901 rc
= dixLookupDrawable(&pDraw
, stuff
->d
, client
, M_ANY
, DixGetAttrAccess
);
1905 LEGAL_NEW_RESOURCE(stuff
->fid
, client
);
1907 if (!(pFence
= (SyncFence
*) SyncCreate(client
, stuff
->fid
, SYNC_FENCE
)))
1910 miSyncInitFence(pDraw
->pScreen
, pFence
, stuff
->initially_triggered
);
1912 if (!AddResource(stuff
->fid
, RTFence
, (pointer
) pFence
))
1915 return client
->noClientException
;
1919 FreeFence(void *obj
, XID id
)
1921 SyncFence
*pFence
= (SyncFence
*) obj
;
1923 miSyncDestroyFence(pFence
);
1929 SyncVerifyFence(SyncFence
** ppSyncFence
, XID fid
, ClientPtr client
, Mask mode
)
1931 int rc
= dixLookupResourceByType((pointer
*) ppSyncFence
, fid
, RTFence
,
1935 client
->errorValue
= fid
;
1941 ProcSyncTriggerFence(ClientPtr client
)
1943 REQUEST(xSyncTriggerFenceReq
);
1947 REQUEST_SIZE_MATCH(xSyncTriggerFenceReq
);
1949 rc
= dixLookupResourceByType((pointer
*) &pFence
, stuff
->fid
, RTFence
,
1950 client
, DixWriteAccess
);
1954 miSyncTriggerFence(pFence
);
1956 return client
->noClientException
;
1960 ProcSyncResetFence(ClientPtr client
)
1962 REQUEST(xSyncResetFenceReq
);
1966 REQUEST_SIZE_MATCH(xSyncResetFenceReq
);
1968 rc
= dixLookupResourceByType((pointer
*) &pFence
, stuff
->fid
, RTFence
,
1969 client
, DixWriteAccess
);
1973 if (pFence
->funcs
.CheckTriggered(pFence
) != TRUE
)
1976 pFence
->funcs
.Reset(pFence
);
1978 return client
->noClientException
;
1982 ProcSyncDestroyFence(ClientPtr client
)
1984 REQUEST(xSyncDestroyFenceReq
);
1988 REQUEST_SIZE_MATCH(xSyncDestroyFenceReq
);
1990 rc
= dixLookupResourceByType((pointer
*) &pFence
, stuff
->fid
, RTFence
,
1991 client
, DixDestroyAccess
);
1995 FreeResource(stuff
->fid
, RT_NONE
);
1996 return client
->noClientException
;
2000 ProcSyncQueryFence(ClientPtr client
)
2002 REQUEST(xSyncQueryFenceReq
);
2003 xSyncQueryFenceReply rep
;
2007 REQUEST_SIZE_MATCH(xSyncQueryFenceReq
);
2009 rc
= dixLookupResourceByType((pointer
*) &pFence
, stuff
->fid
,
2010 RTFence
, client
, DixReadAccess
);
2014 rep
= (xSyncQueryFenceReply
) {
2016 .sequenceNumber
= client
->sequence
,
2019 .triggered
= pFence
->funcs
.CheckTriggered(pFence
)
2022 if (client
->swapped
) {
2023 swaps(&rep
.sequenceNumber
);
2027 WriteToClient(client
, sizeof(xSyncQueryFenceReply
), &rep
);
2028 return client
->noClientException
;
2032 ProcSyncAwaitFence(ClientPtr client
)
2034 REQUEST(xSyncAwaitFenceReq
);
2035 SyncAwaitUnion
*pAwaitUnion
;
2038 /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
2039 * CARD32 in protocol definitions */
2040 CARD32
*pProtocolFences
;
2046 REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq
);
2048 len
= client
->req_len
<< 2;
2049 len
-= sz_xSyncAwaitFenceReq
;
2050 items
= len
/ sizeof(CARD32
);
2052 if (items
* sizeof(CARD32
) != len
) {
2056 client
->errorValue
= items
;
2060 if (!(pAwaitUnion
= SyncAwaitPrologue(client
, items
)))
2063 /* don't need to do any more memory allocation for this request! */
2065 pProtocolFences
= (CARD32
*) &stuff
[1];
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
2073 FreeResource(pAwaitUnion
->header
.delete_id
, RT_NONE
);
2074 client
->errorValue
= *pProtocolFences
;
2075 return SyncErrorBase
+ XSyncBadFence
;
2078 pAwait
->trigger
.pSync
= NULL
;
2079 /* Provide acceptable values for these unused fields to
2080 * satisfy SyncInitTrigger's validation logic
2082 pAwait
->trigger
.value_type
= XSyncAbsolute
;
2083 XSyncIntToValue(&pAwait
->trigger
.wait_value
, 0);
2084 pAwait
->trigger
.test_type
= 0;
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
2092 FreeResource(pAwaitUnion
->header
.delete_id
, RT_NONE
);
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
++;
2104 SyncAwaitEpilogue(client
, items
, pAwaitUnion
);
2106 return client
->noClientException
;
2110 * ** Given an extension request, call the appropriate request procedure
2113 ProcSyncDispatch(ClientPtr client
)
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
);
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
);
2164 * Boring Swapping stuff ...
2168 SProcSyncInitialize(ClientPtr client
)
2170 REQUEST(xSyncInitializeReq
);
2171 swaps(&stuff
->length
);
2172 REQUEST_SIZE_MATCH(xSyncInitializeReq
);
2174 return ProcSyncInitialize(client
);
2178 SProcSyncListSystemCounters(ClientPtr client
)
2180 REQUEST(xSyncListSystemCountersReq
);
2181 swaps(&stuff
->length
);
2182 REQUEST_SIZE_MATCH(xSyncListSystemCountersReq
);
2184 return ProcSyncListSystemCounters(client
);
2188 SProcSyncCreateCounter(ClientPtr client
)
2190 REQUEST(xSyncCreateCounterReq
);
2191 swaps(&stuff
->length
);
2192 REQUEST_SIZE_MATCH(xSyncCreateCounterReq
);
2194 swapl(&stuff
->initial_value_lo
);
2195 swapl(&stuff
->initial_value_hi
);
2197 return ProcSyncCreateCounter(client
);
2201 SProcSyncSetCounter(ClientPtr client
)
2203 REQUEST(xSyncSetCounterReq
);
2204 swaps(&stuff
->length
);
2205 REQUEST_SIZE_MATCH(xSyncSetCounterReq
);
2207 swapl(&stuff
->value_lo
);
2208 swapl(&stuff
->value_hi
);
2210 return ProcSyncSetCounter(client
);
2214 SProcSyncChangeCounter(ClientPtr client
)
2216 REQUEST(xSyncChangeCounterReq
);
2217 swaps(&stuff
->length
);
2218 REQUEST_SIZE_MATCH(xSyncChangeCounterReq
);
2220 swapl(&stuff
->value_lo
);
2221 swapl(&stuff
->value_hi
);
2223 return ProcSyncChangeCounter(client
);
2227 SProcSyncQueryCounter(ClientPtr client
)
2229 REQUEST(xSyncQueryCounterReq
);
2230 swaps(&stuff
->length
);
2231 REQUEST_SIZE_MATCH(xSyncQueryCounterReq
);
2232 swapl(&stuff
->counter
);
2234 return ProcSyncQueryCounter(client
);
2238 SProcSyncDestroyCounter(ClientPtr client
)
2240 REQUEST(xSyncDestroyCounterReq
);
2241 swaps(&stuff
->length
);
2242 REQUEST_SIZE_MATCH(xSyncDestroyCounterReq
);
2243 swapl(&stuff
->counter
);
2245 return ProcSyncDestroyCounter(client
);
2249 SProcSyncAwait(ClientPtr client
)
2251 REQUEST(xSyncAwaitReq
);
2252 swaps(&stuff
->length
);
2253 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq
);
2256 return ProcSyncAwait(client
);
2260 SProcSyncCreateAlarm(ClientPtr client
)
2262 REQUEST(xSyncCreateAlarmReq
);
2263 swaps(&stuff
->length
);
2264 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq
);
2266 swapl(&stuff
->valueMask
);
2269 return ProcSyncCreateAlarm(client
);
2273 SProcSyncChangeAlarm(ClientPtr client
)
2275 REQUEST(xSyncChangeAlarmReq
);
2276 swaps(&stuff
->length
);
2277 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq
);
2278 swapl(&stuff
->alarm
);
2279 swapl(&stuff
->valueMask
);
2281 return ProcSyncChangeAlarm(client
);
2285 SProcSyncQueryAlarm(ClientPtr client
)
2287 REQUEST(xSyncQueryAlarmReq
);
2288 swaps(&stuff
->length
);
2289 REQUEST_SIZE_MATCH(xSyncQueryAlarmReq
);
2290 swapl(&stuff
->alarm
);
2292 return ProcSyncQueryAlarm(client
);
2296 SProcSyncDestroyAlarm(ClientPtr client
)
2298 REQUEST(xSyncDestroyAlarmReq
);
2299 swaps(&stuff
->length
);
2300 REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq
);
2301 swapl(&stuff
->alarm
);
2303 return ProcSyncDestroyAlarm(client
);
2307 SProcSyncSetPriority(ClientPtr client
)
2309 REQUEST(xSyncSetPriorityReq
);
2310 swaps(&stuff
->length
);
2311 REQUEST_SIZE_MATCH(xSyncSetPriorityReq
);
2313 swapl(&stuff
->priority
);
2315 return ProcSyncSetPriority(client
);
2319 SProcSyncGetPriority(ClientPtr client
)
2321 REQUEST(xSyncGetPriorityReq
);
2322 swaps(&stuff
->length
);
2323 REQUEST_SIZE_MATCH(xSyncGetPriorityReq
);
2326 return ProcSyncGetPriority(client
);
2330 SProcSyncCreateFence(ClientPtr client
)
2332 REQUEST(xSyncCreateFenceReq
);
2333 swaps(&stuff
->length
);
2334 REQUEST_SIZE_MATCH(xSyncCreateFenceReq
);
2337 return ProcSyncCreateFence(client
);
2341 SProcSyncTriggerFence(ClientPtr client
)
2343 REQUEST(xSyncTriggerFenceReq
);
2344 swaps(&stuff
->length
);
2345 REQUEST_SIZE_MATCH(xSyncTriggerFenceReq
);
2348 return ProcSyncTriggerFence(client
);
2352 SProcSyncResetFence(ClientPtr client
)
2354 REQUEST(xSyncResetFenceReq
);
2355 swaps(&stuff
->length
);
2356 REQUEST_SIZE_MATCH(xSyncResetFenceReq
);
2359 return ProcSyncResetFence(client
);
2363 SProcSyncDestroyFence(ClientPtr client
)
2365 REQUEST(xSyncDestroyFenceReq
);
2366 swaps(&stuff
->length
);
2367 REQUEST_SIZE_MATCH(xSyncDestroyFenceReq
);
2370 return ProcSyncDestroyFence(client
);
2374 SProcSyncQueryFence(ClientPtr client
)
2376 REQUEST(xSyncQueryFenceReq
);
2377 swaps(&stuff
->length
);
2378 REQUEST_SIZE_MATCH(xSyncQueryFenceReq
);
2381 return ProcSyncQueryFence(client
);
2385 SProcSyncAwaitFence(ClientPtr client
)
2387 REQUEST(xSyncAwaitFenceReq
);
2388 swaps(&stuff
->length
);
2389 REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq
);
2392 return ProcSyncAwaitFence(client
);
2396 SProcSyncDispatch(ClientPtr client
)
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
);
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
);
2451 SCounterNotifyEvent(xSyncCounterNotifyEvent
* from
,
2452 xSyncCounterNotifyEvent
* to
)
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
;
2468 SAlarmNotifyEvent(xSyncAlarmNotifyEvent
* from
, xSyncAlarmNotifyEvent
* to
)
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
;
2483 * ** Close everything down. ** This is fairly simple for now.
2487 SyncResetProc(ExtensionEntry
* extEntry
)
2493 * ** Initialise the extension.
2496 SyncExtensionInit(void)
2498 ExtensionEntry
*extEntry
;
2501 for (s
= 0; s
< screenInfo
.numScreens
; s
++)
2502 miSyncSetup(screenInfo
.screens
[s
]);
2504 if (RTCounter
== 0) {
2505 RTCounter
= CreateNewResourceType(FreeCounter
, "SyncCounter");
2506 xorg_list_init(&SysCounterList
);
2508 RTAlarm
= CreateNewResourceType(FreeAlarm
, "SyncAlarm");
2509 RTAwait
= CreateNewResourceType(FreeAwait
, "SyncAwait");
2510 RTFence
= CreateNewResourceType(FreeFence
, "SyncFence");
2512 RTAwait
|= RC_NEVERRETAIN
;
2513 RTAlarmClient
= CreateNewResourceType(FreeAlarmClient
, "SyncAlarmClient");
2515 RTAlarmClient
|= RC_NEVERRETAIN
;
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
);
2528 SyncEventBase
= extEntry
->eventBase
;
2529 SyncErrorBase
= extEntry
->errorBase
;
2530 EventSwapVector
[SyncEventBase
+ XSyncCounterNotify
] =
2531 (EventSwapPtr
) SCounterNotifyEvent
;
2532 EventSwapVector
[SyncEventBase
+ XSyncAlarmNotify
] =
2533 (EventSwapPtr
) SAlarmNotifyEvent
;
2535 SetResourceTypeErrorValue(RTCounter
, SyncErrorBase
+ XSyncBadCounter
);
2536 SetResourceTypeErrorValue(RTAlarm
, SyncErrorBase
+ XSyncBadAlarm
);
2537 SetResourceTypeErrorValue(RTFence
, SyncErrorBase
+ XSyncBadFence
);
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.
2545 SyncInitServerTime();
2549 fprintf(stderr
, "Sync Extension %d.%d\n",
2550 SYNC_MAJOR_VERSION
, SYNC_MINOR_VERSION
);
2555 * ***** SERVERTIME implementation - should go in its own file in OS directory?
2558 static pointer ServertimeCounter
;
2559 static XSyncValue Now
;
2560 static XSyncValue
*pnext_time
;
2564 unsigned long millis = GetTimeInMillis();\
2565 unsigned long maxis = XSyncValueHigh32(Now);\
2566 if (millis < XSyncValueLow32(Now)) maxis++;\
2567 XSyncIntsToValue(&Now, millis, maxis);\
2571 *** Server Block Handler
2572 *** code inspired by multibuffer extension (now deprecated)
2574 /*ARGSUSED*/ static void
2575 ServertimeBlockHandler(void *env
, struct timeval
**wt
, void *LastSelectMask
)
2578 unsigned long timeout
;
2583 if (XSyncValueGreaterOrEqual(Now
, *pnext_time
)) {
2589 XSyncValueSubtract(&delay
, *pnext_time
, Now
, &overflow
);
2591 timeout
= XSyncValueLow32(delay
);
2593 AdjustWaitForDelay(wt
, timeout
); /* os/utils.c */
2600 /*ARGSUSED*/ static void
2601 ServertimeWakeupHandler(void *env
, int rc
, void *LastSelectMask
)
2606 if (XSyncValueGreaterOrEqual(Now
, *pnext_time
)) {
2607 SyncChangeCounter(ServertimeCounter
, Now
);
2613 ServertimeQueryValue(void *pCounter
, CARD64
* pValue_return
)
2616 *pValue_return
= Now
;
2620 ServertimeBracketValues(void *pCounter
, CARD64
* pbracket_less
,
2621 CARD64
* pbracket_greater
)
2623 if (!pnext_time
&& pbracket_greater
) {
2624 RegisterBlockAndWakeupHandlers(ServertimeBlockHandler
,
2625 ServertimeWakeupHandler
, NULL
);
2627 else if (pnext_time
&& !pbracket_greater
) {
2628 RemoveBlockAndWakeupHandlers(ServertimeBlockHandler
,
2629 ServertimeWakeupHandler
, NULL
);
2631 pnext_time
= pbracket_greater
;
2635 SyncInitServerTime(void)
2639 XSyncIntsToValue(&Now
, GetTimeInMillis(), 0);
2640 XSyncIntToValue(&resolution
, 4);
2641 ServertimeCounter
= SyncCreateSystemCounter("SERVERTIME", Now
, resolution
,
2642 XSyncCounterNeverDecreases
,
2643 ServertimeQueryValue
,
2644 ServertimeBracketValues
);
2649 * IDLETIME implementation
2653 XSyncValue
*value_less
;
2654 XSyncValue
*value_greater
;
2659 IdleTimeQueryValue(pointer pCounter
, CARD64
* pValue_return
)
2665 SyncCounter
*counter
= pCounter
;
2666 IdleCounterPriv
*priv
= SysCounterGetPrivate(counter
);
2667 deviceid
= priv
->deviceid
;
2670 deviceid
= XIAllDevices
;
2671 idle
= GetTimeInMillis() - LastEventTime(deviceid
).milliseconds
;
2672 XSyncIntsToValue(pValue_return
, idle
, 0);
2676 IdleTimeBlockHandler(pointer pCounter
, struct timeval
**wt
, pointer LastSelectMask
)
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
;
2686 if (!less
&& !greater
)
2689 old_idle
= counter
->value
;
2690 IdleTimeQueryValue(counter
, &idle
);
2691 counter
->value
= idle
; /* push, so CheckTrigger works */
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.
2699 if (less
&& XSyncValueGreaterThan(idle
, *less
) &&
2700 LastEventTimeWasReset(priv
->deviceid
)) {
2701 AdjustWaitForDelay(wt
, 0);
2702 } else if (less
&& XSyncValueLessOrEqual(idle
, *less
)) {
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.
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);
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.
2724 if (XSyncValueEqual(idle
, *less
))
2725 AdjustWaitForDelay(wt
, 1);
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.
2735 if (XSyncValueLessThan(idle
, *greater
)) {
2739 XSyncValueSubtract(&value
, *greater
, idle
, &overflow
);
2740 AdjustWaitForDelay(wt
, XSyncValueLow32(value
));
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);
2754 counter
->value
= old_idle
; /* pop */
2758 IdleTimeCheckBrackets(SyncCounter
*counter
, XSyncValue idle
, XSyncValue
*less
, XSyncValue
*greater
)
2760 if ((greater
&& XSyncValueGreaterOrEqual(idle
, *greater
)) ||
2761 (less
&& XSyncValueLessOrEqual(idle
, *less
))) {
2762 SyncChangeCounter(counter
, idle
);
2765 SyncUpdateCounter(counter
, idle
);
2769 IdleTimeWakeupHandler(pointer pCounter
, int rc
, pointer LastSelectMask
)
2771 SyncCounter
*counter
= pCounter
;
2772 IdleCounterPriv
*priv
= SysCounterGetPrivate(counter
);
2773 XSyncValue
*less
= priv
->value_less
,
2774 *greater
= priv
->value_greater
;
2777 if (!less
&& !greater
)
2780 IdleTimeQueryValue(pCounter
, &idle
);
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
2788 if (LastEventTimeWasReset(priv
->deviceid
)) {
2789 LastEventTimeToggleResetFlag(priv
->deviceid
, FALSE
);
2790 if (!XSyncValueIsZero(idle
)) {
2792 XSyncIntsToValue(&zero
, 0, 0);
2793 IdleTimeCheckBrackets(counter
, zero
, less
, greater
);
2794 less
= priv
->value_less
;
2795 greater
= priv
->value_greater
;
2799 IdleTimeCheckBrackets(counter
, idle
, less
, greater
);
2803 IdleTimeBracketValues(pointer pCounter
, CARD64
* pbracket_less
,
2804 CARD64
* pbracket_greater
)
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
);
2812 if (registered
&& !pbracket_less
&& !pbracket_greater
) {
2813 RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler
,
2814 IdleTimeWakeupHandler
, pCounter
);
2816 else if (!registered
&& (pbracket_less
|| pbracket_greater
)) {
2817 /* Reset flag must be zero so we don't force a idle timer reset on
2819 LastEventTimeToggleResetAll(FALSE
);
2820 RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler
,
2821 IdleTimeWakeupHandler
, pCounter
);
2824 priv
->value_greater
= pbracket_greater
;
2825 priv
->value_less
= pbracket_less
;
2829 init_system_idle_counter(const char *name
, int deviceid
)
2833 SyncCounter
*idle_time_counter
;
2835 IdleTimeQueryValue(NULL
, &idle
);
2836 XSyncIntToValue(&resolution
, 4);
2838 idle_time_counter
= SyncCreateSystemCounter(name
, idle
, resolution
,
2839 XSyncCounterUnrestricted
,
2841 IdleTimeBracketValues
);
2843 if (idle_time_counter
!= NULL
) {
2844 IdleCounterPriv
*priv
= malloc(sizeof(IdleCounterPriv
));
2846 priv
->value_less
= priv
->value_greater
= NULL
;
2847 priv
->deviceid
= deviceid
;
2849 idle_time_counter
->pSysCounterInfo
->private = priv
;
2852 return idle_time_counter
;
2856 SyncInitIdleTime(void)
2858 init_system_idle_counter("IDLETIME", XIAllDevices
);
2862 SyncInitDeviceIdleTime(DeviceIntPtr dev
)
2864 char timer_name
[64];
2865 sprintf(timer_name
, "DEVICEIDLETIME %d", dev
->id
);
2867 return init_system_idle_counter(timer_name
, dev
->id
);
2870 void SyncRemoveDeviceIdleTime(SyncCounter
*counter
)
2872 /* FreeAllResources() frees all system counters before the devices are
2873 shut down, check if there are any left before freeing the device's
2875 if (counter
&& !xorg_list_is_empty(&SysCounterList
))
2876 xorg_list_del(&counter
->pSysCounterInfo
->entry
);