1706f2543Smrg/* 2706f2543Smrg 3706f2543SmrgCopyright 1991, 1993, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included 12706f2543Smrgin all copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17706f2543SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543SmrgOTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg 22706f2543SmrgExcept as contained in this notice, the name of The Open Group shall 23706f2543Smrgnot be used in advertising or otherwise to promote the sale, use or 24706f2543Smrgother dealings in this Software without prior written authorization 25706f2543Smrgfrom The Open Group. 26706f2543Smrg 27706f2543Smrg 28706f2543SmrgCopyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, 29706f2543Smrgand Olivetti Research Limited, Cambridge, England. 30706f2543Smrg 31706f2543Smrg All Rights Reserved 32706f2543Smrg 33706f2543SmrgPermission to use, copy, modify, and distribute this software and its 34706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 35706f2543Smrgprovided that the above copyright notice appear in all copies and that 36706f2543Smrgboth that copyright notice and this permission notice appear in 37706f2543Smrgsupporting documentation, and that the names of Digital or Olivetti 38706f2543Smrgnot be used in advertising or publicity pertaining to distribution of the 39706f2543Smrgsoftware without specific, written prior permission. Digital and Olivetti 40706f2543Smrgmake no representations about the suitability of this software 41706f2543Smrgfor any purpose. It is provided "as is" without express or implied warranty. 42706f2543Smrg 43706f2543SmrgDIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 44706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 45706f2543SmrgFITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR 46706f2543SmrgCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 47706f2543SmrgUSE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 48706f2543SmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 49706f2543SmrgPERFORMANCE OF THIS SOFTWARE. 50706f2543Smrg 51706f2543Smrg*/ 52706f2543Smrg 53706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 54706f2543Smrg#include <dix-config.h> 55706f2543Smrg#endif 56706f2543Smrg 57706f2543Smrg#include <string.h> 58706f2543Smrg 59706f2543Smrg#include <X11/X.h> 60706f2543Smrg#include <X11/Xproto.h> 61706f2543Smrg#include <X11/Xmd.h> 62706f2543Smrg#include "scrnintstr.h" 63706f2543Smrg#include "os.h" 64706f2543Smrg#include "extnsionst.h" 65706f2543Smrg#include "dixstruct.h" 66706f2543Smrg#include "pixmapstr.h" 67706f2543Smrg#include "resource.h" 68706f2543Smrg#include "opaque.h" 69706f2543Smrg#include <X11/extensions/syncproto.h> 70706f2543Smrg#include "syncsrv.h" 71706f2543Smrg#include "syncsdk.h" 72706f2543Smrg#include "protocol-versions.h" 73706f2543Smrg 74706f2543Smrg#include <stdio.h> 75706f2543Smrg#if !defined(WIN32) 76706f2543Smrg#include <sys/time.h> 77706f2543Smrg#endif 78706f2543Smrg 79706f2543Smrg#include "modinit.h" 80706f2543Smrg 81706f2543Smrg/* 82706f2543Smrg * Local Global Variables 83706f2543Smrg */ 84706f2543Smrgstatic int SyncEventBase; 85706f2543Smrgstatic int SyncErrorBase; 86706f2543Smrgstatic RESTYPE RTCounter = 0; 87706f2543Smrgstatic RESTYPE RTAwait; 88706f2543Smrgstatic RESTYPE RTAlarm; 89706f2543Smrgstatic RESTYPE RTAlarmClient; 90706f2543Smrgstatic RESTYPE RTFence; 91706f2543Smrgstatic int SyncNumSystemCounters = 0; 92706f2543Smrgstatic SyncCounter **SysCounterList = NULL; 93706f2543Smrgstatic int SyncNumInvalidCounterWarnings = 0; 94706f2543Smrg#define MAX_INVALID_COUNTER_WARNINGS 5 95706f2543Smrg 96706f2543Smrgstatic const char *WARN_INVALID_COUNTER_COMPARE = 97706f2543Smrg"Warning: Non-counter XSync object using Counter-only\n" 98706f2543Smrg" comparison. Result will never be true.\n"; 99706f2543Smrg 100706f2543Smrgstatic const char *WARN_INVALID_COUNTER_ALARM = 101706f2543Smrg"Warning: Non-counter XSync object used in alarm. This is\n" 102706f2543Smrg" the result of a programming error in the X server.\n"; 103706f2543Smrg 104706f2543Smrg#define IsSystemCounter(pCounter) \ 105706f2543Smrg (pCounter && (pCounter->sync.client == NULL)) 106706f2543Smrg 107706f2543Smrg/* these are all the alarm attributes that pertain to the alarm's trigger */ 108706f2543Smrg#define XSyncCAAllTrigger \ 109706f2543Smrg (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) 110706f2543Smrg 111706f2543Smrgstatic void SyncComputeBracketValues(SyncCounter *); 112706f2543Smrg 113706f2543Smrgstatic void SyncInitServerTime(void); 114706f2543Smrg 115706f2543Smrgstatic void SyncInitIdleTime(void); 116706f2543Smrg 117706f2543Smrgstatic Bool 118706f2543SmrgSyncCheckWarnIsCounter(const SyncObject* pSync, const char *warning) 119706f2543Smrg{ 120706f2543Smrg if (pSync && (SYNC_COUNTER != pSync->type)) 121706f2543Smrg { 122706f2543Smrg if (SyncNumInvalidCounterWarnings++ < MAX_INVALID_COUNTER_WARNINGS) 123706f2543Smrg { 124706f2543Smrg ErrorF("%s", warning); 125706f2543Smrg ErrorF(" Counter type: %d\n", pSync->type); 126706f2543Smrg } 127706f2543Smrg 128706f2543Smrg return FALSE; 129706f2543Smrg } 130706f2543Smrg 131706f2543Smrg return TRUE; 132706f2543Smrg} 133706f2543Smrg 134706f2543Smrg/* Each counter maintains a simple linked list of triggers that are 135706f2543Smrg * interested in the counter. The two functions below are used to 136706f2543Smrg * delete and add triggers on this list. 137706f2543Smrg */ 138706f2543Smrgstatic void 139706f2543SmrgSyncDeleteTriggerFromSyncObject(SyncTrigger *pTrigger) 140706f2543Smrg{ 141706f2543Smrg SyncTriggerList *pCur; 142706f2543Smrg SyncTriggerList *pPrev; 143706f2543Smrg SyncCounter *pCounter; 144706f2543Smrg 145706f2543Smrg /* pSync needs to be stored in pTrigger before calling here. */ 146706f2543Smrg 147706f2543Smrg if (!pTrigger->pSync) 148706f2543Smrg return; 149706f2543Smrg 150706f2543Smrg pPrev = NULL; 151706f2543Smrg pCur = pTrigger->pSync->pTriglist; 152706f2543Smrg 153706f2543Smrg while (pCur) 154706f2543Smrg { 155706f2543Smrg if (pCur->pTrigger == pTrigger) 156706f2543Smrg { 157706f2543Smrg if (pPrev) 158706f2543Smrg pPrev->next = pCur->next; 159706f2543Smrg else 160706f2543Smrg pTrigger->pSync->pTriglist = pCur->next; 161706f2543Smrg 162706f2543Smrg free(pCur); 163706f2543Smrg break; 164706f2543Smrg } 165706f2543Smrg 166706f2543Smrg pPrev = pCur; 167706f2543Smrg pCur = pCur->next; 168706f2543Smrg } 169706f2543Smrg 170706f2543Smrg if (SYNC_COUNTER == pTrigger->pSync->type) 171706f2543Smrg { 172706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 173706f2543Smrg 174706f2543Smrg if (IsSystemCounter(pCounter)) 175706f2543Smrg SyncComputeBracketValues(pCounter); 176706f2543Smrg } else if (SYNC_FENCE == pTrigger->pSync->type) { 177706f2543Smrg SyncFence* pFence = (SyncFence*) pTrigger->pSync; 178706f2543Smrg pFence->funcs.DeleteTrigger(pTrigger); 179706f2543Smrg } 180706f2543Smrg} 181706f2543Smrg 182706f2543Smrg 183706f2543Smrgstatic int 184706f2543SmrgSyncAddTriggerToSyncObject(SyncTrigger *pTrigger) 185706f2543Smrg{ 186706f2543Smrg SyncTriggerList *pCur; 187706f2543Smrg SyncCounter *pCounter; 188706f2543Smrg 189706f2543Smrg if (!pTrigger->pSync) 190706f2543Smrg return Success; 191706f2543Smrg 192706f2543Smrg /* don't do anything if it's already there */ 193706f2543Smrg for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next) 194706f2543Smrg { 195706f2543Smrg if (pCur->pTrigger == pTrigger) 196706f2543Smrg return Success; 197706f2543Smrg } 198706f2543Smrg 199706f2543Smrg if (!(pCur = malloc(sizeof(SyncTriggerList)))) 200706f2543Smrg return BadAlloc; 201706f2543Smrg 202706f2543Smrg pCur->pTrigger = pTrigger; 203706f2543Smrg pCur->next = pTrigger->pSync->pTriglist; 204706f2543Smrg pTrigger->pSync->pTriglist = pCur; 205706f2543Smrg 206706f2543Smrg if (SYNC_COUNTER == pTrigger->pSync->type) 207706f2543Smrg { 208706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 209706f2543Smrg 210706f2543Smrg if (IsSystemCounter(pCounter)) 211706f2543Smrg SyncComputeBracketValues(pCounter); 212706f2543Smrg } else if (SYNC_FENCE == pTrigger->pSync->type) { 213706f2543Smrg SyncFence* pFence = (SyncFence*) pTrigger->pSync; 214706f2543Smrg pFence->funcs.AddTrigger(pTrigger); 215706f2543Smrg } 216706f2543Smrg 217706f2543Smrg return Success; 218706f2543Smrg} 219706f2543Smrg 220706f2543Smrg 221706f2543Smrg/* Below are five possible functions that can be plugged into 222706f2543Smrg * pTrigger->CheckTrigger for counter sync objects, corresponding to 223706f2543Smrg * the four possible test-types, and the one possible function that 224706f2543Smrg * can be plugged into pTrigger->CheckTrigger for fence sync objects. 225706f2543Smrg * These functions are called after the sync object's state changes 226706f2543Smrg * but are also passed the old state so they can inspect both the old 227706f2543Smrg * and new values. (PositiveTransition and NegativeTransition need to 228706f2543Smrg * see both pieces of information.) These functions return the truth 229706f2543Smrg * value of the trigger. 230706f2543Smrg * 231706f2543Smrg * All of them include the condition pTrigger->pSync == NULL. 232706f2543Smrg * This is because the spec says that a trigger with a sync value 233706f2543Smrg * of None is always TRUE. 234706f2543Smrg */ 235706f2543Smrg 236706f2543Smrgstatic Bool 237706f2543SmrgSyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) 238706f2543Smrg{ 239706f2543Smrg SyncCounter *pCounter; 240706f2543Smrg 241706f2543Smrg /* Non-counter sync objects should never get here because they 242706f2543Smrg * never trigger this comparison. */ 243706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 244706f2543Smrg return FALSE; 245706f2543Smrg 246706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 247706f2543Smrg 248706f2543Smrg return (pCounter == NULL || 249706f2543Smrg XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)); 250706f2543Smrg} 251706f2543Smrg 252706f2543Smrgstatic Bool 253706f2543SmrgSyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) 254706f2543Smrg{ 255706f2543Smrg SyncCounter *pCounter; 256706f2543Smrg 257706f2543Smrg /* Non-counter sync objects should never get here because they 258706f2543Smrg * never trigger this comparison. */ 259706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 260706f2543Smrg return FALSE; 261706f2543Smrg 262706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 263706f2543Smrg 264706f2543Smrg return (pCounter == NULL || 265706f2543Smrg XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)); 266706f2543Smrg} 267706f2543Smrg 268706f2543Smrgstatic Bool 269706f2543SmrgSyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) 270706f2543Smrg{ 271706f2543Smrg SyncCounter *pCounter; 272706f2543Smrg 273706f2543Smrg /* Non-counter sync objects should never get here because they 274706f2543Smrg * never trigger this comparison. */ 275706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 276706f2543Smrg return FALSE; 277706f2543Smrg 278706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 279706f2543Smrg 280706f2543Smrg return (pCounter == NULL || 281706f2543Smrg (XSyncValueLessThan(oldval, pTrigger->test_value) && 282706f2543Smrg XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value))); 283706f2543Smrg} 284706f2543Smrg 285706f2543Smrgstatic Bool 286706f2543SmrgSyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) 287706f2543Smrg{ 288706f2543Smrg SyncCounter *pCounter; 289706f2543Smrg 290706f2543Smrg /* Non-counter sync objects should never get here because they 291706f2543Smrg * never trigger this comparison. */ 292706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 293706f2543Smrg return FALSE; 294706f2543Smrg 295706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 296706f2543Smrg 297706f2543Smrg return (pCounter == NULL || 298706f2543Smrg (XSyncValueGreaterThan(oldval, pTrigger->test_value) && 299706f2543Smrg XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value))); 300706f2543Smrg} 301706f2543Smrg 302706f2543Smrgstatic Bool 303706f2543SmrgSyncCheckTriggerFence(SyncTrigger *pTrigger, CARD64 unused) 304706f2543Smrg{ 305706f2543Smrg SyncFence* pFence = (SyncFence*) pTrigger->pSync; 306706f2543Smrg (void)unused; 307706f2543Smrg 308706f2543Smrg return (pFence == NULL || 309706f2543Smrg pFence->funcs.CheckTriggered(pFence)); 310706f2543Smrg} 311706f2543Smrg 312706f2543Smrgstatic int 313706f2543SmrgSyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject, 314706f2543Smrg RESTYPE resType, Mask changes) 315706f2543Smrg{ 316706f2543Smrg SyncObject *pSync = pTrigger->pSync; 317706f2543Smrg SyncCounter *pCounter = NULL; 318706f2543Smrg int rc; 319706f2543Smrg Bool newSyncObject = FALSE; 320706f2543Smrg 321706f2543Smrg if (changes & XSyncCACounter) 322706f2543Smrg { 323706f2543Smrg if (syncObject == None) 324706f2543Smrg pSync = NULL; 325706f2543Smrg else if (Success != (rc = dixLookupResourceByType ((pointer *)&pSync, 326706f2543Smrg syncObject, resType, client, DixReadAccess))) 327706f2543Smrg { 328706f2543Smrg client->errorValue = syncObject; 329706f2543Smrg return rc; 330706f2543Smrg } 331706f2543Smrg if (pSync != pTrigger->pSync) 332706f2543Smrg { /* new counter for trigger */ 333706f2543Smrg SyncDeleteTriggerFromSyncObject(pTrigger); 334706f2543Smrg pTrigger->pSync = pSync; 335706f2543Smrg newSyncObject = TRUE; 336706f2543Smrg } 337706f2543Smrg } 338706f2543Smrg 339706f2543Smrg /* if system counter, ask it what the current value is */ 340706f2543Smrg 341706f2543Smrg if (pSync && SYNC_COUNTER == pSync->type) 342706f2543Smrg { 343706f2543Smrg pCounter = (SyncCounter *)pSync; 344706f2543Smrg 345706f2543Smrg if (IsSystemCounter(pCounter)) 346706f2543Smrg { 347706f2543Smrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 348706f2543Smrg &pCounter->value); 349706f2543Smrg } 350706f2543Smrg } 351706f2543Smrg 352706f2543Smrg if (changes & XSyncCAValueType) 353706f2543Smrg { 354706f2543Smrg if (pTrigger->value_type != XSyncRelative && 355706f2543Smrg pTrigger->value_type != XSyncAbsolute) 356706f2543Smrg { 357706f2543Smrg client->errorValue = pTrigger->value_type; 358706f2543Smrg return BadValue; 359706f2543Smrg } 360706f2543Smrg } 361706f2543Smrg 362706f2543Smrg if (changes & XSyncCATestType) 363706f2543Smrg { 364706f2543Smrg 365706f2543Smrg if (pSync && SYNC_FENCE == pSync->type) 366706f2543Smrg { 367706f2543Smrg pTrigger->CheckTrigger = SyncCheckTriggerFence; 368706f2543Smrg } 369706f2543Smrg else 370706f2543Smrg { 371706f2543Smrg /* select appropriate CheckTrigger function */ 372706f2543Smrg 373706f2543Smrg switch (pTrigger->test_type) 374706f2543Smrg { 375706f2543Smrg case XSyncPositiveTransition: 376706f2543Smrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; 377706f2543Smrg break; 378706f2543Smrg case XSyncNegativeTransition: 379706f2543Smrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; 380706f2543Smrg break; 381706f2543Smrg case XSyncPositiveComparison: 382706f2543Smrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; 383706f2543Smrg break; 384706f2543Smrg case XSyncNegativeComparison: 385706f2543Smrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; 386706f2543Smrg break; 387706f2543Smrg default: 388706f2543Smrg client->errorValue = pTrigger->test_type; 389706f2543Smrg return BadValue; 390706f2543Smrg } 391706f2543Smrg } 392706f2543Smrg } 393706f2543Smrg 394706f2543Smrg if (changes & (XSyncCAValueType | XSyncCAValue)) 395706f2543Smrg { 396706f2543Smrg if (pTrigger->value_type == XSyncAbsolute) 397706f2543Smrg pTrigger->test_value = pTrigger->wait_value; 398706f2543Smrg else /* relative */ 399706f2543Smrg { 400706f2543Smrg Bool overflow; 401706f2543Smrg if (pCounter == NULL) 402706f2543Smrg return BadMatch; 403706f2543Smrg 404706f2543Smrg XSyncValueAdd(&pTrigger->test_value, pCounter->value, 405706f2543Smrg pTrigger->wait_value, &overflow); 406706f2543Smrg if (overflow) 407706f2543Smrg { 408706f2543Smrg client->errorValue = XSyncValueHigh32(pTrigger->wait_value); 409706f2543Smrg return BadValue; 410706f2543Smrg } 411706f2543Smrg } 412706f2543Smrg } 413706f2543Smrg 414706f2543Smrg /* we wait until we're sure there are no errors before registering 415706f2543Smrg * a new counter on a trigger 416706f2543Smrg */ 417706f2543Smrg if (newSyncObject) 418706f2543Smrg { 419706f2543Smrg if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success) 420706f2543Smrg return rc; 421706f2543Smrg } 422706f2543Smrg else if (pCounter && IsSystemCounter(pCounter)) 423706f2543Smrg { 424706f2543Smrg SyncComputeBracketValues(pCounter); 425706f2543Smrg } 426706f2543Smrg 427706f2543Smrg return Success; 428706f2543Smrg} 429706f2543Smrg 430706f2543Smrg/* AlarmNotify events happen in response to actions taken on an Alarm or 431706f2543Smrg * the counter used by the alarm. AlarmNotify may be sent to multiple 432706f2543Smrg * clients. The alarm maintains a list of clients interested in events. 433706f2543Smrg */ 434706f2543Smrgstatic void 435706f2543SmrgSyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) 436706f2543Smrg{ 437706f2543Smrg SyncAlarmClientList *pcl; 438706f2543Smrg xSyncAlarmNotifyEvent ane; 439706f2543Smrg SyncTrigger *pTrigger = &pAlarm->trigger; 440706f2543Smrg SyncCounter *pCounter; 441706f2543Smrg 442706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM)) 443706f2543Smrg return; 444706f2543Smrg 445706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 446706f2543Smrg 447706f2543Smrg UpdateCurrentTime(); 448706f2543Smrg 449706f2543Smrg ane.type = SyncEventBase + XSyncAlarmNotify; 450706f2543Smrg ane.kind = XSyncAlarmNotify; 451706f2543Smrg ane.alarm = pAlarm->alarm_id; 452706f2543Smrg if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type) 453706f2543Smrg { 454706f2543Smrg ane.counter_value_hi = XSyncValueHigh32(pCounter->value); 455706f2543Smrg ane.counter_value_lo = XSyncValueLow32(pCounter->value); 456706f2543Smrg } 457706f2543Smrg else 458706f2543Smrg { /* XXX what else can we do if there's no counter? */ 459706f2543Smrg ane.counter_value_hi = ane.counter_value_lo = 0; 460706f2543Smrg } 461706f2543Smrg 462706f2543Smrg ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); 463706f2543Smrg ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); 464706f2543Smrg ane.time = currentTime.milliseconds; 465706f2543Smrg ane.state = pAlarm->state; 466706f2543Smrg 467706f2543Smrg /* send to owner */ 468706f2543Smrg if (pAlarm->events) 469706f2543Smrg WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); 470706f2543Smrg 471706f2543Smrg /* send to other interested clients */ 472706f2543Smrg for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) 473706f2543Smrg WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); 474706f2543Smrg} 475706f2543Smrg 476706f2543Smrg 477706f2543Smrg/* CounterNotify events only occur in response to an Await. The events 478706f2543Smrg * go only to the Awaiting client. 479706f2543Smrg */ 480706f2543Smrgstatic void 481706f2543SmrgSyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, 482706f2543Smrg int num_events) 483706f2543Smrg{ 484706f2543Smrg xSyncCounterNotifyEvent *pEvents, *pev; 485706f2543Smrg int i; 486706f2543Smrg 487706f2543Smrg if (client->clientGone) 488706f2543Smrg return; 489706f2543Smrg pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent)); 490706f2543Smrg if (!pEvents) 491706f2543Smrg return; 492706f2543Smrg UpdateCurrentTime(); 493706f2543Smrg for (i = 0; i < num_events; i++, ppAwait++, pev++) 494706f2543Smrg { 495706f2543Smrg SyncTrigger *pTrigger = &(*ppAwait)->trigger; 496706f2543Smrg pev->type = SyncEventBase + XSyncCounterNotify; 497706f2543Smrg pev->kind = XSyncCounterNotify; 498706f2543Smrg pev->counter = pTrigger->pSync->id; 499706f2543Smrg pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); 500706f2543Smrg pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 501706f2543Smrg if (SYNC_COUNTER == pTrigger->pSync->type) 502706f2543Smrg { 503706f2543Smrg SyncCounter *pCounter = (SyncCounter *)pTrigger->pSync; 504706f2543Smrg 505706f2543Smrg pev->counter_value_lo = XSyncValueLow32(pCounter->value); 506706f2543Smrg pev->counter_value_hi = XSyncValueHigh32(pCounter->value); 507706f2543Smrg } 508706f2543Smrg else 509706f2543Smrg { 510706f2543Smrg pev->counter_value_lo = 0; 511706f2543Smrg pev->counter_value_hi = 0; 512706f2543Smrg } 513706f2543Smrg 514706f2543Smrg pev->time = currentTime.milliseconds; 515706f2543Smrg pev->count = num_events - i - 1; /* events remaining */ 516706f2543Smrg pev->destroyed = pTrigger->pSync->beingDestroyed; 517706f2543Smrg } 518706f2543Smrg /* swapping will be taken care of by this */ 519706f2543Smrg WriteEventsToClient(client, num_events, (xEvent *)pEvents); 520706f2543Smrg free(pEvents); 521706f2543Smrg} 522706f2543Smrg 523706f2543Smrg 524706f2543Smrg/* This function is called when an alarm's counter is destroyed. 525706f2543Smrg * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). 526706f2543Smrg */ 527706f2543Smrgstatic void 528706f2543SmrgSyncAlarmCounterDestroyed(SyncTrigger *pTrigger) 529706f2543Smrg{ 530706f2543Smrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 531706f2543Smrg 532706f2543Smrg pAlarm->state = XSyncAlarmInactive; 533706f2543Smrg SyncSendAlarmNotifyEvents(pAlarm); 534706f2543Smrg pTrigger->pSync = NULL; 535706f2543Smrg} 536706f2543Smrg 537706f2543Smrg 538706f2543Smrg/* This function is called when an alarm "goes off." 539706f2543Smrg * It is plugged into pTrigger->TriggerFired (for alarm triggers). 540706f2543Smrg */ 541706f2543Smrgstatic void 542706f2543SmrgSyncAlarmTriggerFired(SyncTrigger *pTrigger) 543706f2543Smrg{ 544706f2543Smrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 545706f2543Smrg SyncCounter *pCounter; 546706f2543Smrg CARD64 new_test_value; 547706f2543Smrg 548706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM)) 549706f2543Smrg return; 550706f2543Smrg 551706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 552706f2543Smrg 553706f2543Smrg /* no need to check alarm unless it's active */ 554706f2543Smrg if (pAlarm->state != XSyncAlarmActive) 555706f2543Smrg return; 556706f2543Smrg 557706f2543Smrg /* " if the counter value is None, or if the delta is 0 and 558706f2543Smrg * the test-type is PositiveComparison or NegativeComparison, 559706f2543Smrg * no change is made to value (test-value) and the alarm 560706f2543Smrg * state is changed to Inactive before the event is generated." 561706f2543Smrg */ 562706f2543Smrg if (pCounter == NULL 563706f2543Smrg || (XSyncValueIsZero(pAlarm->delta) 564706f2543Smrg && (pAlarm->trigger.test_type == XSyncPositiveComparison 565706f2543Smrg || pAlarm->trigger.test_type == XSyncNegativeComparison))) 566706f2543Smrg pAlarm->state = XSyncAlarmInactive; 567706f2543Smrg 568706f2543Smrg new_test_value = pAlarm->trigger.test_value; 569706f2543Smrg 570706f2543Smrg if (pAlarm->state == XSyncAlarmActive) 571706f2543Smrg { 572706f2543Smrg Bool overflow; 573706f2543Smrg CARD64 oldvalue; 574706f2543Smrg SyncTrigger *paTrigger = &pAlarm->trigger; 575706f2543Smrg SyncCounter *paCounter; 576706f2543Smrg 577706f2543Smrg if (!SyncCheckWarnIsCounter(paTrigger->pSync, 578706f2543Smrg WARN_INVALID_COUNTER_ALARM)) 579706f2543Smrg return; 580706f2543Smrg 581706f2543Smrg paCounter = (SyncCounter *)pTrigger->pSync; 582706f2543Smrg 583706f2543Smrg /* "The alarm is updated by repeatedly adding delta to the 584706f2543Smrg * value of the trigger and re-initializing it until it 585706f2543Smrg * becomes FALSE." 586706f2543Smrg */ 587706f2543Smrg oldvalue = paTrigger->test_value; 588706f2543Smrg 589706f2543Smrg /* XXX really should do something smarter here */ 590706f2543Smrg 591706f2543Smrg do 592706f2543Smrg { 593706f2543Smrg XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, 594706f2543Smrg pAlarm->delta, &overflow); 595706f2543Smrg } while (!overflow && 596706f2543Smrg (*paTrigger->CheckTrigger)(paTrigger, 597706f2543Smrg paCounter->value)); 598706f2543Smrg 599706f2543Smrg new_test_value = paTrigger->test_value; 600706f2543Smrg paTrigger->test_value = oldvalue; 601706f2543Smrg 602706f2543Smrg /* "If this update would cause value to fall outside the range 603706f2543Smrg * for an INT64...no change is made to value (test-value) and 604706f2543Smrg * the alarm state is changed to Inactive before the event is 605706f2543Smrg * generated." 606706f2543Smrg */ 607706f2543Smrg if (overflow) 608706f2543Smrg { 609706f2543Smrg new_test_value = oldvalue; 610706f2543Smrg pAlarm->state = XSyncAlarmInactive; 611706f2543Smrg } 612706f2543Smrg } 613706f2543Smrg /* The AlarmNotify event has to have the "new state of the alarm" 614706f2543Smrg * which we can't be sure of until this point. However, it has 615706f2543Smrg * to have the "old" trigger test value. That's the reason for 616706f2543Smrg * all the newvalue/oldvalue shuffling above. After we send the 617706f2543Smrg * events, give the trigger its new test value. 618706f2543Smrg */ 619706f2543Smrg SyncSendAlarmNotifyEvents(pAlarm); 620706f2543Smrg pTrigger->test_value = new_test_value; 621706f2543Smrg} 622706f2543Smrg 623706f2543Smrg 624706f2543Smrg/* This function is called when an Await unblocks, either as a result 625706f2543Smrg * of the trigger firing OR the counter being destroyed. 626706f2543Smrg * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed 627706f2543Smrg * (for Await triggers). 628706f2543Smrg */ 629706f2543Smrgstatic void 630706f2543SmrgSyncAwaitTriggerFired(SyncTrigger *pTrigger) 631706f2543Smrg{ 632706f2543Smrg SyncAwait *pAwait = (SyncAwait *)pTrigger; 633706f2543Smrg int numwaits; 634706f2543Smrg SyncAwaitUnion *pAwaitUnion; 635706f2543Smrg SyncAwait **ppAwait; 636706f2543Smrg int num_events = 0; 637706f2543Smrg 638706f2543Smrg pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; 639706f2543Smrg numwaits = pAwaitUnion->header.num_waitconditions; 640706f2543Smrg ppAwait = malloc(numwaits * sizeof(SyncAwait *)); 641706f2543Smrg if (!ppAwait) 642706f2543Smrg goto bail; 643706f2543Smrg 644706f2543Smrg pAwait = &(pAwaitUnion+1)->await; 645706f2543Smrg 646706f2543Smrg /* "When a client is unblocked, all the CounterNotify events for 647706f2543Smrg * the Await request are generated contiguously. If count is 0 648706f2543Smrg * there are no more events to follow for this request. If 649706f2543Smrg * count is n, there are at least n more events to follow." 650706f2543Smrg * 651706f2543Smrg * Thus, it is best to find all the counters for which events 652706f2543Smrg * need to be sent first, so that an accurate count field can 653706f2543Smrg * be stored in the events. 654706f2543Smrg */ 655706f2543Smrg for ( ; numwaits; numwaits--, pAwait++) 656706f2543Smrg { 657706f2543Smrg CARD64 diff; 658706f2543Smrg Bool overflow, diffgreater, diffequal; 659706f2543Smrg 660706f2543Smrg /* "A CounterNotify event with the destroyed flag set to TRUE is 661706f2543Smrg * always generated if the counter for one of the triggers is 662706f2543Smrg * destroyed." 663706f2543Smrg */ 664706f2543Smrg if (pAwait->trigger.pSync->beingDestroyed) 665706f2543Smrg { 666706f2543Smrg ppAwait[num_events++] = pAwait; 667706f2543Smrg continue; 668706f2543Smrg } 669706f2543Smrg 670706f2543Smrg if (SYNC_COUNTER == pAwait->trigger.pSync->type) 671706f2543Smrg { 672706f2543Smrg SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync; 673706f2543Smrg 674706f2543Smrg /* "The difference between the counter and the test value is 675706f2543Smrg * calculated by subtracting the test value from the value of 676706f2543Smrg * the counter." 677706f2543Smrg */ 678706f2543Smrg XSyncValueSubtract(&diff, pCounter->value, 679706f2543Smrg pAwait->trigger.test_value, &overflow); 680706f2543Smrg 681706f2543Smrg /* "If the difference lies outside the range for an INT64, an 682706f2543Smrg * event is not generated." 683706f2543Smrg */ 684706f2543Smrg if (overflow) 685706f2543Smrg continue; 686706f2543Smrg diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); 687706f2543Smrg diffequal = XSyncValueEqual(diff, pAwait->event_threshold); 688706f2543Smrg 689706f2543Smrg /* "If the test-type is PositiveTransition or 690706f2543Smrg * PositiveComparison, a CounterNotify event is generated if 691706f2543Smrg * the difference is at least event-threshold. If the test-type 692706f2543Smrg * is NegativeTransition or NegativeComparison, a CounterNotify 693706f2543Smrg * event is generated if the difference is at most 694706f2543Smrg * event-threshold." 695706f2543Smrg */ 696706f2543Smrg 697706f2543Smrg if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || 698706f2543Smrg pAwait->trigger.test_type == XSyncPositiveTransition) 699706f2543Smrg && (diffgreater || diffequal)) 700706f2543Smrg || 701706f2543Smrg ((pAwait->trigger.test_type == XSyncNegativeComparison || 702706f2543Smrg pAwait->trigger.test_type == XSyncNegativeTransition) 703706f2543Smrg && (!diffgreater) /* less or equal */ 704706f2543Smrg ) 705706f2543Smrg ) 706706f2543Smrg { 707706f2543Smrg ppAwait[num_events++] = pAwait; 708706f2543Smrg } 709706f2543Smrg } 710706f2543Smrg } 711706f2543Smrg if (num_events) 712706f2543Smrg SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, 713706f2543Smrg num_events); 714706f2543Smrg free(ppAwait); 715706f2543Smrg 716706f2543Smrgbail: 717706f2543Smrg /* unblock the client */ 718706f2543Smrg AttendClient(pAwaitUnion->header.client); 719706f2543Smrg /* delete the await */ 720706f2543Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 721706f2543Smrg} 722706f2543Smrg 723706f2543Smrg 724706f2543Smrg/* This function should always be used to change a counter's value so that 725706f2543Smrg * any triggers depending on the counter will be checked. 726706f2543Smrg */ 727706f2543Smrgvoid 728706f2543SmrgSyncChangeCounter(SyncCounter *pCounter, CARD64 newval) 729706f2543Smrg{ 730706f2543Smrg SyncTriggerList *ptl, *pnext; 731706f2543Smrg CARD64 oldval; 732706f2543Smrg 733706f2543Smrg oldval = pCounter->value; 734706f2543Smrg pCounter->value = newval; 735706f2543Smrg 736706f2543Smrg /* run through triggers to see if any become true */ 737706f2543Smrg for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) 738706f2543Smrg { 739706f2543Smrg pnext = ptl->next; 740706f2543Smrg if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) 741706f2543Smrg (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); 742706f2543Smrg } 743706f2543Smrg 744706f2543Smrg if (IsSystemCounter(pCounter)) 745706f2543Smrg { 746706f2543Smrg SyncComputeBracketValues(pCounter); 747706f2543Smrg } 748706f2543Smrg} 749706f2543Smrg 750706f2543Smrg 751706f2543Smrg/* loosely based on dix/events.c/EventSelectForWindow */ 752706f2543Smrgstatic Bool 753706f2543SmrgSyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) 754706f2543Smrg{ 755706f2543Smrg SyncAlarmClientList *pClients; 756706f2543Smrg 757706f2543Smrg if (client == pAlarm->client) /* alarm owner */ 758706f2543Smrg { 759706f2543Smrg pAlarm->events = wantevents; 760706f2543Smrg return Success; 761706f2543Smrg } 762706f2543Smrg 763706f2543Smrg /* see if the client is already on the list (has events selected) */ 764706f2543Smrg 765706f2543Smrg for (pClients = pAlarm->pEventClients; pClients; 766706f2543Smrg pClients = pClients->next) 767706f2543Smrg { 768706f2543Smrg if (pClients->client == client) 769706f2543Smrg { 770706f2543Smrg /* client's presence on the list indicates desire for 771706f2543Smrg * events. If the client doesn't want events, remove it 772706f2543Smrg * from the list. If the client does want events, do 773706f2543Smrg * nothing, since it's already got them. 774706f2543Smrg */ 775706f2543Smrg if (!wantevents) 776706f2543Smrg { 777706f2543Smrg FreeResource(pClients->delete_id, RT_NONE); 778706f2543Smrg } 779706f2543Smrg return Success; 780706f2543Smrg } 781706f2543Smrg } 782706f2543Smrg 783706f2543Smrg /* if we get here, this client does not currently have 784706f2543Smrg * events selected on the alarm 785706f2543Smrg */ 786706f2543Smrg 787706f2543Smrg if (!wantevents) 788706f2543Smrg /* client doesn't want events, and we just discovered that it 789706f2543Smrg * doesn't have them, so there's nothing to do. 790706f2543Smrg */ 791706f2543Smrg return Success; 792706f2543Smrg 793706f2543Smrg /* add new client to pAlarm->pEventClients */ 794706f2543Smrg 795706f2543Smrg pClients = malloc(sizeof(SyncAlarmClientList)); 796706f2543Smrg if (!pClients) 797706f2543Smrg return BadAlloc; 798706f2543Smrg 799706f2543Smrg /* register it as a resource so it will be cleaned up 800706f2543Smrg * if the client dies 801706f2543Smrg */ 802706f2543Smrg 803706f2543Smrg pClients->delete_id = FakeClientID(client->index); 804706f2543Smrg 805706f2543Smrg /* link it into list after we know all the allocations succeed */ 806706f2543Smrg pClients->next = pAlarm->pEventClients; 807706f2543Smrg pAlarm->pEventClients = pClients; 808706f2543Smrg pClients->client = client; 809706f2543Smrg 810706f2543Smrg if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) 811706f2543Smrg return BadAlloc; 812706f2543Smrg 813706f2543Smrg return Success; 814706f2543Smrg} 815706f2543Smrg 816706f2543Smrg/* 817706f2543Smrg * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm 818706f2543Smrg */ 819706f2543Smrgstatic int 820706f2543SmrgSyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, 821706f2543Smrg CARD32 *values) 822706f2543Smrg{ 823706f2543Smrg int status; 824706f2543Smrg XSyncCounter counter; 825706f2543Smrg Mask origmask = mask; 826706f2543Smrg 827706f2543Smrg counter = 828706f2543Smrg pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None; 829706f2543Smrg 830706f2543Smrg while (mask) 831706f2543Smrg { 832706f2543Smrg int index2 = lowbit(mask); 833706f2543Smrg mask &= ~index2; 834706f2543Smrg switch (index2) 835706f2543Smrg { 836706f2543Smrg case XSyncCACounter: 837706f2543Smrg mask &= ~XSyncCACounter; 838706f2543Smrg /* sanity check in SyncInitTrigger */ 839706f2543Smrg counter = *values++; 840706f2543Smrg break; 841706f2543Smrg 842706f2543Smrg case XSyncCAValueType: 843706f2543Smrg mask &= ~XSyncCAValueType; 844706f2543Smrg /* sanity check in SyncInitTrigger */ 845706f2543Smrg pAlarm->trigger.value_type = *values++; 846706f2543Smrg break; 847706f2543Smrg 848706f2543Smrg case XSyncCAValue: 849706f2543Smrg mask &= ~XSyncCAValue; 850706f2543Smrg XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); 851706f2543Smrg values += 2; 852706f2543Smrg break; 853706f2543Smrg 854706f2543Smrg case XSyncCATestType: 855706f2543Smrg mask &= ~XSyncCATestType; 856706f2543Smrg /* sanity check in SyncInitTrigger */ 857706f2543Smrg pAlarm->trigger.test_type = *values++; 858706f2543Smrg break; 859706f2543Smrg 860706f2543Smrg case XSyncCADelta: 861706f2543Smrg mask &= ~XSyncCADelta; 862706f2543Smrg XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); 863706f2543Smrg values += 2; 864706f2543Smrg break; 865706f2543Smrg 866706f2543Smrg case XSyncCAEvents: 867706f2543Smrg mask &= ~XSyncCAEvents; 868706f2543Smrg if ((*values != xTrue) && (*values != xFalse)) 869706f2543Smrg { 870706f2543Smrg client->errorValue = *values; 871706f2543Smrg return BadValue; 872706f2543Smrg } 873706f2543Smrg status = SyncEventSelectForAlarm(pAlarm, client, 874706f2543Smrg (Bool)(*values++)); 875706f2543Smrg if (status != Success) 876706f2543Smrg return status; 877706f2543Smrg break; 878706f2543Smrg 879706f2543Smrg default: 880706f2543Smrg client->errorValue = mask; 881706f2543Smrg return BadValue; 882706f2543Smrg } 883706f2543Smrg } 884706f2543Smrg 885706f2543Smrg /* "If the test-type is PositiveComparison or PositiveTransition 886706f2543Smrg * and delta is less than zero, or if the test-type is 887706f2543Smrg * NegativeComparison or NegativeTransition and delta is 888706f2543Smrg * greater than zero, a Match error is generated." 889706f2543Smrg */ 890706f2543Smrg if (origmask & (XSyncCADelta|XSyncCATestType)) 891706f2543Smrg { 892706f2543Smrg CARD64 zero; 893706f2543Smrg XSyncIntToValue(&zero, 0); 894706f2543Smrg if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || 895706f2543Smrg (pAlarm->trigger.test_type == XSyncPositiveTransition)) 896706f2543Smrg && XSyncValueLessThan(pAlarm->delta, zero)) 897706f2543Smrg || 898706f2543Smrg (((pAlarm->trigger.test_type == XSyncNegativeComparison) || 899706f2543Smrg (pAlarm->trigger.test_type == XSyncNegativeTransition)) 900706f2543Smrg && XSyncValueGreaterThan(pAlarm->delta, zero)) 901706f2543Smrg ) 902706f2543Smrg { 903706f2543Smrg return BadMatch; 904706f2543Smrg } 905706f2543Smrg } 906706f2543Smrg 907706f2543Smrg /* postpone this until now, when we're sure nothing else can go wrong */ 908706f2543Smrg if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter, 909706f2543Smrg origmask & XSyncCAAllTrigger)) != Success) 910706f2543Smrg return status; 911706f2543Smrg 912706f2543Smrg /* XXX spec does not really say to do this - needs clarification */ 913706f2543Smrg pAlarm->state = XSyncAlarmActive; 914706f2543Smrg return Success; 915706f2543Smrg} 916706f2543Smrg 917706f2543Smrgstatic SyncObject * 918706f2543SmrgSyncCreate(ClientPtr client, XID id, unsigned char type) 919706f2543Smrg{ 920706f2543Smrg SyncObject *pSync; 921706f2543Smrg 922706f2543Smrg switch (type) { 923706f2543Smrg case SYNC_COUNTER: 924706f2543Smrg pSync = malloc(sizeof(SyncCounter)); 925706f2543Smrg break; 926706f2543Smrg case SYNC_FENCE: 927706f2543Smrg pSync = (SyncObject*)dixAllocateObjectWithPrivates(SyncFence, 928706f2543Smrg PRIVATE_SYNC_FENCE); 929706f2543Smrg break; 930706f2543Smrg default: 931706f2543Smrg return NULL; 932706f2543Smrg } 933706f2543Smrg 934706f2543Smrg if (!pSync) 935706f2543Smrg return NULL; 936706f2543Smrg 937706f2543Smrg pSync->client = client; 938706f2543Smrg pSync->id = id; 939706f2543Smrg pSync->pTriglist = NULL; 940706f2543Smrg pSync->beingDestroyed = FALSE; 941706f2543Smrg pSync->type = type; 942706f2543Smrg 943706f2543Smrg return pSync; 944706f2543Smrg} 945706f2543Smrg 946706f2543Smrg 947706f2543Smrgstatic SyncCounter * 948706f2543SmrgSyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) 949706f2543Smrg{ 950706f2543Smrg SyncCounter *pCounter; 951706f2543Smrg 952706f2543Smrg if (!(pCounter = (SyncCounter *)SyncCreate(client, 953706f2543Smrg id, 954706f2543Smrg SYNC_COUNTER))) 955706f2543Smrg return NULL; 956706f2543Smrg 957706f2543Smrg pCounter->value = initialvalue; 958706f2543Smrg pCounter->pSysCounterInfo = NULL; 959706f2543Smrg 960706f2543Smrg if (!AddResource(id, RTCounter, (pointer) pCounter)) 961706f2543Smrg return NULL; 962706f2543Smrg 963706f2543Smrg return pCounter; 964706f2543Smrg} 965706f2543Smrg 966706f2543Smrgstatic int FreeCounter(void *, XID); 967706f2543Smrg 968706f2543Smrg/* 969706f2543Smrg * ***** System Counter utilities 970706f2543Smrg */ 971706f2543Smrg 972706f2543Smrgpointer 973706f2543SmrgSyncCreateSystemCounter( 974706f2543Smrg char *name, 975706f2543Smrg CARD64 initial, 976706f2543Smrg CARD64 resolution, 977706f2543Smrg SyncCounterType counterType, 978706f2543Smrg void (*QueryValue)(pointer /* pCounter */, 979706f2543Smrg CARD64 * /* pValue_return */), 980706f2543Smrg void (*BracketValues)(pointer /* pCounter */, 981706f2543Smrg CARD64 * /* pbracket_less */, 982706f2543Smrg CARD64 * /* pbracket_greater */) 983706f2543Smrg ) 984706f2543Smrg{ 985706f2543Smrg SyncCounter *pCounter; 986706f2543Smrg 987706f2543Smrg SysCounterList = realloc(SysCounterList, 988706f2543Smrg (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); 989706f2543Smrg if (!SysCounterList) 990706f2543Smrg return NULL; 991706f2543Smrg 992706f2543Smrg /* this function may be called before SYNC has been initialized, so we 993706f2543Smrg * have to make sure RTCounter is created. 994706f2543Smrg */ 995706f2543Smrg if (RTCounter == 0) 996706f2543Smrg { 997706f2543Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 998706f2543Smrg if (RTCounter == 0) 999706f2543Smrg { 1000706f2543Smrg return NULL; 1001706f2543Smrg } 1002706f2543Smrg } 1003706f2543Smrg 1004706f2543Smrg pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); 1005706f2543Smrg 1006706f2543Smrg if (pCounter) 1007706f2543Smrg { 1008706f2543Smrg SysCounterInfo *psci; 1009706f2543Smrg 1010706f2543Smrg psci = malloc(sizeof(SysCounterInfo)); 1011706f2543Smrg if (!psci) 1012706f2543Smrg { 1013706f2543Smrg FreeResource(pCounter->sync.id, RT_NONE); 1014706f2543Smrg return pCounter; 1015706f2543Smrg } 1016706f2543Smrg pCounter->pSysCounterInfo = psci; 1017706f2543Smrg psci->name = name; 1018706f2543Smrg psci->resolution = resolution; 1019706f2543Smrg psci->counterType = counterType; 1020706f2543Smrg psci->QueryValue = QueryValue; 1021706f2543Smrg psci->BracketValues = BracketValues; 1022706f2543Smrg XSyncMaxValue(&psci->bracket_greater); 1023706f2543Smrg XSyncMinValue(&psci->bracket_less); 1024706f2543Smrg SysCounterList[SyncNumSystemCounters++] = pCounter; 1025706f2543Smrg } 1026706f2543Smrg return pCounter; 1027706f2543Smrg} 1028706f2543Smrg 1029706f2543Smrgvoid 1030706f2543SmrgSyncDestroySystemCounter(pointer pSysCounter) 1031706f2543Smrg{ 1032706f2543Smrg SyncCounter *pCounter = (SyncCounter *)pSysCounter; 1033706f2543Smrg FreeResource(pCounter->sync.id, RT_NONE); 1034706f2543Smrg} 1035706f2543Smrg 1036706f2543Smrgstatic void 1037706f2543SmrgSyncComputeBracketValues(SyncCounter *pCounter) 1038706f2543Smrg{ 1039706f2543Smrg SyncTriggerList *pCur; 1040706f2543Smrg SyncTrigger *pTrigger; 1041706f2543Smrg SysCounterInfo *psci; 1042706f2543Smrg CARD64 *pnewgtval = NULL; 1043706f2543Smrg CARD64 *pnewltval = NULL; 1044706f2543Smrg SyncCounterType ct; 1045706f2543Smrg 1046706f2543Smrg if (!pCounter) 1047706f2543Smrg return; 1048706f2543Smrg 1049706f2543Smrg psci = pCounter->pSysCounterInfo; 1050706f2543Smrg ct = pCounter->pSysCounterInfo->counterType; 1051706f2543Smrg if (ct == XSyncCounterNeverChanges) 1052706f2543Smrg return; 1053706f2543Smrg 1054706f2543Smrg XSyncMaxValue(&psci->bracket_greater); 1055706f2543Smrg XSyncMinValue(&psci->bracket_less); 1056706f2543Smrg 1057706f2543Smrg for (pCur = pCounter->sync.pTriglist; pCur; pCur = pCur->next) 1058706f2543Smrg { 1059706f2543Smrg pTrigger = pCur->pTrigger; 1060706f2543Smrg 1061706f2543Smrg if (pTrigger->test_type == XSyncPositiveComparison && 1062706f2543Smrg ct != XSyncCounterNeverIncreases) 1063706f2543Smrg { 1064706f2543Smrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1065706f2543Smrg XSyncValueLessThan(pTrigger->test_value, 1066706f2543Smrg psci->bracket_greater)) 1067706f2543Smrg { 1068706f2543Smrg psci->bracket_greater = pTrigger->test_value; 1069706f2543Smrg pnewgtval = &psci->bracket_greater; 1070706f2543Smrg } 1071706f2543Smrg } 1072706f2543Smrg else if (pTrigger->test_type == XSyncNegativeComparison && 1073706f2543Smrg ct != XSyncCounterNeverDecreases) 1074706f2543Smrg { 1075706f2543Smrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1076706f2543Smrg XSyncValueGreaterThan(pTrigger->test_value, 1077706f2543Smrg psci->bracket_less)) 1078706f2543Smrg { 1079706f2543Smrg psci->bracket_less = pTrigger->test_value; 1080706f2543Smrg pnewltval = &psci->bracket_less; 1081706f2543Smrg } 1082706f2543Smrg } 1083706f2543Smrg else if (pTrigger->test_type == XSyncNegativeTransition && 1084706f2543Smrg ct != XSyncCounterNeverIncreases) 1085706f2543Smrg { 1086706f2543Smrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1087706f2543Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) 1088706f2543Smrg { 1089706f2543Smrg psci->bracket_less = pTrigger->test_value; 1090706f2543Smrg pnewltval = &psci->bracket_less; 1091706f2543Smrg } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) && 1092706f2543Smrg XSyncValueLessThan(pTrigger->test_value, 1093706f2543Smrg psci->bracket_greater)) 1094706f2543Smrg { 1095706f2543Smrg /* 1096706f2543Smrg * The value is exactly equal to our threshold. We want one 1097706f2543Smrg * more event in the positive direction to ensure we pick up 1098706f2543Smrg * when the value *exceeds* this threshold. 1099706f2543Smrg */ 1100706f2543Smrg psci->bracket_greater = pTrigger->test_value; 1101706f2543Smrg pnewgtval = &psci->bracket_greater; 1102706f2543Smrg } 1103706f2543Smrg } 1104706f2543Smrg else if (pTrigger->test_type == XSyncPositiveTransition && 1105706f2543Smrg ct != XSyncCounterNeverDecreases) 1106706f2543Smrg { 1107706f2543Smrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1108706f2543Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) 1109706f2543Smrg { 1110706f2543Smrg psci->bracket_greater = pTrigger->test_value; 1111706f2543Smrg pnewgtval = &psci->bracket_greater; 1112706f2543Smrg } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) && 1113706f2543Smrg XSyncValueGreaterThan(pTrigger->test_value, 1114706f2543Smrg psci->bracket_less)) 1115706f2543Smrg { 1116706f2543Smrg /* 1117706f2543Smrg * The value is exactly equal to our threshold. We want one 1118706f2543Smrg * more event in the negative direction to ensure we pick up 1119706f2543Smrg * when the value is less than this threshold. 1120706f2543Smrg */ 1121706f2543Smrg psci->bracket_less = pTrigger->test_value; 1122706f2543Smrg pnewltval = &psci->bracket_less; 1123706f2543Smrg } 1124706f2543Smrg } 1125706f2543Smrg } /* end for each trigger */ 1126706f2543Smrg 1127706f2543Smrg if (pnewgtval || pnewltval) 1128706f2543Smrg { 1129706f2543Smrg (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); 1130706f2543Smrg } 1131706f2543Smrg} 1132706f2543Smrg 1133706f2543Smrg/* 1134706f2543Smrg * ***** Resource delete functions 1135706f2543Smrg */ 1136706f2543Smrg 1137706f2543Smrg/* ARGSUSED */ 1138706f2543Smrgstatic int 1139706f2543SmrgFreeAlarm(void *addr, XID id) 1140706f2543Smrg{ 1141706f2543Smrg SyncAlarm *pAlarm = (SyncAlarm *) addr; 1142706f2543Smrg 1143706f2543Smrg pAlarm->state = XSyncAlarmDestroyed; 1144706f2543Smrg 1145706f2543Smrg SyncSendAlarmNotifyEvents(pAlarm); 1146706f2543Smrg 1147706f2543Smrg /* delete event selections */ 1148706f2543Smrg 1149706f2543Smrg while (pAlarm->pEventClients) 1150706f2543Smrg FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 1151706f2543Smrg 1152706f2543Smrg SyncDeleteTriggerFromSyncObject(&pAlarm->trigger); 1153706f2543Smrg 1154706f2543Smrg free(pAlarm); 1155706f2543Smrg return Success; 1156706f2543Smrg} 1157706f2543Smrg 1158706f2543Smrg 1159706f2543Smrg/* 1160706f2543Smrg * ** Cleanup after the destruction of a Counter 1161706f2543Smrg */ 1162706f2543Smrg/* ARGSUSED */ 1163706f2543Smrgstatic int 1164706f2543SmrgFreeCounter(void *env, XID id) 1165706f2543Smrg{ 1166706f2543Smrg SyncCounter *pCounter = (SyncCounter *) env; 1167706f2543Smrg SyncTriggerList *ptl, *pnext; 1168706f2543Smrg 1169706f2543Smrg pCounter->sync.beingDestroyed = TRUE; 1170706f2543Smrg /* tell all the counter's triggers that the counter has been destroyed */ 1171706f2543Smrg for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) 1172706f2543Smrg { 1173706f2543Smrg (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); 1174706f2543Smrg pnext = ptl->next; 1175706f2543Smrg free(ptl); /* destroy the trigger list as we go */ 1176706f2543Smrg } 1177706f2543Smrg if (IsSystemCounter(pCounter)) 1178706f2543Smrg { 1179706f2543Smrg int i, found = 0; 1180706f2543Smrg 1181706f2543Smrg free(pCounter->pSysCounterInfo); 1182706f2543Smrg 1183706f2543Smrg /* find the counter in the list of system counters and remove it */ 1184706f2543Smrg 1185706f2543Smrg if (SysCounterList) 1186706f2543Smrg { 1187706f2543Smrg for (i = 0; i < SyncNumSystemCounters; i++) 1188706f2543Smrg { 1189706f2543Smrg if (SysCounterList[i] == pCounter) 1190706f2543Smrg { 1191706f2543Smrg found = i; 1192706f2543Smrg break; 1193706f2543Smrg } 1194706f2543Smrg } 1195706f2543Smrg if (found < (SyncNumSystemCounters-1)) 1196706f2543Smrg { 1197706f2543Smrg for (i = found; i < SyncNumSystemCounters-1; i++) 1198706f2543Smrg { 1199706f2543Smrg SysCounterList[i] = SysCounterList[i+1]; 1200706f2543Smrg } 1201706f2543Smrg } 1202706f2543Smrg } 1203706f2543Smrg SyncNumSystemCounters--; 1204706f2543Smrg } 1205706f2543Smrg free(pCounter); 1206706f2543Smrg return Success; 1207706f2543Smrg} 1208706f2543Smrg 1209706f2543Smrg/* 1210706f2543Smrg * ** Cleanup after Await 1211706f2543Smrg */ 1212706f2543Smrg/* ARGSUSED */ 1213706f2543Smrgstatic int 1214706f2543SmrgFreeAwait(void *addr, XID id) 1215706f2543Smrg{ 1216706f2543Smrg SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 1217706f2543Smrg SyncAwait *pAwait; 1218706f2543Smrg int numwaits; 1219706f2543Smrg 1220706f2543Smrg pAwait = &(pAwaitUnion+1)->await; /* first await on list */ 1221706f2543Smrg 1222706f2543Smrg /* remove triggers from counters */ 1223706f2543Smrg 1224706f2543Smrg for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 1225706f2543Smrg numwaits--, pAwait++) 1226706f2543Smrg { 1227706f2543Smrg /* If the counter is being destroyed, FreeCounter will delete 1228706f2543Smrg * the trigger list itself, so don't do it here. 1229706f2543Smrg */ 1230706f2543Smrg SyncObject *pSync = pAwait->trigger.pSync; 1231706f2543Smrg if (pSync && !pSync->beingDestroyed) 1232706f2543Smrg SyncDeleteTriggerFromSyncObject(&pAwait->trigger); 1233706f2543Smrg } 1234706f2543Smrg free(pAwaitUnion); 1235706f2543Smrg return Success; 1236706f2543Smrg} 1237706f2543Smrg 1238706f2543Smrg/* loosely based on dix/events.c/OtherClientGone */ 1239706f2543Smrgstatic int 1240706f2543SmrgFreeAlarmClient(void *value, XID id) 1241706f2543Smrg{ 1242706f2543Smrg SyncAlarm *pAlarm = (SyncAlarm *)value; 1243706f2543Smrg SyncAlarmClientList *pCur, *pPrev; 1244706f2543Smrg 1245706f2543Smrg for (pPrev = NULL, pCur = pAlarm->pEventClients; 1246706f2543Smrg pCur; 1247706f2543Smrg pPrev = pCur, pCur = pCur->next) 1248706f2543Smrg { 1249706f2543Smrg if (pCur->delete_id == id) 1250706f2543Smrg { 1251706f2543Smrg if (pPrev) 1252706f2543Smrg pPrev->next = pCur->next; 1253706f2543Smrg else 1254706f2543Smrg pAlarm->pEventClients = pCur->next; 1255706f2543Smrg free(pCur); 1256706f2543Smrg return Success; 1257706f2543Smrg } 1258706f2543Smrg } 1259706f2543Smrg FatalError("alarm client not on event list"); 1260706f2543Smrg /*NOTREACHED*/ 1261706f2543Smrg} 1262706f2543Smrg 1263706f2543Smrg 1264706f2543Smrg/* 1265706f2543Smrg * ***** Proc functions 1266706f2543Smrg */ 1267706f2543Smrg 1268706f2543Smrg 1269706f2543Smrg/* 1270706f2543Smrg * ** Initialize the extension 1271706f2543Smrg */ 1272706f2543Smrgstatic int 1273706f2543SmrgProcSyncInitialize(ClientPtr client) 1274706f2543Smrg{ 1275706f2543Smrg xSyncInitializeReply rep; 1276706f2543Smrg int n; 1277706f2543Smrg 1278706f2543Smrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 1279706f2543Smrg 1280706f2543Smrg memset(&rep, 0, sizeof(xSyncInitializeReply)); 1281706f2543Smrg rep.type = X_Reply; 1282706f2543Smrg rep.sequenceNumber = client->sequence; 1283706f2543Smrg rep.majorVersion = SERVER_SYNC_MAJOR_VERSION; 1284706f2543Smrg rep.minorVersion = SERVER_SYNC_MINOR_VERSION; 1285706f2543Smrg rep.length = 0; 1286706f2543Smrg 1287706f2543Smrg if (client->swapped) 1288706f2543Smrg { 1289706f2543Smrg swaps(&rep.sequenceNumber, n); 1290706f2543Smrg } 1291706f2543Smrg WriteToClient(client, sizeof(rep), (char *) &rep); 1292706f2543Smrg return Success; 1293706f2543Smrg} 1294706f2543Smrg 1295706f2543Smrg/* 1296706f2543Smrg * ** Get list of system counters available through the extension 1297706f2543Smrg */ 1298706f2543Smrgstatic int 1299706f2543SmrgProcSyncListSystemCounters(ClientPtr client) 1300706f2543Smrg{ 1301706f2543Smrg xSyncListSystemCountersReply rep; 1302706f2543Smrg int i, len; 1303706f2543Smrg xSyncSystemCounter *list = NULL, *walklist = NULL; 1304706f2543Smrg 1305706f2543Smrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 1306706f2543Smrg 1307706f2543Smrg rep.type = X_Reply; 1308706f2543Smrg rep.sequenceNumber = client->sequence; 1309706f2543Smrg rep.nCounters = SyncNumSystemCounters; 1310706f2543Smrg 1311706f2543Smrg for (i = len = 0; i < SyncNumSystemCounters; i++) 1312706f2543Smrg { 1313706f2543Smrg char *name = SysCounterList[i]->pSysCounterInfo->name; 1314706f2543Smrg /* pad to 4 byte boundary */ 1315706f2543Smrg len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); 1316706f2543Smrg } 1317706f2543Smrg 1318706f2543Smrg if (len) 1319706f2543Smrg { 1320706f2543Smrg walklist = list = malloc(len); 1321706f2543Smrg if (!list) 1322706f2543Smrg return BadAlloc; 1323706f2543Smrg } 1324706f2543Smrg 1325706f2543Smrg rep.length = bytes_to_int32(len); 1326706f2543Smrg 1327706f2543Smrg if (client->swapped) 1328706f2543Smrg { 1329706f2543Smrg char n; 1330706f2543Smrg swaps(&rep.sequenceNumber, n); 1331706f2543Smrg swapl(&rep.length, n); 1332706f2543Smrg swapl(&rep.nCounters, n); 1333706f2543Smrg } 1334706f2543Smrg 1335706f2543Smrg for (i = 0; i < SyncNumSystemCounters; i++) 1336706f2543Smrg { 1337706f2543Smrg int namelen; 1338706f2543Smrg char *pname_in_reply; 1339706f2543Smrg SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; 1340706f2543Smrg 1341706f2543Smrg walklist->counter = SysCounterList[i]->sync.id; 1342706f2543Smrg walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 1343706f2543Smrg walklist->resolution_lo = XSyncValueLow32(psci->resolution); 1344706f2543Smrg namelen = strlen(psci->name); 1345706f2543Smrg walklist->name_length = namelen; 1346706f2543Smrg 1347706f2543Smrg if (client->swapped) 1348706f2543Smrg { 1349706f2543Smrg char n; 1350706f2543Smrg swapl(&walklist->counter, n); 1351706f2543Smrg swapl(&walklist->resolution_hi, n); 1352706f2543Smrg swapl(&walklist->resolution_lo, n); 1353706f2543Smrg swaps(&walklist->name_length, n); 1354706f2543Smrg } 1355706f2543Smrg 1356706f2543Smrg pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; 1357706f2543Smrg strncpy(pname_in_reply, psci->name, namelen); 1358706f2543Smrg walklist = (xSyncSystemCounter *) (((char *)walklist) + 1359706f2543Smrg pad_to_int32(sz_xSyncSystemCounter + namelen)); 1360706f2543Smrg } 1361706f2543Smrg 1362706f2543Smrg WriteToClient(client, sizeof(rep), (char *) &rep); 1363706f2543Smrg if (len) 1364706f2543Smrg { 1365706f2543Smrg WriteToClient(client, len, (char *) list); 1366706f2543Smrg free(list); 1367706f2543Smrg } 1368706f2543Smrg 1369706f2543Smrg return Success; 1370706f2543Smrg} 1371706f2543Smrg 1372706f2543Smrg/* 1373706f2543Smrg * ** Set client Priority 1374706f2543Smrg */ 1375706f2543Smrgstatic int 1376706f2543SmrgProcSyncSetPriority(ClientPtr client) 1377706f2543Smrg{ 1378706f2543Smrg REQUEST(xSyncSetPriorityReq); 1379706f2543Smrg ClientPtr priorityclient; 1380706f2543Smrg int rc; 1381706f2543Smrg 1382706f2543Smrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 1383706f2543Smrg 1384706f2543Smrg if (stuff->id == None) 1385706f2543Smrg priorityclient = client; 1386706f2543Smrg else { 1387706f2543Smrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1388706f2543Smrg DixSetAttrAccess); 1389706f2543Smrg if (rc != Success) 1390706f2543Smrg return rc; 1391706f2543Smrg } 1392706f2543Smrg 1393706f2543Smrg if (priorityclient->priority != stuff->priority) 1394706f2543Smrg { 1395706f2543Smrg priorityclient->priority = stuff->priority; 1396706f2543Smrg 1397706f2543Smrg /* The following will force the server back into WaitForSomething 1398706f2543Smrg * so that the change in this client's priority is immediately 1399706f2543Smrg * reflected. 1400706f2543Smrg */ 1401706f2543Smrg isItTimeToYield = TRUE; 1402706f2543Smrg dispatchException |= DE_PRIORITYCHANGE; 1403706f2543Smrg } 1404706f2543Smrg return Success; 1405706f2543Smrg} 1406706f2543Smrg 1407706f2543Smrg/* 1408706f2543Smrg * ** Get client Priority 1409706f2543Smrg */ 1410706f2543Smrgstatic int 1411706f2543SmrgProcSyncGetPriority(ClientPtr client) 1412706f2543Smrg{ 1413706f2543Smrg REQUEST(xSyncGetPriorityReq); 1414706f2543Smrg xSyncGetPriorityReply rep; 1415706f2543Smrg ClientPtr priorityclient; 1416706f2543Smrg int rc; 1417706f2543Smrg 1418706f2543Smrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 1419706f2543Smrg 1420706f2543Smrg if (stuff->id == None) 1421706f2543Smrg priorityclient = client; 1422706f2543Smrg else { 1423706f2543Smrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1424706f2543Smrg DixGetAttrAccess); 1425706f2543Smrg if (rc != Success) 1426706f2543Smrg return rc; 1427706f2543Smrg } 1428706f2543Smrg 1429706f2543Smrg rep.type = X_Reply; 1430706f2543Smrg rep.length = 0; 1431706f2543Smrg rep.sequenceNumber = client->sequence; 1432706f2543Smrg rep.priority = priorityclient->priority; 1433706f2543Smrg 1434706f2543Smrg if (client->swapped) 1435706f2543Smrg { 1436706f2543Smrg char n; 1437706f2543Smrg swaps(&rep.sequenceNumber, n); 1438706f2543Smrg swapl(&rep.priority, n); 1439706f2543Smrg } 1440706f2543Smrg 1441706f2543Smrg WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); 1442706f2543Smrg 1443706f2543Smrg return Success; 1444706f2543Smrg} 1445706f2543Smrg 1446706f2543Smrg/* 1447706f2543Smrg * ** Create a new counter 1448706f2543Smrg */ 1449706f2543Smrgstatic int 1450706f2543SmrgProcSyncCreateCounter(ClientPtr client) 1451706f2543Smrg{ 1452706f2543Smrg REQUEST(xSyncCreateCounterReq); 1453706f2543Smrg CARD64 initial; 1454706f2543Smrg 1455706f2543Smrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 1456706f2543Smrg 1457706f2543Smrg LEGAL_NEW_RESOURCE(stuff->cid, client); 1458706f2543Smrg 1459706f2543Smrg XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); 1460706f2543Smrg if (!SyncCreateCounter(client, stuff->cid, initial)) 1461706f2543Smrg return BadAlloc; 1462706f2543Smrg 1463706f2543Smrg return Success; 1464706f2543Smrg} 1465706f2543Smrg 1466706f2543Smrg/* 1467706f2543Smrg * ** Set Counter value 1468706f2543Smrg */ 1469706f2543Smrgstatic int 1470706f2543SmrgProcSyncSetCounter(ClientPtr client) 1471706f2543Smrg{ 1472706f2543Smrg REQUEST(xSyncSetCounterReq); 1473706f2543Smrg SyncCounter *pCounter; 1474706f2543Smrg CARD64 newvalue; 1475706f2543Smrg int rc; 1476706f2543Smrg 1477706f2543Smrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 1478706f2543Smrg 1479706f2543Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, 1480706f2543Smrg client, DixWriteAccess); 1481706f2543Smrg if (rc != Success) 1482706f2543Smrg return rc; 1483706f2543Smrg 1484706f2543Smrg if (IsSystemCounter(pCounter)) 1485706f2543Smrg { 1486706f2543Smrg client->errorValue = stuff->cid; 1487706f2543Smrg return BadAccess; 1488706f2543Smrg } 1489706f2543Smrg 1490706f2543Smrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 1491706f2543Smrg SyncChangeCounter(pCounter, newvalue); 1492706f2543Smrg return Success; 1493706f2543Smrg} 1494706f2543Smrg 1495706f2543Smrg/* 1496706f2543Smrg * ** Change Counter value 1497706f2543Smrg */ 1498706f2543Smrgstatic int 1499706f2543SmrgProcSyncChangeCounter(ClientPtr client) 1500706f2543Smrg{ 1501706f2543Smrg REQUEST(xSyncChangeCounterReq); 1502706f2543Smrg SyncCounter *pCounter; 1503706f2543Smrg CARD64 newvalue; 1504706f2543Smrg Bool overflow; 1505706f2543Smrg int rc; 1506706f2543Smrg 1507706f2543Smrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 1508706f2543Smrg 1509706f2543Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, 1510706f2543Smrg client, DixWriteAccess); 1511706f2543Smrg if (rc != Success) 1512706f2543Smrg return rc; 1513706f2543Smrg 1514706f2543Smrg if (IsSystemCounter(pCounter)) 1515706f2543Smrg { 1516706f2543Smrg client->errorValue = stuff->cid; 1517706f2543Smrg return BadAccess; 1518706f2543Smrg } 1519706f2543Smrg 1520706f2543Smrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 1521706f2543Smrg XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 1522706f2543Smrg if (overflow) 1523706f2543Smrg { 1524706f2543Smrg /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 1525706f2543Smrg client->errorValue = stuff->value_hi; 1526706f2543Smrg return BadValue; 1527706f2543Smrg } 1528706f2543Smrg SyncChangeCounter(pCounter, newvalue); 1529706f2543Smrg return Success; 1530706f2543Smrg} 1531706f2543Smrg 1532706f2543Smrg/* 1533706f2543Smrg * ** Destroy a counter 1534706f2543Smrg */ 1535706f2543Smrgstatic int 1536706f2543SmrgProcSyncDestroyCounter(ClientPtr client) 1537706f2543Smrg{ 1538706f2543Smrg REQUEST(xSyncDestroyCounterReq); 1539706f2543Smrg SyncCounter *pCounter; 1540706f2543Smrg int rc; 1541706f2543Smrg 1542706f2543Smrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 1543706f2543Smrg 1544706f2543Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, 1545706f2543Smrg client, DixDestroyAccess); 1546706f2543Smrg if (rc != Success) 1547706f2543Smrg return rc; 1548706f2543Smrg 1549706f2543Smrg if (IsSystemCounter(pCounter)) 1550706f2543Smrg { 1551706f2543Smrg client->errorValue = stuff->counter; 1552706f2543Smrg return BadAccess; 1553706f2543Smrg } 1554706f2543Smrg FreeResource(pCounter->sync.id, RT_NONE); 1555706f2543Smrg return Success; 1556706f2543Smrg} 1557706f2543Smrg 1558706f2543Smrgstatic SyncAwaitUnion* 1559706f2543SmrgSyncAwaitPrologue(ClientPtr client, int items) 1560706f2543Smrg{ 1561706f2543Smrg SyncAwaitUnion *pAwaitUnion; 1562706f2543Smrg 1563706f2543Smrg /* all the memory for the entire await list is allocated 1564706f2543Smrg * here in one chunk 1565706f2543Smrg */ 1566706f2543Smrg pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion)); 1567706f2543Smrg if (!pAwaitUnion) 1568706f2543Smrg return NULL; 1569706f2543Smrg 1570706f2543Smrg /* first item is the header, remainder are real wait conditions */ 1571706f2543Smrg 1572706f2543Smrg pAwaitUnion->header.delete_id = FakeClientID(client->index); 1573706f2543Smrg pAwaitUnion->header.client = client; 1574706f2543Smrg pAwaitUnion->header.num_waitconditions = 0; 1575706f2543Smrg 1576706f2543Smrg if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 1577706f2543Smrg return NULL; 1578706f2543Smrg 1579706f2543Smrg return pAwaitUnion; 1580706f2543Smrg} 1581706f2543Smrg 1582706f2543Smrgstatic void 1583706f2543SmrgSyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion) 1584706f2543Smrg{ 1585706f2543Smrg SyncAwait *pAwait; 1586706f2543Smrg int i; 1587706f2543Smrg 1588706f2543Smrg IgnoreClient(client); 1589706f2543Smrg 1590706f2543Smrg /* see if any of the triggers are already true */ 1591706f2543Smrg 1592706f2543Smrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 1593706f2543Smrg for (i = 0; i < items; i++, pAwait++) 1594706f2543Smrg { 1595706f2543Smrg CARD64 value; 1596706f2543Smrg 1597706f2543Smrg /* don't have to worry about NULL counters because the request 1598706f2543Smrg * errors before we get here out if they occur 1599706f2543Smrg */ 1600706f2543Smrg switch (pAwait->trigger.pSync->type) { 1601706f2543Smrg case SYNC_COUNTER: 1602706f2543Smrg value = ((SyncCounter *)pAwait->trigger.pSync)->value; 1603706f2543Smrg break; 1604706f2543Smrg default: 1605706f2543Smrg XSyncIntToValue(&value, 0); 1606706f2543Smrg } 1607706f2543Smrg 1608706f2543Smrg if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value)) 1609706f2543Smrg { 1610706f2543Smrg (*pAwait->trigger.TriggerFired)(&pAwait->trigger); 1611706f2543Smrg break; /* once is enough */ 1612706f2543Smrg } 1613706f2543Smrg } 1614706f2543Smrg} 1615706f2543Smrg 1616706f2543Smrg/* 1617706f2543Smrg * ** Await 1618706f2543Smrg */ 1619706f2543Smrgstatic int 1620706f2543SmrgProcSyncAwait(ClientPtr client) 1621706f2543Smrg{ 1622706f2543Smrg REQUEST(xSyncAwaitReq); 1623706f2543Smrg int len, items; 1624706f2543Smrg int i; 1625706f2543Smrg xSyncWaitCondition *pProtocolWaitConds; 1626706f2543Smrg SyncAwaitUnion *pAwaitUnion; 1627706f2543Smrg SyncAwait *pAwait; 1628706f2543Smrg int status; 1629706f2543Smrg 1630706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 1631706f2543Smrg 1632706f2543Smrg len = client->req_len << 2; 1633706f2543Smrg len -= sz_xSyncAwaitReq; 1634706f2543Smrg items = len / sz_xSyncWaitCondition; 1635706f2543Smrg 1636706f2543Smrg if (items * sz_xSyncWaitCondition != len) 1637706f2543Smrg { 1638706f2543Smrg return BadLength; 1639706f2543Smrg } 1640706f2543Smrg if (items == 0) 1641706f2543Smrg { 1642706f2543Smrg client->errorValue = items; /* XXX protocol change */ 1643706f2543Smrg return BadValue; 1644706f2543Smrg } 1645706f2543Smrg 1646706f2543Smrg if (!(pAwaitUnion = SyncAwaitPrologue(client, items))) 1647706f2543Smrg return BadAlloc; 1648706f2543Smrg 1649706f2543Smrg /* don't need to do any more memory allocation for this request! */ 1650706f2543Smrg 1651706f2543Smrg pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; 1652706f2543Smrg 1653706f2543Smrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 1654706f2543Smrg for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) 1655706f2543Smrg { 1656706f2543Smrg if (pProtocolWaitConds->counter == None) /* XXX protocol change */ 1657706f2543Smrg { 1658706f2543Smrg /* this should take care of removing any triggers created by 1659706f2543Smrg * this request that have already been registered on sync objects 1660706f2543Smrg */ 1661706f2543Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 1662706f2543Smrg client->errorValue = pProtocolWaitConds->counter; 1663706f2543Smrg return SyncErrorBase + XSyncBadCounter; 1664706f2543Smrg } 1665706f2543Smrg 1666706f2543Smrg /* sanity checks are in SyncInitTrigger */ 1667706f2543Smrg pAwait->trigger.pSync = NULL; 1668706f2543Smrg pAwait->trigger.value_type = pProtocolWaitConds->value_type; 1669706f2543Smrg XSyncIntsToValue(&pAwait->trigger.wait_value, 1670706f2543Smrg pProtocolWaitConds->wait_value_lo, 1671706f2543Smrg pProtocolWaitConds->wait_value_hi); 1672706f2543Smrg pAwait->trigger.test_type = pProtocolWaitConds->test_type; 1673706f2543Smrg 1674706f2543Smrg status = SyncInitTrigger(client, &pAwait->trigger, 1675706f2543Smrg pProtocolWaitConds->counter, RTCounter, 1676706f2543Smrg XSyncCAAllTrigger); 1677706f2543Smrg if (status != Success) 1678706f2543Smrg { 1679706f2543Smrg /* this should take care of removing any triggers created by 1680706f2543Smrg * this request that have already been registered on sync objects 1681706f2543Smrg */ 1682706f2543Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 1683706f2543Smrg return status; 1684706f2543Smrg } 1685706f2543Smrg /* this is not a mistake -- same function works for both cases */ 1686706f2543Smrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 1687706f2543Smrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 1688706f2543Smrg XSyncIntsToValue(&pAwait->event_threshold, 1689706f2543Smrg pProtocolWaitConds->event_threshold_lo, 1690706f2543Smrg pProtocolWaitConds->event_threshold_hi); 1691706f2543Smrg pAwait->pHeader = &pAwaitUnion->header; 1692706f2543Smrg pAwaitUnion->header.num_waitconditions++; 1693706f2543Smrg } 1694706f2543Smrg 1695706f2543Smrg SyncAwaitEpilogue(client, items, pAwaitUnion); 1696706f2543Smrg 1697706f2543Smrg return Success; 1698706f2543Smrg} 1699706f2543Smrg 1700706f2543Smrg 1701706f2543Smrg/* 1702706f2543Smrg * ** Query a counter 1703706f2543Smrg */ 1704706f2543Smrgstatic int 1705706f2543SmrgProcSyncQueryCounter(ClientPtr client) 1706706f2543Smrg{ 1707706f2543Smrg REQUEST(xSyncQueryCounterReq); 1708706f2543Smrg xSyncQueryCounterReply rep; 1709706f2543Smrg SyncCounter *pCounter; 1710706f2543Smrg int rc; 1711706f2543Smrg 1712706f2543Smrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 1713706f2543Smrg 1714706f2543Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, 1715706f2543Smrg RTCounter, client, DixReadAccess); 1716706f2543Smrg if (rc != Success) 1717706f2543Smrg return rc; 1718706f2543Smrg 1719706f2543Smrg rep.type = X_Reply; 1720706f2543Smrg rep.length = 0; 1721706f2543Smrg rep.sequenceNumber = client->sequence; 1722706f2543Smrg 1723706f2543Smrg /* if system counter, ask it what the current value is */ 1724706f2543Smrg 1725706f2543Smrg if (IsSystemCounter(pCounter)) 1726706f2543Smrg { 1727706f2543Smrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 1728706f2543Smrg &pCounter->value); 1729706f2543Smrg } 1730706f2543Smrg 1731706f2543Smrg rep.value_hi = XSyncValueHigh32(pCounter->value); 1732706f2543Smrg rep.value_lo = XSyncValueLow32(pCounter->value); 1733706f2543Smrg if (client->swapped) 1734706f2543Smrg { 1735706f2543Smrg char n; 1736706f2543Smrg swaps(&rep.sequenceNumber, n); 1737706f2543Smrg swapl(&rep.length, n); 1738706f2543Smrg swapl(&rep.value_hi, n); 1739706f2543Smrg swapl(&rep.value_lo, n); 1740706f2543Smrg } 1741706f2543Smrg WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); 1742706f2543Smrg return Success; 1743706f2543Smrg} 1744706f2543Smrg 1745706f2543Smrg 1746706f2543Smrg/* 1747706f2543Smrg * ** Create Alarm 1748706f2543Smrg */ 1749706f2543Smrgstatic int 1750706f2543SmrgProcSyncCreateAlarm(ClientPtr client) 1751706f2543Smrg{ 1752706f2543Smrg REQUEST(xSyncCreateAlarmReq); 1753706f2543Smrg SyncAlarm *pAlarm; 1754706f2543Smrg int status; 1755706f2543Smrg unsigned long len, vmask; 1756706f2543Smrg SyncTrigger *pTrigger; 1757706f2543Smrg 1758706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 1759706f2543Smrg 1760706f2543Smrg LEGAL_NEW_RESOURCE(stuff->id, client); 1761706f2543Smrg 1762706f2543Smrg vmask = stuff->valueMask; 1763706f2543Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); 1764706f2543Smrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 1765706f2543Smrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 1766706f2543Smrg return BadLength; 1767706f2543Smrg 1768706f2543Smrg if (!(pAlarm = malloc(sizeof(SyncAlarm)))) 1769706f2543Smrg { 1770706f2543Smrg return BadAlloc; 1771706f2543Smrg } 1772706f2543Smrg 1773706f2543Smrg /* set up defaults */ 1774706f2543Smrg 1775706f2543Smrg pTrigger = &pAlarm->trigger; 1776706f2543Smrg pTrigger->pSync = NULL; 1777706f2543Smrg pTrigger->value_type = XSyncAbsolute; 1778706f2543Smrg XSyncIntToValue(&pTrigger->wait_value, 0L); 1779706f2543Smrg pTrigger->test_type = XSyncPositiveComparison; 1780706f2543Smrg pTrigger->TriggerFired = SyncAlarmTriggerFired; 1781706f2543Smrg pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 1782706f2543Smrg status = SyncInitTrigger(client, pTrigger, None, RTCounter, 1783706f2543Smrg XSyncCAAllTrigger); 1784706f2543Smrg if (status != Success) 1785706f2543Smrg { 1786706f2543Smrg free(pAlarm); 1787706f2543Smrg return status; 1788706f2543Smrg } 1789706f2543Smrg 1790706f2543Smrg pAlarm->client = client; 1791706f2543Smrg pAlarm->alarm_id = stuff->id; 1792706f2543Smrg XSyncIntToValue(&pAlarm->delta, 1L); 1793706f2543Smrg pAlarm->events = TRUE; 1794706f2543Smrg pAlarm->state = XSyncAlarmInactive; 1795706f2543Smrg pAlarm->pEventClients = NULL; 1796706f2543Smrg status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 1797706f2543Smrg (CARD32 *)&stuff[1]); 1798706f2543Smrg if (status != Success) 1799706f2543Smrg { 1800706f2543Smrg free(pAlarm); 1801706f2543Smrg return status; 1802706f2543Smrg } 1803706f2543Smrg 1804706f2543Smrg if (!AddResource(stuff->id, RTAlarm, pAlarm)) 1805706f2543Smrg return BadAlloc; 1806706f2543Smrg 1807706f2543Smrg /* see if alarm already triggered. NULL counter will not trigger 1808706f2543Smrg * in CreateAlarm and sets alarm state to Inactive. 1809706f2543Smrg */ 1810706f2543Smrg 1811706f2543Smrg if (!pTrigger->pSync) 1812706f2543Smrg { 1813706f2543Smrg pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 1814706f2543Smrg } 1815706f2543Smrg else 1816706f2543Smrg { 1817706f2543Smrg SyncCounter *pCounter; 1818706f2543Smrg 1819706f2543Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, 1820706f2543Smrg WARN_INVALID_COUNTER_ALARM)) 1821706f2543Smrg { 1822706f2543Smrg FreeResource(stuff->id, RT_NONE); 1823706f2543Smrg return BadAlloc; 1824706f2543Smrg } 1825706f2543Smrg 1826706f2543Smrg pCounter = (SyncCounter *)pTrigger->pSync; 1827706f2543Smrg 1828706f2543Smrg if ((*pTrigger->CheckTrigger)(pTrigger, pCounter->value)) 1829706f2543Smrg (*pTrigger->TriggerFired)(pTrigger); 1830706f2543Smrg } 1831706f2543Smrg 1832706f2543Smrg return Success; 1833706f2543Smrg} 1834706f2543Smrg 1835706f2543Smrg/* 1836706f2543Smrg * ** Change Alarm 1837706f2543Smrg */ 1838706f2543Smrgstatic int 1839706f2543SmrgProcSyncChangeAlarm(ClientPtr client) 1840706f2543Smrg{ 1841706f2543Smrg REQUEST(xSyncChangeAlarmReq); 1842706f2543Smrg SyncAlarm *pAlarm; 1843706f2543Smrg SyncCounter *pCounter = NULL; 1844706f2543Smrg long vmask; 1845706f2543Smrg int len, status; 1846706f2543Smrg 1847706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 1848706f2543Smrg 1849706f2543Smrg status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 1850706f2543Smrg client, DixWriteAccess); 1851706f2543Smrg if (status != Success) 1852706f2543Smrg return status; 1853706f2543Smrg 1854706f2543Smrg vmask = stuff->valueMask; 1855706f2543Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); 1856706f2543Smrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 1857706f2543Smrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 1858706f2543Smrg return BadLength; 1859706f2543Smrg 1860706f2543Smrg if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 1861706f2543Smrg (CARD32 *)&stuff[1])) != Success) 1862706f2543Smrg return status; 1863706f2543Smrg 1864706f2543Smrg if (SyncCheckWarnIsCounter(pAlarm->trigger.pSync, 1865706f2543Smrg WARN_INVALID_COUNTER_ALARM)) 1866706f2543Smrg pCounter = (SyncCounter *)pAlarm->trigger.pSync; 1867706f2543Smrg 1868706f2543Smrg /* see if alarm already triggered. NULL counter WILL trigger 1869706f2543Smrg * in ChangeAlarm. 1870706f2543Smrg */ 1871706f2543Smrg 1872706f2543Smrg if (!pCounter || 1873706f2543Smrg (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, pCounter->value)) 1874706f2543Smrg { 1875706f2543Smrg (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); 1876706f2543Smrg } 1877706f2543Smrg return Success; 1878706f2543Smrg} 1879706f2543Smrg 1880706f2543Smrgstatic int 1881706f2543SmrgProcSyncQueryAlarm(ClientPtr client) 1882706f2543Smrg{ 1883706f2543Smrg REQUEST(xSyncQueryAlarmReq); 1884706f2543Smrg SyncAlarm *pAlarm; 1885706f2543Smrg xSyncQueryAlarmReply rep; 1886706f2543Smrg SyncTrigger *pTrigger; 1887706f2543Smrg int rc; 1888706f2543Smrg 1889706f2543Smrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 1890706f2543Smrg 1891706f2543Smrg rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 1892706f2543Smrg client, DixReadAccess); 1893706f2543Smrg if (rc != Success) 1894706f2543Smrg return rc; 1895706f2543Smrg 1896706f2543Smrg rep.type = X_Reply; 1897706f2543Smrg rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); 1898706f2543Smrg rep.sequenceNumber = client->sequence; 1899706f2543Smrg 1900706f2543Smrg pTrigger = &pAlarm->trigger; 1901706f2543Smrg rep.counter = (pTrigger->pSync) ? pTrigger->pSync->id : None; 1902706f2543Smrg 1903706f2543Smrg#if 0 /* XXX unclear what to do, depends on whether relative value-types 1904706f2543Smrg * are "consumed" immediately and are considered absolute from then 1905706f2543Smrg * on. 1906706f2543Smrg */ 1907706f2543Smrg rep.value_type = pTrigger->value_type; 1908706f2543Smrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); 1909706f2543Smrg rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); 1910706f2543Smrg#else 1911706f2543Smrg rep.value_type = XSyncAbsolute; 1912706f2543Smrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 1913706f2543Smrg rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); 1914706f2543Smrg#endif 1915706f2543Smrg 1916706f2543Smrg rep.test_type = pTrigger->test_type; 1917706f2543Smrg rep.delta_hi = XSyncValueHigh32(pAlarm->delta); 1918706f2543Smrg rep.delta_lo = XSyncValueLow32(pAlarm->delta); 1919706f2543Smrg rep.events = pAlarm->events; 1920706f2543Smrg rep.state = pAlarm->state; 1921706f2543Smrg 1922706f2543Smrg if (client->swapped) 1923706f2543Smrg { 1924706f2543Smrg char n; 1925706f2543Smrg swaps(&rep.sequenceNumber, n); 1926706f2543Smrg swapl(&rep.length, n); 1927706f2543Smrg swapl(&rep.counter, n); 1928706f2543Smrg swapl(&rep.wait_value_hi, n); 1929706f2543Smrg swapl(&rep.wait_value_lo, n); 1930706f2543Smrg swapl(&rep.test_type, n); 1931706f2543Smrg swapl(&rep.delta_hi, n); 1932706f2543Smrg swapl(&rep.delta_lo, n); 1933706f2543Smrg } 1934706f2543Smrg 1935706f2543Smrg WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); 1936706f2543Smrg return Success; 1937706f2543Smrg} 1938706f2543Smrg 1939706f2543Smrgstatic int 1940706f2543SmrgProcSyncDestroyAlarm(ClientPtr client) 1941706f2543Smrg{ 1942706f2543Smrg SyncAlarm *pAlarm; 1943706f2543Smrg int rc; 1944706f2543Smrg REQUEST(xSyncDestroyAlarmReq); 1945706f2543Smrg 1946706f2543Smrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 1947706f2543Smrg 1948706f2543Smrg rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 1949706f2543Smrg client, DixDestroyAccess); 1950706f2543Smrg if (rc != Success) 1951706f2543Smrg return rc; 1952706f2543Smrg 1953706f2543Smrg FreeResource(stuff->alarm, RT_NONE); 1954706f2543Smrg return Success; 1955706f2543Smrg} 1956706f2543Smrg 1957706f2543Smrgstatic int 1958706f2543SmrgProcSyncCreateFence(ClientPtr client) 1959706f2543Smrg{ 1960706f2543Smrg REQUEST(xSyncCreateFenceReq); 1961706f2543Smrg DrawablePtr pDraw; 1962706f2543Smrg SyncFence *pFence; 1963706f2543Smrg int rc; 1964706f2543Smrg 1965706f2543Smrg REQUEST_SIZE_MATCH(xSyncCreateFenceReq); 1966706f2543Smrg 1967706f2543Smrg rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess); 1968706f2543Smrg if (rc != Success) 1969706f2543Smrg return rc; 1970706f2543Smrg 1971706f2543Smrg LEGAL_NEW_RESOURCE(stuff->fid, client); 1972706f2543Smrg 1973706f2543Smrg if (!(pFence = (SyncFence *)SyncCreate(client, 1974706f2543Smrg stuff->fid, 1975706f2543Smrg SYNC_FENCE))) 1976706f2543Smrg return BadAlloc; 1977706f2543Smrg 1978706f2543Smrg miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered); 1979706f2543Smrg 1980706f2543Smrg if (!AddResource(stuff->fid, RTFence, (pointer) pFence)) 1981706f2543Smrg return BadAlloc; 1982706f2543Smrg 1983706f2543Smrg return client->noClientException; 1984706f2543Smrg} 1985706f2543Smrg 1986706f2543Smrgstatic int 1987706f2543SmrgFreeFence(void *obj, XID id) 1988706f2543Smrg{ 1989706f2543Smrg SyncFence *pFence = (SyncFence *) obj; 1990706f2543Smrg 1991706f2543Smrg miSyncDestroyFence(pFence); 1992706f2543Smrg 1993706f2543Smrg return Success; 1994706f2543Smrg} 1995706f2543Smrg 1996706f2543Smrgint SyncVerifyFence(SyncFence **ppSyncFence, XID fid, 1997706f2543Smrg ClientPtr client, Mask mode) 1998706f2543Smrg{ 1999706f2543Smrg int rc = dixLookupResourceByType((pointer *)ppSyncFence, fid, RTFence, 2000706f2543Smrg client, mode); 2001706f2543Smrg 2002706f2543Smrg if (rc != Success) 2003706f2543Smrg client->errorValue = fid; 2004706f2543Smrg 2005706f2543Smrg return rc; 2006706f2543Smrg} 2007706f2543Smrg 2008706f2543Smrgstatic int 2009706f2543SmrgProcSyncTriggerFence(ClientPtr client) 2010706f2543Smrg{ 2011706f2543Smrg REQUEST(xSyncTriggerFenceReq); 2012706f2543Smrg SyncFence *pFence; 2013706f2543Smrg int rc; 2014706f2543Smrg 2015706f2543Smrg REQUEST_SIZE_MATCH(xSyncTriggerFenceReq); 2016706f2543Smrg 2017706f2543Smrg rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence, 2018706f2543Smrg client, DixWriteAccess); 2019706f2543Smrg if (rc != Success) 2020706f2543Smrg return rc; 2021706f2543Smrg 2022706f2543Smrg miSyncTriggerFence(pFence); 2023706f2543Smrg 2024706f2543Smrg return client->noClientException; 2025706f2543Smrg} 2026706f2543Smrg 2027706f2543Smrgstatic int 2028706f2543SmrgProcSyncResetFence(ClientPtr client) 2029706f2543Smrg{ 2030706f2543Smrg REQUEST(xSyncResetFenceReq); 2031706f2543Smrg SyncFence *pFence; 2032706f2543Smrg int rc; 2033706f2543Smrg 2034706f2543Smrg REQUEST_SIZE_MATCH(xSyncResetFenceReq); 2035706f2543Smrg 2036706f2543Smrg rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence, 2037706f2543Smrg client, DixWriteAccess); 2038706f2543Smrg if (rc != Success) 2039706f2543Smrg return rc; 2040706f2543Smrg 2041706f2543Smrg if (pFence->funcs.CheckTriggered(pFence) != TRUE) 2042706f2543Smrg return BadMatch; 2043706f2543Smrg 2044706f2543Smrg pFence->funcs.Reset(pFence); 2045706f2543Smrg 2046706f2543Smrg return client->noClientException; 2047706f2543Smrg} 2048706f2543Smrg 2049706f2543Smrgstatic int 2050706f2543SmrgProcSyncDestroyFence(ClientPtr client) 2051706f2543Smrg{ 2052706f2543Smrg REQUEST(xSyncDestroyFenceReq); 2053706f2543Smrg SyncFence *pFence; 2054706f2543Smrg int rc; 2055706f2543Smrg 2056706f2543Smrg REQUEST_SIZE_MATCH(xSyncDestroyFenceReq); 2057706f2543Smrg 2058706f2543Smrg rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence, 2059706f2543Smrg client, DixDestroyAccess); 2060706f2543Smrg if (rc != Success) 2061706f2543Smrg return rc; 2062706f2543Smrg 2063706f2543Smrg FreeResource(stuff->fid, RT_NONE); 2064706f2543Smrg return client->noClientException; 2065706f2543Smrg} 2066706f2543Smrg 2067706f2543Smrgstatic int 2068706f2543SmrgProcSyncQueryFence(ClientPtr client) 2069706f2543Smrg{ 2070706f2543Smrg REQUEST(xSyncQueryFenceReq); 2071706f2543Smrg xSyncQueryFenceReply rep; 2072706f2543Smrg SyncFence *pFence; 2073706f2543Smrg int rc; 2074706f2543Smrg 2075706f2543Smrg REQUEST_SIZE_MATCH(xSyncQueryFenceReq); 2076706f2543Smrg 2077706f2543Smrg rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, 2078706f2543Smrg RTFence, client, DixReadAccess); 2079706f2543Smrg if (rc != Success) 2080706f2543Smrg return rc; 2081706f2543Smrg 2082706f2543Smrg rep.type = X_Reply; 2083706f2543Smrg rep.length = 0; 2084706f2543Smrg rep.sequenceNumber = client->sequence; 2085706f2543Smrg 2086706f2543Smrg rep.triggered = pFence->funcs.CheckTriggered(pFence); 2087706f2543Smrg 2088706f2543Smrg if (client->swapped) 2089706f2543Smrg { 2090706f2543Smrg char n; 2091706f2543Smrg swaps(&rep.sequenceNumber, n); 2092706f2543Smrg swapl(&rep.length, n); 2093706f2543Smrg } 2094706f2543Smrg 2095706f2543Smrg WriteToClient(client, sizeof(xSyncQueryFenceReply), (char *) &rep); 2096706f2543Smrg return client->noClientException; 2097706f2543Smrg} 2098706f2543Smrg 2099706f2543Smrgstatic int 2100706f2543SmrgProcSyncAwaitFence(ClientPtr client) 2101706f2543Smrg{ 2102706f2543Smrg REQUEST(xSyncAwaitFenceReq); 2103706f2543Smrg SyncAwaitUnion *pAwaitUnion; 2104706f2543Smrg SyncAwait *pAwait; 2105706f2543Smrg /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to 2106706f2543Smrg * CARD32 in protocol definitions */ 2107706f2543Smrg CARD32 *pProtocolFences; 2108706f2543Smrg int status; 2109706f2543Smrg int len; 2110706f2543Smrg int items; 2111706f2543Smrg int i; 2112706f2543Smrg 2113706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq); 2114706f2543Smrg 2115706f2543Smrg len = client->req_len << 2; 2116706f2543Smrg len -= sz_xSyncAwaitFenceReq; 2117706f2543Smrg items = len / sizeof(CARD32); 2118706f2543Smrg 2119706f2543Smrg if (items * sizeof(CARD32) != len) 2120706f2543Smrg { 2121706f2543Smrg return BadLength; 2122706f2543Smrg } 2123706f2543Smrg if (items == 0) 2124706f2543Smrg { 2125706f2543Smrg client->errorValue = items; 2126706f2543Smrg return BadValue; 2127706f2543Smrg } 2128706f2543Smrg 2129706f2543Smrg if (!(pAwaitUnion = SyncAwaitPrologue(client, items))) 2130706f2543Smrg return BadAlloc; 2131706f2543Smrg 2132706f2543Smrg /* don't need to do any more memory allocation for this request! */ 2133706f2543Smrg 2134706f2543Smrg pProtocolFences = (CARD32 *) & stuff[1]; 2135706f2543Smrg 2136706f2543Smrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 2137706f2543Smrg for (i = 0; i < items; i++, pProtocolFences++, pAwait++) 2138706f2543Smrg { 2139706f2543Smrg if (*pProtocolFences == None) 2140706f2543Smrg { 2141706f2543Smrg /* this should take care of removing any triggers created by 2142706f2543Smrg * this request that have already been registered on sync objects 2143706f2543Smrg */ 2144706f2543Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 2145706f2543Smrg client->errorValue = *pProtocolFences; 2146706f2543Smrg return SyncErrorBase + XSyncBadFence; 2147706f2543Smrg } 2148706f2543Smrg 2149706f2543Smrg pAwait->trigger.pSync = NULL; 2150706f2543Smrg /* Provide acceptable values for these unused fields to 2151706f2543Smrg * satisfy SyncInitTrigger's validation logic 2152706f2543Smrg */ 2153706f2543Smrg pAwait->trigger.value_type = XSyncAbsolute; 2154706f2543Smrg XSyncIntToValue(&pAwait->trigger.wait_value, 0); 2155706f2543Smrg pAwait->trigger.test_type = 0; 2156706f2543Smrg 2157706f2543Smrg status = SyncInitTrigger(client, &pAwait->trigger, 2158706f2543Smrg *pProtocolFences, RTFence, 2159706f2543Smrg XSyncCAAllTrigger); 2160706f2543Smrg if (status != Success) 2161706f2543Smrg { 2162706f2543Smrg /* this should take care of removing any triggers created by 2163706f2543Smrg * this request that have already been registered on sync objects 2164706f2543Smrg */ 2165706f2543Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 2166706f2543Smrg return status; 2167706f2543Smrg } 2168706f2543Smrg /* this is not a mistake -- same function works for both cases */ 2169706f2543Smrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 2170706f2543Smrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 2171706f2543Smrg /* event_threshold is unused for fence syncs */ 2172706f2543Smrg XSyncIntToValue(&pAwait->event_threshold, 0); 2173706f2543Smrg pAwait->pHeader = &pAwaitUnion->header; 2174706f2543Smrg pAwaitUnion->header.num_waitconditions++; 2175706f2543Smrg } 2176706f2543Smrg 2177706f2543Smrg SyncAwaitEpilogue(client, items, pAwaitUnion); 2178706f2543Smrg 2179706f2543Smrg return client->noClientException; 2180706f2543Smrg} 2181706f2543Smrg 2182706f2543Smrg/* 2183706f2543Smrg * ** Given an extension request, call the appropriate request procedure 2184706f2543Smrg */ 2185706f2543Smrgstatic int 2186706f2543SmrgProcSyncDispatch(ClientPtr client) 2187706f2543Smrg{ 2188706f2543Smrg REQUEST(xReq); 2189706f2543Smrg 2190706f2543Smrg switch (stuff->data) 2191706f2543Smrg { 2192706f2543Smrg case X_SyncInitialize: 2193706f2543Smrg return ProcSyncInitialize(client); 2194706f2543Smrg case X_SyncListSystemCounters: 2195706f2543Smrg return ProcSyncListSystemCounters(client); 2196706f2543Smrg case X_SyncCreateCounter: 2197706f2543Smrg return ProcSyncCreateCounter(client); 2198706f2543Smrg case X_SyncSetCounter: 2199706f2543Smrg return ProcSyncSetCounter(client); 2200706f2543Smrg case X_SyncChangeCounter: 2201706f2543Smrg return ProcSyncChangeCounter(client); 2202706f2543Smrg case X_SyncQueryCounter: 2203706f2543Smrg return ProcSyncQueryCounter(client); 2204706f2543Smrg case X_SyncDestroyCounter: 2205706f2543Smrg return ProcSyncDestroyCounter(client); 2206706f2543Smrg case X_SyncAwait: 2207706f2543Smrg return ProcSyncAwait(client); 2208706f2543Smrg case X_SyncCreateAlarm: 2209706f2543Smrg return ProcSyncCreateAlarm(client); 2210706f2543Smrg case X_SyncChangeAlarm: 2211706f2543Smrg return ProcSyncChangeAlarm(client); 2212706f2543Smrg case X_SyncQueryAlarm: 2213706f2543Smrg return ProcSyncQueryAlarm(client); 2214706f2543Smrg case X_SyncDestroyAlarm: 2215706f2543Smrg return ProcSyncDestroyAlarm(client); 2216706f2543Smrg case X_SyncSetPriority: 2217706f2543Smrg return ProcSyncSetPriority(client); 2218706f2543Smrg case X_SyncGetPriority: 2219706f2543Smrg return ProcSyncGetPriority(client); 2220706f2543Smrg case X_SyncCreateFence: 2221706f2543Smrg return ProcSyncCreateFence(client); 2222706f2543Smrg case X_SyncTriggerFence: 2223706f2543Smrg return ProcSyncTriggerFence(client); 2224706f2543Smrg case X_SyncResetFence: 2225706f2543Smrg return ProcSyncResetFence(client); 2226706f2543Smrg case X_SyncDestroyFence: 2227706f2543Smrg return ProcSyncDestroyFence(client); 2228706f2543Smrg case X_SyncQueryFence: 2229706f2543Smrg return ProcSyncQueryFence(client); 2230706f2543Smrg case X_SyncAwaitFence: 2231706f2543Smrg return ProcSyncAwaitFence(client); 2232706f2543Smrg default: 2233706f2543Smrg return BadRequest; 2234706f2543Smrg } 2235706f2543Smrg} 2236706f2543Smrg 2237706f2543Smrg/* 2238706f2543Smrg * Boring Swapping stuff ... 2239706f2543Smrg */ 2240706f2543Smrg 2241706f2543Smrgstatic int 2242706f2543SmrgSProcSyncInitialize(ClientPtr client) 2243706f2543Smrg{ 2244706f2543Smrg REQUEST(xSyncInitializeReq); 2245706f2543Smrg char n; 2246706f2543Smrg 2247706f2543Smrg swaps(&stuff->length, n); 2248706f2543Smrg REQUEST_SIZE_MATCH (xSyncInitializeReq); 2249706f2543Smrg 2250706f2543Smrg return ProcSyncInitialize(client); 2251706f2543Smrg} 2252706f2543Smrg 2253706f2543Smrgstatic int 2254706f2543SmrgSProcSyncListSystemCounters(ClientPtr client) 2255706f2543Smrg{ 2256706f2543Smrg REQUEST(xSyncListSystemCountersReq); 2257706f2543Smrg char n; 2258706f2543Smrg 2259706f2543Smrg swaps(&stuff->length, n); 2260706f2543Smrg REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); 2261706f2543Smrg 2262706f2543Smrg return ProcSyncListSystemCounters(client); 2263706f2543Smrg} 2264706f2543Smrg 2265706f2543Smrgstatic int 2266706f2543SmrgSProcSyncCreateCounter(ClientPtr client) 2267706f2543Smrg{ 2268706f2543Smrg REQUEST(xSyncCreateCounterReq); 2269706f2543Smrg char n; 2270706f2543Smrg 2271706f2543Smrg swaps(&stuff->length, n); 2272706f2543Smrg REQUEST_SIZE_MATCH (xSyncCreateCounterReq); 2273706f2543Smrg swapl(&stuff->cid, n); 2274706f2543Smrg swapl(&stuff->initial_value_lo, n); 2275706f2543Smrg swapl(&stuff->initial_value_hi, n); 2276706f2543Smrg 2277706f2543Smrg return ProcSyncCreateCounter(client); 2278706f2543Smrg} 2279706f2543Smrg 2280706f2543Smrgstatic int 2281706f2543SmrgSProcSyncSetCounter(ClientPtr client) 2282706f2543Smrg{ 2283706f2543Smrg REQUEST(xSyncSetCounterReq); 2284706f2543Smrg char n; 2285706f2543Smrg 2286706f2543Smrg swaps(&stuff->length, n); 2287706f2543Smrg REQUEST_SIZE_MATCH (xSyncSetCounterReq); 2288706f2543Smrg swapl(&stuff->cid, n); 2289706f2543Smrg swapl(&stuff->value_lo, n); 2290706f2543Smrg swapl(&stuff->value_hi, n); 2291706f2543Smrg 2292706f2543Smrg return ProcSyncSetCounter(client); 2293706f2543Smrg} 2294706f2543Smrg 2295706f2543Smrgstatic int 2296706f2543SmrgSProcSyncChangeCounter(ClientPtr client) 2297706f2543Smrg{ 2298706f2543Smrg REQUEST(xSyncChangeCounterReq); 2299706f2543Smrg char n; 2300706f2543Smrg 2301706f2543Smrg swaps(&stuff->length, n); 2302706f2543Smrg REQUEST_SIZE_MATCH (xSyncChangeCounterReq); 2303706f2543Smrg swapl(&stuff->cid, n); 2304706f2543Smrg swapl(&stuff->value_lo, n); 2305706f2543Smrg swapl(&stuff->value_hi, n); 2306706f2543Smrg 2307706f2543Smrg return ProcSyncChangeCounter(client); 2308706f2543Smrg} 2309706f2543Smrg 2310706f2543Smrgstatic int 2311706f2543SmrgSProcSyncQueryCounter(ClientPtr client) 2312706f2543Smrg{ 2313706f2543Smrg REQUEST(xSyncQueryCounterReq); 2314706f2543Smrg char n; 2315706f2543Smrg 2316706f2543Smrg swaps(&stuff->length, n); 2317706f2543Smrg REQUEST_SIZE_MATCH (xSyncQueryCounterReq); 2318706f2543Smrg swapl(&stuff->counter, n); 2319706f2543Smrg 2320706f2543Smrg return ProcSyncQueryCounter(client); 2321706f2543Smrg} 2322706f2543Smrg 2323706f2543Smrgstatic int 2324706f2543SmrgSProcSyncDestroyCounter(ClientPtr client) 2325706f2543Smrg{ 2326706f2543Smrg REQUEST(xSyncDestroyCounterReq); 2327706f2543Smrg char n; 2328706f2543Smrg 2329706f2543Smrg swaps(&stuff->length, n); 2330706f2543Smrg REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); 2331706f2543Smrg swapl(&stuff->counter, n); 2332706f2543Smrg 2333706f2543Smrg return ProcSyncDestroyCounter(client); 2334706f2543Smrg} 2335706f2543Smrg 2336706f2543Smrgstatic int 2337706f2543SmrgSProcSyncAwait(ClientPtr client) 2338706f2543Smrg{ 2339706f2543Smrg REQUEST(xSyncAwaitReq); 2340706f2543Smrg char n; 2341706f2543Smrg 2342706f2543Smrg swaps(&stuff->length, n); 2343706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 2344706f2543Smrg SwapRestL(stuff); 2345706f2543Smrg 2346706f2543Smrg return ProcSyncAwait(client); 2347706f2543Smrg} 2348706f2543Smrg 2349706f2543Smrgstatic int 2350706f2543SmrgSProcSyncCreateAlarm(ClientPtr client) 2351706f2543Smrg{ 2352706f2543Smrg REQUEST(xSyncCreateAlarmReq); 2353706f2543Smrg char n; 2354706f2543Smrg 2355706f2543Smrg swaps(&stuff->length, n); 2356706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 2357706f2543Smrg swapl(&stuff->id, n); 2358706f2543Smrg swapl(&stuff->valueMask, n); 2359706f2543Smrg SwapRestL(stuff); 2360706f2543Smrg 2361706f2543Smrg return ProcSyncCreateAlarm(client); 2362706f2543Smrg} 2363706f2543Smrg 2364706f2543Smrgstatic int 2365706f2543SmrgSProcSyncChangeAlarm(ClientPtr client) 2366706f2543Smrg{ 2367706f2543Smrg REQUEST(xSyncChangeAlarmReq); 2368706f2543Smrg char n; 2369706f2543Smrg 2370706f2543Smrg swaps(&stuff->length, n); 2371706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 2372706f2543Smrg swapl(&stuff->alarm, n); 2373706f2543Smrg swapl(&stuff->valueMask, n); 2374706f2543Smrg SwapRestL(stuff); 2375706f2543Smrg return ProcSyncChangeAlarm(client); 2376706f2543Smrg} 2377706f2543Smrg 2378706f2543Smrgstatic int 2379706f2543SmrgSProcSyncQueryAlarm(ClientPtr client) 2380706f2543Smrg{ 2381706f2543Smrg REQUEST(xSyncQueryAlarmReq); 2382706f2543Smrg char n; 2383706f2543Smrg 2384706f2543Smrg swaps(&stuff->length, n); 2385706f2543Smrg REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); 2386706f2543Smrg swapl(&stuff->alarm, n); 2387706f2543Smrg 2388706f2543Smrg return ProcSyncQueryAlarm(client); 2389706f2543Smrg} 2390706f2543Smrg 2391706f2543Smrgstatic int 2392706f2543SmrgSProcSyncDestroyAlarm(ClientPtr client) 2393706f2543Smrg{ 2394706f2543Smrg REQUEST(xSyncDestroyAlarmReq); 2395706f2543Smrg char n; 2396706f2543Smrg 2397706f2543Smrg swaps(&stuff->length, n); 2398706f2543Smrg REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); 2399706f2543Smrg swapl(&stuff->alarm, n); 2400706f2543Smrg 2401706f2543Smrg return ProcSyncDestroyAlarm(client); 2402706f2543Smrg} 2403706f2543Smrg 2404706f2543Smrgstatic int 2405706f2543SmrgSProcSyncSetPriority(ClientPtr client) 2406706f2543Smrg{ 2407706f2543Smrg REQUEST(xSyncSetPriorityReq); 2408706f2543Smrg char n; 2409706f2543Smrg 2410706f2543Smrg swaps(&stuff->length, n); 2411706f2543Smrg REQUEST_SIZE_MATCH (xSyncSetPriorityReq); 2412706f2543Smrg swapl(&stuff->id, n); 2413706f2543Smrg swapl(&stuff->priority, n); 2414706f2543Smrg 2415706f2543Smrg return ProcSyncSetPriority(client); 2416706f2543Smrg} 2417706f2543Smrg 2418706f2543Smrgstatic int 2419706f2543SmrgSProcSyncGetPriority(ClientPtr client) 2420706f2543Smrg{ 2421706f2543Smrg REQUEST(xSyncGetPriorityReq); 2422706f2543Smrg char n; 2423706f2543Smrg 2424706f2543Smrg swaps(&stuff->length, n); 2425706f2543Smrg REQUEST_SIZE_MATCH (xSyncGetPriorityReq); 2426706f2543Smrg swapl(&stuff->id, n); 2427706f2543Smrg 2428706f2543Smrg return ProcSyncGetPriority(client); 2429706f2543Smrg} 2430706f2543Smrg 2431706f2543Smrgstatic int 2432706f2543SmrgSProcSyncCreateFence(ClientPtr client) 2433706f2543Smrg{ 2434706f2543Smrg REQUEST(xSyncCreateFenceReq); 2435706f2543Smrg char n; 2436706f2543Smrg 2437706f2543Smrg swaps(&stuff->length, n); 2438706f2543Smrg REQUEST_SIZE_MATCH (xSyncCreateFenceReq); 2439706f2543Smrg swapl(&stuff->fid, n); 2440706f2543Smrg 2441706f2543Smrg return ProcSyncCreateFence(client); 2442706f2543Smrg} 2443706f2543Smrg 2444706f2543Smrgstatic int 2445706f2543SmrgSProcSyncTriggerFence(ClientPtr client) 2446706f2543Smrg{ 2447706f2543Smrg REQUEST(xSyncTriggerFenceReq); 2448706f2543Smrg char n; 2449706f2543Smrg 2450706f2543Smrg swaps(&stuff->length, n); 2451706f2543Smrg REQUEST_SIZE_MATCH (xSyncTriggerFenceReq); 2452706f2543Smrg swapl(&stuff->fid, n); 2453706f2543Smrg 2454706f2543Smrg return ProcSyncTriggerFence(client); 2455706f2543Smrg} 2456706f2543Smrg 2457706f2543Smrgstatic int 2458706f2543SmrgSProcSyncResetFence(ClientPtr client) 2459706f2543Smrg{ 2460706f2543Smrg REQUEST(xSyncResetFenceReq); 2461706f2543Smrg char n; 2462706f2543Smrg 2463706f2543Smrg swaps(&stuff->length, n); 2464706f2543Smrg REQUEST_SIZE_MATCH (xSyncResetFenceReq); 2465706f2543Smrg swapl(&stuff->fid, n); 2466706f2543Smrg 2467706f2543Smrg return ProcSyncResetFence(client); 2468706f2543Smrg} 2469706f2543Smrg 2470706f2543Smrgstatic int 2471706f2543SmrgSProcSyncDestroyFence(ClientPtr client) 2472706f2543Smrg{ 2473706f2543Smrg REQUEST(xSyncDestroyFenceReq); 2474706f2543Smrg char n; 2475706f2543Smrg 2476706f2543Smrg swaps(&stuff->length, n); 2477706f2543Smrg REQUEST_SIZE_MATCH (xSyncDestroyFenceReq); 2478706f2543Smrg swapl(&stuff->fid, n); 2479706f2543Smrg 2480706f2543Smrg return ProcSyncDestroyFence(client); 2481706f2543Smrg} 2482706f2543Smrg 2483706f2543Smrgstatic int 2484706f2543SmrgSProcSyncQueryFence(ClientPtr client) 2485706f2543Smrg{ 2486706f2543Smrg REQUEST(xSyncQueryFenceReq); 2487706f2543Smrg char n; 2488706f2543Smrg 2489706f2543Smrg swaps(&stuff->length, n); 2490706f2543Smrg REQUEST_SIZE_MATCH (xSyncQueryFenceReq); 2491706f2543Smrg swapl(&stuff->fid, n); 2492706f2543Smrg 2493706f2543Smrg return ProcSyncQueryFence(client); 2494706f2543Smrg} 2495706f2543Smrg 2496706f2543Smrgstatic int 2497706f2543SmrgSProcSyncAwaitFence(ClientPtr client) 2498706f2543Smrg{ 2499706f2543Smrg REQUEST(xSyncAwaitFenceReq); 2500706f2543Smrg char n; 2501706f2543Smrg 2502706f2543Smrg swaps(&stuff->length, n); 2503706f2543Smrg REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq); 2504706f2543Smrg SwapRestL(stuff); 2505706f2543Smrg 2506706f2543Smrg return ProcSyncAwaitFence(client); 2507706f2543Smrg} 2508706f2543Smrg 2509706f2543Smrgstatic int 2510706f2543SmrgSProcSyncDispatch(ClientPtr client) 2511706f2543Smrg{ 2512706f2543Smrg REQUEST(xReq); 2513706f2543Smrg 2514706f2543Smrg switch (stuff->data) 2515706f2543Smrg { 2516706f2543Smrg case X_SyncInitialize: 2517706f2543Smrg return SProcSyncInitialize(client); 2518706f2543Smrg case X_SyncListSystemCounters: 2519706f2543Smrg return SProcSyncListSystemCounters(client); 2520706f2543Smrg case X_SyncCreateCounter: 2521706f2543Smrg return SProcSyncCreateCounter(client); 2522706f2543Smrg case X_SyncSetCounter: 2523706f2543Smrg return SProcSyncSetCounter(client); 2524706f2543Smrg case X_SyncChangeCounter: 2525706f2543Smrg return SProcSyncChangeCounter(client); 2526706f2543Smrg case X_SyncQueryCounter: 2527706f2543Smrg return SProcSyncQueryCounter(client); 2528706f2543Smrg case X_SyncDestroyCounter: 2529706f2543Smrg return SProcSyncDestroyCounter(client); 2530706f2543Smrg case X_SyncAwait: 2531706f2543Smrg return SProcSyncAwait(client); 2532706f2543Smrg case X_SyncCreateAlarm: 2533706f2543Smrg return SProcSyncCreateAlarm(client); 2534706f2543Smrg case X_SyncChangeAlarm: 2535706f2543Smrg return SProcSyncChangeAlarm(client); 2536706f2543Smrg case X_SyncQueryAlarm: 2537706f2543Smrg return SProcSyncQueryAlarm(client); 2538706f2543Smrg case X_SyncDestroyAlarm: 2539706f2543Smrg return SProcSyncDestroyAlarm(client); 2540706f2543Smrg case X_SyncSetPriority: 2541706f2543Smrg return SProcSyncSetPriority(client); 2542706f2543Smrg case X_SyncGetPriority: 2543706f2543Smrg return SProcSyncGetPriority(client); 2544706f2543Smrg case X_SyncCreateFence: 2545706f2543Smrg return SProcSyncCreateFence(client); 2546706f2543Smrg case X_SyncTriggerFence: 2547706f2543Smrg return SProcSyncTriggerFence(client); 2548706f2543Smrg case X_SyncResetFence: 2549706f2543Smrg return SProcSyncResetFence(client); 2550706f2543Smrg case X_SyncDestroyFence: 2551706f2543Smrg return SProcSyncDestroyFence(client); 2552706f2543Smrg case X_SyncQueryFence: 2553706f2543Smrg return SProcSyncQueryFence(client); 2554706f2543Smrg case X_SyncAwaitFence: 2555706f2543Smrg return SProcSyncAwaitFence(client); 2556706f2543Smrg default: 2557706f2543Smrg return BadRequest; 2558706f2543Smrg } 2559706f2543Smrg} 2560706f2543Smrg 2561706f2543Smrg/* 2562706f2543Smrg * Event Swapping 2563706f2543Smrg */ 2564706f2543Smrg 2565706f2543Smrgstatic void 2566706f2543SmrgSCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) 2567706f2543Smrg{ 2568706f2543Smrg to->type = from->type; 2569706f2543Smrg to->kind = from->kind; 2570706f2543Smrg cpswaps(from->sequenceNumber, to->sequenceNumber); 2571706f2543Smrg cpswapl(from->counter, to->counter); 2572706f2543Smrg cpswapl(from->wait_value_lo, to->wait_value_lo); 2573706f2543Smrg cpswapl(from->wait_value_hi, to->wait_value_hi); 2574706f2543Smrg cpswapl(from->counter_value_lo, to->counter_value_lo); 2575706f2543Smrg cpswapl(from->counter_value_hi, to->counter_value_hi); 2576706f2543Smrg cpswapl(from->time, to->time); 2577706f2543Smrg cpswaps(from->count, to->count); 2578706f2543Smrg to->destroyed = from->destroyed; 2579706f2543Smrg} 2580706f2543Smrg 2581706f2543Smrg 2582706f2543Smrgstatic void 2583706f2543SmrgSAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) 2584706f2543Smrg{ 2585706f2543Smrg to->type = from->type; 2586706f2543Smrg to->kind = from->kind; 2587706f2543Smrg cpswaps(from->sequenceNumber, to->sequenceNumber); 2588706f2543Smrg cpswapl(from->alarm, to->alarm); 2589706f2543Smrg cpswapl(from->counter_value_lo, to->counter_value_lo); 2590706f2543Smrg cpswapl(from->counter_value_hi, to->counter_value_hi); 2591706f2543Smrg cpswapl(from->alarm_value_lo, to->alarm_value_lo); 2592706f2543Smrg cpswapl(from->alarm_value_hi, to->alarm_value_hi); 2593706f2543Smrg cpswapl(from->time, to->time); 2594706f2543Smrg to->state = from->state; 2595706f2543Smrg} 2596706f2543Smrg 2597706f2543Smrg/* 2598706f2543Smrg * ** Close everything down. ** This is fairly simple for now. 2599706f2543Smrg */ 2600706f2543Smrg/* ARGSUSED */ 2601706f2543Smrgstatic void 2602706f2543SmrgSyncResetProc(ExtensionEntry *extEntry) 2603706f2543Smrg{ 2604706f2543Smrg free(SysCounterList); 2605706f2543Smrg SysCounterList = NULL; 2606706f2543Smrg RTCounter = 0; 2607706f2543Smrg} 2608706f2543Smrg 2609706f2543Smrg/* 2610706f2543Smrg * ** Initialise the extension. 2611706f2543Smrg */ 2612706f2543Smrgvoid 2613706f2543SmrgSyncExtensionInit(void) 2614706f2543Smrg{ 2615706f2543Smrg ExtensionEntry *extEntry; 2616706f2543Smrg int s; 2617706f2543Smrg 2618706f2543Smrg for (s = 0; s < screenInfo.numScreens; s++) 2619706f2543Smrg miSyncSetup(screenInfo.screens[s]); 2620706f2543Smrg 2621706f2543Smrg if (RTCounter == 0) 2622706f2543Smrg { 2623706f2543Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 2624706f2543Smrg } 2625706f2543Smrg RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); 2626706f2543Smrg RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); 2627706f2543Smrg RTFence = CreateNewResourceType(FreeFence, "SyncFence"); 2628706f2543Smrg if (RTAwait) 2629706f2543Smrg RTAwait |= RC_NEVERRETAIN; 2630706f2543Smrg RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); 2631706f2543Smrg if (RTAlarmClient) 2632706f2543Smrg RTAlarmClient |= RC_NEVERRETAIN; 2633706f2543Smrg 2634706f2543Smrg if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 2635706f2543Smrg RTAlarmClient == 0 || 2636706f2543Smrg (extEntry = AddExtension(SYNC_NAME, 2637706f2543Smrg XSyncNumberEvents, XSyncNumberErrors, 2638706f2543Smrg ProcSyncDispatch, SProcSyncDispatch, 2639706f2543Smrg SyncResetProc, 2640706f2543Smrg StandardMinorOpcode)) == NULL) 2641706f2543Smrg { 2642706f2543Smrg ErrorF("Sync Extension %d.%d failed to Initialise\n", 2643706f2543Smrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 2644706f2543Smrg return; 2645706f2543Smrg } 2646706f2543Smrg 2647706f2543Smrg SyncEventBase = extEntry->eventBase; 2648706f2543Smrg SyncErrorBase = extEntry->errorBase; 2649706f2543Smrg EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; 2650706f2543Smrg EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; 2651706f2543Smrg 2652706f2543Smrg SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter); 2653706f2543Smrg SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm); 2654706f2543Smrg SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence); 2655706f2543Smrg 2656706f2543Smrg /* 2657706f2543Smrg * Although SERVERTIME is implemented by the OS layer, we initialise it 2658706f2543Smrg * here because doing it in OsInit() is too early. The resource database 2659706f2543Smrg * is not initialised when OsInit() is called. This is just about OK 2660706f2543Smrg * because there is always a servertime counter. 2661706f2543Smrg */ 2662706f2543Smrg SyncInitServerTime(); 2663706f2543Smrg SyncInitIdleTime(); 2664706f2543Smrg 2665706f2543Smrg#ifdef DEBUG 2666706f2543Smrg fprintf(stderr, "Sync Extension %d.%d\n", 2667706f2543Smrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 2668706f2543Smrg#endif 2669706f2543Smrg} 2670706f2543Smrg 2671706f2543Smrg 2672706f2543Smrg/* 2673706f2543Smrg * ***** SERVERTIME implementation - should go in its own file in OS directory? 2674706f2543Smrg */ 2675706f2543Smrg 2676706f2543Smrg 2677706f2543Smrg 2678706f2543Smrgstatic pointer ServertimeCounter; 2679706f2543Smrgstatic XSyncValue Now; 2680706f2543Smrgstatic XSyncValue *pnext_time; 2681706f2543Smrg 2682706f2543Smrg#define GetTime()\ 2683706f2543Smrg{\ 2684706f2543Smrg unsigned long millis = GetTimeInMillis();\ 2685706f2543Smrg unsigned long maxis = XSyncValueHigh32(Now);\ 2686706f2543Smrg if (millis < XSyncValueLow32(Now)) maxis++;\ 2687706f2543Smrg XSyncIntsToValue(&Now, millis, maxis);\ 2688706f2543Smrg} 2689706f2543Smrg 2690706f2543Smrg/* 2691706f2543Smrg*** Server Block Handler 2692706f2543Smrg*** code inspired by multibuffer extension (now deprecated) 2693706f2543Smrg */ 2694706f2543Smrg/*ARGSUSED*/ 2695706f2543Smrgstatic void 2696706f2543SmrgServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) 2697706f2543Smrg{ 2698706f2543Smrg XSyncValue delay; 2699706f2543Smrg unsigned long timeout; 2700706f2543Smrg 2701706f2543Smrg if (pnext_time) 2702706f2543Smrg { 2703706f2543Smrg GetTime(); 2704706f2543Smrg 2705706f2543Smrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 2706706f2543Smrg { 2707706f2543Smrg timeout = 0; 2708706f2543Smrg } 2709706f2543Smrg else 2710706f2543Smrg { 2711706f2543Smrg Bool overflow; 2712706f2543Smrg XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 2713706f2543Smrg (void)overflow; 2714706f2543Smrg timeout = XSyncValueLow32(delay); 2715706f2543Smrg } 2716706f2543Smrg AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 2717706f2543Smrg } 2718706f2543Smrg} 2719706f2543Smrg 2720706f2543Smrg/* 2721706f2543Smrg*** Wakeup Handler 2722706f2543Smrg */ 2723706f2543Smrg/*ARGSUSED*/ 2724706f2543Smrgstatic void 2725706f2543SmrgServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) 2726706f2543Smrg{ 2727706f2543Smrg if (pnext_time) 2728706f2543Smrg { 2729706f2543Smrg GetTime(); 2730706f2543Smrg 2731706f2543Smrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 2732706f2543Smrg { 2733706f2543Smrg SyncChangeCounter(ServertimeCounter, Now); 2734706f2543Smrg } 2735706f2543Smrg } 2736706f2543Smrg} 2737706f2543Smrg 2738706f2543Smrgstatic void 2739706f2543SmrgServertimeQueryValue(void *pCounter, CARD64 *pValue_return) 2740706f2543Smrg{ 2741706f2543Smrg GetTime(); 2742706f2543Smrg *pValue_return = Now; 2743706f2543Smrg} 2744706f2543Smrg 2745706f2543Smrgstatic void 2746706f2543SmrgServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, 2747706f2543Smrg CARD64 *pbracket_greater) 2748706f2543Smrg{ 2749706f2543Smrg if (!pnext_time && pbracket_greater) 2750706f2543Smrg { 2751706f2543Smrg RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 2752706f2543Smrg ServertimeWakeupHandler, 2753706f2543Smrg NULL); 2754706f2543Smrg } 2755706f2543Smrg else if (pnext_time && !pbracket_greater) 2756706f2543Smrg { 2757706f2543Smrg RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 2758706f2543Smrg ServertimeWakeupHandler, 2759706f2543Smrg NULL); 2760706f2543Smrg } 2761706f2543Smrg pnext_time = pbracket_greater; 2762706f2543Smrg} 2763706f2543Smrg 2764706f2543Smrgstatic void 2765706f2543SmrgSyncInitServerTime(void) 2766706f2543Smrg{ 2767706f2543Smrg CARD64 resolution; 2768706f2543Smrg 2769706f2543Smrg XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 2770706f2543Smrg XSyncIntToValue(&resolution, 4); 2771706f2543Smrg ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 2772706f2543Smrg XSyncCounterNeverDecreases, 2773706f2543Smrg ServertimeQueryValue, ServertimeBracketValues); 2774706f2543Smrg pnext_time = NULL; 2775706f2543Smrg} 2776706f2543Smrg 2777706f2543Smrg 2778706f2543Smrg 2779706f2543Smrg/* 2780706f2543Smrg * IDLETIME implementation 2781706f2543Smrg */ 2782706f2543Smrg 2783706f2543Smrgstatic SyncCounter *IdleTimeCounter; 2784706f2543Smrgstatic XSyncValue *pIdleTimeValueLess; 2785706f2543Smrgstatic XSyncValue *pIdleTimeValueGreater; 2786706f2543Smrg 2787706f2543Smrgstatic void 2788706f2543SmrgIdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 2789706f2543Smrg{ 2790706f2543Smrg CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 2791706f2543Smrg XSyncIntsToValue (pValue_return, idle, 0); 2792706f2543Smrg} 2793706f2543Smrg 2794706f2543Smrgstatic void 2795706f2543SmrgIdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) 2796706f2543Smrg{ 2797706f2543Smrg XSyncValue idle, old_idle; 2798706f2543Smrg SyncTriggerList *list = IdleTimeCounter->sync.pTriglist; 2799706f2543Smrg SyncTrigger *trig; 2800706f2543Smrg 2801706f2543Smrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2802706f2543Smrg return; 2803706f2543Smrg 2804706f2543Smrg old_idle = IdleTimeCounter->value; 2805706f2543Smrg IdleTimeQueryValue (NULL, &idle); 2806706f2543Smrg IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ 2807706f2543Smrg 2808706f2543Smrg if (pIdleTimeValueLess && 2809706f2543Smrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 2810706f2543Smrg { 2811706f2543Smrg /* 2812706f2543Smrg * We've been idle for less than the threshold value, and someone 2813706f2543Smrg * wants to know about that, but now we need to know whether they 2814706f2543Smrg * want level or edge trigger. Check the trigger list against the 2815706f2543Smrg * current idle time, and if any succeed, bomb out of select() 2816706f2543Smrg * immediately so we can reschedule. 2817706f2543Smrg */ 2818706f2543Smrg 2819706f2543Smrg for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) { 2820706f2543Smrg trig = list->pTrigger; 2821706f2543Smrg if (trig->CheckTrigger(trig, old_idle)) { 2822706f2543Smrg AdjustWaitForDelay(wt, 0); 2823706f2543Smrg break; 2824706f2543Smrg } 2825706f2543Smrg } 2826706f2543Smrg /* 2827706f2543Smrg * We've been called exactly on the idle time, but we have a 2828706f2543Smrg * NegativeTransition trigger which requires a transition from an 2829706f2543Smrg * idle time greater than this. Schedule a wakeup for the next 2830706f2543Smrg * millisecond so we won't miss a transition. 2831706f2543Smrg */ 2832706f2543Smrg if (XSyncValueEqual (idle, *pIdleTimeValueLess)) 2833706f2543Smrg AdjustWaitForDelay(wt, 1); 2834706f2543Smrg } 2835706f2543Smrg else if (pIdleTimeValueGreater) 2836706f2543Smrg { 2837706f2543Smrg /* 2838706f2543Smrg * There's a threshold in the positive direction. If we've been 2839706f2543Smrg * idle less than it, schedule a wakeup for sometime in the future. 2840706f2543Smrg * If we've been idle more than it, and someone wants to know about 2841706f2543Smrg * that level-triggered, schedule an immediate wakeup. 2842706f2543Smrg */ 2843706f2543Smrg unsigned long timeout = -1; 2844706f2543Smrg 2845706f2543Smrg if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { 2846706f2543Smrg XSyncValue value; 2847706f2543Smrg Bool overflow; 2848706f2543Smrg 2849706f2543Smrg XSyncValueSubtract (&value, *pIdleTimeValueGreater, 2850706f2543Smrg idle, &overflow); 2851706f2543Smrg timeout = min(timeout, XSyncValueLow32 (value)); 2852706f2543Smrg } else { 2853706f2543Smrg for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) { 2854706f2543Smrg trig = list->pTrigger; 2855706f2543Smrg if (trig->CheckTrigger(trig, old_idle)) { 2856706f2543Smrg timeout = min(timeout, 0); 2857706f2543Smrg break; 2858706f2543Smrg } 2859706f2543Smrg } 2860706f2543Smrg } 2861706f2543Smrg 2862706f2543Smrg AdjustWaitForDelay (wt, timeout); 2863706f2543Smrg } 2864706f2543Smrg 2865706f2543Smrg IdleTimeCounter->value = old_idle; /* pop */ 2866706f2543Smrg} 2867706f2543Smrg 2868706f2543Smrgstatic void 2869706f2543SmrgIdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) 2870706f2543Smrg{ 2871706f2543Smrg XSyncValue idle; 2872706f2543Smrg 2873706f2543Smrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2874706f2543Smrg return; 2875706f2543Smrg 2876706f2543Smrg IdleTimeQueryValue (NULL, &idle); 2877706f2543Smrg 2878706f2543Smrg if ((pIdleTimeValueGreater && 2879706f2543Smrg XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || 2880706f2543Smrg (pIdleTimeValueLess && 2881706f2543Smrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) 2882706f2543Smrg { 2883706f2543Smrg SyncChangeCounter (IdleTimeCounter, idle); 2884706f2543Smrg } 2885706f2543Smrg} 2886706f2543Smrg 2887706f2543Smrgstatic void 2888706f2543SmrgIdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, 2889706f2543Smrg CARD64 *pbracket_greater) 2890706f2543Smrg{ 2891706f2543Smrg Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); 2892706f2543Smrg 2893706f2543Smrg if (registered && !pbracket_less && !pbracket_greater) 2894706f2543Smrg { 2895706f2543Smrg RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 2896706f2543Smrg IdleTimeWakeupHandler, 2897706f2543Smrg NULL); 2898706f2543Smrg } 2899706f2543Smrg else if (!registered && (pbracket_less || pbracket_greater)) 2900706f2543Smrg { 2901706f2543Smrg RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 2902706f2543Smrg IdleTimeWakeupHandler, 2903706f2543Smrg NULL); 2904706f2543Smrg } 2905706f2543Smrg 2906706f2543Smrg pIdleTimeValueGreater = pbracket_greater; 2907706f2543Smrg pIdleTimeValueLess = pbracket_less; 2908706f2543Smrg} 2909706f2543Smrg 2910706f2543Smrgstatic void 2911706f2543SmrgSyncInitIdleTime (void) 2912706f2543Smrg{ 2913706f2543Smrg CARD64 resolution; 2914706f2543Smrg XSyncValue idle; 2915706f2543Smrg 2916706f2543Smrg IdleTimeQueryValue (NULL, &idle); 2917706f2543Smrg XSyncIntToValue (&resolution, 4); 2918706f2543Smrg 2919706f2543Smrg IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, 2920706f2543Smrg XSyncCounterUnrestricted, 2921706f2543Smrg IdleTimeQueryValue, 2922706f2543Smrg IdleTimeBracketValues); 2923706f2543Smrg 2924706f2543Smrg pIdleTimeValueLess = pIdleTimeValueGreater = NULL; 2925706f2543Smrg} 2926