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 #include <dix-config.h>
57 #include <X11/Xproto.h>
59 #include <X11/extensions/syncproto.h>
61 #include "dix/dix_priv.h"
64 #include "scrnintstr.h"
66 #include "extnsionst.h"
67 #include "dixstruct.h"
68 #include "pixmapstr.h"
72 #include "protocol-versions.h"
74 #include "misync_priv.h"
80 #include "extinit_priv.h"
83 * Local Global Variables
85 static int SyncEventBase
;
86 static int SyncErrorBase
;
87 static RESTYPE RTCounter
= 0;
88 static RESTYPE RTAwait
;
89 static RESTYPE RTAlarm
;
90 static RESTYPE RTAlarmClient
;
91 static RESTYPE RTFence
;
92 static struct xorg_list SysCounterList
;
93 static int SyncNumInvalidCounterWarnings
= 0;
95 #define MAX_INVALID_COUNTER_WARNINGS 5
97 static const char *WARN_INVALID_COUNTER_COMPARE
=
98 "Warning: Non-counter XSync object using Counter-only\n"
99 " comparison. Result will never be true.\n";
101 static const char *WARN_INVALID_COUNTER_ALARM
=
102 "Warning: Non-counter XSync object used in alarm. This is\n"
103 " the result of a programming error in the X server.\n";
105 #define IsSystemCounter(pCounter) \
106 (pCounter && (pCounter->sync.client == NULL))
108 /* these are all the alarm attributes that pertain to the alarm's trigger */
109 #define XSyncCAAllTrigger \
110 (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
112 static void SyncComputeBracketValues(SyncCounter
*);
114 static void SyncInitServerTime(void);
116 static void SyncInitIdleTime(void);
119 SysCounterGetPrivate(SyncCounter
*counter
)
121 BUG_WARN(!IsSystemCounter(counter
));
123 return counter
->pSysCounterInfo
? counter
->pSysCounterInfo
->private : NULL
;
127 SyncCheckWarnIsCounter(const SyncObject
* pSync
, const char *warning
)
129 if (pSync
&& (SYNC_COUNTER
!= pSync
->type
)) {
130 if (SyncNumInvalidCounterWarnings
++ < MAX_INVALID_COUNTER_WARNINGS
) {
131 ErrorF("%s", warning
);
132 ErrorF(" Counter type: %d\n", pSync
->type
);
141 /* Each counter maintains a simple linked list of triggers that are
142 * interested in the counter. The two functions below are used to
143 * delete and add triggers on this list.
146 SyncDeleteTriggerFromSyncObject(SyncTrigger
* pTrigger
)
148 SyncTriggerList
*pCur
;
149 SyncTriggerList
*pPrev
;
150 SyncCounter
*pCounter
;
152 /* pSync needs to be stored in pTrigger before calling here. */
154 if (!pTrigger
->pSync
)
158 pCur
= pTrigger
->pSync
->pTriglist
;
161 if (pCur
->pTrigger
== pTrigger
) {
163 pPrev
->next
= pCur
->next
;
165 pTrigger
->pSync
->pTriglist
= pCur
->next
;
175 if (SYNC_COUNTER
== pTrigger
->pSync
->type
) {
176 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
178 if (IsSystemCounter(pCounter
))
179 SyncComputeBracketValues(pCounter
);
181 else if (SYNC_FENCE
== pTrigger
->pSync
->type
) {
182 SyncFence
*pFence
= (SyncFence
*) pTrigger
->pSync
;
184 pFence
->funcs
.DeleteTrigger(pTrigger
);
189 SyncAddTriggerToSyncObject(SyncTrigger
* pTrigger
)
191 SyncTriggerList
*pCur
;
192 SyncCounter
*pCounter
;
194 if (!pTrigger
->pSync
)
197 /* don't do anything if it's already there */
198 for (pCur
= pTrigger
->pSync
->pTriglist
; pCur
; pCur
= pCur
->next
) {
199 if (pCur
->pTrigger
== pTrigger
)
203 if (!(pCur
= malloc(sizeof(SyncTriggerList
))))
206 pCur
->pTrigger
= pTrigger
;
207 pCur
->next
= pTrigger
->pSync
->pTriglist
;
208 pTrigger
->pSync
->pTriglist
= pCur
;
210 if (SYNC_COUNTER
== pTrigger
->pSync
->type
) {
211 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
213 if (IsSystemCounter(pCounter
))
214 SyncComputeBracketValues(pCounter
);
216 else if (SYNC_FENCE
== pTrigger
->pSync
->type
) {
217 SyncFence
*pFence
= (SyncFence
*) pTrigger
->pSync
;
219 pFence
->funcs
.AddTrigger(pTrigger
);
225 /* Below are five possible functions that can be plugged into
226 * pTrigger->CheckTrigger for counter sync objects, corresponding to
227 * the four possible test-types, and the one possible function that
228 * can be plugged into pTrigger->CheckTrigger for fence sync objects.
229 * These functions are called after the sync object's state changes
230 * but are also passed the old state so they can inspect both the old
231 * and new values. (PositiveTransition and NegativeTransition need to
232 * see both pieces of information.) These functions return the truth
233 * value of the trigger.
235 * All of them include the condition pTrigger->pSync == NULL.
236 * This is because the spec says that a trigger with a sync value
237 * of None is always TRUE.
241 SyncCheckTriggerPositiveComparison(SyncTrigger
* pTrigger
, int64_t oldval
)
243 SyncCounter
*pCounter
;
245 /* Non-counter sync objects should never get here because they
246 * never trigger this comparison. */
247 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_COMPARE
))
250 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
252 return pCounter
== NULL
|| pCounter
->value
>= pTrigger
->test_value
;
256 SyncCheckTriggerNegativeComparison(SyncTrigger
* pTrigger
, int64_t 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
|| pCounter
->value
<= pTrigger
->test_value
;
271 SyncCheckTriggerPositiveTransition(SyncTrigger
* pTrigger
, int64_t oldval
)
273 SyncCounter
*pCounter
;
275 /* Non-counter sync objects should never get here because they
276 * never trigger this comparison. */
277 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_COMPARE
))
280 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
282 return (pCounter
== NULL
||
283 (oldval
< pTrigger
->test_value
&&
284 pCounter
->value
>= pTrigger
->test_value
));
288 SyncCheckTriggerNegativeTransition(SyncTrigger
* pTrigger
, int64_t oldval
)
290 SyncCounter
*pCounter
;
292 /* Non-counter sync objects should never get here because they
293 * never trigger this comparison. */
294 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_COMPARE
))
297 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
299 return (pCounter
== NULL
||
300 (oldval
> pTrigger
->test_value
&&
301 pCounter
->value
<= pTrigger
->test_value
));
305 SyncCheckTriggerFence(SyncTrigger
* pTrigger
, int64_t unused
)
307 SyncFence
*pFence
= (SyncFence
*) pTrigger
->pSync
;
311 return (pFence
== NULL
|| pFence
->funcs
.CheckTriggered(pFence
));
315 SyncInitTrigger(ClientPtr client
, SyncTrigger
* pTrigger
, XID syncObject
,
316 RESTYPE resType
, Mask changes
)
318 SyncObject
*pSync
= pTrigger
->pSync
;
319 SyncCounter
*pCounter
= NULL
;
321 Bool newSyncObject
= FALSE
;
323 if (changes
& XSyncCACounter
) {
324 if (syncObject
== None
)
326 else if (Success
!= (rc
= dixLookupResourceByType((void **) &pSync
,
330 client
->errorValue
= syncObject
;
333 if (pSync
!= pTrigger
->pSync
) { /* new counter for trigger */
334 SyncDeleteTriggerFromSyncObject(pTrigger
);
335 pTrigger
->pSync
= pSync
;
336 newSyncObject
= TRUE
;
340 /* if system counter, ask it what the current value is */
342 if (pSync
&& SYNC_COUNTER
== pSync
->type
) {
343 pCounter
= (SyncCounter
*) pSync
;
345 if (IsSystemCounter(pCounter
)) {
346 (*pCounter
->pSysCounterInfo
->QueryValue
) ((void *) pCounter
,
351 if (changes
& XSyncCAValueType
) {
352 if (pTrigger
->value_type
!= XSyncRelative
&&
353 pTrigger
->value_type
!= XSyncAbsolute
) {
354 client
->errorValue
= pTrigger
->value_type
;
359 if (changes
& XSyncCATestType
) {
361 if (pSync
&& SYNC_FENCE
== pSync
->type
) {
362 pTrigger
->CheckTrigger
= SyncCheckTriggerFence
;
365 /* select appropriate CheckTrigger function */
367 switch (pTrigger
->test_type
) {
368 case XSyncPositiveTransition
:
369 pTrigger
->CheckTrigger
= SyncCheckTriggerPositiveTransition
;
371 case XSyncNegativeTransition
:
372 pTrigger
->CheckTrigger
= SyncCheckTriggerNegativeTransition
;
374 case XSyncPositiveComparison
:
375 pTrigger
->CheckTrigger
= SyncCheckTriggerPositiveComparison
;
377 case XSyncNegativeComparison
:
378 pTrigger
->CheckTrigger
= SyncCheckTriggerNegativeComparison
;
381 client
->errorValue
= pTrigger
->test_type
;
387 if (changes
& (XSyncCAValueType
| XSyncCAValue
)) {
388 if (pTrigger
->value_type
== XSyncAbsolute
)
389 pTrigger
->test_value
= pTrigger
->wait_value
;
390 else { /* relative */
393 if (pCounter
== NULL
)
396 overflow
= checked_int64_add(&pTrigger
->test_value
,
397 pCounter
->value
, pTrigger
->wait_value
);
399 client
->errorValue
= pTrigger
->wait_value
>> 32;
405 /* we wait until we're sure there are no errors before registering
406 * a new counter on a trigger
409 if ((rc
= SyncAddTriggerToSyncObject(pTrigger
)) != Success
)
412 else if (pCounter
&& IsSystemCounter(pCounter
)) {
413 SyncComputeBracketValues(pCounter
);
419 /* AlarmNotify events happen in response to actions taken on an Alarm or
420 * the counter used by the alarm. AlarmNotify may be sent to multiple
421 * clients. The alarm maintains a list of clients interested in events.
424 SyncSendAlarmNotifyEvents(SyncAlarm
* pAlarm
)
426 SyncAlarmClientList
*pcl
;
427 xSyncAlarmNotifyEvent ane
;
428 SyncTrigger
*pTrigger
= &pAlarm
->trigger
;
429 SyncCounter
*pCounter
;
431 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_ALARM
))
434 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
438 ane
= (xSyncAlarmNotifyEvent
) {
439 .type
= SyncEventBase
+ XSyncAlarmNotify
,
440 .kind
= XSyncAlarmNotify
,
441 .alarm
= pAlarm
->alarm_id
,
442 .alarm_value_hi
= pTrigger
->test_value
>> 32,
443 .alarm_value_lo
= pTrigger
->test_value
,
444 .time
= currentTime
.milliseconds
,
445 .state
= pAlarm
->state
448 if (pTrigger
->pSync
&& SYNC_COUNTER
== pTrigger
->pSync
->type
) {
449 ane
.counter_value_hi
= pCounter
->value
>> 32;
450 ane
.counter_value_lo
= pCounter
->value
;
453 /* XXX what else can we do if there's no counter? */
454 ane
.counter_value_hi
= ane
.counter_value_lo
= 0;
459 WriteEventsToClient(pAlarm
->client
, 1, (xEvent
*) &ane
);
461 /* send to other interested clients */
462 for (pcl
= pAlarm
->pEventClients
; pcl
; pcl
= pcl
->next
)
463 WriteEventsToClient(pcl
->client
, 1, (xEvent
*) &ane
);
466 /* CounterNotify events only occur in response to an Await. The events
467 * go only to the Awaiting client.
470 SyncSendCounterNotifyEvents(ClientPtr client
, SyncAwait
** ppAwait
,
473 xSyncCounterNotifyEvent
*pEvents
, *pev
;
476 if (client
->clientGone
)
478 pev
= pEvents
= calloc(num_events
, sizeof(xSyncCounterNotifyEvent
));
482 for (i
= 0; i
< num_events
; i
++, ppAwait
++, pev
++) {
483 SyncTrigger
*pTrigger
= &(*ppAwait
)->trigger
;
485 pev
->type
= SyncEventBase
+ XSyncCounterNotify
;
486 pev
->kind
= XSyncCounterNotify
;
487 pev
->counter
= pTrigger
->pSync
->id
;
488 pev
->wait_value_lo
= pTrigger
->test_value
;
489 pev
->wait_value_hi
= pTrigger
->test_value
>> 32;
490 if (SYNC_COUNTER
== pTrigger
->pSync
->type
) {
491 SyncCounter
*pCounter
= (SyncCounter
*) pTrigger
->pSync
;
493 pev
->counter_value_lo
= pCounter
->value
;
494 pev
->counter_value_hi
= pCounter
->value
>> 32;
497 pev
->counter_value_lo
= 0;
498 pev
->counter_value_hi
= 0;
501 pev
->time
= currentTime
.milliseconds
;
502 pev
->count
= num_events
- i
- 1; /* events remaining */
503 pev
->destroyed
= pTrigger
->pSync
->beingDestroyed
;
505 /* swapping will be taken care of by this */
506 WriteEventsToClient(client
, num_events
, (xEvent
*) pEvents
);
510 /* This function is called when an alarm's counter is destroyed.
511 * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
514 SyncAlarmCounterDestroyed(SyncTrigger
* pTrigger
)
516 SyncAlarm
*pAlarm
= (SyncAlarm
*) pTrigger
;
518 pAlarm
->state
= XSyncAlarmInactive
;
519 SyncSendAlarmNotifyEvents(pAlarm
);
520 pTrigger
->pSync
= NULL
;
523 /* This function is called when an alarm "goes off."
524 * It is plugged into pTrigger->TriggerFired (for alarm triggers).
527 SyncAlarmTriggerFired(SyncTrigger
* pTrigger
)
529 SyncAlarm
*pAlarm
= (SyncAlarm
*) pTrigger
;
530 SyncCounter
*pCounter
;
531 int64_t new_test_value
;
533 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
, WARN_INVALID_COUNTER_ALARM
))
536 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
538 /* no need to check alarm unless it's active */
539 if (pAlarm
->state
!= XSyncAlarmActive
)
542 /* " if the counter value is None, or if the delta is 0 and
543 * the test-type is PositiveComparison or NegativeComparison,
544 * no change is made to value (test-value) and the alarm
545 * state is changed to Inactive before the event is generated."
547 if (pCounter
== NULL
|| (pAlarm
->delta
== 0
548 && (pAlarm
->trigger
.test_type
==
549 XSyncPositiveComparison
||
550 pAlarm
->trigger
.test_type
==
551 XSyncNegativeComparison
)))
552 pAlarm
->state
= XSyncAlarmInactive
;
554 new_test_value
= pAlarm
->trigger
.test_value
;
556 if (pAlarm
->state
== XSyncAlarmActive
) {
559 SyncTrigger
*paTrigger
= &pAlarm
->trigger
;
560 SyncCounter
*paCounter
;
562 if (!SyncCheckWarnIsCounter(paTrigger
->pSync
,
563 WARN_INVALID_COUNTER_ALARM
))
566 paCounter
= (SyncCounter
*) pTrigger
->pSync
;
568 /* "The alarm is updated by repeatedly adding delta to the
569 * value of the trigger and re-initializing it until it
572 oldvalue
= paTrigger
->test_value
;
574 /* XXX really should do something smarter here */
577 overflow
= checked_int64_add(&paTrigger
->test_value
,
578 paTrigger
->test_value
, pAlarm
->delta
);
579 } while (!overflow
&&
580 (*paTrigger
->CheckTrigger
) (paTrigger
, paCounter
->value
));
582 new_test_value
= paTrigger
->test_value
;
583 paTrigger
->test_value
= oldvalue
;
585 /* "If this update would cause value to fall outside the range
586 * for an INT64...no change is made to value (test-value) and
587 * the alarm state is changed to Inactive before the event is
591 new_test_value
= oldvalue
;
592 pAlarm
->state
= XSyncAlarmInactive
;
595 /* The AlarmNotify event has to have the "new state of the alarm"
596 * which we can't be sure of until this point. However, it has
597 * to have the "old" trigger test value. That's the reason for
598 * all the newvalue/oldvalue shuffling above. After we send the
599 * events, give the trigger its new test value.
601 SyncSendAlarmNotifyEvents(pAlarm
);
602 pTrigger
->test_value
= new_test_value
;
605 /* This function is called when an Await unblocks, either as a result
606 * of the trigger firing OR the counter being destroyed.
607 * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
608 * (for Await triggers).
611 SyncAwaitTriggerFired(SyncTrigger
* pTrigger
)
613 SyncAwait
*pAwait
= (SyncAwait
*) pTrigger
;
615 SyncAwaitUnion
*pAwaitUnion
;
619 pAwaitUnion
= (SyncAwaitUnion
*) pAwait
->pHeader
;
620 numwaits
= pAwaitUnion
->header
.num_waitconditions
;
621 ppAwait
= xallocarray(numwaits
, sizeof(SyncAwait
*));
625 pAwait
= &(pAwaitUnion
+ 1)->await
;
627 /* "When a client is unblocked, all the CounterNotify events for
628 * the Await request are generated contiguously. If count is 0
629 * there are no more events to follow for this request. If
630 * count is n, there are at least n more events to follow."
632 * Thus, it is best to find all the counters for which events
633 * need to be sent first, so that an accurate count field can
634 * be stored in the events.
636 for (; numwaits
; numwaits
--, pAwait
++) {
638 Bool overflow
, diffgreater
, diffequal
;
640 /* "A CounterNotify event with the destroyed flag set to TRUE is
641 * always generated if the counter for one of the triggers is
644 if (pAwait
->trigger
.pSync
->beingDestroyed
) {
645 ppAwait
[num_events
++] = pAwait
;
649 if (SYNC_COUNTER
== pAwait
->trigger
.pSync
->type
) {
650 SyncCounter
*pCounter
= (SyncCounter
*) pAwait
->trigger
.pSync
;
652 /* "The difference between the counter and the test value is
653 * calculated by subtracting the test value from the value of
656 overflow
= checked_int64_subtract(&diff
, pCounter
->value
,
657 pAwait
->trigger
.test_value
);
659 /* "If the difference lies outside the range for an INT64, an
660 * event is not generated."
664 diffgreater
= diff
> pAwait
->event_threshold
;
665 diffequal
= diff
== pAwait
->event_threshold
;
667 /* "If the test-type is PositiveTransition or
668 * PositiveComparison, a CounterNotify event is generated if
669 * the difference is at least event-threshold. If the test-type
670 * is NegativeTransition or NegativeComparison, a CounterNotify
671 * event is generated if the difference is at most
675 if (((pAwait
->trigger
.test_type
== XSyncPositiveComparison
||
676 pAwait
->trigger
.test_type
== XSyncPositiveTransition
)
677 && (diffgreater
|| diffequal
))
679 ((pAwait
->trigger
.test_type
== XSyncNegativeComparison
||
680 pAwait
->trigger
.test_type
== XSyncNegativeTransition
)
681 && (!diffgreater
) /* less or equal */
684 ppAwait
[num_events
++] = pAwait
;
689 SyncSendCounterNotifyEvents(pAwaitUnion
->header
.client
, ppAwait
,
694 /* unblock the client */
695 AttendClient(pAwaitUnion
->header
.client
);
696 /* delete the await */
697 FreeResource(pAwaitUnion
->header
.delete_id
, X11_RESTYPE_NONE
);
701 SyncUpdateCounter(SyncCounter
*pCounter
, int64_t newval
)
703 int64_t oldval
= pCounter
->value
;
704 pCounter
->value
= newval
;
708 /* This function should always be used to change a counter's value so that
709 * any triggers depending on the counter will be checked.
712 SyncChangeCounter(SyncCounter
* pCounter
, int64_t newval
)
714 SyncTriggerList
*ptl
, *pnext
;
717 oldval
= SyncUpdateCounter(pCounter
, newval
);
719 /* run through triggers to see if any become true */
720 for (ptl
= pCounter
->sync
.pTriglist
; ptl
; ptl
= pnext
) {
722 if ((*ptl
->pTrigger
->CheckTrigger
) (ptl
->pTrigger
, oldval
))
723 (*ptl
->pTrigger
->TriggerFired
) (ptl
->pTrigger
);
726 if (IsSystemCounter(pCounter
)) {
727 SyncComputeBracketValues(pCounter
);
731 /* loosely based on dix/events.c/EventSelectForWindow */
733 SyncEventSelectForAlarm(SyncAlarm
* pAlarm
, ClientPtr client
, Bool wantevents
)
735 SyncAlarmClientList
*pClients
;
737 if (client
== pAlarm
->client
) { /* alarm owner */
738 pAlarm
->events
= wantevents
;
742 /* see if the client is already on the list (has events selected) */
744 for (pClients
= pAlarm
->pEventClients
; pClients
; pClients
= pClients
->next
) {
745 if (pClients
->client
== client
) {
746 /* client's presence on the list indicates desire for
747 * events. If the client doesn't want events, remove it
748 * from the list. If the client does want events, do
749 * nothing, since it's already got them.
752 FreeResource(pClients
->delete_id
, X11_RESTYPE_NONE
);
758 /* if we get here, this client does not currently have
759 * events selected on the alarm
763 /* client doesn't want events, and we just discovered that it
764 * doesn't have them, so there's nothing to do.
768 /* add new client to pAlarm->pEventClients */
770 pClients
= malloc(sizeof(SyncAlarmClientList
));
774 /* register it as a resource so it will be cleaned up
778 pClients
->delete_id
= FakeClientID(client
->index
);
780 /* link it into list after we know all the allocations succeed */
781 pClients
->next
= pAlarm
->pEventClients
;
782 pAlarm
->pEventClients
= pClients
;
783 pClients
->client
= client
;
785 if (!AddResource(pClients
->delete_id
, RTAlarmClient
, pAlarm
))
792 * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
795 SyncChangeAlarmAttributes(ClientPtr client
, SyncAlarm
* pAlarm
, Mask mask
,
799 XSyncCounter counter
;
800 Mask origmask
= mask
;
802 counter
= pAlarm
->trigger
.pSync
? pAlarm
->trigger
.pSync
->id
: None
;
805 int index2
= lowbit(mask
);
810 mask
&= ~XSyncCACounter
;
811 /* sanity check in SyncInitTrigger */
815 case XSyncCAValueType
:
816 mask
&= ~XSyncCAValueType
;
817 /* sanity check in SyncInitTrigger */
818 pAlarm
->trigger
.value_type
= *values
++;
822 mask
&= ~XSyncCAValue
;
823 pAlarm
->trigger
.wait_value
= ((int64_t)values
[0] << 32) | values
[1];
827 case XSyncCATestType
:
828 mask
&= ~XSyncCATestType
;
829 /* sanity check in SyncInitTrigger */
830 pAlarm
->trigger
.test_type
= *values
++;
834 mask
&= ~XSyncCADelta
;
835 pAlarm
->delta
= ((int64_t)values
[0] << 32) | values
[1];
840 mask
&= ~XSyncCAEvents
;
841 if ((*values
!= xTrue
) && (*values
!= xFalse
)) {
842 client
->errorValue
= *values
;
845 status
= SyncEventSelectForAlarm(pAlarm
, client
,
847 if (status
!= Success
)
852 client
->errorValue
= mask
;
857 /* "If the test-type is PositiveComparison or PositiveTransition
858 * and delta is less than zero, or if the test-type is
859 * NegativeComparison or NegativeTransition and delta is
860 * greater than zero, a Match error is generated."
862 if (origmask
& (XSyncCADelta
| XSyncCATestType
)) {
863 if ((((pAlarm
->trigger
.test_type
== XSyncPositiveComparison
) ||
864 (pAlarm
->trigger
.test_type
== XSyncPositiveTransition
))
865 && pAlarm
->delta
< 0)
867 (((pAlarm
->trigger
.test_type
== XSyncNegativeComparison
) ||
868 (pAlarm
->trigger
.test_type
== XSyncNegativeTransition
))
869 && pAlarm
->delta
> 0)
875 /* postpone this until now, when we're sure nothing else can go wrong */
876 if ((status
= SyncInitTrigger(client
, &pAlarm
->trigger
, counter
, RTCounter
,
877 origmask
& XSyncCAAllTrigger
)) != Success
)
880 /* XXX spec does not really say to do this - needs clarification */
881 pAlarm
->state
= XSyncAlarmActive
;
886 SyncCreate(ClientPtr client
, XID id
, unsigned char type
)
893 pSync
= malloc(sizeof(SyncCounter
));
897 pSync
= (SyncObject
*) dixAllocateObjectWithPrivates(SyncFence
,
908 pSync
->initialized
= FALSE
;
910 if (!AddResource(id
, resType
, (void *) pSync
))
913 pSync
->client
= client
;
915 pSync
->pTriglist
= NULL
;
916 pSync
->beingDestroyed
= FALSE
;
923 SyncCreateFenceFromFD(ClientPtr client
, DrawablePtr pDraw
, XID id
, int fd
, BOOL initially_triggered
)
925 #ifdef HAVE_XSHMFENCE
929 pFence
= (SyncFence
*) SyncCreate(client
, id
, SYNC_FENCE
);
933 status
= miSyncInitFenceFromFD(pDraw
, pFence
, fd
, initially_triggered
);
934 if (status
!= Success
) {
935 FreeResource(pFence
->sync
.id
, X11_RESTYPE_NONE
);
941 return BadImplementation
;
946 SyncFDFromFence(ClientPtr client
, DrawablePtr pDraw
, SyncFence
*pFence
)
948 #ifdef HAVE_XSHMFENCE
949 return miSyncFDFromFence(pDraw
, pFence
);
951 return BadImplementation
;
956 SyncCreateCounter(ClientPtr client
, XSyncCounter id
, int64_t initialvalue
)
958 SyncCounter
*pCounter
;
960 if (!(pCounter
= (SyncCounter
*) SyncCreate(client
, id
, SYNC_COUNTER
)))
963 pCounter
->value
= initialvalue
;
964 pCounter
->pSysCounterInfo
= NULL
;
966 pCounter
->sync
.initialized
= TRUE
;
971 static int FreeCounter(void *, XID
);
974 * ***** System Counter utilities
978 SyncCreateSystemCounter(const char *name
,
981 SyncCounterType counterType
,
982 SyncSystemCounterQueryValue QueryValue
,
983 SyncSystemCounterBracketValues BracketValues
986 SyncCounter
*pCounter
= SyncCreateCounter(NULL
, FakeClientID(0), initial
);
989 SysCounterInfo
*psci
;
991 psci
= malloc(sizeof(SysCounterInfo
));
993 FreeResource(pCounter
->sync
.id
, X11_RESTYPE_NONE
);
996 pCounter
->pSysCounterInfo
= psci
;
997 psci
->pCounter
= pCounter
;
998 psci
->name
= strdup(name
);
999 psci
->resolution
= resolution
;
1000 psci
->counterType
= counterType
;
1001 psci
->QueryValue
= QueryValue
;
1002 psci
->BracketValues
= BracketValues
;
1003 psci
->private = NULL
;
1004 psci
->bracket_greater
= LLONG_MAX
;
1005 psci
->bracket_less
= LLONG_MIN
;
1006 xorg_list_add(&psci
->entry
, &SysCounterList
);
1012 SyncDestroySystemCounter(void *pSysCounter
)
1014 SyncCounter
*pCounter
= (SyncCounter
*) pSysCounter
;
1016 FreeResource(pCounter
->sync
.id
, X11_RESTYPE_NONE
);
1020 SyncComputeBracketValues(SyncCounter
* pCounter
)
1022 SyncTriggerList
*pCur
;
1023 SyncTrigger
*pTrigger
;
1024 SysCounterInfo
*psci
;
1025 int64_t *pnewgtval
= NULL
;
1026 int64_t *pnewltval
= NULL
;
1032 psci
= pCounter
->pSysCounterInfo
;
1033 ct
= pCounter
->pSysCounterInfo
->counterType
;
1034 if (ct
== XSyncCounterNeverChanges
)
1037 psci
->bracket_greater
= LLONG_MAX
;
1038 psci
->bracket_less
= LLONG_MIN
;
1040 for (pCur
= pCounter
->sync
.pTriglist
; pCur
; pCur
= pCur
->next
) {
1041 pTrigger
= pCur
->pTrigger
;
1043 if (pTrigger
->test_type
== XSyncPositiveComparison
&&
1044 ct
!= XSyncCounterNeverIncreases
) {
1045 if (pCounter
->value
< pTrigger
->test_value
&&
1046 pTrigger
->test_value
< psci
->bracket_greater
) {
1047 psci
->bracket_greater
= pTrigger
->test_value
;
1048 pnewgtval
= &psci
->bracket_greater
;
1050 else if (pCounter
->value
> pTrigger
->test_value
&&
1051 pTrigger
->test_value
> psci
->bracket_less
) {
1052 psci
->bracket_less
= pTrigger
->test_value
;
1053 pnewltval
= &psci
->bracket_less
;
1056 else if (pTrigger
->test_type
== XSyncNegativeComparison
&&
1057 ct
!= XSyncCounterNeverDecreases
) {
1058 if (pCounter
->value
> pTrigger
->test_value
&&
1059 pTrigger
->test_value
> psci
->bracket_less
) {
1060 psci
->bracket_less
= pTrigger
->test_value
;
1061 pnewltval
= &psci
->bracket_less
;
1063 else if (pCounter
->value
< pTrigger
->test_value
&&
1064 pTrigger
->test_value
< psci
->bracket_greater
) {
1065 psci
->bracket_greater
= pTrigger
->test_value
;
1066 pnewgtval
= &psci
->bracket_greater
;
1069 else if (pTrigger
->test_type
== XSyncNegativeTransition
&&
1070 ct
!= XSyncCounterNeverIncreases
) {
1071 if (pCounter
->value
>= pTrigger
->test_value
&&
1072 pTrigger
->test_value
> psci
->bracket_less
) {
1074 * If the value is exactly equal to our threshold, we want one
1075 * more event in the negative direction to ensure we pick up
1076 * when the value is less than this threshold.
1078 psci
->bracket_less
= pTrigger
->test_value
;
1079 pnewltval
= &psci
->bracket_less
;
1081 else if (pCounter
->value
< pTrigger
->test_value
&&
1082 pTrigger
->test_value
< psci
->bracket_greater
) {
1083 psci
->bracket_greater
= pTrigger
->test_value
;
1084 pnewgtval
= &psci
->bracket_greater
;
1087 else if (pTrigger
->test_type
== XSyncPositiveTransition
&&
1088 ct
!= XSyncCounterNeverDecreases
) {
1089 if (pCounter
->value
<= pTrigger
->test_value
&&
1090 pTrigger
->test_value
< psci
->bracket_greater
) {
1092 * If the value is exactly equal to our threshold, we
1093 * want one more event in the positive direction to
1094 * ensure we pick up when the value *exceeds* this
1097 psci
->bracket_greater
= pTrigger
->test_value
;
1098 pnewgtval
= &psci
->bracket_greater
;
1100 else if (pCounter
->value
> pTrigger
->test_value
&&
1101 pTrigger
->test_value
> psci
->bracket_less
) {
1102 psci
->bracket_less
= pTrigger
->test_value
;
1103 pnewltval
= &psci
->bracket_less
;
1106 } /* end for each trigger */
1108 (*psci
->BracketValues
) ((void *) pCounter
, pnewltval
, pnewgtval
);
1113 * ***** Resource delete functions
1118 FreeAlarm(void *addr
, XID id
)
1120 SyncAlarm
*pAlarm
= (SyncAlarm
*) addr
;
1122 pAlarm
->state
= XSyncAlarmDestroyed
;
1124 SyncSendAlarmNotifyEvents(pAlarm
);
1126 /* delete event selections */
1128 while (pAlarm
->pEventClients
)
1129 FreeResource(pAlarm
->pEventClients
->delete_id
, X11_RESTYPE_NONE
);
1131 SyncDeleteTriggerFromSyncObject(&pAlarm
->trigger
);
1138 * ** Cleanup after the destruction of a Counter
1142 FreeCounter(void *env
, XID id
)
1144 SyncCounter
*pCounter
= (SyncCounter
*) env
;
1146 pCounter
->sync
.beingDestroyed
= TRUE
;
1148 if (pCounter
->sync
.initialized
) {
1149 SyncTriggerList
*ptl
, *pnext
;
1151 /* tell all the counter's triggers that counter has been destroyed */
1152 for (ptl
= pCounter
->sync
.pTriglist
; ptl
; ptl
= pnext
) {
1153 (*ptl
->pTrigger
->CounterDestroyed
) (ptl
->pTrigger
);
1155 free(ptl
); /* destroy the trigger list as we go */
1157 if (IsSystemCounter(pCounter
)) {
1158 xorg_list_del(&pCounter
->pSysCounterInfo
->entry
);
1159 free(pCounter
->pSysCounterInfo
->name
);
1160 free(pCounter
->pSysCounterInfo
->private);
1161 free(pCounter
->pSysCounterInfo
);
1170 * ** Cleanup after Await
1174 FreeAwait(void *addr
, XID id
)
1176 SyncAwaitUnion
*pAwaitUnion
= (SyncAwaitUnion
*) addr
;
1180 pAwait
= &(pAwaitUnion
+ 1)->await
; /* first await on list */
1182 /* remove triggers from counters */
1184 for (numwaits
= pAwaitUnion
->header
.num_waitconditions
; numwaits
;
1185 numwaits
--, pAwait
++) {
1186 /* If the counter is being destroyed, FreeCounter will delete
1187 * the trigger list itself, so don't do it here.
1189 SyncObject
*pSync
= pAwait
->trigger
.pSync
;
1191 if (pSync
&& !pSync
->beingDestroyed
)
1192 SyncDeleteTriggerFromSyncObject(&pAwait
->trigger
);
1198 /* loosely based on dix/events.c/OtherClientGone */
1200 FreeAlarmClient(void *value
, XID id
)
1202 SyncAlarm
*pAlarm
= (SyncAlarm
*) value
;
1203 SyncAlarmClientList
*pCur
, *pPrev
;
1205 for (pPrev
= NULL
, pCur
= pAlarm
->pEventClients
;
1206 pCur
; pPrev
= pCur
, pCur
= pCur
->next
) {
1207 if (pCur
->delete_id
== id
) {
1209 pPrev
->next
= pCur
->next
;
1211 pAlarm
->pEventClients
= pCur
->next
;
1216 FatalError("alarm client not on event list");
1220 * ***** Proc functions
1224 * ** Initialize the extension
1227 ProcSyncInitialize(ClientPtr client
)
1229 xSyncInitializeReply rep
= {
1231 .sequenceNumber
= client
->sequence
,
1233 .majorVersion
= SERVER_SYNC_MAJOR_VERSION
,
1234 .minorVersion
= SERVER_SYNC_MINOR_VERSION
,
1237 REQUEST_SIZE_MATCH(xSyncInitializeReq
);
1239 if (client
->swapped
) {
1240 swaps(&rep
.sequenceNumber
);
1242 WriteToClient(client
, sizeof(rep
), &rep
);
1247 * ** Get list of system counters available through the extension
1250 ProcSyncListSystemCounters(ClientPtr client
)
1252 xSyncListSystemCountersReply rep
= {
1254 .sequenceNumber
= client
->sequence
,
1257 SysCounterInfo
*psci
;
1259 xSyncSystemCounter
*list
= NULL
, *walklist
= NULL
;
1261 REQUEST_SIZE_MATCH(xSyncListSystemCountersReq
);
1263 xorg_list_for_each_entry(psci
, &SysCounterList
, entry
) {
1264 /* pad to 4 byte boundary */
1265 len
+= pad_to_int32(sz_xSyncSystemCounter
+ strlen(psci
->name
));
1270 walklist
= list
= malloc(len
);
1275 rep
.length
= bytes_to_int32(len
);
1277 if (client
->swapped
) {
1278 swaps(&rep
.sequenceNumber
);
1280 swapl(&rep
.nCounters
);
1283 xorg_list_for_each_entry(psci
, &SysCounterList
, entry
) {
1285 char *pname_in_reply
;
1287 walklist
->counter
= psci
->pCounter
->sync
.id
;
1288 walklist
->resolution_hi
= psci
->resolution
>> 32;
1289 walklist
->resolution_lo
= psci
->resolution
;
1290 namelen
= strlen(psci
->name
);
1291 walklist
->name_length
= namelen
;
1293 if (client
->swapped
) {
1294 swapl(&walklist
->counter
);
1295 swapl(&walklist
->resolution_hi
);
1296 swapl(&walklist
->resolution_lo
);
1297 swaps(&walklist
->name_length
);
1300 pname_in_reply
= ((char *) walklist
) + sz_xSyncSystemCounter
;
1301 strncpy(pname_in_reply
, psci
->name
, namelen
);
1302 walklist
= (xSyncSystemCounter
*) (((char *) walklist
) +
1303 pad_to_int32(sz_xSyncSystemCounter
+
1307 WriteToClient(client
, sizeof(rep
), &rep
);
1309 WriteToClient(client
, len
, list
);
1317 * ** Set client Priority
1320 ProcSyncSetPriority(ClientPtr client
)
1322 REQUEST(xSyncSetPriorityReq
);
1323 ClientPtr priorityclient
;
1326 REQUEST_SIZE_MATCH(xSyncSetPriorityReq
);
1328 if (stuff
->id
== None
)
1329 priorityclient
= client
;
1331 rc
= dixLookupClient(&priorityclient
, stuff
->id
, client
,
1337 if (priorityclient
->priority
!= stuff
->priority
) {
1338 priorityclient
->priority
= stuff
->priority
;
1340 /* The following will force the server back into WaitForSomething
1341 * so that the change in this client's priority is immediately
1344 isItTimeToYield
= TRUE
;
1345 dispatchException
|= DE_PRIORITYCHANGE
;
1351 * ** Get client Priority
1354 ProcSyncGetPriority(ClientPtr client
)
1356 REQUEST(xSyncGetPriorityReq
);
1357 xSyncGetPriorityReply rep
;
1358 ClientPtr priorityclient
;
1361 REQUEST_SIZE_MATCH(xSyncGetPriorityReq
);
1363 if (stuff
->id
== None
)
1364 priorityclient
= client
;
1366 rc
= dixLookupClient(&priorityclient
, stuff
->id
, client
,
1372 rep
= (xSyncGetPriorityReply
) {
1374 .sequenceNumber
= client
->sequence
,
1376 .priority
= priorityclient
->priority
1379 if (client
->swapped
) {
1380 swaps(&rep
.sequenceNumber
);
1381 swapl(&rep
.priority
);
1384 WriteToClient(client
, sizeof(xSyncGetPriorityReply
), &rep
);
1390 * ** Create a new counter
1393 ProcSyncCreateCounter(ClientPtr client
)
1395 REQUEST(xSyncCreateCounterReq
);
1398 REQUEST_SIZE_MATCH(xSyncCreateCounterReq
);
1400 LEGAL_NEW_RESOURCE(stuff
->cid
, client
);
1402 initial
= ((int64_t)stuff
->initial_value_hi
<< 32) | stuff
->initial_value_lo
;
1404 if (!SyncCreateCounter(client
, stuff
->cid
, initial
))
1411 * ** Set Counter value
1414 ProcSyncSetCounter(ClientPtr client
)
1416 REQUEST(xSyncSetCounterReq
);
1417 SyncCounter
*pCounter
;
1421 REQUEST_SIZE_MATCH(xSyncSetCounterReq
);
1423 rc
= dixLookupResourceByType((void **) &pCounter
, stuff
->cid
, RTCounter
,
1424 client
, DixWriteAccess
);
1428 if (IsSystemCounter(pCounter
)) {
1429 client
->errorValue
= stuff
->cid
;
1433 newvalue
= ((int64_t)stuff
->value_hi
<< 32) | stuff
->value_lo
;
1434 SyncChangeCounter(pCounter
, newvalue
);
1439 * ** Change Counter value
1442 ProcSyncChangeCounter(ClientPtr client
)
1444 REQUEST(xSyncChangeCounterReq
);
1445 SyncCounter
*pCounter
;
1450 REQUEST_SIZE_MATCH(xSyncChangeCounterReq
);
1452 rc
= dixLookupResourceByType((void **) &pCounter
, stuff
->cid
, RTCounter
,
1453 client
, DixWriteAccess
);
1457 if (IsSystemCounter(pCounter
)) {
1458 client
->errorValue
= stuff
->cid
;
1462 newvalue
= (int64_t)stuff
->value_hi
<< 32 | stuff
->value_lo
;
1463 overflow
= checked_int64_add(&newvalue
, newvalue
, pCounter
->value
);
1465 /* XXX 64 bit value can't fit in 32 bits; do the best we can */
1466 client
->errorValue
= stuff
->value_hi
;
1469 SyncChangeCounter(pCounter
, newvalue
);
1474 * ** Destroy a counter
1477 ProcSyncDestroyCounter(ClientPtr client
)
1479 REQUEST(xSyncDestroyCounterReq
);
1480 SyncCounter
*pCounter
;
1483 REQUEST_SIZE_MATCH(xSyncDestroyCounterReq
);
1485 rc
= dixLookupResourceByType((void **) &pCounter
, stuff
->counter
,
1486 RTCounter
, client
, DixDestroyAccess
);
1490 if (IsSystemCounter(pCounter
)) {
1491 client
->errorValue
= stuff
->counter
;
1494 FreeResource(pCounter
->sync
.id
, X11_RESTYPE_NONE
);
1498 static SyncAwaitUnion
*
1499 SyncAwaitPrologue(ClientPtr client
, int items
)
1501 SyncAwaitUnion
*pAwaitUnion
;
1503 /* all the memory for the entire await list is allocated
1506 pAwaitUnion
= xallocarray(items
+ 1, sizeof(SyncAwaitUnion
));
1510 /* first item is the header, remainder are real wait conditions */
1512 pAwaitUnion
->header
.delete_id
= FakeClientID(client
->index
);
1513 pAwaitUnion
->header
.client
= client
;
1514 pAwaitUnion
->header
.num_waitconditions
= 0;
1516 if (!AddResource(pAwaitUnion
->header
.delete_id
, RTAwait
, pAwaitUnion
))
1523 SyncAwaitEpilogue(ClientPtr client
, int items
, SyncAwaitUnion
* pAwaitUnion
)
1528 IgnoreClient(client
);
1530 /* see if any of the triggers are already true */
1532 pAwait
= &(pAwaitUnion
+ 1)->await
; /* skip over header */
1533 for (i
= 0; i
< items
; i
++, pAwait
++) {
1536 /* don't have to worry about NULL counters because the request
1537 * errors before we get here out if they occur
1539 switch (pAwait
->trigger
.pSync
->type
) {
1541 value
= ((SyncCounter
*) pAwait
->trigger
.pSync
)->value
;
1547 if ((*pAwait
->trigger
.CheckTrigger
) (&pAwait
->trigger
, value
)) {
1548 (*pAwait
->trigger
.TriggerFired
) (&pAwait
->trigger
);
1549 break; /* once is enough */
1558 ProcSyncAwait(ClientPtr client
)
1560 REQUEST(xSyncAwaitReq
);
1563 xSyncWaitCondition
*pProtocolWaitConds
;
1564 SyncAwaitUnion
*pAwaitUnion
;
1568 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq
);
1570 len
= client
->req_len
<< 2;
1571 len
-= sz_xSyncAwaitReq
;
1572 items
= len
/ sz_xSyncWaitCondition
;
1574 if (items
* sz_xSyncWaitCondition
!= len
) {
1578 client
->errorValue
= items
; /* XXX protocol change */
1582 if (!(pAwaitUnion
= SyncAwaitPrologue(client
, items
)))
1585 /* don't need to do any more memory allocation for this request! */
1587 pProtocolWaitConds
= (xSyncWaitCondition
*) &stuff
[1];
1589 pAwait
= &(pAwaitUnion
+ 1)->await
; /* skip over header */
1590 for (i
= 0; i
< items
; i
++, pProtocolWaitConds
++, pAwait
++) {
1591 if (pProtocolWaitConds
->counter
== None
) { /* XXX protocol change */
1592 /* this should take care of removing any triggers created by
1593 * this request that have already been registered on sync objects
1595 FreeResource(pAwaitUnion
->header
.delete_id
, X11_RESTYPE_NONE
);
1596 client
->errorValue
= pProtocolWaitConds
->counter
;
1597 return SyncErrorBase
+ XSyncBadCounter
;
1600 /* sanity checks are in SyncInitTrigger */
1601 pAwait
->trigger
.pSync
= NULL
;
1602 pAwait
->trigger
.value_type
= pProtocolWaitConds
->value_type
;
1603 pAwait
->trigger
.wait_value
=
1604 ((int64_t)pProtocolWaitConds
->wait_value_hi
<< 32) |
1605 pProtocolWaitConds
->wait_value_lo
;
1606 pAwait
->trigger
.test_type
= pProtocolWaitConds
->test_type
;
1608 status
= SyncInitTrigger(client
, &pAwait
->trigger
,
1609 pProtocolWaitConds
->counter
, RTCounter
,
1611 if (status
!= Success
) {
1612 /* this should take care of removing any triggers created by
1613 * this request that have already been registered on sync objects
1615 FreeResource(pAwaitUnion
->header
.delete_id
, X11_RESTYPE_NONE
);
1618 /* this is not a mistake -- same function works for both cases */
1619 pAwait
->trigger
.TriggerFired
= SyncAwaitTriggerFired
;
1620 pAwait
->trigger
.CounterDestroyed
= SyncAwaitTriggerFired
;
1621 pAwait
->event_threshold
=
1622 ((int64_t) pProtocolWaitConds
->event_threshold_hi
<< 32) |
1623 pProtocolWaitConds
->event_threshold_lo
;
1625 pAwait
->pHeader
= &pAwaitUnion
->header
;
1626 pAwaitUnion
->header
.num_waitconditions
++;
1629 SyncAwaitEpilogue(client
, items
, pAwaitUnion
);
1635 * ** Query a counter
1638 ProcSyncQueryCounter(ClientPtr client
)
1640 REQUEST(xSyncQueryCounterReq
);
1641 xSyncQueryCounterReply rep
;
1642 SyncCounter
*pCounter
;
1645 REQUEST_SIZE_MATCH(xSyncQueryCounterReq
);
1647 rc
= dixLookupResourceByType((void **) &pCounter
, stuff
->counter
,
1648 RTCounter
, client
, DixReadAccess
);
1652 /* if system counter, ask it what the current value is */
1653 if (IsSystemCounter(pCounter
)) {
1654 (*pCounter
->pSysCounterInfo
->QueryValue
) ((void *) pCounter
,
1658 rep
= (xSyncQueryCounterReply
) {
1660 .sequenceNumber
= client
->sequence
,
1662 .value_hi
= pCounter
->value
>> 32,
1663 .value_lo
= pCounter
->value
1666 if (client
->swapped
) {
1667 swaps(&rep
.sequenceNumber
);
1669 swapl(&rep
.value_hi
);
1670 swapl(&rep
.value_lo
);
1672 WriteToClient(client
, sizeof(xSyncQueryCounterReply
), &rep
);
1680 ProcSyncCreateAlarm(ClientPtr client
)
1682 REQUEST(xSyncCreateAlarmReq
);
1685 unsigned long len
, vmask
;
1686 SyncTrigger
*pTrigger
;
1688 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq
);
1690 LEGAL_NEW_RESOURCE(stuff
->id
, client
);
1692 vmask
= stuff
->valueMask
;
1693 len
= client
->req_len
- bytes_to_int32(sizeof(xSyncCreateAlarmReq
));
1694 /* the "extra" call to Ones accounts for the presence of 64 bit values */
1695 if (len
!= (Ones(vmask
) + Ones(vmask
& (XSyncCAValue
| XSyncCADelta
))))
1698 if (!(pAlarm
= malloc(sizeof(SyncAlarm
)))) {
1702 /* set up defaults */
1704 pTrigger
= &pAlarm
->trigger
;
1705 pTrigger
->pSync
= NULL
;
1706 pTrigger
->value_type
= XSyncAbsolute
;
1707 pTrigger
->wait_value
= 0;
1708 pTrigger
->test_type
= XSyncPositiveComparison
;
1709 pTrigger
->TriggerFired
= SyncAlarmTriggerFired
;
1710 pTrigger
->CounterDestroyed
= SyncAlarmCounterDestroyed
;
1711 status
= SyncInitTrigger(client
, pTrigger
, None
, RTCounter
,
1713 if (status
!= Success
) {
1718 pAlarm
->client
= client
;
1719 pAlarm
->alarm_id
= stuff
->id
;
1721 pAlarm
->events
= TRUE
;
1722 pAlarm
->state
= XSyncAlarmInactive
;
1723 pAlarm
->pEventClients
= NULL
;
1724 status
= SyncChangeAlarmAttributes(client
, pAlarm
, vmask
,
1725 (CARD32
*) &stuff
[1]);
1726 if (status
!= Success
) {
1731 if (!AddResource(stuff
->id
, RTAlarm
, pAlarm
))
1734 /* see if alarm already triggered. NULL counter will not trigger
1735 * in CreateAlarm and sets alarm state to Inactive.
1738 if (!pTrigger
->pSync
) {
1739 pAlarm
->state
= XSyncAlarmInactive
; /* XXX protocol change */
1742 SyncCounter
*pCounter
;
1744 if (!SyncCheckWarnIsCounter(pTrigger
->pSync
,
1745 WARN_INVALID_COUNTER_ALARM
)) {
1746 FreeResource(stuff
->id
, X11_RESTYPE_NONE
);
1750 pCounter
= (SyncCounter
*) pTrigger
->pSync
;
1752 if ((*pTrigger
->CheckTrigger
) (pTrigger
, pCounter
->value
))
1753 (*pTrigger
->TriggerFired
) (pTrigger
);
1763 ProcSyncChangeAlarm(ClientPtr client
)
1765 REQUEST(xSyncChangeAlarmReq
);
1767 SyncCounter
*pCounter
= NULL
;
1771 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq
);
1773 status
= dixLookupResourceByType((void **) &pAlarm
, stuff
->alarm
, RTAlarm
,
1774 client
, DixWriteAccess
);
1775 if (status
!= Success
)
1778 vmask
= stuff
->valueMask
;
1779 len
= client
->req_len
- bytes_to_int32(sizeof(xSyncChangeAlarmReq
));
1780 /* the "extra" call to Ones accounts for the presence of 64 bit values */
1781 if (len
!= (Ones(vmask
) + Ones(vmask
& (XSyncCAValue
| XSyncCADelta
))))
1784 if ((status
= SyncChangeAlarmAttributes(client
, pAlarm
, vmask
,
1785 (CARD32
*) &stuff
[1])) != Success
)
1788 if (SyncCheckWarnIsCounter(pAlarm
->trigger
.pSync
,
1789 WARN_INVALID_COUNTER_ALARM
))
1790 pCounter
= (SyncCounter
*) pAlarm
->trigger
.pSync
;
1792 /* see if alarm already triggered. NULL counter WILL trigger
1797 (*pAlarm
->trigger
.CheckTrigger
) (&pAlarm
->trigger
, pCounter
->value
)) {
1798 (*pAlarm
->trigger
.TriggerFired
) (&pAlarm
->trigger
);
1804 ProcSyncQueryAlarm(ClientPtr client
)
1806 REQUEST(xSyncQueryAlarmReq
);
1808 xSyncQueryAlarmReply rep
;
1809 SyncTrigger
*pTrigger
;
1812 REQUEST_SIZE_MATCH(xSyncQueryAlarmReq
);
1814 rc
= dixLookupResourceByType((void **) &pAlarm
, stuff
->alarm
, RTAlarm
,
1815 client
, DixReadAccess
);
1819 pTrigger
= &pAlarm
->trigger
;
1820 rep
= (xSyncQueryAlarmReply
) {
1822 .sequenceNumber
= client
->sequence
,
1824 bytes_to_int32(sizeof(xSyncQueryAlarmReply
) - sizeof(xGenericReply
)),
1825 .counter
= (pTrigger
->pSync
) ? pTrigger
->pSync
->id
: None
,
1827 #if 0 /* XXX unclear what to do, depends on whether relative value-types
1828 * are "consumed" immediately and are considered absolute from then
1831 .value_type
= pTrigger
->value_type
,
1832 .wait_value_hi
= pTrigger
->wait_value
>> 32,
1833 .wait_value_lo
= pTrigger
->wait_value
,
1835 .value_type
= XSyncAbsolute
,
1836 .wait_value_hi
= pTrigger
->test_value
>> 32,
1837 .wait_value_lo
= pTrigger
->test_value
,
1840 .test_type
= pTrigger
->test_type
,
1841 .delta_hi
= pAlarm
->delta
>> 32,
1842 .delta_lo
= pAlarm
->delta
,
1843 .events
= pAlarm
->events
,
1844 .state
= pAlarm
->state
1847 if (client
->swapped
) {
1848 swaps(&rep
.sequenceNumber
);
1850 swapl(&rep
.counter
);
1851 swapl(&rep
.wait_value_hi
);
1852 swapl(&rep
.wait_value_lo
);
1853 swapl(&rep
.test_type
);
1854 swapl(&rep
.delta_hi
);
1855 swapl(&rep
.delta_lo
);
1858 WriteToClient(client
, sizeof(xSyncQueryAlarmReply
), &rep
);
1863 ProcSyncDestroyAlarm(ClientPtr client
)
1868 REQUEST(xSyncDestroyAlarmReq
);
1870 REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq
);
1872 rc
= dixLookupResourceByType((void **) &pAlarm
, stuff
->alarm
, RTAlarm
,
1873 client
, DixDestroyAccess
);
1877 FreeResource(stuff
->alarm
, X11_RESTYPE_NONE
);
1882 ProcSyncCreateFence(ClientPtr client
)
1884 REQUEST(xSyncCreateFenceReq
);
1889 REQUEST_SIZE_MATCH(xSyncCreateFenceReq
);
1891 rc
= dixLookupDrawable(&pDraw
, stuff
->d
, client
, M_ANY
, DixGetAttrAccess
);
1895 LEGAL_NEW_RESOURCE(stuff
->fid
, client
);
1897 if (!(pFence
= (SyncFence
*) SyncCreate(client
, stuff
->fid
, SYNC_FENCE
)))
1900 miSyncInitFence(pDraw
->pScreen
, pFence
, stuff
->initially_triggered
);
1906 FreeFence(void *obj
, XID id
)
1908 SyncFence
*pFence
= (SyncFence
*) obj
;
1910 miSyncDestroyFence(pFence
);
1916 SyncVerifyFence(SyncFence
** ppSyncFence
, XID fid
, ClientPtr client
, Mask mode
)
1918 int rc
= dixLookupResourceByType((void **) ppSyncFence
, fid
, RTFence
,
1922 client
->errorValue
= fid
;
1928 ProcSyncTriggerFence(ClientPtr client
)
1930 REQUEST(xSyncTriggerFenceReq
);
1934 REQUEST_SIZE_MATCH(xSyncTriggerFenceReq
);
1936 rc
= dixLookupResourceByType((void **) &pFence
, stuff
->fid
, RTFence
,
1937 client
, DixWriteAccess
);
1941 miSyncTriggerFence(pFence
);
1947 ProcSyncResetFence(ClientPtr client
)
1949 REQUEST(xSyncResetFenceReq
);
1953 REQUEST_SIZE_MATCH(xSyncResetFenceReq
);
1955 rc
= dixLookupResourceByType((void **) &pFence
, stuff
->fid
, RTFence
,
1956 client
, DixWriteAccess
);
1960 if (pFence
->funcs
.CheckTriggered(pFence
) != TRUE
)
1963 pFence
->funcs
.Reset(pFence
);
1969 ProcSyncDestroyFence(ClientPtr client
)
1971 REQUEST(xSyncDestroyFenceReq
);
1975 REQUEST_SIZE_MATCH(xSyncDestroyFenceReq
);
1977 rc
= dixLookupResourceByType((void **) &pFence
, stuff
->fid
, RTFence
,
1978 client
, DixDestroyAccess
);
1982 FreeResource(stuff
->fid
, X11_RESTYPE_NONE
);
1987 ProcSyncQueryFence(ClientPtr client
)
1989 REQUEST(xSyncQueryFenceReq
);
1990 xSyncQueryFenceReply rep
;
1994 REQUEST_SIZE_MATCH(xSyncQueryFenceReq
);
1996 rc
= dixLookupResourceByType((void **) &pFence
, stuff
->fid
,
1997 RTFence
, client
, DixReadAccess
);
2001 rep
= (xSyncQueryFenceReply
) {
2003 .sequenceNumber
= client
->sequence
,
2006 .triggered
= pFence
->funcs
.CheckTriggered(pFence
)
2009 if (client
->swapped
) {
2010 swaps(&rep
.sequenceNumber
);
2014 WriteToClient(client
, sizeof(xSyncQueryFenceReply
), &rep
);
2019 ProcSyncAwaitFence(ClientPtr client
)
2021 REQUEST(xSyncAwaitFenceReq
);
2022 SyncAwaitUnion
*pAwaitUnion
;
2025 /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
2026 * CARD32 in protocol definitions */
2027 CARD32
*pProtocolFences
;
2033 REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq
);
2035 len
= client
->req_len
<< 2;
2036 len
-= sz_xSyncAwaitFenceReq
;
2037 items
= len
/ sizeof(CARD32
);
2039 if (items
* sizeof(CARD32
) != len
) {
2043 client
->errorValue
= items
;
2047 if (!(pAwaitUnion
= SyncAwaitPrologue(client
, items
)))
2050 /* don't need to do any more memory allocation for this request! */
2052 pProtocolFences
= (CARD32
*) &stuff
[1];
2054 pAwait
= &(pAwaitUnion
+ 1)->await
; /* skip over header */
2055 for (i
= 0; i
< items
; i
++, pProtocolFences
++, pAwait
++) {
2056 if (*pProtocolFences
== None
) {
2057 /* this should take care of removing any triggers created by
2058 * this request that have already been registered on sync objects
2060 FreeResource(pAwaitUnion
->header
.delete_id
, X11_RESTYPE_NONE
);
2061 client
->errorValue
= *pProtocolFences
;
2062 return SyncErrorBase
+ XSyncBadFence
;
2065 pAwait
->trigger
.pSync
= NULL
;
2066 /* Provide acceptable values for these unused fields to
2067 * satisfy SyncInitTrigger's validation logic
2069 pAwait
->trigger
.value_type
= XSyncAbsolute
;
2070 pAwait
->trigger
.wait_value
= 0;
2071 pAwait
->trigger
.test_type
= 0;
2073 status
= SyncInitTrigger(client
, &pAwait
->trigger
,
2074 *pProtocolFences
, RTFence
, XSyncCAAllTrigger
);
2075 if (status
!= Success
) {
2076 /* this should take care of removing any triggers created by
2077 * this request that have already been registered on sync objects
2079 FreeResource(pAwaitUnion
->header
.delete_id
, X11_RESTYPE_NONE
);
2082 /* this is not a mistake -- same function works for both cases */
2083 pAwait
->trigger
.TriggerFired
= SyncAwaitTriggerFired
;
2084 pAwait
->trigger
.CounterDestroyed
= SyncAwaitTriggerFired
;
2085 /* event_threshold is unused for fence syncs */
2086 pAwait
->event_threshold
= 0;
2087 pAwait
->pHeader
= &pAwaitUnion
->header
;
2088 pAwaitUnion
->header
.num_waitconditions
++;
2091 SyncAwaitEpilogue(client
, items
, pAwaitUnion
);
2097 * ** Given an extension request, call the appropriate request procedure
2100 ProcSyncDispatch(ClientPtr client
)
2104 switch (stuff
->data
) {
2105 case X_SyncInitialize
:
2106 return ProcSyncInitialize(client
);
2107 case X_SyncListSystemCounters
:
2108 return ProcSyncListSystemCounters(client
);
2109 case X_SyncCreateCounter
:
2110 return ProcSyncCreateCounter(client
);
2111 case X_SyncSetCounter
:
2112 return ProcSyncSetCounter(client
);
2113 case X_SyncChangeCounter
:
2114 return ProcSyncChangeCounter(client
);
2115 case X_SyncQueryCounter
:
2116 return ProcSyncQueryCounter(client
);
2117 case X_SyncDestroyCounter
:
2118 return ProcSyncDestroyCounter(client
);
2120 return ProcSyncAwait(client
);
2121 case X_SyncCreateAlarm
:
2122 return ProcSyncCreateAlarm(client
);
2123 case X_SyncChangeAlarm
:
2124 return ProcSyncChangeAlarm(client
);
2125 case X_SyncQueryAlarm
:
2126 return ProcSyncQueryAlarm(client
);
2127 case X_SyncDestroyAlarm
:
2128 return ProcSyncDestroyAlarm(client
);
2129 case X_SyncSetPriority
:
2130 return ProcSyncSetPriority(client
);
2131 case X_SyncGetPriority
:
2132 return ProcSyncGetPriority(client
);
2133 case X_SyncCreateFence
:
2134 return ProcSyncCreateFence(client
);
2135 case X_SyncTriggerFence
:
2136 return ProcSyncTriggerFence(client
);
2137 case X_SyncResetFence
:
2138 return ProcSyncResetFence(client
);
2139 case X_SyncDestroyFence
:
2140 return ProcSyncDestroyFence(client
);
2141 case X_SyncQueryFence
:
2142 return ProcSyncQueryFence(client
);
2143 case X_SyncAwaitFence
:
2144 return ProcSyncAwaitFence(client
);
2151 * Boring Swapping stuff ...
2155 SProcSyncInitialize(ClientPtr client
)
2157 REQUEST(xSyncInitializeReq
);
2158 swaps(&stuff
->length
);
2159 REQUEST_SIZE_MATCH(xSyncInitializeReq
);
2161 return ProcSyncInitialize(client
);
2165 SProcSyncListSystemCounters(ClientPtr client
)
2167 REQUEST(xSyncListSystemCountersReq
);
2168 swaps(&stuff
->length
);
2169 REQUEST_SIZE_MATCH(xSyncListSystemCountersReq
);
2171 return ProcSyncListSystemCounters(client
);
2175 SProcSyncCreateCounter(ClientPtr client
)
2177 REQUEST(xSyncCreateCounterReq
);
2178 swaps(&stuff
->length
);
2179 REQUEST_SIZE_MATCH(xSyncCreateCounterReq
);
2181 swapl(&stuff
->initial_value_lo
);
2182 swapl(&stuff
->initial_value_hi
);
2184 return ProcSyncCreateCounter(client
);
2188 SProcSyncSetCounter(ClientPtr client
)
2190 REQUEST(xSyncSetCounterReq
);
2191 swaps(&stuff
->length
);
2192 REQUEST_SIZE_MATCH(xSyncSetCounterReq
);
2194 swapl(&stuff
->value_lo
);
2195 swapl(&stuff
->value_hi
);
2197 return ProcSyncSetCounter(client
);
2201 SProcSyncChangeCounter(ClientPtr client
)
2203 REQUEST(xSyncChangeCounterReq
);
2204 swaps(&stuff
->length
);
2205 REQUEST_SIZE_MATCH(xSyncChangeCounterReq
);
2207 swapl(&stuff
->value_lo
);
2208 swapl(&stuff
->value_hi
);
2210 return ProcSyncChangeCounter(client
);
2214 SProcSyncQueryCounter(ClientPtr client
)
2216 REQUEST(xSyncQueryCounterReq
);
2217 swaps(&stuff
->length
);
2218 REQUEST_SIZE_MATCH(xSyncQueryCounterReq
);
2219 swapl(&stuff
->counter
);
2221 return ProcSyncQueryCounter(client
);
2225 SProcSyncDestroyCounter(ClientPtr client
)
2227 REQUEST(xSyncDestroyCounterReq
);
2228 swaps(&stuff
->length
);
2229 REQUEST_SIZE_MATCH(xSyncDestroyCounterReq
);
2230 swapl(&stuff
->counter
);
2232 return ProcSyncDestroyCounter(client
);
2236 SProcSyncAwait(ClientPtr client
)
2238 REQUEST(xSyncAwaitReq
);
2239 swaps(&stuff
->length
);
2240 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq
);
2243 return ProcSyncAwait(client
);
2247 SProcSyncCreateAlarm(ClientPtr client
)
2249 REQUEST(xSyncCreateAlarmReq
);
2250 swaps(&stuff
->length
);
2251 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq
);
2253 swapl(&stuff
->valueMask
);
2256 return ProcSyncCreateAlarm(client
);
2260 SProcSyncChangeAlarm(ClientPtr client
)
2262 REQUEST(xSyncChangeAlarmReq
);
2263 swaps(&stuff
->length
);
2264 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq
);
2265 swapl(&stuff
->alarm
);
2266 swapl(&stuff
->valueMask
);
2268 return ProcSyncChangeAlarm(client
);
2272 SProcSyncQueryAlarm(ClientPtr client
)
2274 REQUEST(xSyncQueryAlarmReq
);
2275 swaps(&stuff
->length
);
2276 REQUEST_SIZE_MATCH(xSyncQueryAlarmReq
);
2277 swapl(&stuff
->alarm
);
2279 return ProcSyncQueryAlarm(client
);
2283 SProcSyncDestroyAlarm(ClientPtr client
)
2285 REQUEST(xSyncDestroyAlarmReq
);
2286 swaps(&stuff
->length
);
2287 REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq
);
2288 swapl(&stuff
->alarm
);
2290 return ProcSyncDestroyAlarm(client
);
2294 SProcSyncSetPriority(ClientPtr client
)
2296 REQUEST(xSyncSetPriorityReq
);
2297 swaps(&stuff
->length
);
2298 REQUEST_SIZE_MATCH(xSyncSetPriorityReq
);
2300 swapl(&stuff
->priority
);
2302 return ProcSyncSetPriority(client
);
2306 SProcSyncGetPriority(ClientPtr client
)
2308 REQUEST(xSyncGetPriorityReq
);
2309 swaps(&stuff
->length
);
2310 REQUEST_SIZE_MATCH(xSyncGetPriorityReq
);
2313 return ProcSyncGetPriority(client
);
2317 SProcSyncCreateFence(ClientPtr client
)
2319 REQUEST(xSyncCreateFenceReq
);
2320 swaps(&stuff
->length
);
2321 REQUEST_SIZE_MATCH(xSyncCreateFenceReq
);
2325 return ProcSyncCreateFence(client
);
2329 SProcSyncTriggerFence(ClientPtr client
)
2331 REQUEST(xSyncTriggerFenceReq
);
2332 swaps(&stuff
->length
);
2333 REQUEST_SIZE_MATCH(xSyncTriggerFenceReq
);
2336 return ProcSyncTriggerFence(client
);
2340 SProcSyncResetFence(ClientPtr client
)
2342 REQUEST(xSyncResetFenceReq
);
2343 swaps(&stuff
->length
);
2344 REQUEST_SIZE_MATCH(xSyncResetFenceReq
);
2347 return ProcSyncResetFence(client
);
2351 SProcSyncDestroyFence(ClientPtr client
)
2353 REQUEST(xSyncDestroyFenceReq
);
2354 swaps(&stuff
->length
);
2355 REQUEST_SIZE_MATCH(xSyncDestroyFenceReq
);
2358 return ProcSyncDestroyFence(client
);
2362 SProcSyncQueryFence(ClientPtr client
)
2364 REQUEST(xSyncQueryFenceReq
);
2365 swaps(&stuff
->length
);
2366 REQUEST_SIZE_MATCH(xSyncQueryFenceReq
);
2369 return ProcSyncQueryFence(client
);
2373 SProcSyncAwaitFence(ClientPtr client
)
2375 REQUEST(xSyncAwaitFenceReq
);
2376 swaps(&stuff
->length
);
2377 REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq
);
2380 return ProcSyncAwaitFence(client
);
2384 SProcSyncDispatch(ClientPtr client
)
2388 switch (stuff
->data
) {
2389 case X_SyncInitialize
:
2390 return SProcSyncInitialize(client
);
2391 case X_SyncListSystemCounters
:
2392 return SProcSyncListSystemCounters(client
);
2393 case X_SyncCreateCounter
:
2394 return SProcSyncCreateCounter(client
);
2395 case X_SyncSetCounter
:
2396 return SProcSyncSetCounter(client
);
2397 case X_SyncChangeCounter
:
2398 return SProcSyncChangeCounter(client
);
2399 case X_SyncQueryCounter
:
2400 return SProcSyncQueryCounter(client
);
2401 case X_SyncDestroyCounter
:
2402 return SProcSyncDestroyCounter(client
);
2404 return SProcSyncAwait(client
);
2405 case X_SyncCreateAlarm
:
2406 return SProcSyncCreateAlarm(client
);
2407 case X_SyncChangeAlarm
:
2408 return SProcSyncChangeAlarm(client
);
2409 case X_SyncQueryAlarm
:
2410 return SProcSyncQueryAlarm(client
);
2411 case X_SyncDestroyAlarm
:
2412 return SProcSyncDestroyAlarm(client
);
2413 case X_SyncSetPriority
:
2414 return SProcSyncSetPriority(client
);
2415 case X_SyncGetPriority
:
2416 return SProcSyncGetPriority(client
);
2417 case X_SyncCreateFence
:
2418 return SProcSyncCreateFence(client
);
2419 case X_SyncTriggerFence
:
2420 return SProcSyncTriggerFence(client
);
2421 case X_SyncResetFence
:
2422 return SProcSyncResetFence(client
);
2423 case X_SyncDestroyFence
:
2424 return SProcSyncDestroyFence(client
);
2425 case X_SyncQueryFence
:
2426 return SProcSyncQueryFence(client
);
2427 case X_SyncAwaitFence
:
2428 return SProcSyncAwaitFence(client
);
2439 SCounterNotifyEvent(xSyncCounterNotifyEvent
* from
,
2440 xSyncCounterNotifyEvent
* to
)
2442 to
->type
= from
->type
;
2443 to
->kind
= from
->kind
;
2444 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
2445 cpswapl(from
->counter
, to
->counter
);
2446 cpswapl(from
->wait_value_lo
, to
->wait_value_lo
);
2447 cpswapl(from
->wait_value_hi
, to
->wait_value_hi
);
2448 cpswapl(from
->counter_value_lo
, to
->counter_value_lo
);
2449 cpswapl(from
->counter_value_hi
, to
->counter_value_hi
);
2450 cpswapl(from
->time
, to
->time
);
2451 cpswaps(from
->count
, to
->count
);
2452 to
->destroyed
= from
->destroyed
;
2456 SAlarmNotifyEvent(xSyncAlarmNotifyEvent
* from
, xSyncAlarmNotifyEvent
* to
)
2458 to
->type
= from
->type
;
2459 to
->kind
= from
->kind
;
2460 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
2461 cpswapl(from
->alarm
, to
->alarm
);
2462 cpswapl(from
->counter_value_lo
, to
->counter_value_lo
);
2463 cpswapl(from
->counter_value_hi
, to
->counter_value_hi
);
2464 cpswapl(from
->alarm_value_lo
, to
->alarm_value_lo
);
2465 cpswapl(from
->alarm_value_hi
, to
->alarm_value_hi
);
2466 cpswapl(from
->time
, to
->time
);
2467 to
->state
= from
->state
;
2471 * ** Close everything down. ** This is fairly simple for now.
2475 SyncResetProc(ExtensionEntry
* extEntry
)
2481 * ** Initialise the extension.
2484 SyncExtensionInit(void)
2486 ExtensionEntry
*extEntry
;
2489 for (s
= 0; s
< screenInfo
.numScreens
; s
++)
2490 miSyncSetup(screenInfo
.screens
[s
]);
2492 RTCounter
= CreateNewResourceType(FreeCounter
, "SyncCounter");
2493 xorg_list_init(&SysCounterList
);
2494 RTAlarm
= CreateNewResourceType(FreeAlarm
, "SyncAlarm");
2495 RTAwait
= CreateNewResourceType(FreeAwait
, "SyncAwait");
2496 RTFence
= CreateNewResourceType(FreeFence
, "SyncFence");
2498 RTAwait
|= RC_NEVERRETAIN
;
2499 RTAlarmClient
= CreateNewResourceType(FreeAlarmClient
, "SyncAlarmClient");
2501 RTAlarmClient
|= RC_NEVERRETAIN
;
2503 if (RTCounter
== 0 || RTAwait
== 0 || RTAlarm
== 0 ||
2504 RTAlarmClient
== 0 ||
2505 (extEntry
= AddExtension(SYNC_NAME
,
2506 XSyncNumberEvents
, XSyncNumberErrors
,
2507 ProcSyncDispatch
, SProcSyncDispatch
,
2508 SyncResetProc
, StandardMinorOpcode
)) == NULL
) {
2509 ErrorF("Sync Extension %d.%d failed to Initialise\n",
2510 SYNC_MAJOR_VERSION
, SYNC_MINOR_VERSION
);
2514 SyncEventBase
= extEntry
->eventBase
;
2515 SyncErrorBase
= extEntry
->errorBase
;
2516 EventSwapVector
[SyncEventBase
+ XSyncCounterNotify
] =
2517 (EventSwapPtr
) SCounterNotifyEvent
;
2518 EventSwapVector
[SyncEventBase
+ XSyncAlarmNotify
] =
2519 (EventSwapPtr
) SAlarmNotifyEvent
;
2521 SetResourceTypeErrorValue(RTCounter
, SyncErrorBase
+ XSyncBadCounter
);
2522 SetResourceTypeErrorValue(RTAlarm
, SyncErrorBase
+ XSyncBadAlarm
);
2523 SetResourceTypeErrorValue(RTFence
, SyncErrorBase
+ XSyncBadFence
);
2526 * Although SERVERTIME is implemented by the OS layer, we initialise it
2527 * here because doing it in OsInit() is too early. The resource database
2528 * is not initialised when OsInit() is called. This is just about OK
2529 * because there is always a servertime counter.
2531 SyncInitServerTime();
2535 fprintf(stderr
, "Sync Extension %d.%d\n",
2536 SYNC_MAJOR_VERSION
, SYNC_MINOR_VERSION
);
2541 * ***** SERVERTIME implementation - should go in its own file in OS directory?
2544 static void *ServertimeCounter
;
2546 static int64_t *pnext_time
;
2548 static void GetTime(void)
2550 unsigned long millis
= GetTimeInMillis();
2551 unsigned long maxis
= Now
>> 32;
2553 if (millis
< (Now
& 0xffffffff))
2556 Now
= ((int64_t)maxis
<< 32) | millis
;
2560 *** Server Block Handler
2561 *** code inspired by multibuffer extension (now deprecated)
2563 /*ARGSUSED*/ static void
2564 ServertimeBlockHandler(void *env
, void *wt
)
2566 unsigned long timeout
;
2571 if (Now
>= *pnext_time
) {
2575 timeout
= *pnext_time
- Now
;
2577 AdjustWaitForDelay(wt
, timeout
); /* os/utils.c */
2584 /*ARGSUSED*/ static void
2585 ServertimeWakeupHandler(void *env
, int rc
)
2590 if (Now
>= *pnext_time
) {
2591 SyncChangeCounter(ServertimeCounter
, Now
);
2597 ServertimeQueryValue(void *pCounter
, int64_t *pValue_return
)
2600 *pValue_return
= Now
;
2604 ServertimeBracketValues(void *pCounter
, int64_t *pbracket_less
,
2605 int64_t *pbracket_greater
)
2607 if (!pnext_time
&& pbracket_greater
) {
2608 RegisterBlockAndWakeupHandlers(ServertimeBlockHandler
,
2609 ServertimeWakeupHandler
, NULL
);
2611 else if (pnext_time
&& !pbracket_greater
) {
2612 RemoveBlockAndWakeupHandlers(ServertimeBlockHandler
,
2613 ServertimeWakeupHandler
, NULL
);
2615 pnext_time
= pbracket_greater
;
2619 SyncInitServerTime(void)
2621 int64_t resolution
= 4;
2623 Now
= GetTimeInMillis();
2624 ServertimeCounter
= SyncCreateSystemCounter("SERVERTIME", Now
, resolution
,
2625 XSyncCounterNeverDecreases
,
2626 ServertimeQueryValue
,
2627 ServertimeBracketValues
);
2632 * IDLETIME implementation
2636 int64_t *value_less
;
2637 int64_t *value_greater
;
2642 IdleTimeQueryValue(void *pCounter
, int64_t *pValue_return
)
2648 SyncCounter
*counter
= pCounter
;
2649 IdleCounterPriv
*priv
= SysCounterGetPrivate(counter
);
2650 deviceid
= priv
->deviceid
;
2653 deviceid
= XIAllDevices
;
2654 idle
= GetTimeInMillis() - LastEventTime(deviceid
).milliseconds
;
2655 *pValue_return
= idle
;
2659 IdleTimeBlockHandler(void *pCounter
, void *wt
)
2661 SyncCounter
*counter
= pCounter
;
2662 IdleCounterPriv
*priv
= SysCounterGetPrivate(counter
);
2663 int64_t *less
= priv
->value_less
;
2664 int64_t *greater
= priv
->value_greater
;
2665 int64_t idle
, old_idle
;
2666 SyncTriggerList
*list
= counter
->sync
.pTriglist
;
2669 if (!less
&& !greater
)
2672 old_idle
= counter
->value
;
2673 IdleTimeQueryValue(counter
, &idle
);
2674 counter
->value
= idle
; /* push, so CheckTrigger works */
2677 * There's an indefinite amount of time between ProcessInputEvents()
2678 * where the idle time is reset and the time we actually get here. idle
2679 * may be past the lower bracket if we dawdled with the events, so
2680 * check for whether we did reset and bomb out of select immediately.
2682 if (less
&& idle
> *less
&&
2683 LastEventTimeWasReset(priv
->deviceid
)) {
2684 AdjustWaitForDelay(wt
, 0);
2685 } else if (less
&& idle
<= *less
) {
2687 * We've been idle for less than the threshold value, and someone
2688 * wants to know about that, but now we need to know whether they
2689 * want level or edge trigger. Check the trigger list against the
2690 * current idle time, and if any succeed, bomb out of select()
2691 * immediately so we can reschedule.
2694 for (list
= counter
->sync
.pTriglist
; list
; list
= list
->next
) {
2695 trig
= list
->pTrigger
;
2696 if (trig
->CheckTrigger(trig
, old_idle
)) {
2697 AdjustWaitForDelay(wt
, 0);
2702 * We've been called exactly on the idle time, but we have a
2703 * NegativeTransition trigger which requires a transition from an
2704 * idle time greater than this. Schedule a wakeup for the next
2705 * millisecond so we won't miss a transition.
2708 AdjustWaitForDelay(wt
, 1);
2712 * There's a threshold in the positive direction. If we've been
2713 * idle less than it, schedule a wakeup for sometime in the future.
2714 * If we've been idle more than it, and someone wants to know about
2715 * that level-triggered, schedule an immediate wakeup.
2718 if (idle
< *greater
) {
2719 AdjustWaitForDelay(wt
, *greater
- idle
);
2722 for (list
= counter
->sync
.pTriglist
; list
;
2723 list
= list
->next
) {
2724 trig
= list
->pTrigger
;
2725 if (trig
->CheckTrigger(trig
, old_idle
)) {
2726 AdjustWaitForDelay(wt
, 0);
2733 counter
->value
= old_idle
; /* pop */
2737 IdleTimeCheckBrackets(SyncCounter
*counter
, int64_t idle
,
2738 int64_t *less
, int64_t *greater
)
2740 if ((greater
&& idle
>= *greater
) ||
2741 (less
&& idle
<= *less
)) {
2742 SyncChangeCounter(counter
, idle
);
2745 SyncUpdateCounter(counter
, idle
);
2749 IdleTimeWakeupHandler(void *pCounter
, int rc
)
2751 SyncCounter
*counter
= pCounter
;
2752 IdleCounterPriv
*priv
= SysCounterGetPrivate(counter
);
2753 int64_t *less
= priv
->value_less
;
2754 int64_t *greater
= priv
->value_greater
;
2757 if (!less
&& !greater
)
2760 IdleTimeQueryValue(pCounter
, &idle
);
2763 There is no guarantee for the WakeupHandler to be called within a specific
2764 timeframe. Idletime may go to 0, but by the time we get here, it may be
2765 non-zero and alarms for a pos. transition on 0 won't get triggered.
2766 https://bugs.freedesktop.org/show_bug.cgi?id=70476
2768 if (LastEventTimeWasReset(priv
->deviceid
)) {
2769 LastEventTimeToggleResetFlag(priv
->deviceid
, FALSE
);
2771 IdleTimeCheckBrackets(counter
, 0, less
, greater
);
2772 less
= priv
->value_less
;
2773 greater
= priv
->value_greater
;
2777 IdleTimeCheckBrackets(counter
, idle
, less
, greater
);
2781 IdleTimeBracketValues(void *pCounter
, int64_t *pbracket_less
,
2782 int64_t *pbracket_greater
)
2784 SyncCounter
*counter
= pCounter
;
2785 IdleCounterPriv
*priv
= SysCounterGetPrivate(counter
);
2786 int64_t *less
= priv
->value_less
;
2787 int64_t *greater
= priv
->value_greater
;
2788 Bool registered
= (less
|| greater
);
2790 if (registered
&& !pbracket_less
&& !pbracket_greater
) {
2791 RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler
,
2792 IdleTimeWakeupHandler
, pCounter
);
2794 else if (!registered
&& (pbracket_less
|| pbracket_greater
)) {
2795 /* Reset flag must be zero so we don't force a idle timer reset on
2797 LastEventTimeToggleResetAll(FALSE
);
2798 RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler
,
2799 IdleTimeWakeupHandler
, pCounter
);
2802 priv
->value_greater
= pbracket_greater
;
2803 priv
->value_less
= pbracket_less
;
2807 init_system_idle_counter(const char *name
, int deviceid
)
2809 int64_t resolution
= 4;
2811 SyncCounter
*idle_time_counter
;
2813 IdleTimeQueryValue(NULL
, &idle
);
2815 idle_time_counter
= SyncCreateSystemCounter(name
, idle
, resolution
,
2816 XSyncCounterUnrestricted
,
2818 IdleTimeBracketValues
);
2820 if (idle_time_counter
!= NULL
) {
2821 IdleCounterPriv
*priv
= malloc(sizeof(IdleCounterPriv
));
2823 priv
->value_less
= priv
->value_greater
= NULL
;
2824 priv
->deviceid
= deviceid
;
2826 idle_time_counter
->pSysCounterInfo
->private = priv
;
2829 return idle_time_counter
;
2833 SyncInitIdleTime(void)
2835 init_system_idle_counter("IDLETIME", XIAllDevices
);
2839 SyncInitDeviceIdleTime(DeviceIntPtr dev
)
2841 char timer_name
[64];
2842 sprintf(timer_name
, "DEVICEIDLETIME %d", dev
->id
);
2844 return init_system_idle_counter(timer_name
, dev
->id
);
2847 void SyncRemoveDeviceIdleTime(SyncCounter
*counter
)
2849 /* FreeAllResources() frees all system counters before the devices are
2850 shut down, check if there are any left before freeing the device's
2852 if (counter
&& !xorg_list_is_empty(&SysCounterList
))
2853 xorg_list_del(&counter
->pSysCounterInfo
->entry
);