sync.c revision a0d10bb6
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 == XSyncNegativeTransition && 1172 ct != XSyncCounterNeverIncreases) 1173 { 1174 if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1175 XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) 1176 { 1177 psci->bracket_less = pTrigger->test_value; 1178 pnewltval = &psci->bracket_less; 1179 } 1180 } 1181 else if (pTrigger->test_type == XSyncPositiveTransition && 1182 ct != XSyncCounterNeverDecreases) 1183 { 1184 if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1185 XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) 1186 { 1187 psci->bracket_greater = pTrigger->test_value; 1188 pnewgtval = &psci->bracket_greater; 1189 } 1190 } 1191 } /* end for each trigger */ 1192 1193 if (pnewgtval || pnewltval) 1194 { 1195 (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); 1196 } 1197} 1198 1199/* 1200 * ***** Resource delete functions 1201 */ 1202 1203/* ARGSUSED */ 1204static int 1205FreeAlarm(addr, id) 1206 pointer addr; 1207 XID id; 1208{ 1209 SyncAlarm *pAlarm = (SyncAlarm *) addr; 1210 1211 pAlarm->state = XSyncAlarmDestroyed; 1212 1213 SyncSendAlarmNotifyEvents(pAlarm); 1214 1215 /* delete event selections */ 1216 1217 while (pAlarm->pEventClients) 1218 FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 1219 1220 SyncDeleteTriggerFromCounter(&pAlarm->trigger); 1221 1222 xfree(pAlarm); 1223 return Success; 1224} 1225 1226 1227/* 1228 * ** Cleanup after the destruction of a Counter 1229 */ 1230/* ARGSUSED */ 1231static int 1232FreeCounter(env, id) 1233 pointer env; 1234 XID id; 1235{ 1236 SyncCounter *pCounter = (SyncCounter *) env; 1237 SyncTriggerList *ptl, *pnext; 1238 1239 pCounter->beingDestroyed = TRUE; 1240 /* tell all the counter's triggers that the counter has been destroyed */ 1241 for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 1242 { 1243 (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); 1244 pnext = ptl->next; 1245 xfree(ptl); /* destroy the trigger list as we go */ 1246 } 1247 if (IsSystemCounter(pCounter)) 1248 { 1249 int i, found = 0; 1250 1251 xfree(pCounter->pSysCounterInfo); 1252 1253 /* find the counter in the list of system counters and remove it */ 1254 1255 if (SysCounterList) 1256 { 1257 for (i = 0; i < SyncNumSystemCounters; i++) 1258 { 1259 if (SysCounterList[i] == pCounter) 1260 { 1261 found = i; 1262 break; 1263 } 1264 } 1265 if (found < (SyncNumSystemCounters-1)) 1266 { 1267 for (i = found; i < SyncNumSystemCounters-1; i++) 1268 { 1269 SysCounterList[i] = SysCounterList[i+1]; 1270 } 1271 } 1272 } 1273 SyncNumSystemCounters--; 1274 } 1275 xfree(pCounter); 1276 return Success; 1277} 1278 1279/* 1280 * ** Cleanup after Await 1281 */ 1282/* ARGSUSED */ 1283static int 1284FreeAwait(addr, id) 1285 pointer addr; 1286 XID id; 1287{ 1288 SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 1289 SyncAwait *pAwait; 1290 int numwaits; 1291 1292 pAwait = &(pAwaitUnion+1)->await; /* first await on list */ 1293 1294 /* remove triggers from counters */ 1295 1296 for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 1297 numwaits--, pAwait++) 1298 { 1299 /* If the counter is being destroyed, FreeCounter will delete 1300 * the trigger list itself, so don't do it here. 1301 */ 1302 SyncCounter *pCounter = pAwait->trigger.pCounter; 1303 if (pCounter && !pCounter->beingDestroyed) 1304 SyncDeleteTriggerFromCounter(&pAwait->trigger); 1305 } 1306 xfree(pAwaitUnion); 1307 return Success; 1308} 1309 1310/* loosely based on dix/events.c/OtherClientGone */ 1311static int 1312FreeAlarmClient(value, id) 1313 pointer value; /* must conform to DeleteType */ 1314 XID id; 1315{ 1316 SyncAlarm *pAlarm = (SyncAlarm *)value; 1317 SyncAlarmClientList *pCur, *pPrev; 1318 1319 for (pPrev = NULL, pCur = pAlarm->pEventClients; 1320 pCur; 1321 pPrev = pCur, pCur = pCur->next) 1322 { 1323 if (pCur->delete_id == id) 1324 { 1325 if (pPrev) 1326 pPrev->next = pCur->next; 1327 else 1328 pAlarm->pEventClients = pCur->next; 1329 xfree(pCur); 1330 return(Success); 1331 } 1332 } 1333 FatalError("alarm client not on event list"); 1334 /*NOTREACHED*/ 1335} 1336 1337 1338/* 1339 * ***** Proc functions 1340 */ 1341 1342 1343/* 1344 * ** Initialize the extension 1345 */ 1346static int 1347ProcSyncInitialize(client) 1348 ClientPtr client; 1349{ 1350 xSyncInitializeReply rep; 1351 int n; 1352 1353 REQUEST_SIZE_MATCH(xSyncInitializeReq); 1354 1355 rep.type = X_Reply; 1356 rep.sequenceNumber = client->sequence; 1357 rep.majorVersion = SYNC_MAJOR_VERSION; 1358 rep.minorVersion = SYNC_MINOR_VERSION; 1359 rep.length = 0; 1360 1361 if (client->swapped) 1362 { 1363 swaps(&rep.sequenceNumber, n); 1364 } 1365 WriteToClient(client, sizeof(rep), (char *) &rep); 1366 return (client->noClientException); 1367} 1368 1369/* 1370 * ** Get list of system counters available through the extension 1371 */ 1372static int 1373ProcSyncListSystemCounters(client) 1374 ClientPtr client; 1375{ 1376 xSyncListSystemCountersReply rep; 1377 int i, len; 1378 xSyncSystemCounter *list = NULL, *walklist = NULL; 1379 1380 REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 1381 1382 rep.type = X_Reply; 1383 rep.sequenceNumber = client->sequence; 1384 rep.nCounters = SyncNumSystemCounters; 1385 1386 for (i = len = 0; i < SyncNumSystemCounters; i++) 1387 { 1388 char *name = SysCounterList[i]->pSysCounterInfo->name; 1389 /* pad to 4 byte boundary */ 1390 len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3; 1391 } 1392 1393 if (len) 1394 { 1395 walklist = list = (xSyncSystemCounter *) xalloc(len); 1396 if (!list) 1397 return BadAlloc; 1398 } 1399 1400 rep.length = len >> 2; 1401 1402 if (client->swapped) 1403 { 1404 char n; 1405 swaps(&rep.sequenceNumber, n); 1406 swapl(&rep.length, n); 1407 swapl(&rep.nCounters, n); 1408 } 1409 1410 for (i = 0; i < SyncNumSystemCounters; i++) 1411 { 1412 int namelen; 1413 char *pname_in_reply; 1414 SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; 1415 1416 walklist->counter = SysCounterList[i]->id; 1417 walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 1418 walklist->resolution_lo = XSyncValueLow32(psci->resolution); 1419 namelen = strlen(psci->name); 1420 walklist->name_length = namelen; 1421 1422 if (client->swapped) 1423 { 1424 char n; 1425 swapl(&walklist->counter, n); 1426 swapl(&walklist->resolution_hi, n); 1427 swapl(&walklist->resolution_lo, n); 1428 swaps(&walklist->name_length, n); 1429 } 1430 1431 pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; 1432 strncpy(pname_in_reply, psci->name, namelen); 1433 walklist = (xSyncSystemCounter *) (((char *)walklist) + 1434 ((sz_xSyncSystemCounter + namelen + 3) & ~3)); 1435 } 1436 1437 WriteToClient(client, sizeof(rep), (char *) &rep); 1438 if (len) 1439 { 1440 WriteToClient(client, len, (char *) list); 1441 xfree(list); 1442 } 1443 1444 return (client->noClientException); 1445} 1446 1447/* 1448 * ** Set client Priority 1449 */ 1450static int 1451ProcSyncSetPriority(client) 1452 ClientPtr client; 1453{ 1454 REQUEST(xSyncSetPriorityReq); 1455 ClientPtr priorityclient; 1456 int rc; 1457 1458 REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 1459 1460 if (stuff->id == None) 1461 priorityclient = client; 1462 else { 1463 rc = dixLookupClient(&priorityclient, stuff->id, client, 1464 DixSetAttrAccess); 1465 if (rc != Success) 1466 return rc; 1467 } 1468 1469 if (priorityclient->priority != stuff->priority) 1470 { 1471 priorityclient->priority = stuff->priority; 1472 1473 /* The following will force the server back into WaitForSomething 1474 * so that the change in this client's priority is immediately 1475 * reflected. 1476 */ 1477 isItTimeToYield = TRUE; 1478 dispatchException |= DE_PRIORITYCHANGE; 1479 } 1480 return Success; 1481} 1482 1483/* 1484 * ** Get client Priority 1485 */ 1486static int 1487ProcSyncGetPriority(client) 1488 ClientPtr client; 1489{ 1490 REQUEST(xSyncGetPriorityReq); 1491 xSyncGetPriorityReply rep; 1492 ClientPtr priorityclient; 1493 int rc; 1494 1495 REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 1496 1497 if (stuff->id == None) 1498 priorityclient = client; 1499 else { 1500 rc = dixLookupClient(&priorityclient, stuff->id, client, 1501 DixGetAttrAccess); 1502 if (rc != Success) 1503 return rc; 1504 } 1505 1506 rep.type = X_Reply; 1507 rep.length = 0; 1508 rep.sequenceNumber = client->sequence; 1509 rep.priority = priorityclient->priority; 1510 1511 if (client->swapped) 1512 { 1513 char n; 1514 swaps(&rep.sequenceNumber, n); 1515 swapl(&rep.priority, n); 1516 } 1517 1518 WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); 1519 1520 return (client->noClientException); 1521} 1522 1523/* 1524 * ** Create a new counter 1525 */ 1526static int 1527ProcSyncCreateCounter(client) 1528 ClientPtr client; 1529{ 1530 REQUEST(xSyncCreateCounterReq); 1531 CARD64 initial; 1532 1533 REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 1534 1535 LEGAL_NEW_RESOURCE(stuff->cid, client); 1536 1537 XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); 1538 if (!SyncCreateCounter(client, stuff->cid, initial)) 1539 return BadAlloc; 1540 1541 return (client->noClientException); 1542} 1543 1544/* 1545 * ** Set Counter value 1546 */ 1547static int 1548ProcSyncSetCounter(client) 1549 ClientPtr client; 1550{ 1551 REQUEST(xSyncSetCounterReq); 1552 SyncCounter *pCounter; 1553 CARD64 newvalue; 1554 1555 REQUEST_SIZE_MATCH(xSyncSetCounterReq); 1556 1557 pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid, 1558 RTCounter, DixWriteAccess); 1559 if (pCounter == NULL) 1560 { 1561 client->errorValue = stuff->cid; 1562 return SyncErrorBase + XSyncBadCounter; 1563 } 1564 1565 if (IsSystemCounter(pCounter)) 1566 { 1567 client->errorValue = stuff->cid; 1568 return BadAccess; 1569 } 1570 1571 XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 1572 SyncChangeCounter(pCounter, newvalue); 1573 return Success; 1574} 1575 1576/* 1577 * ** Change Counter value 1578 */ 1579static int 1580ProcSyncChangeCounter(client) 1581 ClientPtr client; 1582{ 1583 REQUEST(xSyncChangeCounterReq); 1584 SyncCounter *pCounter; 1585 CARD64 newvalue; 1586 Bool overflow; 1587 1588 REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 1589 1590 pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, 1591 RTCounter, DixWriteAccess); 1592 if (pCounter == NULL) 1593 { 1594 client->errorValue = stuff->cid; 1595 return SyncErrorBase + XSyncBadCounter; 1596 } 1597 1598 if (IsSystemCounter(pCounter)) 1599 { 1600 client->errorValue = stuff->cid; 1601 return BadAccess; 1602 } 1603 1604 XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 1605 XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 1606 if (overflow) 1607 { 1608 /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 1609 client->errorValue = stuff->value_hi; 1610 return BadValue; 1611 } 1612 SyncChangeCounter(pCounter, newvalue); 1613 return Success; 1614} 1615 1616/* 1617 * ** Destroy a counter 1618 */ 1619static int 1620ProcSyncDestroyCounter(client) 1621 ClientPtr client; 1622{ 1623 REQUEST(xSyncDestroyCounterReq); 1624 SyncCounter *pCounter; 1625 1626 REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 1627 1628 pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, 1629 RTCounter, DixDestroyAccess); 1630 if (pCounter == NULL) 1631 { 1632 client->errorValue = stuff->counter; 1633 return SyncErrorBase + XSyncBadCounter; 1634 } 1635 if (IsSystemCounter(pCounter)) 1636 { 1637 client->errorValue = stuff->counter; 1638 return BadAccess; 1639 } 1640 FreeResource(pCounter->id, RT_NONE); 1641 return Success; 1642} 1643 1644 1645/* 1646 * ** Await 1647 */ 1648static int 1649ProcSyncAwait(client) 1650 ClientPtr client; 1651{ 1652 REQUEST(xSyncAwaitReq); 1653 int len, items; 1654 int i; 1655 xSyncWaitCondition *pProtocolWaitConds; 1656 SyncAwaitUnion *pAwaitUnion; 1657 SyncAwait *pAwait; 1658 int status; 1659 1660 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 1661 1662 len = client->req_len << 2; 1663 len -= sz_xSyncAwaitReq; 1664 items = len / sz_xSyncWaitCondition; 1665 1666 if (items * sz_xSyncWaitCondition != len) 1667 { 1668 return BadLength; 1669 } 1670 if (items == 0) 1671 { 1672 client->errorValue = items; /* XXX protocol change */ 1673 return BadValue; 1674 } 1675 1676 pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; 1677 1678 /* all the memory for the entire await list is allocated 1679 * here in one chunk 1680 */ 1681 pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion)); 1682 if (!pAwaitUnion) 1683 return BadAlloc; 1684 1685 /* first item is the header, remainder are real wait conditions */ 1686 1687 pAwaitUnion->header.delete_id = FakeClientID(client->index); 1688 if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 1689 { 1690 xfree(pAwaitUnion); 1691 return BadAlloc; 1692 } 1693 1694 /* don't need to do any more memory allocation for this request! */ 1695 1696 pAwaitUnion->header.client = client; 1697 pAwaitUnion->header.num_waitconditions = 0; 1698 1699 pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 1700 for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) 1701 { 1702 if (pProtocolWaitConds->counter == None) /* XXX protocol change */ 1703 { 1704 /* this should take care of removing any triggers created by 1705 * this request that have already been registered on counters 1706 */ 1707 FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 1708 client->errorValue = pProtocolWaitConds->counter; 1709 return SyncErrorBase + XSyncBadCounter; 1710 } 1711 1712 /* sanity checks are in SyncInitTrigger */ 1713 pAwait->trigger.pCounter = NULL; 1714 pAwait->trigger.value_type = pProtocolWaitConds->value_type; 1715 XSyncIntsToValue(&pAwait->trigger.wait_value, 1716 pProtocolWaitConds->wait_value_lo, 1717 pProtocolWaitConds->wait_value_hi); 1718 pAwait->trigger.test_type = pProtocolWaitConds->test_type; 1719 1720 status = SyncInitTrigger(client, &pAwait->trigger, 1721 pProtocolWaitConds->counter, XSyncCAAllTrigger); 1722 if (status != Success) 1723 { 1724 /* this should take care of removing any triggers created by 1725 * this request that have already been registered on counters 1726 */ 1727 FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 1728 return status; 1729 } 1730 /* this is not a mistake -- same function works for both cases */ 1731 pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 1732 pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 1733 XSyncIntsToValue(&pAwait->event_threshold, 1734 pProtocolWaitConds->event_threshold_lo, 1735 pProtocolWaitConds->event_threshold_hi); 1736 pAwait->pHeader = &pAwaitUnion->header; 1737 pAwaitUnion->header.num_waitconditions++; 1738 } 1739 1740 IgnoreClient(client); 1741 1742 /* see if any of the triggers are already true */ 1743 1744 pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 1745 for (i = 0; i < items; i++, pAwait++) 1746 { 1747 /* don't have to worry about NULL counters because the request 1748 * errors before we get here out if they occur 1749 */ 1750 if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, 1751 pAwait->trigger.pCounter->value)) 1752 { 1753 (*pAwait->trigger.TriggerFired)(&pAwait->trigger); 1754 break; /* once is enough */ 1755 } 1756 } 1757 return Success; 1758} 1759 1760 1761/* 1762 * ** Query a counter 1763 */ 1764static int 1765ProcSyncQueryCounter(client) 1766 ClientPtr client; 1767{ 1768 REQUEST(xSyncQueryCounterReq); 1769 xSyncQueryCounterReply rep; 1770 SyncCounter *pCounter; 1771 1772 REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 1773 1774 pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, 1775 RTCounter, DixReadAccess); 1776 if (pCounter == NULL) 1777 { 1778 client->errorValue = stuff->counter; 1779 return SyncErrorBase + XSyncBadCounter; 1780 } 1781 1782 rep.type = X_Reply; 1783 rep.length = 0; 1784 rep.sequenceNumber = client->sequence; 1785 1786 /* if system counter, ask it what the current value is */ 1787 1788 if (IsSystemCounter(pCounter)) 1789 { 1790 (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 1791 &pCounter->value); 1792 } 1793 1794 rep.value_hi = XSyncValueHigh32(pCounter->value); 1795 rep.value_lo = XSyncValueLow32(pCounter->value); 1796 if (client->swapped) 1797 { 1798 char n; 1799 swaps(&rep.sequenceNumber, n); 1800 swapl(&rep.length, n); 1801 swapl(&rep.value_hi, n); 1802 swapl(&rep.value_lo, n); 1803 } 1804 WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); 1805 return (client->noClientException); 1806} 1807 1808 1809/* 1810 * ** Create Alarm 1811 */ 1812static int 1813ProcSyncCreateAlarm(client) 1814 ClientPtr client; 1815{ 1816 REQUEST(xSyncCreateAlarmReq); 1817 SyncAlarm *pAlarm; 1818 int status; 1819 unsigned long len, vmask; 1820 SyncTrigger *pTrigger; 1821 1822 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 1823 1824 LEGAL_NEW_RESOURCE(stuff->id, client); 1825 1826 vmask = stuff->valueMask; 1827 len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2); 1828 /* the "extra" call to Ones accounts for the presence of 64 bit values */ 1829 if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 1830 return BadLength; 1831 1832 if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm)))) 1833 { 1834 return BadAlloc; 1835 } 1836 1837 /* set up defaults */ 1838 1839 pTrigger = &pAlarm->trigger; 1840 pTrigger->pCounter = NULL; 1841 pTrigger->value_type = XSyncAbsolute; 1842 XSyncIntToValue(&pTrigger->wait_value, 0L); 1843 pTrigger->test_type = XSyncPositiveComparison; 1844 pTrigger->TriggerFired = SyncAlarmTriggerFired; 1845 pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 1846 status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); 1847 if (status != Success) 1848 { 1849 xfree(pAlarm); 1850 return status; 1851 } 1852 1853 pAlarm->client = client; 1854 pAlarm->alarm_id = stuff->id; 1855 XSyncIntToValue(&pAlarm->delta, 1L); 1856 pAlarm->events = TRUE; 1857 pAlarm->state = XSyncAlarmInactive; 1858 pAlarm->pEventClients = NULL; 1859 status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 1860 (CARD32 *)&stuff[1]); 1861 if (status != Success) 1862 { 1863 xfree(pAlarm); 1864 return status; 1865 } 1866 1867 if (!AddResource(stuff->id, RTAlarm, pAlarm)) 1868 { 1869 xfree(pAlarm); 1870 return BadAlloc; 1871 } 1872 1873 /* see if alarm already triggered. NULL counter will not trigger 1874 * in CreateAlarm and sets alarm state to Inactive. 1875 */ 1876 1877 if (!pTrigger->pCounter) 1878 { 1879 pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 1880 } 1881 else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) 1882 { 1883 (*pTrigger->TriggerFired)(pTrigger); 1884 } 1885 1886 return Success; 1887} 1888 1889/* 1890 * ** Change Alarm 1891 */ 1892static int 1893ProcSyncChangeAlarm(client) 1894 ClientPtr client; 1895{ 1896 REQUEST(xSyncChangeAlarmReq); 1897 SyncAlarm *pAlarm; 1898 long vmask; 1899 int len, status; 1900 1901 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 1902 1903 if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 1904 RTAlarm, DixWriteAccess))) 1905 { 1906 client->errorValue = stuff->alarm; 1907 return SyncErrorBase + XSyncBadAlarm; 1908 } 1909 1910 vmask = stuff->valueMask; 1911 len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2); 1912 /* the "extra" call to Ones accounts for the presence of 64 bit values */ 1913 if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 1914 return BadLength; 1915 1916 if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 1917 (CARD32 *)&stuff[1])) != Success) 1918 return status; 1919 1920 /* see if alarm already triggered. NULL counter WILL trigger 1921 * in ChangeAlarm. 1922 */ 1923 1924 if (!pAlarm->trigger.pCounter || 1925 (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, 1926 pAlarm->trigger.pCounter->value)) 1927 { 1928 (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); 1929 } 1930 return Success; 1931} 1932 1933static int 1934ProcSyncQueryAlarm(client) 1935 ClientPtr client; 1936{ 1937 REQUEST(xSyncQueryAlarmReq); 1938 SyncAlarm *pAlarm; 1939 xSyncQueryAlarmReply rep; 1940 SyncTrigger *pTrigger; 1941 1942 REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 1943 1944 pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 1945 RTAlarm, DixReadAccess); 1946 if (!pAlarm) 1947 { 1948 client->errorValue = stuff->alarm; 1949 return (SyncErrorBase + XSyncBadAlarm); 1950 } 1951 1952 rep.type = X_Reply; 1953 rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2; 1954 rep.sequenceNumber = client->sequence; 1955 1956 pTrigger = &pAlarm->trigger; 1957 rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; 1958 1959#if 0 /* XXX unclear what to do, depends on whether relative value-types 1960 * are "consumed" immediately and are considered absolute from then 1961 * on. 1962 */ 1963 rep.value_type = pTrigger->value_type; 1964 rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); 1965 rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); 1966#else 1967 rep.value_type = XSyncAbsolute; 1968 rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 1969 rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); 1970#endif 1971 1972 rep.test_type = pTrigger->test_type; 1973 rep.delta_hi = XSyncValueHigh32(pAlarm->delta); 1974 rep.delta_lo = XSyncValueLow32(pAlarm->delta); 1975 rep.events = pAlarm->events; 1976 rep.state = pAlarm->state; 1977 1978 if (client->swapped) 1979 { 1980 char n; 1981 swaps(&rep.sequenceNumber, n); 1982 swapl(&rep.length, n); 1983 swapl(&rep.counter, n); 1984 swapl(&rep.wait_value_hi, n); 1985 swapl(&rep.wait_value_lo, n); 1986 swapl(&rep.test_type, n); 1987 swapl(&rep.delta_hi, n); 1988 swapl(&rep.delta_lo, n); 1989 } 1990 1991 WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); 1992 return (client->noClientException); 1993} 1994 1995 1996static int 1997ProcSyncDestroyAlarm(client) 1998 ClientPtr client; 1999{ 2000 REQUEST(xSyncDestroyAlarmReq); 2001 2002 REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 2003 2004 if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 2005 RTAlarm, DixDestroyAccess))) 2006 { 2007 client->errorValue = stuff->alarm; 2008 return SyncErrorBase + XSyncBadAlarm; 2009 } 2010 2011 FreeResource(stuff->alarm, RT_NONE); 2012 return (client->noClientException); 2013} 2014 2015/* 2016 * ** Given an extension request, call the appropriate request procedure 2017 */ 2018static int 2019ProcSyncDispatch(client) 2020 ClientPtr client; 2021{ 2022 REQUEST(xReq); 2023 2024 switch (stuff->data) 2025 { 2026 2027 case X_SyncInitialize: 2028 return ProcSyncInitialize(client); 2029 case X_SyncListSystemCounters: 2030 return ProcSyncListSystemCounters(client); 2031 case X_SyncCreateCounter: 2032 return ProcSyncCreateCounter(client); 2033 case X_SyncSetCounter: 2034 return ProcSyncSetCounter(client); 2035 case X_SyncChangeCounter: 2036 return ProcSyncChangeCounter(client); 2037 case X_SyncQueryCounter: 2038 return ProcSyncQueryCounter(client); 2039 case X_SyncDestroyCounter: 2040 return ProcSyncDestroyCounter(client); 2041 case X_SyncAwait: 2042 return ProcSyncAwait(client); 2043 case X_SyncCreateAlarm: 2044 return ProcSyncCreateAlarm(client); 2045 case X_SyncChangeAlarm: 2046 return ProcSyncChangeAlarm(client); 2047 case X_SyncQueryAlarm: 2048 return ProcSyncQueryAlarm(client); 2049 case X_SyncDestroyAlarm: 2050 return ProcSyncDestroyAlarm(client); 2051 case X_SyncSetPriority: 2052 return ProcSyncSetPriority(client); 2053 case X_SyncGetPriority: 2054 return ProcSyncGetPriority(client); 2055 default: 2056 return BadRequest; 2057 } 2058} 2059 2060/* 2061 * Boring Swapping stuff ... 2062 */ 2063 2064static int 2065SProcSyncInitialize(client) 2066 ClientPtr client; 2067{ 2068 REQUEST(xSyncInitializeReq); 2069 char n; 2070 2071 swaps(&stuff->length, n); 2072 REQUEST_SIZE_MATCH (xSyncInitializeReq); 2073 2074 return ProcSyncInitialize(client); 2075} 2076 2077static int 2078SProcSyncListSystemCounters(client) 2079 ClientPtr client; 2080{ 2081 REQUEST(xSyncListSystemCountersReq); 2082 char n; 2083 2084 swaps(&stuff->length, n); 2085 REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); 2086 2087 return ProcSyncListSystemCounters(client); 2088} 2089 2090static int 2091SProcSyncCreateCounter(client) 2092 ClientPtr client; 2093{ 2094 REQUEST(xSyncCreateCounterReq); 2095 char n; 2096 2097 swaps(&stuff->length, n); 2098 REQUEST_SIZE_MATCH (xSyncCreateCounterReq); 2099 swapl(&stuff->cid, n); 2100 swapl(&stuff->initial_value_lo, n); 2101 swapl(&stuff->initial_value_hi, n); 2102 2103 return ProcSyncCreateCounter(client); 2104} 2105 2106static int 2107SProcSyncSetCounter(client) 2108 ClientPtr client; 2109{ 2110 REQUEST(xSyncSetCounterReq); 2111 char n; 2112 2113 swaps(&stuff->length, n); 2114 REQUEST_SIZE_MATCH (xSyncSetCounterReq); 2115 swapl(&stuff->cid, n); 2116 swapl(&stuff->value_lo, n); 2117 swapl(&stuff->value_hi, n); 2118 2119 return ProcSyncSetCounter(client); 2120} 2121 2122static int 2123SProcSyncChangeCounter(client) 2124 ClientPtr client; 2125{ 2126 REQUEST(xSyncChangeCounterReq); 2127 char n; 2128 2129 swaps(&stuff->length, n); 2130 REQUEST_SIZE_MATCH (xSyncChangeCounterReq); 2131 swapl(&stuff->cid, n); 2132 swapl(&stuff->value_lo, n); 2133 swapl(&stuff->value_hi, n); 2134 2135 return ProcSyncChangeCounter(client); 2136} 2137 2138static int 2139SProcSyncQueryCounter(client) 2140 ClientPtr client; 2141{ 2142 REQUEST(xSyncQueryCounterReq); 2143 char n; 2144 2145 swaps(&stuff->length, n); 2146 REQUEST_SIZE_MATCH (xSyncQueryCounterReq); 2147 swapl(&stuff->counter, n); 2148 2149 return ProcSyncQueryCounter(client); 2150} 2151 2152static int 2153SProcSyncDestroyCounter(client) 2154 ClientPtr client; 2155{ 2156 REQUEST(xSyncDestroyCounterReq); 2157 char n; 2158 2159 swaps(&stuff->length, n); 2160 REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); 2161 swapl(&stuff->counter, n); 2162 2163 return ProcSyncDestroyCounter(client); 2164} 2165 2166static int 2167SProcSyncAwait(client) 2168 ClientPtr client; 2169{ 2170 REQUEST(xSyncAwaitReq); 2171 char n; 2172 2173 swaps(&stuff->length, n); 2174 REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 2175 SwapRestL(stuff); 2176 2177 return ProcSyncAwait(client); 2178} 2179 2180 2181static int 2182SProcSyncCreateAlarm(client) 2183 ClientPtr client; 2184{ 2185 REQUEST(xSyncCreateAlarmReq); 2186 char n; 2187 2188 swaps(&stuff->length, n); 2189 REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 2190 swapl(&stuff->id, n); 2191 swapl(&stuff->valueMask, n); 2192 SwapRestL(stuff); 2193 2194 return ProcSyncCreateAlarm(client); 2195} 2196 2197static int 2198SProcSyncChangeAlarm(client) 2199 ClientPtr client; 2200{ 2201 REQUEST(xSyncChangeAlarmReq); 2202 char n; 2203 2204 swaps(&stuff->length, n); 2205 REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 2206 swapl(&stuff->alarm, n); 2207 swapl(&stuff->valueMask, n); 2208 SwapRestL(stuff); 2209 return ProcSyncChangeAlarm(client); 2210} 2211 2212static int 2213SProcSyncQueryAlarm(client) 2214 ClientPtr client; 2215{ 2216 REQUEST(xSyncQueryAlarmReq); 2217 char n; 2218 2219 swaps(&stuff->length, n); 2220 REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); 2221 swapl(&stuff->alarm, n); 2222 2223 return ProcSyncQueryAlarm(client); 2224} 2225 2226static int 2227SProcSyncDestroyAlarm(client) 2228 ClientPtr client; 2229{ 2230 REQUEST(xSyncDestroyAlarmReq); 2231 char n; 2232 2233 swaps(&stuff->length, n); 2234 REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); 2235 swapl(&stuff->alarm, n); 2236 2237 return ProcSyncDestroyAlarm(client); 2238} 2239 2240static int 2241SProcSyncSetPriority(client) 2242 ClientPtr client; 2243{ 2244 REQUEST(xSyncSetPriorityReq); 2245 char n; 2246 2247 swaps(&stuff->length, n); 2248 REQUEST_SIZE_MATCH (xSyncSetPriorityReq); 2249 swapl(&stuff->id, n); 2250 swapl(&stuff->priority, n); 2251 2252 return ProcSyncSetPriority(client); 2253} 2254 2255static int 2256SProcSyncGetPriority(client) 2257 ClientPtr client; 2258{ 2259 REQUEST(xSyncGetPriorityReq); 2260 char n; 2261 2262 swaps(&stuff->length, n); 2263 REQUEST_SIZE_MATCH (xSyncGetPriorityReq); 2264 swapl(&stuff->id, n); 2265 2266 return ProcSyncGetPriority(client); 2267} 2268 2269 2270static int 2271SProcSyncDispatch(client) 2272 ClientPtr client; 2273{ 2274 REQUEST(xReq); 2275 2276 switch (stuff->data) 2277 { 2278 case X_SyncInitialize: 2279 return SProcSyncInitialize(client); 2280 case X_SyncListSystemCounters: 2281 return SProcSyncListSystemCounters(client); 2282 case X_SyncCreateCounter: 2283 return SProcSyncCreateCounter(client); 2284 case X_SyncSetCounter: 2285 return SProcSyncSetCounter(client); 2286 case X_SyncChangeCounter: 2287 return SProcSyncChangeCounter(client); 2288 case X_SyncQueryCounter: 2289 return SProcSyncQueryCounter(client); 2290 case X_SyncDestroyCounter: 2291 return SProcSyncDestroyCounter(client); 2292 case X_SyncAwait: 2293 return SProcSyncAwait(client); 2294 case X_SyncCreateAlarm: 2295 return SProcSyncCreateAlarm(client); 2296 case X_SyncChangeAlarm: 2297 return SProcSyncChangeAlarm(client); 2298 case X_SyncQueryAlarm: 2299 return SProcSyncQueryAlarm(client); 2300 case X_SyncDestroyAlarm: 2301 return SProcSyncDestroyAlarm(client); 2302 case X_SyncSetPriority: 2303 return SProcSyncSetPriority(client); 2304 case X_SyncGetPriority: 2305 return SProcSyncGetPriority(client); 2306 default: 2307 return BadRequest; 2308 } 2309} 2310 2311/* 2312 * Event Swapping 2313 */ 2314 2315static void 2316SCounterNotifyEvent(from, to) 2317 xSyncCounterNotifyEvent *from, *to; 2318{ 2319 to->type = from->type; 2320 to->kind = from->kind; 2321 cpswaps(from->sequenceNumber, to->sequenceNumber); 2322 cpswapl(from->counter, to->counter); 2323 cpswapl(from->wait_value_lo, to->wait_value_lo); 2324 cpswapl(from->wait_value_hi, to->wait_value_hi); 2325 cpswapl(from->counter_value_lo, to->counter_value_lo); 2326 cpswapl(from->counter_value_hi, to->counter_value_hi); 2327 cpswapl(from->time, to->time); 2328 cpswaps(from->count, to->count); 2329 to->destroyed = from->destroyed; 2330} 2331 2332 2333static void 2334SAlarmNotifyEvent(from, to) 2335 xSyncAlarmNotifyEvent *from, *to; 2336{ 2337 to->type = from->type; 2338 to->kind = from->kind; 2339 cpswaps(from->sequenceNumber, to->sequenceNumber); 2340 cpswapl(from->alarm, to->alarm); 2341 cpswapl(from->counter_value_lo, to->counter_value_lo); 2342 cpswapl(from->counter_value_hi, to->counter_value_hi); 2343 cpswapl(from->alarm_value_lo, to->alarm_value_lo); 2344 cpswapl(from->alarm_value_hi, to->alarm_value_hi); 2345 cpswapl(from->time, to->time); 2346 to->state = from->state; 2347} 2348 2349/* 2350 * ** Close everything down. ** This is fairly simple for now. 2351 */ 2352/* ARGSUSED */ 2353static void 2354SyncResetProc(extEntry) 2355 ExtensionEntry *extEntry; 2356{ 2357 xfree(SysCounterList); 2358 SysCounterList = NULL; 2359 RTCounter = 0; 2360} 2361 2362 2363/* 2364 * ** Initialise the extension. 2365 */ 2366void 2367SyncExtensionInit(INITARGS) 2368{ 2369 ExtensionEntry *extEntry; 2370 2371 if (RTCounter == 0) 2372 { 2373 RTCounter = CreateNewResourceType(FreeCounter); 2374 } 2375 RTAlarm = CreateNewResourceType(FreeAlarm); 2376 RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN; 2377 RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN; 2378 2379 if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 2380 RTAlarmClient == 0 || 2381 (extEntry = AddExtension(SYNC_NAME, 2382 XSyncNumberEvents, XSyncNumberErrors, 2383 ProcSyncDispatch, SProcSyncDispatch, 2384 SyncResetProc, 2385 StandardMinorOpcode)) == NULL) 2386 { 2387 ErrorF("Sync Extension %d.%d failed to Initialise\n", 2388 SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 2389 return; 2390 } 2391 2392 SyncEventBase = extEntry->eventBase; 2393 SyncErrorBase = extEntry->errorBase; 2394 EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; 2395 EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; 2396 2397 /* 2398 * Although SERVERTIME is implemented by the OS layer, we initialise it 2399 * here because doing it in OsInit() is too early. The resource database 2400 * is not initialised when OsInit() is called. This is just about OK 2401 * because there is always a servertime counter. 2402 */ 2403 SyncInitServerTime(); 2404 SyncInitIdleTime(); 2405 2406#ifdef DEBUG 2407 fprintf(stderr, "Sync Extension %d.%d\n", 2408 SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 2409#endif 2410} 2411 2412 2413/* 2414 * ***** SERVERTIME implementation - should go in its own file in OS directory? 2415 */ 2416 2417 2418 2419static pointer ServertimeCounter; 2420static XSyncValue Now; 2421static XSyncValue *pnext_time; 2422 2423#define GetTime()\ 2424{\ 2425 unsigned long millis = GetTimeInMillis();\ 2426 unsigned long maxis = XSyncValueHigh32(Now);\ 2427 if (millis < XSyncValueLow32(Now)) maxis++;\ 2428 XSyncIntsToValue(&Now, millis, maxis);\ 2429} 2430 2431/* 2432*** Server Block Handler 2433*** code inspired by multibuffer extension 2434 */ 2435/*ARGSUSED*/ 2436static void ServertimeBlockHandler(env, wt, LastSelectMask) 2437pointer env; 2438struct timeval **wt; 2439pointer LastSelectMask; 2440{ 2441 XSyncValue delay; 2442 unsigned long timeout; 2443 2444 if (pnext_time) 2445 { 2446 GetTime(); 2447 2448 if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 2449 { 2450 timeout = 0; 2451 } 2452 else 2453 { 2454 Bool overflow; 2455 XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 2456 (void)overflow; 2457 timeout = XSyncValueLow32(delay); 2458 } 2459 AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 2460 } 2461} 2462 2463/* 2464*** Wakeup Handler 2465 */ 2466/*ARGSUSED*/ 2467static void ServertimeWakeupHandler(env, rc, LastSelectMask) 2468pointer env; 2469int rc; 2470pointer LastSelectMask; 2471{ 2472 if (pnext_time) 2473 { 2474 GetTime(); 2475 2476 if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 2477 { 2478 SyncChangeCounter(ServertimeCounter, Now); 2479 } 2480 } 2481} 2482 2483static void 2484ServertimeQueryValue(pCounter, pValue_return) 2485 pointer pCounter; 2486 CARD64 *pValue_return; 2487{ 2488 GetTime(); 2489 *pValue_return = Now; 2490} 2491 2492static void 2493ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater) 2494 pointer pCounter; 2495 CARD64 *pbracket_less; 2496 CARD64 *pbracket_greater; 2497{ 2498 if (!pnext_time && pbracket_greater) 2499 { 2500 RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 2501 ServertimeWakeupHandler, 2502 NULL); 2503 } 2504 else if (pnext_time && !pbracket_greater) 2505 { 2506 RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 2507 ServertimeWakeupHandler, 2508 NULL); 2509 } 2510 pnext_time = pbracket_greater; 2511} 2512 2513static void 2514SyncInitServerTime(void) 2515{ 2516 CARD64 resolution; 2517 2518 XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 2519 XSyncIntToValue(&resolution, 4); 2520 ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 2521 XSyncCounterNeverDecreases, 2522 ServertimeQueryValue, ServertimeBracketValues); 2523 pnext_time = NULL; 2524} 2525 2526 2527 2528/* 2529 * IDLETIME implementation 2530 */ 2531 2532static SyncCounter *IdleTimeCounter; 2533static XSyncValue *pIdleTimeValueLess; 2534static XSyncValue *pIdleTimeValueGreater; 2535 2536static void 2537IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 2538{ 2539 CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 2540 XSyncIntsToValue (pValue_return, idle, 0); 2541} 2542 2543static void 2544IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) 2545{ 2546 XSyncValue idle, old_idle; 2547 SyncTriggerList *list = IdleTimeCounter->pTriglist; 2548 SyncTrigger *trig; 2549 2550 if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2551 return; 2552 2553 old_idle = IdleTimeCounter->value; 2554 IdleTimeQueryValue (NULL, &idle); 2555 IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ 2556 2557 if (pIdleTimeValueLess && 2558 XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 2559 { 2560 /* 2561 * We've been idle for less than the threshold value, and someone 2562 * wants to know about that, but now we need to know whether they 2563 * want level or edge trigger. Check the trigger list against the 2564 * current idle time, and if any succeed, bomb out of select() 2565 * immediately so we can reschedule. 2566 */ 2567 2568 for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 2569 trig = list->pTrigger; 2570 if (trig->CheckTrigger(trig, old_idle)) { 2571 AdjustWaitForDelay(wt, 0); 2572 break; 2573 } 2574 } 2575 } 2576 else if (pIdleTimeValueGreater) 2577 { 2578 /* 2579 * There's a threshold in the positive direction. If we've been 2580 * idle less than it, schedule a wakeup for sometime in the future. 2581 * If we've been idle more than it, and someone wants to know about 2582 * that level-triggered, schedule an immediate wakeup. 2583 */ 2584 unsigned long timeout = -1; 2585 2586 if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { 2587 XSyncValue value; 2588 Bool overflow; 2589 2590 XSyncValueSubtract (&value, *pIdleTimeValueGreater, 2591 idle, &overflow); 2592 timeout = min(timeout, XSyncValueLow32 (value)); 2593 } else { 2594 for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 2595 trig = list->pTrigger; 2596 if (trig->CheckTrigger(trig, old_idle)) { 2597 timeout = min(timeout, 0); 2598 break; 2599 } 2600 } 2601 } 2602 2603 AdjustWaitForDelay (wt, timeout); 2604 } 2605 2606 IdleTimeCounter->value = old_idle; /* pop */ 2607} 2608 2609static void 2610IdleTimeWakeupHandler (pointer env, 2611 int rc, 2612 pointer LastSelectMask) 2613{ 2614 XSyncValue idle; 2615 2616 if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2617 return; 2618 2619 IdleTimeQueryValue (NULL, &idle); 2620 2621 if ((pIdleTimeValueGreater && 2622 XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || 2623 (pIdleTimeValueLess && 2624 XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) 2625 { 2626 SyncChangeCounter (IdleTimeCounter, idle); 2627 } 2628} 2629 2630static void 2631IdleTimeBracketValues (pointer pCounter, 2632 CARD64 *pbracket_less, 2633 CARD64 *pbracket_greater) 2634{ 2635 Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); 2636 2637 if (registered && !pbracket_less && !pbracket_greater) 2638 { 2639 RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 2640 IdleTimeWakeupHandler, 2641 NULL); 2642 } 2643 else if (!registered && (pbracket_less || pbracket_greater)) 2644 { 2645 RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 2646 IdleTimeWakeupHandler, 2647 NULL); 2648 } 2649 2650 pIdleTimeValueGreater = pbracket_greater; 2651 pIdleTimeValueLess = pbracket_less; 2652} 2653 2654static void 2655SyncInitIdleTime (void) 2656{ 2657 CARD64 resolution; 2658 XSyncValue idle; 2659 2660 IdleTimeQueryValue (NULL, &idle); 2661 XSyncIntToValue (&resolution, 4); 2662 2663 IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, 2664 XSyncCounterUnrestricted, 2665 IdleTimeQueryValue, 2666 IdleTimeBracketValues); 2667 2668 pIdleTimeValueLess = pIdleTimeValueGreater = NULL; 2669} 2670