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