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