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