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