sync.c revision f7df2e56
105b261ecSmrg/* 205b261ecSmrg 305b261ecSmrgCopyright 1991, 1993, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included 1205b261ecSmrgin all copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE. 2105b261ecSmrg 2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall 2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or 2405b261ecSmrgother dealings in this Software without prior written authorization 2505b261ecSmrgfrom The Open Group. 2605b261ecSmrg 2705b261ecSmrgCopyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, 2805b261ecSmrgand Olivetti Research Limited, Cambridge, England. 2905b261ecSmrg 3005b261ecSmrg All Rights Reserved 3105b261ecSmrg 3205b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3305b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3405b261ecSmrgprovided that the above copyright notice appear in all copies and that 3505b261ecSmrgboth that copyright notice and this permission notice appear in 364202a189Smrgsupporting documentation, and that the names of Digital or Olivetti 3705b261ecSmrgnot be used in advertising or publicity pertaining to distribution of the 3805b261ecSmrgsoftware without specific, written prior permission. Digital and Olivetti 3905b261ecSmrgmake no representations about the suitability of this software 4005b261ecSmrgfor any purpose. It is provided "as is" without express or implied warranty. 4105b261ecSmrg 4205b261ecSmrgDIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 4305b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 4405b261ecSmrgFITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR 4505b261ecSmrgCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 4605b261ecSmrgUSE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 4705b261ecSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 4805b261ecSmrgPERFORMANCE OF THIS SOFTWARE. 4905b261ecSmrg 5005b261ecSmrg*/ 5105b261ecSmrg 5205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5305b261ecSmrg#include <dix-config.h> 5405b261ecSmrg#endif 5505b261ecSmrg 5605b261ecSmrg#include <string.h> 5705b261ecSmrg 5805b261ecSmrg#include <X11/X.h> 5905b261ecSmrg#include <X11/Xproto.h> 6005b261ecSmrg#include <X11/Xmd.h> 6165b04b38Smrg#include "scrnintstr.h" 6205b261ecSmrg#include "os.h" 6305b261ecSmrg#include "extnsionst.h" 6405b261ecSmrg#include "dixstruct.h" 6565b04b38Smrg#include "pixmapstr.h" 6605b261ecSmrg#include "resource.h" 6705b261ecSmrg#include "opaque.h" 684202a189Smrg#include <X11/extensions/syncproto.h> 694202a189Smrg#include "syncsrv.h" 7065b04b38Smrg#include "syncsdk.h" 711b684552Smrg#include "protocol-versions.h" 72f7df2e56Smrg#include "inputstr.h" 7305b261ecSmrg 7405b261ecSmrg#include <stdio.h> 75637ac9abSmrg#if !defined(WIN32) 7605b261ecSmrg#include <sys/time.h> 7705b261ecSmrg#endif 7805b261ecSmrg 79f7df2e56Smrg#include "extinit.h" 8005b261ecSmrg 8105b261ecSmrg/* 8205b261ecSmrg * Local Global Variables 8305b261ecSmrg */ 84f7df2e56Smrgstatic int SyncEventBase; 85f7df2e56Smrgstatic int SyncErrorBase; 86f7df2e56Smrgstatic RESTYPE RTCounter = 0; 87f7df2e56Smrgstatic RESTYPE RTAwait; 88f7df2e56Smrgstatic RESTYPE RTAlarm; 89f7df2e56Smrgstatic RESTYPE RTAlarmClient; 90f7df2e56Smrgstatic RESTYPE RTFence; 91f7df2e56Smrgstatic struct xorg_list SysCounterList; 9265b04b38Smrgstatic int SyncNumInvalidCounterWarnings = 0; 93f7df2e56Smrg 9465b04b38Smrg#define MAX_INVALID_COUNTER_WARNINGS 5 9565b04b38Smrg 9665b04b38Smrgstatic const char *WARN_INVALID_COUNTER_COMPARE = 97f7df2e56Smrg "Warning: Non-counter XSync object using Counter-only\n" 98f7df2e56Smrg " comparison. Result will never be true.\n"; 9965b04b38Smrg 10065b04b38Smrgstatic const char *WARN_INVALID_COUNTER_ALARM = 101f7df2e56Smrg "Warning: Non-counter XSync object used in alarm. This is\n" 102f7df2e56Smrg " the result of a programming error in the X server.\n"; 10305b261ecSmrg 10405b261ecSmrg#define IsSystemCounter(pCounter) \ 10565b04b38Smrg (pCounter && (pCounter->sync.client == NULL)) 10605b261ecSmrg 10705b261ecSmrg/* these are all the alarm attributes that pertain to the alarm's trigger */ 10805b261ecSmrg#define XSyncCAAllTrigger \ 10905b261ecSmrg (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) 11005b261ecSmrg 1114202a189Smrgstatic void SyncComputeBracketValues(SyncCounter *); 11205b261ecSmrg 1134202a189Smrgstatic void SyncInitServerTime(void); 11405b261ecSmrg 1154202a189Smrgstatic void SyncInitIdleTime(void); 11605b261ecSmrg 117f7df2e56Smrgstatic inline void* 118f7df2e56SmrgSysCounterGetPrivate(SyncCounter *counter) 119f7df2e56Smrg{ 120f7df2e56Smrg BUG_WARN(!IsSystemCounter(counter)); 121f7df2e56Smrg 122f7df2e56Smrg return counter->pSysCounterInfo ? counter->pSysCounterInfo->private : NULL; 123f7df2e56Smrg} 124f7df2e56Smrg 12565b04b38Smrgstatic Bool 126f7df2e56SmrgSyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning) 12765b04b38Smrg{ 128f7df2e56Smrg if (pSync && (SYNC_COUNTER != pSync->type)) { 129f7df2e56Smrg if (SyncNumInvalidCounterWarnings++ < MAX_INVALID_COUNTER_WARNINGS) { 130f7df2e56Smrg ErrorF("%s", warning); 131f7df2e56Smrg ErrorF(" Counter type: %d\n", pSync->type); 132f7df2e56Smrg } 13365b04b38Smrg 134f7df2e56Smrg return FALSE; 13565b04b38Smrg } 13665b04b38Smrg 13765b04b38Smrg return TRUE; 13865b04b38Smrg} 13905b261ecSmrg 14005b261ecSmrg/* Each counter maintains a simple linked list of triggers that are 14105b261ecSmrg * interested in the counter. The two functions below are used to 14205b261ecSmrg * delete and add triggers on this list. 14305b261ecSmrg */ 144f7df2e56Smrgvoid 145f7df2e56SmrgSyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger) 14605b261ecSmrg{ 14705b261ecSmrg SyncTriggerList *pCur; 14805b261ecSmrg SyncTriggerList *pPrev; 14965b04b38Smrg SyncCounter *pCounter; 15005b261ecSmrg 15165b04b38Smrg /* pSync needs to be stored in pTrigger before calling here. */ 15205b261ecSmrg 15365b04b38Smrg if (!pTrigger->pSync) 154f7df2e56Smrg return; 15505b261ecSmrg 15605b261ecSmrg pPrev = NULL; 15765b04b38Smrg pCur = pTrigger->pSync->pTriglist; 15805b261ecSmrg 159f7df2e56Smrg while (pCur) { 160f7df2e56Smrg if (pCur->pTrigger == pTrigger) { 161f7df2e56Smrg if (pPrev) 162f7df2e56Smrg pPrev->next = pCur->next; 163f7df2e56Smrg else 164f7df2e56Smrg pTrigger->pSync->pTriglist = pCur->next; 165f7df2e56Smrg 166f7df2e56Smrg free(pCur); 167f7df2e56Smrg break; 168f7df2e56Smrg } 1694202a189Smrg 170f7df2e56Smrg pPrev = pCur; 171f7df2e56Smrg pCur = pCur->next; 17205b261ecSmrg } 1734202a189Smrg 174f7df2e56Smrg if (SYNC_COUNTER == pTrigger->pSync->type) { 175f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 17665b04b38Smrg 177f7df2e56Smrg if (IsSystemCounter(pCounter)) 178f7df2e56Smrg SyncComputeBracketValues(pCounter); 17965b04b38Smrg } 180f7df2e56Smrg else if (SYNC_FENCE == pTrigger->pSync->type) { 181f7df2e56Smrg SyncFence *pFence = (SyncFence *) pTrigger->pSync; 18205b261ecSmrg 183f7df2e56Smrg pFence->funcs.DeleteTrigger(pTrigger); 184f7df2e56Smrg } 185f7df2e56Smrg} 18605b261ecSmrg 187f7df2e56Smrgint 188f7df2e56SmrgSyncAddTriggerToSyncObject(SyncTrigger * pTrigger) 18905b261ecSmrg{ 19005b261ecSmrg SyncTriggerList *pCur; 19165b04b38Smrg SyncCounter *pCounter; 19205b261ecSmrg 19365b04b38Smrg if (!pTrigger->pSync) 194f7df2e56Smrg return Success; 19505b261ecSmrg 19605b261ecSmrg /* don't do anything if it's already there */ 197f7df2e56Smrg for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next) { 198f7df2e56Smrg if (pCur->pTrigger == pTrigger) 199f7df2e56Smrg return Success; 20005b261ecSmrg } 20105b261ecSmrg 2024202a189Smrg if (!(pCur = malloc(sizeof(SyncTriggerList)))) 203f7df2e56Smrg return BadAlloc; 20405b261ecSmrg 20505b261ecSmrg pCur->pTrigger = pTrigger; 20665b04b38Smrg pCur->next = pTrigger->pSync->pTriglist; 20765b04b38Smrg pTrigger->pSync->pTriglist = pCur; 20805b261ecSmrg 209f7df2e56Smrg if (SYNC_COUNTER == pTrigger->pSync->type) { 210f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 21165b04b38Smrg 212f7df2e56Smrg if (IsSystemCounter(pCounter)) 213f7df2e56Smrg SyncComputeBracketValues(pCounter); 214f7df2e56Smrg } 215f7df2e56Smrg else if (SYNC_FENCE == pTrigger->pSync->type) { 216f7df2e56Smrg SyncFence *pFence = (SyncFence *) pTrigger->pSync; 217f7df2e56Smrg 218f7df2e56Smrg pFence->funcs.AddTrigger(pTrigger); 21965b04b38Smrg } 22005b261ecSmrg 22105b261ecSmrg return Success; 22205b261ecSmrg} 22305b261ecSmrg 22465b04b38Smrg/* Below are five possible functions that can be plugged into 22565b04b38Smrg * pTrigger->CheckTrigger for counter sync objects, corresponding to 22665b04b38Smrg * the four possible test-types, and the one possible function that 22765b04b38Smrg * can be plugged into pTrigger->CheckTrigger for fence sync objects. 22865b04b38Smrg * These functions are called after the sync object's state changes 22965b04b38Smrg * but are also passed the old state so they can inspect both the old 23065b04b38Smrg * and new values. (PositiveTransition and NegativeTransition need to 23165b04b38Smrg * see both pieces of information.) These functions return the truth 23265b04b38Smrg * value of the trigger. 23305b261ecSmrg * 23465b04b38Smrg * All of them include the condition pTrigger->pSync == NULL. 23565b04b38Smrg * This is because the spec says that a trigger with a sync value 23605b261ecSmrg * of None is always TRUE. 23705b261ecSmrg */ 23805b261ecSmrg 23905b261ecSmrgstatic Bool 240f7df2e56SmrgSyncCheckTriggerPositiveComparison(SyncTrigger * pTrigger, CARD64 oldval) 24105b261ecSmrg{ 24265b04b38Smrg SyncCounter *pCounter; 24365b04b38Smrg 24465b04b38Smrg /* Non-counter sync objects should never get here because they 24565b04b38Smrg * never trigger this comparison. */ 24665b04b38Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 247f7df2e56Smrg return FALSE; 24865b04b38Smrg 249f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 25065b04b38Smrg 25165b04b38Smrg return (pCounter == NULL || 252f7df2e56Smrg XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)); 25305b261ecSmrg} 25405b261ecSmrg 25505b261ecSmrgstatic Bool 256f7df2e56SmrgSyncCheckTriggerNegativeComparison(SyncTrigger * pTrigger, CARD64 oldval) 25705b261ecSmrg{ 25865b04b38Smrg SyncCounter *pCounter; 25965b04b38Smrg 26065b04b38Smrg /* Non-counter sync objects should never get here because they 26165b04b38Smrg * never trigger this comparison. */ 26265b04b38Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 263f7df2e56Smrg return FALSE; 26465b04b38Smrg 265f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 26665b04b38Smrg 26765b04b38Smrg return (pCounter == NULL || 268f7df2e56Smrg XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)); 26905b261ecSmrg} 27005b261ecSmrg 27105b261ecSmrgstatic Bool 272f7df2e56SmrgSyncCheckTriggerPositiveTransition(SyncTrigger * pTrigger, CARD64 oldval) 27305b261ecSmrg{ 27465b04b38Smrg SyncCounter *pCounter; 27565b04b38Smrg 27665b04b38Smrg /* Non-counter sync objects should never get here because they 27765b04b38Smrg * never trigger this comparison. */ 27865b04b38Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 279f7df2e56Smrg return FALSE; 28065b04b38Smrg 281f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 28265b04b38Smrg 28365b04b38Smrg return (pCounter == NULL || 284f7df2e56Smrg (XSyncValueLessThan(oldval, pTrigger->test_value) && 285f7df2e56Smrg XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value))); 28605b261ecSmrg} 28705b261ecSmrg 28805b261ecSmrgstatic Bool 289f7df2e56SmrgSyncCheckTriggerNegativeTransition(SyncTrigger * pTrigger, CARD64 oldval) 29005b261ecSmrg{ 29165b04b38Smrg SyncCounter *pCounter; 29265b04b38Smrg 29365b04b38Smrg /* Non-counter sync objects should never get here because they 29465b04b38Smrg * never trigger this comparison. */ 29565b04b38Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE)) 296f7df2e56Smrg return FALSE; 29765b04b38Smrg 298f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 29965b04b38Smrg 30065b04b38Smrg return (pCounter == NULL || 301f7df2e56Smrg (XSyncValueGreaterThan(oldval, pTrigger->test_value) && 302f7df2e56Smrg XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value))); 30365b04b38Smrg} 30465b04b38Smrg 30565b04b38Smrgstatic Bool 306f7df2e56SmrgSyncCheckTriggerFence(SyncTrigger * pTrigger, CARD64 unused) 30765b04b38Smrg{ 308f7df2e56Smrg SyncFence *pFence = (SyncFence *) pTrigger->pSync; 309f7df2e56Smrg 310f7df2e56Smrg (void) unused; 31165b04b38Smrg 312f7df2e56Smrg return (pFence == NULL || pFence->funcs.CheckTriggered(pFence)); 31305b261ecSmrg} 31405b261ecSmrg 3154202a189Smrgstatic int 316f7df2e56SmrgSyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject, 317f7df2e56Smrg RESTYPE resType, Mask changes) 31805b261ecSmrg{ 31965b04b38Smrg SyncObject *pSync = pTrigger->pSync; 32065b04b38Smrg SyncCounter *pCounter = NULL; 321f7df2e56Smrg int rc; 322f7df2e56Smrg Bool newSyncObject = FALSE; 323f7df2e56Smrg 324f7df2e56Smrg if (changes & XSyncCACounter) { 325f7df2e56Smrg if (syncObject == None) 326f7df2e56Smrg pSync = NULL; 327f7df2e56Smrg else if (Success != (rc = dixLookupResourceByType((void **) &pSync, 328f7df2e56Smrg syncObject, resType, 329f7df2e56Smrg client, 330f7df2e56Smrg DixReadAccess))) { 331f7df2e56Smrg client->errorValue = syncObject; 332f7df2e56Smrg return rc; 333f7df2e56Smrg } 334f7df2e56Smrg if (pSync != pTrigger->pSync) { /* new counter for trigger */ 335f7df2e56Smrg SyncDeleteTriggerFromSyncObject(pTrigger); 336f7df2e56Smrg pTrigger->pSync = pSync; 337f7df2e56Smrg newSyncObject = TRUE; 338f7df2e56Smrg } 33905b261ecSmrg } 34005b261ecSmrg 34105b261ecSmrg /* if system counter, ask it what the current value is */ 34205b261ecSmrg 343f7df2e56Smrg if (pSync && SYNC_COUNTER == pSync->type) { 344f7df2e56Smrg pCounter = (SyncCounter *) pSync; 345f7df2e56Smrg 346f7df2e56Smrg if (IsSystemCounter(pCounter)) { 347f7df2e56Smrg (*pCounter->pSysCounterInfo->QueryValue) ((void *) pCounter, 348f7df2e56Smrg &pCounter->value); 349f7df2e56Smrg } 350f7df2e56Smrg } 351f7df2e56Smrg 352f7df2e56Smrg if (changes & XSyncCAValueType) { 353f7df2e56Smrg if (pTrigger->value_type != XSyncRelative && 354f7df2e56Smrg pTrigger->value_type != XSyncAbsolute) { 355f7df2e56Smrg client->errorValue = pTrigger->value_type; 356f7df2e56Smrg return BadValue; 357f7df2e56Smrg } 358f7df2e56Smrg } 359f7df2e56Smrg 360f7df2e56Smrg if (changes & XSyncCATestType) { 361f7df2e56Smrg 362f7df2e56Smrg if (pSync && SYNC_FENCE == pSync->type) { 363f7df2e56Smrg pTrigger->CheckTrigger = SyncCheckTriggerFence; 364f7df2e56Smrg } 365f7df2e56Smrg else { 366f7df2e56Smrg /* select appropriate CheckTrigger function */ 367f7df2e56Smrg 368f7df2e56Smrg switch (pTrigger->test_type) { 369f7df2e56Smrg case XSyncPositiveTransition: 370f7df2e56Smrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; 371f7df2e56Smrg break; 372f7df2e56Smrg case XSyncNegativeTransition: 373f7df2e56Smrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; 374f7df2e56Smrg break; 375f7df2e56Smrg case XSyncPositiveComparison: 376f7df2e56Smrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; 377f7df2e56Smrg break; 378f7df2e56Smrg case XSyncNegativeComparison: 379f7df2e56Smrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; 380f7df2e56Smrg break; 381f7df2e56Smrg default: 382f7df2e56Smrg client->errorValue = pTrigger->test_type; 383f7df2e56Smrg return BadValue; 384f7df2e56Smrg } 385f7df2e56Smrg } 386f7df2e56Smrg } 387f7df2e56Smrg 388f7df2e56Smrg if (changes & (XSyncCAValueType | XSyncCAValue)) { 389f7df2e56Smrg if (pTrigger->value_type == XSyncAbsolute) 390f7df2e56Smrg pTrigger->test_value = pTrigger->wait_value; 391f7df2e56Smrg else { /* relative */ 392f7df2e56Smrg 393f7df2e56Smrg Bool overflow; 394f7df2e56Smrg 395f7df2e56Smrg if (pCounter == NULL) 396f7df2e56Smrg return BadMatch; 397f7df2e56Smrg 398f7df2e56Smrg XSyncValueAdd(&pTrigger->test_value, pCounter->value, 399f7df2e56Smrg pTrigger->wait_value, &overflow); 400f7df2e56Smrg if (overflow) { 401f7df2e56Smrg client->errorValue = XSyncValueHigh32(pTrigger->wait_value); 402f7df2e56Smrg return BadValue; 403f7df2e56Smrg } 404f7df2e56Smrg } 40505b261ecSmrg } 40605b261ecSmrg 40705b261ecSmrg /* we wait until we're sure there are no errors before registering 40805b261ecSmrg * a new counter on a trigger 40905b261ecSmrg */ 410f7df2e56Smrg if (newSyncObject) { 411f7df2e56Smrg if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success) 412f7df2e56Smrg return rc; 41305b261ecSmrg } 414f7df2e56Smrg else if (pCounter && IsSystemCounter(pCounter)) { 415f7df2e56Smrg SyncComputeBracketValues(pCounter); 41605b261ecSmrg } 4174202a189Smrg 41805b261ecSmrg return Success; 41905b261ecSmrg} 42005b261ecSmrg 42105b261ecSmrg/* AlarmNotify events happen in response to actions taken on an Alarm or 4224202a189Smrg * the counter used by the alarm. AlarmNotify may be sent to multiple 42305b261ecSmrg * clients. The alarm maintains a list of clients interested in events. 42405b261ecSmrg */ 42505b261ecSmrgstatic void 426f7df2e56SmrgSyncSendAlarmNotifyEvents(SyncAlarm * pAlarm) 42705b261ecSmrg{ 42805b261ecSmrg SyncAlarmClientList *pcl; 42905b261ecSmrg xSyncAlarmNotifyEvent ane; 43005b261ecSmrg SyncTrigger *pTrigger = &pAlarm->trigger; 43165b04b38Smrg SyncCounter *pCounter; 43265b04b38Smrg 43365b04b38Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM)) 434f7df2e56Smrg return; 43565b04b38Smrg 436f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 43705b261ecSmrg 43805b261ecSmrg UpdateCurrentTime(); 43905b261ecSmrg 440f7df2e56Smrg ane = (xSyncAlarmNotifyEvent) { 441f7df2e56Smrg .type = SyncEventBase + XSyncAlarmNotify, 442f7df2e56Smrg .kind = XSyncAlarmNotify, 443f7df2e56Smrg .alarm = pAlarm->alarm_id, 444f7df2e56Smrg .alarm_value_hi = XSyncValueHigh32(pTrigger->test_value), 445f7df2e56Smrg .alarm_value_lo = XSyncValueLow32(pTrigger->test_value), 446f7df2e56Smrg .time = currentTime.milliseconds, 447f7df2e56Smrg .state = pAlarm->state 448f7df2e56Smrg }; 449f7df2e56Smrg 450f7df2e56Smrg if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type) { 451f7df2e56Smrg ane.counter_value_hi = XSyncValueHigh32(pCounter->value); 452f7df2e56Smrg ane.counter_value_lo = XSyncValueLow32(pCounter->value); 45305b261ecSmrg } 454f7df2e56Smrg else { 455f7df2e56Smrg /* XXX what else can we do if there's no counter? */ 456f7df2e56Smrg ane.counter_value_hi = ane.counter_value_lo = 0; 45705b261ecSmrg } 45805b261ecSmrg 45905b261ecSmrg /* send to owner */ 4604202a189Smrg if (pAlarm->events) 461f7df2e56Smrg WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); 46205b261ecSmrg 46305b261ecSmrg /* send to other interested clients */ 46405b261ecSmrg for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) 465f7df2e56Smrg WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); 46605b261ecSmrg} 46705b261ecSmrg 4684202a189Smrg/* CounterNotify events only occur in response to an Await. The events 46905b261ecSmrg * go only to the Awaiting client. 47005b261ecSmrg */ 47105b261ecSmrgstatic void 472f7df2e56SmrgSyncSendCounterNotifyEvents(ClientPtr client, SyncAwait ** ppAwait, 473f7df2e56Smrg int num_events) 47405b261ecSmrg{ 47505b261ecSmrg xSyncCounterNotifyEvent *pEvents, *pev; 47605b261ecSmrg int i; 47705b261ecSmrg 47805b261ecSmrg if (client->clientGone) 479f7df2e56Smrg return; 480f7df2e56Smrg pev = pEvents = calloc(num_events, sizeof(xSyncCounterNotifyEvent)); 4814202a189Smrg if (!pEvents) 482f7df2e56Smrg return; 48305b261ecSmrg UpdateCurrentTime(); 484f7df2e56Smrg for (i = 0; i < num_events; i++, ppAwait++, pev++) { 485f7df2e56Smrg SyncTrigger *pTrigger = &(*ppAwait)->trigger; 486f7df2e56Smrg 487f7df2e56Smrg pev->type = SyncEventBase + XSyncCounterNotify; 488f7df2e56Smrg pev->kind = XSyncCounterNotify; 489f7df2e56Smrg pev->counter = pTrigger->pSync->id; 490f7df2e56Smrg pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); 491f7df2e56Smrg pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 492f7df2e56Smrg if (SYNC_COUNTER == pTrigger->pSync->type) { 493f7df2e56Smrg SyncCounter *pCounter = (SyncCounter *) pTrigger->pSync; 494f7df2e56Smrg 495f7df2e56Smrg pev->counter_value_lo = XSyncValueLow32(pCounter->value); 496f7df2e56Smrg pev->counter_value_hi = XSyncValueHigh32(pCounter->value); 497f7df2e56Smrg } 498f7df2e56Smrg else { 499f7df2e56Smrg pev->counter_value_lo = 0; 500f7df2e56Smrg pev->counter_value_hi = 0; 501f7df2e56Smrg } 502f7df2e56Smrg 503f7df2e56Smrg pev->time = currentTime.milliseconds; 504f7df2e56Smrg pev->count = num_events - i - 1; /* events remaining */ 505f7df2e56Smrg pev->destroyed = pTrigger->pSync->beingDestroyed; 50605b261ecSmrg } 50705b261ecSmrg /* swapping will be taken care of by this */ 508f7df2e56Smrg WriteEventsToClient(client, num_events, (xEvent *) pEvents); 5094202a189Smrg free(pEvents); 51005b261ecSmrg} 51105b261ecSmrg 51205b261ecSmrg/* This function is called when an alarm's counter is destroyed. 51305b261ecSmrg * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). 51405b261ecSmrg */ 5154202a189Smrgstatic void 516f7df2e56SmrgSyncAlarmCounterDestroyed(SyncTrigger * pTrigger) 51705b261ecSmrg{ 518f7df2e56Smrg SyncAlarm *pAlarm = (SyncAlarm *) pTrigger; 51905b261ecSmrg 52005b261ecSmrg pAlarm->state = XSyncAlarmInactive; 52105b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 52265b04b38Smrg pTrigger->pSync = NULL; 52305b261ecSmrg} 52405b261ecSmrg 5254202a189Smrg/* This function is called when an alarm "goes off." 52605b261ecSmrg * It is plugged into pTrigger->TriggerFired (for alarm triggers). 52705b261ecSmrg */ 52805b261ecSmrgstatic void 529f7df2e56SmrgSyncAlarmTriggerFired(SyncTrigger * pTrigger) 53005b261ecSmrg{ 531f7df2e56Smrg SyncAlarm *pAlarm = (SyncAlarm *) pTrigger; 53265b04b38Smrg SyncCounter *pCounter; 53305b261ecSmrg CARD64 new_test_value; 53405b261ecSmrg 53565b04b38Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM)) 536f7df2e56Smrg return; 53765b04b38Smrg 538f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 53965b04b38Smrg 54005b261ecSmrg /* no need to check alarm unless it's active */ 54105b261ecSmrg if (pAlarm->state != XSyncAlarmActive) 542f7df2e56Smrg return; 54305b261ecSmrg 54405b261ecSmrg /* " if the counter value is None, or if the delta is 0 and 54505b261ecSmrg * the test-type is PositiveComparison or NegativeComparison, 54605b261ecSmrg * no change is made to value (test-value) and the alarm 54705b261ecSmrg * state is changed to Inactive before the event is generated." 54805b261ecSmrg */ 549f7df2e56Smrg if (pCounter == NULL || (XSyncValueIsZero(pAlarm->delta) 550f7df2e56Smrg && (pAlarm->trigger.test_type == 551f7df2e56Smrg XSyncPositiveComparison || 552f7df2e56Smrg pAlarm->trigger.test_type == 553f7df2e56Smrg XSyncNegativeComparison))) 554f7df2e56Smrg pAlarm->state = XSyncAlarmInactive; 55505b261ecSmrg 55605b261ecSmrg new_test_value = pAlarm->trigger.test_value; 55705b261ecSmrg 558f7df2e56Smrg if (pAlarm->state == XSyncAlarmActive) { 559f7df2e56Smrg Bool overflow; 560f7df2e56Smrg CARD64 oldvalue; 561f7df2e56Smrg SyncTrigger *paTrigger = &pAlarm->trigger; 562f7df2e56Smrg SyncCounter *paCounter; 563f7df2e56Smrg 564f7df2e56Smrg if (!SyncCheckWarnIsCounter(paTrigger->pSync, 565f7df2e56Smrg WARN_INVALID_COUNTER_ALARM)) 566f7df2e56Smrg return; 567f7df2e56Smrg 568f7df2e56Smrg paCounter = (SyncCounter *) pTrigger->pSync; 569f7df2e56Smrg 570f7df2e56Smrg /* "The alarm is updated by repeatedly adding delta to the 571f7df2e56Smrg * value of the trigger and re-initializing it until it 572f7df2e56Smrg * becomes FALSE." 573f7df2e56Smrg */ 574f7df2e56Smrg oldvalue = paTrigger->test_value; 575f7df2e56Smrg 576f7df2e56Smrg /* XXX really should do something smarter here */ 577f7df2e56Smrg 578f7df2e56Smrg do { 579f7df2e56Smrg XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, 580f7df2e56Smrg pAlarm->delta, &overflow); 581f7df2e56Smrg } while (!overflow && 582f7df2e56Smrg (*paTrigger->CheckTrigger) (paTrigger, paCounter->value)); 583f7df2e56Smrg 584f7df2e56Smrg new_test_value = paTrigger->test_value; 585f7df2e56Smrg paTrigger->test_value = oldvalue; 586f7df2e56Smrg 587f7df2e56Smrg /* "If this update would cause value to fall outside the range 588f7df2e56Smrg * for an INT64...no change is made to value (test-value) and 589f7df2e56Smrg * the alarm state is changed to Inactive before the event is 590f7df2e56Smrg * generated." 591f7df2e56Smrg */ 592f7df2e56Smrg if (overflow) { 593f7df2e56Smrg new_test_value = oldvalue; 594f7df2e56Smrg pAlarm->state = XSyncAlarmInactive; 595f7df2e56Smrg } 59605b261ecSmrg } 59705b261ecSmrg /* The AlarmNotify event has to have the "new state of the alarm" 59805b261ecSmrg * which we can't be sure of until this point. However, it has 59905b261ecSmrg * to have the "old" trigger test value. That's the reason for 60005b261ecSmrg * all the newvalue/oldvalue shuffling above. After we send the 60105b261ecSmrg * events, give the trigger its new test value. 60205b261ecSmrg */ 60305b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 60405b261ecSmrg pTrigger->test_value = new_test_value; 60505b261ecSmrg} 60605b261ecSmrg 60705b261ecSmrg/* This function is called when an Await unblocks, either as a result 60805b261ecSmrg * of the trigger firing OR the counter being destroyed. 60905b261ecSmrg * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed 61005b261ecSmrg * (for Await triggers). 61105b261ecSmrg */ 61205b261ecSmrgstatic void 613f7df2e56SmrgSyncAwaitTriggerFired(SyncTrigger * pTrigger) 61405b261ecSmrg{ 615f7df2e56Smrg SyncAwait *pAwait = (SyncAwait *) pTrigger; 61605b261ecSmrg int numwaits; 61705b261ecSmrg SyncAwaitUnion *pAwaitUnion; 61805b261ecSmrg SyncAwait **ppAwait; 61905b261ecSmrg int num_events = 0; 62005b261ecSmrg 621f7df2e56Smrg pAwaitUnion = (SyncAwaitUnion *) pAwait->pHeader; 62205b261ecSmrg numwaits = pAwaitUnion->header.num_waitconditions; 623f7df2e56Smrg ppAwait = xallocarray(numwaits, sizeof(SyncAwait *)); 62405b261ecSmrg if (!ppAwait) 625f7df2e56Smrg goto bail; 62605b261ecSmrg 627f7df2e56Smrg pAwait = &(pAwaitUnion + 1)->await; 62805b261ecSmrg 62905b261ecSmrg /* "When a client is unblocked, all the CounterNotify events for 63005b261ecSmrg * the Await request are generated contiguously. If count is 0 63105b261ecSmrg * there are no more events to follow for this request. If 63205b261ecSmrg * count is n, there are at least n more events to follow." 63305b261ecSmrg * 63405b261ecSmrg * Thus, it is best to find all the counters for which events 63505b261ecSmrg * need to be sent first, so that an accurate count field can 63605b261ecSmrg * be stored in the events. 63705b261ecSmrg */ 638f7df2e56Smrg for (; numwaits; numwaits--, pAwait++) { 639f7df2e56Smrg CARD64 diff; 640f7df2e56Smrg Bool overflow, diffgreater, diffequal; 641f7df2e56Smrg 642f7df2e56Smrg /* "A CounterNotify event with the destroyed flag set to TRUE is 643f7df2e56Smrg * always generated if the counter for one of the triggers is 644f7df2e56Smrg * destroyed." 645f7df2e56Smrg */ 646f7df2e56Smrg if (pAwait->trigger.pSync->beingDestroyed) { 647f7df2e56Smrg ppAwait[num_events++] = pAwait; 648f7df2e56Smrg continue; 649f7df2e56Smrg } 650f7df2e56Smrg 651f7df2e56Smrg if (SYNC_COUNTER == pAwait->trigger.pSync->type) { 652f7df2e56Smrg SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync; 653f7df2e56Smrg 654f7df2e56Smrg /* "The difference between the counter and the test value is 655f7df2e56Smrg * calculated by subtracting the test value from the value of 656f7df2e56Smrg * the counter." 657f7df2e56Smrg */ 658f7df2e56Smrg XSyncValueSubtract(&diff, pCounter->value, 659f7df2e56Smrg pAwait->trigger.test_value, &overflow); 660f7df2e56Smrg 661f7df2e56Smrg /* "If the difference lies outside the range for an INT64, an 662f7df2e56Smrg * event is not generated." 663f7df2e56Smrg */ 664f7df2e56Smrg if (overflow) 665f7df2e56Smrg continue; 666f7df2e56Smrg diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); 667f7df2e56Smrg diffequal = XSyncValueEqual(diff, pAwait->event_threshold); 668f7df2e56Smrg 669f7df2e56Smrg /* "If the test-type is PositiveTransition or 670f7df2e56Smrg * PositiveComparison, a CounterNotify event is generated if 671f7df2e56Smrg * the difference is at least event-threshold. If the test-type 672f7df2e56Smrg * is NegativeTransition or NegativeComparison, a CounterNotify 673f7df2e56Smrg * event is generated if the difference is at most 674f7df2e56Smrg * event-threshold." 675f7df2e56Smrg */ 676f7df2e56Smrg 677f7df2e56Smrg if (((pAwait->trigger.test_type == XSyncPositiveComparison || 678f7df2e56Smrg pAwait->trigger.test_type == XSyncPositiveTransition) 679f7df2e56Smrg && (diffgreater || diffequal)) 680f7df2e56Smrg || 681f7df2e56Smrg ((pAwait->trigger.test_type == XSyncNegativeComparison || 682f7df2e56Smrg pAwait->trigger.test_type == XSyncNegativeTransition) 683f7df2e56Smrg && (!diffgreater) /* less or equal */ 684f7df2e56Smrg ) 685f7df2e56Smrg ) { 686f7df2e56Smrg ppAwait[num_events++] = pAwait; 687f7df2e56Smrg } 688f7df2e56Smrg } 68905b261ecSmrg } 69005b261ecSmrg if (num_events) 691f7df2e56Smrg SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, 692f7df2e56Smrg num_events); 6934202a189Smrg free(ppAwait); 69405b261ecSmrg 695f7df2e56Smrg bail: 69605b261ecSmrg /* unblock the client */ 69705b261ecSmrg AttendClient(pAwaitUnion->header.client); 69805b261ecSmrg /* delete the await */ 69905b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 70005b261ecSmrg} 70105b261ecSmrg 702f7df2e56Smrgstatic CARD64 703f7df2e56SmrgSyncUpdateCounter(SyncCounter *pCounter, CARD64 newval) 704f7df2e56Smrg{ 705f7df2e56Smrg CARD64 oldval = pCounter->value; 706f7df2e56Smrg pCounter->value = newval; 707f7df2e56Smrg return oldval; 708f7df2e56Smrg} 70905b261ecSmrg 71005b261ecSmrg/* This function should always be used to change a counter's value so that 71105b261ecSmrg * any triggers depending on the counter will be checked. 71205b261ecSmrg */ 71305b261ecSmrgvoid 714f7df2e56SmrgSyncChangeCounter(SyncCounter * pCounter, CARD64 newval) 71505b261ecSmrg{ 716f7df2e56Smrg SyncTriggerList *ptl, *pnext; 71705b261ecSmrg CARD64 oldval; 71805b261ecSmrg 719f7df2e56Smrg oldval = SyncUpdateCounter(pCounter, newval); 72005b261ecSmrg 72105b261ecSmrg /* run through triggers to see if any become true */ 722f7df2e56Smrg for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) { 723f7df2e56Smrg pnext = ptl->next; 724f7df2e56Smrg if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval)) 725f7df2e56Smrg (*ptl->pTrigger->TriggerFired) (ptl->pTrigger); 72605b261ecSmrg } 72705b261ecSmrg 728f7df2e56Smrg if (IsSystemCounter(pCounter)) { 729f7df2e56Smrg SyncComputeBracketValues(pCounter); 73005b261ecSmrg } 73105b261ecSmrg} 73205b261ecSmrg 73305b261ecSmrg/* loosely based on dix/events.c/EventSelectForWindow */ 73405b261ecSmrgstatic Bool 735f7df2e56SmrgSyncEventSelectForAlarm(SyncAlarm * pAlarm, ClientPtr client, Bool wantevents) 73605b261ecSmrg{ 73705b261ecSmrg SyncAlarmClientList *pClients; 73805b261ecSmrg 739f7df2e56Smrg if (client == pAlarm->client) { /* alarm owner */ 740f7df2e56Smrg pAlarm->events = wantevents; 741f7df2e56Smrg return Success; 74205b261ecSmrg } 74305b261ecSmrg 74405b261ecSmrg /* see if the client is already on the list (has events selected) */ 74505b261ecSmrg 746f7df2e56Smrg for (pClients = pAlarm->pEventClients; pClients; pClients = pClients->next) { 747f7df2e56Smrg if (pClients->client == client) { 748f7df2e56Smrg /* client's presence on the list indicates desire for 749f7df2e56Smrg * events. If the client doesn't want events, remove it 750f7df2e56Smrg * from the list. If the client does want events, do 751f7df2e56Smrg * nothing, since it's already got them. 752f7df2e56Smrg */ 753f7df2e56Smrg if (!wantevents) { 754f7df2e56Smrg FreeResource(pClients->delete_id, RT_NONE); 755f7df2e56Smrg } 756f7df2e56Smrg return Success; 757f7df2e56Smrg } 75805b261ecSmrg } 75905b261ecSmrg 76005b261ecSmrg /* if we get here, this client does not currently have 76105b261ecSmrg * events selected on the alarm 76205b261ecSmrg */ 76305b261ecSmrg 76405b261ecSmrg if (!wantevents) 765f7df2e56Smrg /* client doesn't want events, and we just discovered that it 766f7df2e56Smrg * doesn't have them, so there's nothing to do. 767f7df2e56Smrg */ 768f7df2e56Smrg return Success; 76905b261ecSmrg 77005b261ecSmrg /* add new client to pAlarm->pEventClients */ 77105b261ecSmrg 7724202a189Smrg pClients = malloc(sizeof(SyncAlarmClientList)); 77305b261ecSmrg if (!pClients) 774f7df2e56Smrg return BadAlloc; 77505b261ecSmrg 7764202a189Smrg /* register it as a resource so it will be cleaned up 77705b261ecSmrg * if the client dies 77805b261ecSmrg */ 77905b261ecSmrg 78005b261ecSmrg pClients->delete_id = FakeClientID(client->index); 78105b261ecSmrg 78205b261ecSmrg /* link it into list after we know all the allocations succeed */ 78305b261ecSmrg pClients->next = pAlarm->pEventClients; 78405b261ecSmrg pAlarm->pEventClients = pClients; 78505b261ecSmrg pClients->client = client; 78665b04b38Smrg 78765b04b38Smrg if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) 788f7df2e56Smrg return BadAlloc; 78965b04b38Smrg 79005b261ecSmrg return Success; 79105b261ecSmrg} 79205b261ecSmrg 79305b261ecSmrg/* 79405b261ecSmrg * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm 79505b261ecSmrg */ 7964202a189Smrgstatic int 797f7df2e56SmrgSyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask, 798f7df2e56Smrg CARD32 *values) 799f7df2e56Smrg{ 800f7df2e56Smrg int status; 801f7df2e56Smrg XSyncCounter counter; 802f7df2e56Smrg Mask origmask = mask; 803f7df2e56Smrg 804f7df2e56Smrg counter = pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None; 805f7df2e56Smrg 806f7df2e56Smrg while (mask) { 807f7df2e56Smrg int index2 = lowbit(mask); 808f7df2e56Smrg 809f7df2e56Smrg mask &= ~index2; 810f7df2e56Smrg switch (index2) { 811f7df2e56Smrg case XSyncCACounter: 812f7df2e56Smrg mask &= ~XSyncCACounter; 813f7df2e56Smrg /* sanity check in SyncInitTrigger */ 814f7df2e56Smrg counter = *values++; 815f7df2e56Smrg break; 816f7df2e56Smrg 817f7df2e56Smrg case XSyncCAValueType: 818f7df2e56Smrg mask &= ~XSyncCAValueType; 819f7df2e56Smrg /* sanity check in SyncInitTrigger */ 820f7df2e56Smrg pAlarm->trigger.value_type = *values++; 821f7df2e56Smrg break; 822f7df2e56Smrg 823f7df2e56Smrg case XSyncCAValue: 824f7df2e56Smrg mask &= ~XSyncCAValue; 825f7df2e56Smrg XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); 826f7df2e56Smrg values += 2; 827f7df2e56Smrg break; 828f7df2e56Smrg 829f7df2e56Smrg case XSyncCATestType: 830f7df2e56Smrg mask &= ~XSyncCATestType; 831f7df2e56Smrg /* sanity check in SyncInitTrigger */ 832f7df2e56Smrg pAlarm->trigger.test_type = *values++; 833f7df2e56Smrg break; 834f7df2e56Smrg 835f7df2e56Smrg case XSyncCADelta: 836f7df2e56Smrg mask &= ~XSyncCADelta; 837f7df2e56Smrg XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); 838f7df2e56Smrg values += 2; 839f7df2e56Smrg break; 840f7df2e56Smrg 841f7df2e56Smrg case XSyncCAEvents: 842f7df2e56Smrg mask &= ~XSyncCAEvents; 843f7df2e56Smrg if ((*values != xTrue) && (*values != xFalse)) { 844f7df2e56Smrg client->errorValue = *values; 845f7df2e56Smrg return BadValue; 846f7df2e56Smrg } 847f7df2e56Smrg status = SyncEventSelectForAlarm(pAlarm, client, 848f7df2e56Smrg (Bool) (*values++)); 849f7df2e56Smrg if (status != Success) 850f7df2e56Smrg return status; 851f7df2e56Smrg break; 852f7df2e56Smrg 853f7df2e56Smrg default: 854f7df2e56Smrg client->errorValue = mask; 855f7df2e56Smrg return BadValue; 856f7df2e56Smrg } 85705b261ecSmrg } 85805b261ecSmrg 85905b261ecSmrg /* "If the test-type is PositiveComparison or PositiveTransition 86005b261ecSmrg * and delta is less than zero, or if the test-type is 86105b261ecSmrg * NegativeComparison or NegativeTransition and delta is 86205b261ecSmrg * greater than zero, a Match error is generated." 86305b261ecSmrg */ 864f7df2e56Smrg if (origmask & (XSyncCADelta | XSyncCATestType)) { 865f7df2e56Smrg CARD64 zero; 866f7df2e56Smrg 867f7df2e56Smrg XSyncIntToValue(&zero, 0); 868f7df2e56Smrg if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || 869f7df2e56Smrg (pAlarm->trigger.test_type == XSyncPositiveTransition)) 870f7df2e56Smrg && XSyncValueLessThan(pAlarm->delta, zero)) 871f7df2e56Smrg || 872f7df2e56Smrg (((pAlarm->trigger.test_type == XSyncNegativeComparison) || 873f7df2e56Smrg (pAlarm->trigger.test_type == XSyncNegativeTransition)) 874f7df2e56Smrg && XSyncValueGreaterThan(pAlarm->delta, zero)) 875f7df2e56Smrg ) { 876f7df2e56Smrg return BadMatch; 877f7df2e56Smrg } 87805b261ecSmrg } 87905b261ecSmrg 88005b261ecSmrg /* postpone this until now, when we're sure nothing else can go wrong */ 88165b04b38Smrg if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter, 882f7df2e56Smrg origmask & XSyncCAAllTrigger)) != Success) 883f7df2e56Smrg return status; 88405b261ecSmrg 88505b261ecSmrg /* XXX spec does not really say to do this - needs clarification */ 88605b261ecSmrg pAlarm->state = XSyncAlarmActive; 88705b261ecSmrg return Success; 88805b261ecSmrg} 88905b261ecSmrg 89065b04b38Smrgstatic SyncObject * 89165b04b38SmrgSyncCreate(ClientPtr client, XID id, unsigned char type) 89265b04b38Smrg{ 89365b04b38Smrg SyncObject *pSync; 89465b04b38Smrg 89565b04b38Smrg switch (type) { 89665b04b38Smrg case SYNC_COUNTER: 897f7df2e56Smrg pSync = malloc(sizeof(SyncCounter)); 898f7df2e56Smrg break; 89965b04b38Smrg case SYNC_FENCE: 900f7df2e56Smrg pSync = (SyncObject *) dixAllocateObjectWithPrivates(SyncFence, 901f7df2e56Smrg PRIVATE_SYNC_FENCE); 902f7df2e56Smrg break; 90365b04b38Smrg default: 904f7df2e56Smrg return NULL; 90565b04b38Smrg } 90665b04b38Smrg 90765b04b38Smrg if (!pSync) 908f7df2e56Smrg return NULL; 90965b04b38Smrg 91065b04b38Smrg pSync->client = client; 91165b04b38Smrg pSync->id = id; 91265b04b38Smrg pSync->pTriglist = NULL; 91365b04b38Smrg pSync->beingDestroyed = FALSE; 91465b04b38Smrg pSync->type = type; 91565b04b38Smrg 91665b04b38Smrg return pSync; 91765b04b38Smrg} 91865b04b38Smrg 919f7df2e56Smrgint 920f7df2e56SmrgSyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered) 921f7df2e56Smrg{ 922f7df2e56Smrg#if HAVE_XSHMFENCE 923f7df2e56Smrg SyncFence *pFence; 924f7df2e56Smrg int status; 925f7df2e56Smrg 926f7df2e56Smrg pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE); 927f7df2e56Smrg if (!pFence) 928f7df2e56Smrg return BadAlloc; 929f7df2e56Smrg 930f7df2e56Smrg status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered); 931f7df2e56Smrg if (status != Success) { 932f7df2e56Smrg dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE); 933f7df2e56Smrg return status; 934f7df2e56Smrg } 935f7df2e56Smrg 936f7df2e56Smrg if (!AddResource(id, RTFence, (void *) pFence)) 937f7df2e56Smrg return BadAlloc; 938f7df2e56Smrg 939f7df2e56Smrg return Success; 940f7df2e56Smrg#else 941f7df2e56Smrg return BadImplementation; 942f7df2e56Smrg#endif 943f7df2e56Smrg} 944f7df2e56Smrg 945f7df2e56Smrgint 946f7df2e56SmrgSyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence) 947f7df2e56Smrg{ 948f7df2e56Smrg#if HAVE_XSHMFENCE 949f7df2e56Smrg return miSyncFDFromFence(pDraw, pFence); 950f7df2e56Smrg#else 951f7df2e56Smrg return BadImplementation; 952f7df2e56Smrg#endif 953f7df2e56Smrg} 95405b261ecSmrg 95505b261ecSmrgstatic SyncCounter * 9564202a189SmrgSyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) 95705b261ecSmrg{ 95805b261ecSmrg SyncCounter *pCounter; 95905b261ecSmrg 960f7df2e56Smrg if (!(pCounter = (SyncCounter *) SyncCreate(client, id, SYNC_COUNTER))) 961f7df2e56Smrg return NULL; 96205b261ecSmrg 96365b04b38Smrg pCounter->value = initialvalue; 96465b04b38Smrg pCounter->pSysCounterInfo = NULL; 96565b04b38Smrg 966f7df2e56Smrg if (!AddResource(id, RTCounter, (void *) pCounter)) 967f7df2e56Smrg return NULL; 96805b261ecSmrg 96905b261ecSmrg return pCounter; 97005b261ecSmrg} 97105b261ecSmrg 9724202a189Smrgstatic int FreeCounter(void *, XID); 97305b261ecSmrg 97405b261ecSmrg/* 97505b261ecSmrg * ***** System Counter utilities 97605b261ecSmrg */ 97705b261ecSmrg 978f7df2e56SmrgSyncCounter* 979f7df2e56SmrgSyncCreateSystemCounter(const char *name, 980f7df2e56Smrg CARD64 initial, 981f7df2e56Smrg CARD64 resolution, 982f7df2e56Smrg SyncCounterType counterType, 983f7df2e56Smrg SyncSystemCounterQueryValue QueryValue, 984f7df2e56Smrg SyncSystemCounterBracketValues BracketValues 985f7df2e56Smrg ) 986f7df2e56Smrg{ 987f7df2e56Smrg SyncCounter *pCounter; 98805b261ecSmrg 98905b261ecSmrg /* this function may be called before SYNC has been initialized, so we 99005b261ecSmrg * have to make sure RTCounter is created. 99105b261ecSmrg */ 992f7df2e56Smrg if (RTCounter == 0) { 993f7df2e56Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 994f7df2e56Smrg if (RTCounter == 0) { 995f7df2e56Smrg return NULL; 996f7df2e56Smrg } 997f7df2e56Smrg xorg_list_init(&SysCounterList); 99805b261ecSmrg } 99905b261ecSmrg 10004202a189Smrg pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); 100105b261ecSmrg 1002f7df2e56Smrg if (pCounter) { 1003f7df2e56Smrg SysCounterInfo *psci; 1004f7df2e56Smrg 1005f7df2e56Smrg psci = malloc(sizeof(SysCounterInfo)); 1006f7df2e56Smrg if (!psci) { 1007f7df2e56Smrg FreeResource(pCounter->sync.id, RT_NONE); 1008f7df2e56Smrg return pCounter; 1009f7df2e56Smrg } 1010f7df2e56Smrg pCounter->pSysCounterInfo = psci; 1011f7df2e56Smrg psci->pCounter = pCounter; 1012f7df2e56Smrg psci->name = strdup(name); 1013f7df2e56Smrg psci->resolution = resolution; 1014f7df2e56Smrg psci->counterType = counterType; 1015f7df2e56Smrg psci->QueryValue = QueryValue; 1016f7df2e56Smrg psci->BracketValues = BracketValues; 1017f7df2e56Smrg psci->private = NULL; 1018f7df2e56Smrg XSyncMaxValue(&psci->bracket_greater); 1019f7df2e56Smrg XSyncMinValue(&psci->bracket_less); 1020f7df2e56Smrg xorg_list_add(&psci->entry, &SysCounterList); 102105b261ecSmrg } 10224202a189Smrg return pCounter; 102305b261ecSmrg} 102405b261ecSmrg 102505b261ecSmrgvoid 1026f7df2e56SmrgSyncDestroySystemCounter(void *pSysCounter) 102705b261ecSmrg{ 1028f7df2e56Smrg SyncCounter *pCounter = (SyncCounter *) pSysCounter; 1029f7df2e56Smrg 103065b04b38Smrg FreeResource(pCounter->sync.id, RT_NONE); 103105b261ecSmrg} 103205b261ecSmrg 103305b261ecSmrgstatic void 1034f7df2e56SmrgSyncComputeBracketValues(SyncCounter * pCounter) 103505b261ecSmrg{ 103605b261ecSmrg SyncTriggerList *pCur; 103705b261ecSmrg SyncTrigger *pTrigger; 103805b261ecSmrg SysCounterInfo *psci; 103905b261ecSmrg CARD64 *pnewgtval = NULL; 104005b261ecSmrg CARD64 *pnewltval = NULL; 104105b261ecSmrg SyncCounterType ct; 104205b261ecSmrg 104305b261ecSmrg if (!pCounter) 1044f7df2e56Smrg return; 104505b261ecSmrg 104605b261ecSmrg psci = pCounter->pSysCounterInfo; 104705b261ecSmrg ct = pCounter->pSysCounterInfo->counterType; 104805b261ecSmrg if (ct == XSyncCounterNeverChanges) 1049f7df2e56Smrg return; 105005b261ecSmrg 10514202a189Smrg XSyncMaxValue(&psci->bracket_greater); 10524202a189Smrg XSyncMinValue(&psci->bracket_less); 105305b261ecSmrg 1054f7df2e56Smrg for (pCur = pCounter->sync.pTriglist; pCur; pCur = pCur->next) { 1055f7df2e56Smrg pTrigger = pCur->pTrigger; 1056f7df2e56Smrg 105705b261ecSmrg if (pTrigger->test_type == XSyncPositiveComparison && 1058f7df2e56Smrg ct != XSyncCounterNeverIncreases) { 1059f7df2e56Smrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1060f7df2e56Smrg XSyncValueLessThan(pTrigger->test_value, 1061f7df2e56Smrg psci->bracket_greater)) { 1062f7df2e56Smrg psci->bracket_greater = pTrigger->test_value; 1063f7df2e56Smrg pnewgtval = &psci->bracket_greater; 1064f7df2e56Smrg } 1065f7df2e56Smrg else if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1066f7df2e56Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) { 1067f7df2e56Smrg psci->bracket_less = pTrigger->test_value; 1068f7df2e56Smrg pnewltval = &psci->bracket_less; 1069f7df2e56Smrg } 1070f7df2e56Smrg } 1071f7df2e56Smrg else if (pTrigger->test_type == XSyncNegativeComparison && 1072f7df2e56Smrg ct != XSyncCounterNeverDecreases) { 1073f7df2e56Smrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1074f7df2e56Smrg XSyncValueGreaterThan(pTrigger->test_value, 1075f7df2e56Smrg psci->bracket_less)) { 1076f7df2e56Smrg psci->bracket_less = pTrigger->test_value; 1077f7df2e56Smrg pnewltval = &psci->bracket_less; 1078f7df2e56Smrg } 1079f7df2e56Smrg else if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1080f7df2e56Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) { 1081f7df2e56Smrg psci->bracket_greater = pTrigger->test_value; 1082f7df2e56Smrg pnewgtval = &psci->bracket_greater; 1083f7df2e56Smrg } 1084f7df2e56Smrg } 1085f7df2e56Smrg else if (pTrigger->test_type == XSyncNegativeTransition && 1086f7df2e56Smrg ct != XSyncCounterNeverIncreases) { 1087f7df2e56Smrg if (XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value) && 1088f7df2e56Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) { 1089f7df2e56Smrg /* 1090f7df2e56Smrg * If the value is exactly equal to our threshold, we want one 1091f7df2e56Smrg * more event in the negative direction to ensure we pick up 1092f7df2e56Smrg * when the value is less than this threshold. 1093f7df2e56Smrg */ 1094f7df2e56Smrg psci->bracket_less = pTrigger->test_value; 1095f7df2e56Smrg pnewltval = &psci->bracket_less; 1096f7df2e56Smrg } 1097f7df2e56Smrg else if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1098f7df2e56Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) { 1099f7df2e56Smrg psci->bracket_greater = pTrigger->test_value; 1100f7df2e56Smrg pnewgtval = &psci->bracket_greater; 1101f7df2e56Smrg } 1102f7df2e56Smrg } 1103a0d10bb6Smrg else if (pTrigger->test_type == XSyncPositiveTransition && 1104f7df2e56Smrg ct != XSyncCounterNeverDecreases) { 1105f7df2e56Smrg if (XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value) && 1106f7df2e56Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) { 1107f7df2e56Smrg /* 1108f7df2e56Smrg * If the value is exactly equal to our threshold, we 1109f7df2e56Smrg * want one more event in the positive direction to 1110f7df2e56Smrg * ensure we pick up when the value *exceeds* this 1111f7df2e56Smrg * threshold. 1112f7df2e56Smrg */ 1113f7df2e56Smrg psci->bracket_greater = pTrigger->test_value; 1114f7df2e56Smrg pnewgtval = &psci->bracket_greater; 1115f7df2e56Smrg } 1116f7df2e56Smrg else if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1117f7df2e56Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) { 1118f7df2e56Smrg psci->bracket_less = pTrigger->test_value; 1119f7df2e56Smrg pnewltval = &psci->bracket_less; 1120f7df2e56Smrg } 1121f7df2e56Smrg } 1122f7df2e56Smrg } /* end for each trigger */ 1123f7df2e56Smrg 1124f7df2e56Smrg (*psci->BracketValues) ((void *) pCounter, pnewltval, pnewgtval); 1125f7df2e56Smrg 112605b261ecSmrg} 112705b261ecSmrg 112805b261ecSmrg/* 112905b261ecSmrg * ***** Resource delete functions 113005b261ecSmrg */ 113105b261ecSmrg 113205b261ecSmrg/* ARGSUSED */ 113305b261ecSmrgstatic int 11344202a189SmrgFreeAlarm(void *addr, XID id) 113505b261ecSmrg{ 1136f7df2e56Smrg SyncAlarm *pAlarm = (SyncAlarm *) addr; 113705b261ecSmrg 113805b261ecSmrg pAlarm->state = XSyncAlarmDestroyed; 113905b261ecSmrg 114005b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 114105b261ecSmrg 114205b261ecSmrg /* delete event selections */ 114305b261ecSmrg 114405b261ecSmrg while (pAlarm->pEventClients) 1145f7df2e56Smrg FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 114605b261ecSmrg 114765b04b38Smrg SyncDeleteTriggerFromSyncObject(&pAlarm->trigger); 114805b261ecSmrg 11494202a189Smrg free(pAlarm); 115005b261ecSmrg return Success; 115105b261ecSmrg} 115205b261ecSmrg 115305b261ecSmrg/* 115405b261ecSmrg * ** Cleanup after the destruction of a Counter 115505b261ecSmrg */ 115605b261ecSmrg/* ARGSUSED */ 115705b261ecSmrgstatic int 11584202a189SmrgFreeCounter(void *env, XID id) 115905b261ecSmrg{ 1160f7df2e56Smrg SyncCounter *pCounter = (SyncCounter *) env; 116105b261ecSmrg SyncTriggerList *ptl, *pnext; 116205b261ecSmrg 116365b04b38Smrg pCounter->sync.beingDestroyed = TRUE; 116405b261ecSmrg /* tell all the counter's triggers that the counter has been destroyed */ 1165f7df2e56Smrg for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) { 1166f7df2e56Smrg (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger); 1167f7df2e56Smrg pnext = ptl->next; 1168f7df2e56Smrg free(ptl); /* destroy the trigger list as we go */ 1169f7df2e56Smrg } 1170f7df2e56Smrg if (IsSystemCounter(pCounter)) { 1171f7df2e56Smrg xorg_list_del(&pCounter->pSysCounterInfo->entry); 1172f7df2e56Smrg free(pCounter->pSysCounterInfo->name); 1173f7df2e56Smrg free(pCounter->pSysCounterInfo->private); 1174f7df2e56Smrg free(pCounter->pSysCounterInfo); 117505b261ecSmrg } 11764202a189Smrg free(pCounter); 117705b261ecSmrg return Success; 117805b261ecSmrg} 117905b261ecSmrg 118005b261ecSmrg/* 118105b261ecSmrg * ** Cleanup after Await 118205b261ecSmrg */ 118305b261ecSmrg/* ARGSUSED */ 118405b261ecSmrgstatic int 11854202a189SmrgFreeAwait(void *addr, XID id) 118605b261ecSmrg{ 118705b261ecSmrg SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 118805b261ecSmrg SyncAwait *pAwait; 118905b261ecSmrg int numwaits; 119005b261ecSmrg 1191f7df2e56Smrg pAwait = &(pAwaitUnion + 1)->await; /* first await on list */ 119205b261ecSmrg 119305b261ecSmrg /* remove triggers from counters */ 119405b261ecSmrg 119505b261ecSmrg for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 1196f7df2e56Smrg numwaits--, pAwait++) { 1197f7df2e56Smrg /* If the counter is being destroyed, FreeCounter will delete 1198f7df2e56Smrg * the trigger list itself, so don't do it here. 1199f7df2e56Smrg */ 1200f7df2e56Smrg SyncObject *pSync = pAwait->trigger.pSync; 1201f7df2e56Smrg 1202f7df2e56Smrg if (pSync && !pSync->beingDestroyed) 1203f7df2e56Smrg SyncDeleteTriggerFromSyncObject(&pAwait->trigger); 120405b261ecSmrg } 12054202a189Smrg free(pAwaitUnion); 120605b261ecSmrg return Success; 120705b261ecSmrg} 120805b261ecSmrg 120905b261ecSmrg/* loosely based on dix/events.c/OtherClientGone */ 121005b261ecSmrgstatic int 12114202a189SmrgFreeAlarmClient(void *value, XID id) 121205b261ecSmrg{ 1213f7df2e56Smrg SyncAlarm *pAlarm = (SyncAlarm *) value; 121405b261ecSmrg SyncAlarmClientList *pCur, *pPrev; 121505b261ecSmrg 121605b261ecSmrg for (pPrev = NULL, pCur = pAlarm->pEventClients; 1217f7df2e56Smrg pCur; pPrev = pCur, pCur = pCur->next) { 1218f7df2e56Smrg if (pCur->delete_id == id) { 1219f7df2e56Smrg if (pPrev) 1220f7df2e56Smrg pPrev->next = pCur->next; 1221f7df2e56Smrg else 1222f7df2e56Smrg pAlarm->pEventClients = pCur->next; 1223f7df2e56Smrg free(pCur); 1224f7df2e56Smrg return Success; 1225f7df2e56Smrg } 122605b261ecSmrg } 122705b261ecSmrg FatalError("alarm client not on event list"); 1228f7df2e56Smrg /*NOTREACHED*/} 122905b261ecSmrg 123005b261ecSmrg/* 123105b261ecSmrg * ***** Proc functions 123205b261ecSmrg */ 123305b261ecSmrg 123405b261ecSmrg/* 123505b261ecSmrg * ** Initialize the extension 123605b261ecSmrg */ 12374202a189Smrgstatic int 12384202a189SmrgProcSyncInitialize(ClientPtr client) 123905b261ecSmrg{ 1240f7df2e56Smrg xSyncInitializeReply rep = { 1241f7df2e56Smrg .type = X_Reply, 1242f7df2e56Smrg .sequenceNumber = client->sequence, 1243f7df2e56Smrg .length = 0, 1244f7df2e56Smrg .majorVersion = SERVER_SYNC_MAJOR_VERSION, 1245f7df2e56Smrg .minorVersion = SERVER_SYNC_MINOR_VERSION, 1246f7df2e56Smrg }; 124705b261ecSmrg 124805b261ecSmrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 124905b261ecSmrg 1250f7df2e56Smrg if (client->swapped) { 1251f7df2e56Smrg swaps(&rep.sequenceNumber); 125205b261ecSmrg } 1253f7df2e56Smrg WriteToClient(client, sizeof(rep), &rep); 12544202a189Smrg return Success; 125505b261ecSmrg} 125605b261ecSmrg 125705b261ecSmrg/* 125805b261ecSmrg * ** Get list of system counters available through the extension 125905b261ecSmrg */ 12604202a189Smrgstatic int 12614202a189SmrgProcSyncListSystemCounters(ClientPtr client) 126205b261ecSmrg{ 1263f7df2e56Smrg xSyncListSystemCountersReply rep = { 1264f7df2e56Smrg .type = X_Reply, 1265f7df2e56Smrg .sequenceNumber = client->sequence, 1266f7df2e56Smrg .nCounters = 0, 1267f7df2e56Smrg }; 1268f7df2e56Smrg SysCounterInfo *psci; 1269f7df2e56Smrg int len = 0; 127005b261ecSmrg xSyncSystemCounter *list = NULL, *walklist = NULL; 12714202a189Smrg 127205b261ecSmrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 127305b261ecSmrg 1274f7df2e56Smrg xorg_list_for_each_entry(psci, &SysCounterList, entry) { 1275f7df2e56Smrg /* pad to 4 byte boundary */ 1276f7df2e56Smrg len += pad_to_int32(sz_xSyncSystemCounter + strlen(psci->name)); 1277f7df2e56Smrg ++rep.nCounters; 127805b261ecSmrg } 127905b261ecSmrg 1280f7df2e56Smrg if (len) { 1281f7df2e56Smrg walklist = list = malloc(len); 1282f7df2e56Smrg if (!list) 1283f7df2e56Smrg return BadAlloc; 128405b261ecSmrg } 128505b261ecSmrg 12864202a189Smrg rep.length = bytes_to_int32(len); 128705b261ecSmrg 1288f7df2e56Smrg if (client->swapped) { 1289f7df2e56Smrg swaps(&rep.sequenceNumber); 1290f7df2e56Smrg swapl(&rep.length); 1291f7df2e56Smrg swapl(&rep.nCounters); 129205b261ecSmrg } 129305b261ecSmrg 1294f7df2e56Smrg xorg_list_for_each_entry(psci, &SysCounterList, entry) { 1295f7df2e56Smrg int namelen; 1296f7df2e56Smrg char *pname_in_reply; 129705b261ecSmrg 1298f7df2e56Smrg walklist->counter = psci->pCounter->sync.id; 1299f7df2e56Smrg walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 1300f7df2e56Smrg walklist->resolution_lo = XSyncValueLow32(psci->resolution); 1301f7df2e56Smrg namelen = strlen(psci->name); 1302f7df2e56Smrg walklist->name_length = namelen; 130305b261ecSmrg 1304f7df2e56Smrg if (client->swapped) { 1305f7df2e56Smrg swapl(&walklist->counter); 1306f7df2e56Smrg swapl(&walklist->resolution_hi); 1307f7df2e56Smrg swapl(&walklist->resolution_lo); 1308f7df2e56Smrg swaps(&walklist->name_length); 1309f7df2e56Smrg } 131005b261ecSmrg 1311f7df2e56Smrg pname_in_reply = ((char *) walklist) + sz_xSyncSystemCounter; 1312f7df2e56Smrg strncpy(pname_in_reply, psci->name, namelen); 1313f7df2e56Smrg walklist = (xSyncSystemCounter *) (((char *) walklist) + 1314f7df2e56Smrg pad_to_int32(sz_xSyncSystemCounter + 1315f7df2e56Smrg namelen)); 131605b261ecSmrg } 131705b261ecSmrg 1318f7df2e56Smrg WriteToClient(client, sizeof(rep), &rep); 1319f7df2e56Smrg if (len) { 1320f7df2e56Smrg WriteToClient(client, len, list); 1321f7df2e56Smrg free(list); 132205b261ecSmrg } 132305b261ecSmrg 13244202a189Smrg return Success; 132505b261ecSmrg} 132605b261ecSmrg 132705b261ecSmrg/* 132805b261ecSmrg * ** Set client Priority 132905b261ecSmrg */ 13304202a189Smrgstatic int 13314202a189SmrgProcSyncSetPriority(ClientPtr client) 133205b261ecSmrg{ 133305b261ecSmrg REQUEST(xSyncSetPriorityReq); 133405b261ecSmrg ClientPtr priorityclient; 133505b261ecSmrg int rc; 133605b261ecSmrg 133705b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 133805b261ecSmrg 133905b261ecSmrg if (stuff->id == None) 1340f7df2e56Smrg priorityclient = client; 134105b261ecSmrg else { 1342f7df2e56Smrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1343f7df2e56Smrg DixSetAttrAccess); 1344f7df2e56Smrg if (rc != Success) 1345f7df2e56Smrg return rc; 134605b261ecSmrg } 134705b261ecSmrg 1348f7df2e56Smrg if (priorityclient->priority != stuff->priority) { 1349f7df2e56Smrg priorityclient->priority = stuff->priority; 135005b261ecSmrg 1351f7df2e56Smrg /* The following will force the server back into WaitForSomething 1352f7df2e56Smrg * so that the change in this client's priority is immediately 1353f7df2e56Smrg * reflected. 1354f7df2e56Smrg */ 1355f7df2e56Smrg isItTimeToYield = TRUE; 1356f7df2e56Smrg dispatchException |= DE_PRIORITYCHANGE; 135705b261ecSmrg } 135805b261ecSmrg return Success; 135905b261ecSmrg} 136005b261ecSmrg 136105b261ecSmrg/* 136205b261ecSmrg * ** Get client Priority 136305b261ecSmrg */ 13644202a189Smrgstatic int 13654202a189SmrgProcSyncGetPriority(ClientPtr client) 136605b261ecSmrg{ 136705b261ecSmrg REQUEST(xSyncGetPriorityReq); 136805b261ecSmrg xSyncGetPriorityReply rep; 136905b261ecSmrg ClientPtr priorityclient; 137005b261ecSmrg int rc; 137105b261ecSmrg 137205b261ecSmrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 137305b261ecSmrg 137405b261ecSmrg if (stuff->id == None) 1375f7df2e56Smrg priorityclient = client; 137605b261ecSmrg else { 1377f7df2e56Smrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1378f7df2e56Smrg DixGetAttrAccess); 1379f7df2e56Smrg if (rc != Success) 1380f7df2e56Smrg return rc; 138105b261ecSmrg } 138205b261ecSmrg 1383f7df2e56Smrg rep = (xSyncGetPriorityReply) { 1384f7df2e56Smrg .type = X_Reply, 1385f7df2e56Smrg .sequenceNumber = client->sequence, 1386f7df2e56Smrg .length = 0, 1387f7df2e56Smrg .priority = priorityclient->priority 1388f7df2e56Smrg }; 138905b261ecSmrg 1390f7df2e56Smrg if (client->swapped) { 1391f7df2e56Smrg swaps(&rep.sequenceNumber); 1392f7df2e56Smrg swapl(&rep.priority); 139305b261ecSmrg } 139405b261ecSmrg 1395f7df2e56Smrg WriteToClient(client, sizeof(xSyncGetPriorityReply), &rep); 139605b261ecSmrg 13974202a189Smrg return Success; 139805b261ecSmrg} 139905b261ecSmrg 140005b261ecSmrg/* 140105b261ecSmrg * ** Create a new counter 140205b261ecSmrg */ 14034202a189Smrgstatic int 14044202a189SmrgProcSyncCreateCounter(ClientPtr client) 140505b261ecSmrg{ 140605b261ecSmrg REQUEST(xSyncCreateCounterReq); 1407f7df2e56Smrg CARD64 initial; 140805b261ecSmrg 140905b261ecSmrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 141005b261ecSmrg 141105b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 141205b261ecSmrg 1413f7df2e56Smrg XSyncIntsToValue(&initial, stuff->initial_value_lo, 1414f7df2e56Smrg stuff->initial_value_hi); 141505b261ecSmrg if (!SyncCreateCounter(client, stuff->cid, initial)) 1416f7df2e56Smrg return BadAlloc; 141705b261ecSmrg 14184202a189Smrg return Success; 141905b261ecSmrg} 142005b261ecSmrg 142105b261ecSmrg/* 142205b261ecSmrg * ** Set Counter value 142305b261ecSmrg */ 14244202a189Smrgstatic int 14254202a189SmrgProcSyncSetCounter(ClientPtr client) 142605b261ecSmrg{ 142705b261ecSmrg REQUEST(xSyncSetCounterReq); 1428f7df2e56Smrg SyncCounter *pCounter; 1429f7df2e56Smrg CARD64 newvalue; 1430f7df2e56Smrg int rc; 143105b261ecSmrg 143205b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 143305b261ecSmrg 1434f7df2e56Smrg rc = dixLookupResourceByType((void **) &pCounter, stuff->cid, RTCounter, 1435f7df2e56Smrg client, DixWriteAccess); 14364202a189Smrg if (rc != Success) 1437f7df2e56Smrg return rc; 143805b261ecSmrg 1439f7df2e56Smrg if (IsSystemCounter(pCounter)) { 1440f7df2e56Smrg client->errorValue = stuff->cid; 1441f7df2e56Smrg return BadAccess; 144205b261ecSmrg } 144305b261ecSmrg 144405b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 144505b261ecSmrg SyncChangeCounter(pCounter, newvalue); 144605b261ecSmrg return Success; 144705b261ecSmrg} 144805b261ecSmrg 144905b261ecSmrg/* 145005b261ecSmrg * ** Change Counter value 145105b261ecSmrg */ 14524202a189Smrgstatic int 14534202a189SmrgProcSyncChangeCounter(ClientPtr client) 145405b261ecSmrg{ 145505b261ecSmrg REQUEST(xSyncChangeCounterReq); 1456f7df2e56Smrg SyncCounter *pCounter; 1457f7df2e56Smrg CARD64 newvalue; 1458f7df2e56Smrg Bool overflow; 1459f7df2e56Smrg int rc; 146005b261ecSmrg 146105b261ecSmrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 146205b261ecSmrg 1463f7df2e56Smrg rc = dixLookupResourceByType((void **) &pCounter, stuff->cid, RTCounter, 1464f7df2e56Smrg client, DixWriteAccess); 14654202a189Smrg if (rc != Success) 1466f7df2e56Smrg return rc; 146705b261ecSmrg 1468f7df2e56Smrg if (IsSystemCounter(pCounter)) { 1469f7df2e56Smrg client->errorValue = stuff->cid; 1470f7df2e56Smrg return BadAccess; 147105b261ecSmrg } 147205b261ecSmrg 147305b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 147405b261ecSmrg XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 1475f7df2e56Smrg if (overflow) { 1476f7df2e56Smrg /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 1477f7df2e56Smrg client->errorValue = stuff->value_hi; 1478f7df2e56Smrg return BadValue; 147905b261ecSmrg } 148005b261ecSmrg SyncChangeCounter(pCounter, newvalue); 148105b261ecSmrg return Success; 148205b261ecSmrg} 148305b261ecSmrg 148405b261ecSmrg/* 148505b261ecSmrg * ** Destroy a counter 148605b261ecSmrg */ 14874202a189Smrgstatic int 14884202a189SmrgProcSyncDestroyCounter(ClientPtr client) 148905b261ecSmrg{ 149005b261ecSmrg REQUEST(xSyncDestroyCounterReq); 1491f7df2e56Smrg SyncCounter *pCounter; 14924202a189Smrg int rc; 149305b261ecSmrg 149405b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 149505b261ecSmrg 1496f7df2e56Smrg rc = dixLookupResourceByType((void **) &pCounter, stuff->counter, 1497f7df2e56Smrg RTCounter, client, DixDestroyAccess); 14984202a189Smrg if (rc != Success) 1499f7df2e56Smrg return rc; 15004202a189Smrg 1501f7df2e56Smrg if (IsSystemCounter(pCounter)) { 1502f7df2e56Smrg client->errorValue = stuff->counter; 1503f7df2e56Smrg return BadAccess; 150405b261ecSmrg } 150565b04b38Smrg FreeResource(pCounter->sync.id, RT_NONE); 150605b261ecSmrg return Success; 150705b261ecSmrg} 150805b261ecSmrg 1509f7df2e56Smrgstatic SyncAwaitUnion * 151065b04b38SmrgSyncAwaitPrologue(ClientPtr client, int items) 151165b04b38Smrg{ 151265b04b38Smrg SyncAwaitUnion *pAwaitUnion; 151365b04b38Smrg 151465b04b38Smrg /* all the memory for the entire await list is allocated 151565b04b38Smrg * here in one chunk 151665b04b38Smrg */ 1517f7df2e56Smrg pAwaitUnion = xallocarray(items + 1, sizeof(SyncAwaitUnion)); 151865b04b38Smrg if (!pAwaitUnion) 1519f7df2e56Smrg return NULL; 152065b04b38Smrg 152165b04b38Smrg /* first item is the header, remainder are real wait conditions */ 152265b04b38Smrg 152365b04b38Smrg pAwaitUnion->header.delete_id = FakeClientID(client->index); 152465b04b38Smrg pAwaitUnion->header.client = client; 152565b04b38Smrg pAwaitUnion->header.num_waitconditions = 0; 152665b04b38Smrg 152765b04b38Smrg if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 1528f7df2e56Smrg return NULL; 152965b04b38Smrg 153065b04b38Smrg return pAwaitUnion; 153165b04b38Smrg} 153265b04b38Smrg 153365b04b38Smrgstatic void 1534f7df2e56SmrgSyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion * pAwaitUnion) 153565b04b38Smrg{ 153665b04b38Smrg SyncAwait *pAwait; 153765b04b38Smrg int i; 153865b04b38Smrg 153965b04b38Smrg IgnoreClient(client); 154065b04b38Smrg 154165b04b38Smrg /* see if any of the triggers are already true */ 154265b04b38Smrg 1543f7df2e56Smrg pAwait = &(pAwaitUnion + 1)->await; /* skip over header */ 1544f7df2e56Smrg for (i = 0; i < items; i++, pAwait++) { 1545f7df2e56Smrg CARD64 value; 1546f7df2e56Smrg 1547f7df2e56Smrg /* don't have to worry about NULL counters because the request 1548f7df2e56Smrg * errors before we get here out if they occur 1549f7df2e56Smrg */ 1550f7df2e56Smrg switch (pAwait->trigger.pSync->type) { 1551f7df2e56Smrg case SYNC_COUNTER: 1552f7df2e56Smrg value = ((SyncCounter *) pAwait->trigger.pSync)->value; 1553f7df2e56Smrg break; 1554f7df2e56Smrg default: 1555f7df2e56Smrg XSyncIntToValue(&value, 0); 1556f7df2e56Smrg } 155765b04b38Smrg 1558f7df2e56Smrg if ((*pAwait->trigger.CheckTrigger) (&pAwait->trigger, value)) { 1559f7df2e56Smrg (*pAwait->trigger.TriggerFired) (&pAwait->trigger); 1560f7df2e56Smrg break; /* once is enough */ 1561f7df2e56Smrg } 156265b04b38Smrg } 156365b04b38Smrg} 156405b261ecSmrg 156505b261ecSmrg/* 156605b261ecSmrg * ** Await 156705b261ecSmrg */ 15684202a189Smrgstatic int 15694202a189SmrgProcSyncAwait(ClientPtr client) 157005b261ecSmrg{ 157105b261ecSmrg REQUEST(xSyncAwaitReq); 1572f7df2e56Smrg int len, items; 1573f7df2e56Smrg int i; 157405b261ecSmrg xSyncWaitCondition *pProtocolWaitConds; 157505b261ecSmrg SyncAwaitUnion *pAwaitUnion; 1576f7df2e56Smrg SyncAwait *pAwait; 1577f7df2e56Smrg int status; 157805b261ecSmrg 157905b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 158005b261ecSmrg 158105b261ecSmrg len = client->req_len << 2; 158205b261ecSmrg len -= sz_xSyncAwaitReq; 158305b261ecSmrg items = len / sz_xSyncWaitCondition; 158405b261ecSmrg 1585f7df2e56Smrg if (items * sz_xSyncWaitCondition != len) { 1586f7df2e56Smrg return BadLength; 158705b261ecSmrg } 1588f7df2e56Smrg if (items == 0) { 1589f7df2e56Smrg client->errorValue = items; /* XXX protocol change */ 1590f7df2e56Smrg return BadValue; 159105b261ecSmrg } 159205b261ecSmrg 159365b04b38Smrg if (!(pAwaitUnion = SyncAwaitPrologue(client, items))) 1594f7df2e56Smrg return BadAlloc; 159505b261ecSmrg 159605b261ecSmrg /* don't need to do any more memory allocation for this request! */ 159705b261ecSmrg 1598f7df2e56Smrg pProtocolWaitConds = (xSyncWaitCondition *) &stuff[1]; 1599f7df2e56Smrg 1600f7df2e56Smrg pAwait = &(pAwaitUnion + 1)->await; /* skip over header */ 1601f7df2e56Smrg for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) { 1602f7df2e56Smrg if (pProtocolWaitConds->counter == None) { /* XXX protocol change */ 1603f7df2e56Smrg /* this should take care of removing any triggers created by 1604f7df2e56Smrg * this request that have already been registered on sync objects 1605f7df2e56Smrg */ 1606f7df2e56Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 1607f7df2e56Smrg client->errorValue = pProtocolWaitConds->counter; 1608f7df2e56Smrg return SyncErrorBase + XSyncBadCounter; 1609f7df2e56Smrg } 1610f7df2e56Smrg 1611f7df2e56Smrg /* sanity checks are in SyncInitTrigger */ 1612f7df2e56Smrg pAwait->trigger.pSync = NULL; 1613f7df2e56Smrg pAwait->trigger.value_type = pProtocolWaitConds->value_type; 1614f7df2e56Smrg XSyncIntsToValue(&pAwait->trigger.wait_value, 1615f7df2e56Smrg pProtocolWaitConds->wait_value_lo, 1616f7df2e56Smrg pProtocolWaitConds->wait_value_hi); 1617f7df2e56Smrg pAwait->trigger.test_type = pProtocolWaitConds->test_type; 1618f7df2e56Smrg 1619f7df2e56Smrg status = SyncInitTrigger(client, &pAwait->trigger, 1620f7df2e56Smrg pProtocolWaitConds->counter, RTCounter, 1621f7df2e56Smrg XSyncCAAllTrigger); 1622f7df2e56Smrg if (status != Success) { 1623f7df2e56Smrg /* this should take care of removing any triggers created by 1624f7df2e56Smrg * this request that have already been registered on sync objects 1625f7df2e56Smrg */ 1626f7df2e56Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 1627f7df2e56Smrg return status; 1628f7df2e56Smrg } 1629f7df2e56Smrg /* this is not a mistake -- same function works for both cases */ 1630f7df2e56Smrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 1631f7df2e56Smrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 1632f7df2e56Smrg XSyncIntsToValue(&pAwait->event_threshold, 1633f7df2e56Smrg pProtocolWaitConds->event_threshold_lo, 1634f7df2e56Smrg pProtocolWaitConds->event_threshold_hi); 1635f7df2e56Smrg pAwait->pHeader = &pAwaitUnion->header; 1636f7df2e56Smrg pAwaitUnion->header.num_waitconditions++; 163705b261ecSmrg } 163805b261ecSmrg 163965b04b38Smrg SyncAwaitEpilogue(client, items, pAwaitUnion); 164005b261ecSmrg 164105b261ecSmrg return Success; 164205b261ecSmrg} 164305b261ecSmrg 164405b261ecSmrg/* 164505b261ecSmrg * ** Query a counter 164605b261ecSmrg */ 16474202a189Smrgstatic int 16484202a189SmrgProcSyncQueryCounter(ClientPtr client) 164905b261ecSmrg{ 165005b261ecSmrg REQUEST(xSyncQueryCounterReq); 165105b261ecSmrg xSyncQueryCounterReply rep; 1652f7df2e56Smrg SyncCounter *pCounter; 16534202a189Smrg int rc; 165405b261ecSmrg 165505b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 165605b261ecSmrg 1657f7df2e56Smrg rc = dixLookupResourceByType((void **) &pCounter, stuff->counter, 1658f7df2e56Smrg RTCounter, client, DixReadAccess); 16594202a189Smrg if (rc != Success) 1660f7df2e56Smrg return rc; 166105b261ecSmrg 166205b261ecSmrg /* if system counter, ask it what the current value is */ 1663f7df2e56Smrg if (IsSystemCounter(pCounter)) { 1664f7df2e56Smrg (*pCounter->pSysCounterInfo->QueryValue) ((void *) pCounter, 1665f7df2e56Smrg &pCounter->value); 1666f7df2e56Smrg } 1667f7df2e56Smrg 1668f7df2e56Smrg rep = (xSyncQueryCounterReply) { 1669f7df2e56Smrg .type = X_Reply, 1670f7df2e56Smrg .sequenceNumber = client->sequence, 1671f7df2e56Smrg .length = 0, 1672f7df2e56Smrg .value_hi = XSyncValueHigh32(pCounter->value), 1673f7df2e56Smrg .value_lo = XSyncValueLow32(pCounter->value) 1674f7df2e56Smrg }; 1675f7df2e56Smrg 1676f7df2e56Smrg if (client->swapped) { 1677f7df2e56Smrg swaps(&rep.sequenceNumber); 1678f7df2e56Smrg swapl(&rep.length); 1679f7df2e56Smrg swapl(&rep.value_hi); 1680f7df2e56Smrg swapl(&rep.value_lo); 1681f7df2e56Smrg } 1682f7df2e56Smrg WriteToClient(client, sizeof(xSyncQueryCounterReply), &rep); 16834202a189Smrg return Success; 168405b261ecSmrg} 168505b261ecSmrg 168605b261ecSmrg/* 168705b261ecSmrg * ** Create Alarm 168805b261ecSmrg */ 16894202a189Smrgstatic int 16904202a189SmrgProcSyncCreateAlarm(ClientPtr client) 169105b261ecSmrg{ 169205b261ecSmrg REQUEST(xSyncCreateAlarmReq); 1693f7df2e56Smrg SyncAlarm *pAlarm; 1694f7df2e56Smrg int status; 1695f7df2e56Smrg unsigned long len, vmask; 1696f7df2e56Smrg SyncTrigger *pTrigger; 169705b261ecSmrg 169805b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 169905b261ecSmrg 170005b261ecSmrg LEGAL_NEW_RESOURCE(stuff->id, client); 170105b261ecSmrg 170205b261ecSmrg vmask = stuff->valueMask; 17034202a189Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); 170405b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 1705f7df2e56Smrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta)))) 1706f7df2e56Smrg return BadLength; 170705b261ecSmrg 1708f7df2e56Smrg if (!(pAlarm = malloc(sizeof(SyncAlarm)))) { 1709f7df2e56Smrg return BadAlloc; 171005b261ecSmrg } 171105b261ecSmrg 171205b261ecSmrg /* set up defaults */ 171305b261ecSmrg 171405b261ecSmrg pTrigger = &pAlarm->trigger; 171565b04b38Smrg pTrigger->pSync = NULL; 171605b261ecSmrg pTrigger->value_type = XSyncAbsolute; 171705b261ecSmrg XSyncIntToValue(&pTrigger->wait_value, 0L); 171805b261ecSmrg pTrigger->test_type = XSyncPositiveComparison; 171905b261ecSmrg pTrigger->TriggerFired = SyncAlarmTriggerFired; 172005b261ecSmrg pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 172165b04b38Smrg status = SyncInitTrigger(client, pTrigger, None, RTCounter, 1722f7df2e56Smrg XSyncCAAllTrigger); 1723f7df2e56Smrg if (status != Success) { 1724f7df2e56Smrg free(pAlarm); 1725f7df2e56Smrg return status; 172605b261ecSmrg } 172705b261ecSmrg 172805b261ecSmrg pAlarm->client = client; 172905b261ecSmrg pAlarm->alarm_id = stuff->id; 173005b261ecSmrg XSyncIntToValue(&pAlarm->delta, 1L); 173105b261ecSmrg pAlarm->events = TRUE; 173205b261ecSmrg pAlarm->state = XSyncAlarmInactive; 173305b261ecSmrg pAlarm->pEventClients = NULL; 173405b261ecSmrg status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 1735f7df2e56Smrg (CARD32 *) &stuff[1]); 1736f7df2e56Smrg if (status != Success) { 1737f7df2e56Smrg free(pAlarm); 1738f7df2e56Smrg return status; 173905b261ecSmrg } 174005b261ecSmrg 174105b261ecSmrg if (!AddResource(stuff->id, RTAlarm, pAlarm)) 1742f7df2e56Smrg return BadAlloc; 174305b261ecSmrg 174405b261ecSmrg /* see if alarm already triggered. NULL counter will not trigger 174505b261ecSmrg * in CreateAlarm and sets alarm state to Inactive. 174605b261ecSmrg */ 174705b261ecSmrg 1748f7df2e56Smrg if (!pTrigger->pSync) { 1749f7df2e56Smrg pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 175005b261ecSmrg } 1751f7df2e56Smrg else { 1752f7df2e56Smrg SyncCounter *pCounter; 175365b04b38Smrg 1754f7df2e56Smrg if (!SyncCheckWarnIsCounter(pTrigger->pSync, 1755f7df2e56Smrg WARN_INVALID_COUNTER_ALARM)) { 1756f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 1757f7df2e56Smrg return BadAlloc; 1758f7df2e56Smrg } 175965b04b38Smrg 1760f7df2e56Smrg pCounter = (SyncCounter *) pTrigger->pSync; 176165b04b38Smrg 1762f7df2e56Smrg if ((*pTrigger->CheckTrigger) (pTrigger, pCounter->value)) 1763f7df2e56Smrg (*pTrigger->TriggerFired) (pTrigger); 176405b261ecSmrg } 176505b261ecSmrg 176605b261ecSmrg return Success; 176705b261ecSmrg} 176805b261ecSmrg 176905b261ecSmrg/* 177005b261ecSmrg * ** Change Alarm 177105b261ecSmrg */ 17724202a189Smrgstatic int 17734202a189SmrgProcSyncChangeAlarm(ClientPtr client) 177405b261ecSmrg{ 177505b261ecSmrg REQUEST(xSyncChangeAlarmReq); 1776f7df2e56Smrg SyncAlarm *pAlarm; 177765b04b38Smrg SyncCounter *pCounter = NULL; 1778f7df2e56Smrg long vmask; 1779f7df2e56Smrg int len, status; 178005b261ecSmrg 178105b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 178205b261ecSmrg 1783f7df2e56Smrg status = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm, 1784f7df2e56Smrg client, DixWriteAccess); 17854202a189Smrg if (status != Success) 1786f7df2e56Smrg return status; 178705b261ecSmrg 178805b261ecSmrg vmask = stuff->valueMask; 17894202a189Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); 179005b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 1791f7df2e56Smrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta)))) 1792f7df2e56Smrg return BadLength; 179305b261ecSmrg 17944202a189Smrg if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 1795f7df2e56Smrg (CARD32 *) &stuff[1])) != Success) 1796f7df2e56Smrg return status; 179705b261ecSmrg 179865b04b38Smrg if (SyncCheckWarnIsCounter(pAlarm->trigger.pSync, 1799f7df2e56Smrg WARN_INVALID_COUNTER_ALARM)) 1800f7df2e56Smrg pCounter = (SyncCounter *) pAlarm->trigger.pSync; 180165b04b38Smrg 180205b261ecSmrg /* see if alarm already triggered. NULL counter WILL trigger 180305b261ecSmrg * in ChangeAlarm. 180405b261ecSmrg */ 180505b261ecSmrg 180665b04b38Smrg if (!pCounter || 1807f7df2e56Smrg (*pAlarm->trigger.CheckTrigger) (&pAlarm->trigger, pCounter->value)) { 1808f7df2e56Smrg (*pAlarm->trigger.TriggerFired) (&pAlarm->trigger); 180905b261ecSmrg } 181005b261ecSmrg return Success; 181105b261ecSmrg} 181205b261ecSmrg 18134202a189Smrgstatic int 18144202a189SmrgProcSyncQueryAlarm(ClientPtr client) 181505b261ecSmrg{ 181605b261ecSmrg REQUEST(xSyncQueryAlarmReq); 1817f7df2e56Smrg SyncAlarm *pAlarm; 181805b261ecSmrg xSyncQueryAlarmReply rep; 1819f7df2e56Smrg SyncTrigger *pTrigger; 18204202a189Smrg int rc; 182105b261ecSmrg 182205b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 182305b261ecSmrg 1824f7df2e56Smrg rc = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm, 1825f7df2e56Smrg client, DixReadAccess); 18264202a189Smrg if (rc != Success) 1827f7df2e56Smrg return rc; 182805b261ecSmrg 182905b261ecSmrg pTrigger = &pAlarm->trigger; 1830f7df2e56Smrg rep = (xSyncQueryAlarmReply) { 1831f7df2e56Smrg .type = X_Reply, 1832f7df2e56Smrg .sequenceNumber = client->sequence, 1833f7df2e56Smrg .length = 1834f7df2e56Smrg bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)), 1835f7df2e56Smrg .counter = (pTrigger->pSync) ? pTrigger->pSync->id : None, 1836f7df2e56Smrg 1837f7df2e56Smrg#if 0 /* XXX unclear what to do, depends on whether relative value-types 1838f7df2e56Smrg * are "consumed" immediately and are considered absolute from then 1839f7df2e56Smrg * on. 1840f7df2e56Smrg */ 1841f7df2e56Smrg .value_type = pTrigger->value_type, 1842f7df2e56Smrg .wait_value_hi = XSyncValueHigh32(pTrigger->wait_value), 1843f7df2e56Smrg .wait_value_lo = XSyncValueLow32(pTrigger->wait_value), 184405b261ecSmrg#else 1845f7df2e56Smrg .value_type = XSyncAbsolute, 1846f7df2e56Smrg .wait_value_hi = XSyncValueHigh32(pTrigger->test_value), 1847f7df2e56Smrg .wait_value_lo = XSyncValueLow32(pTrigger->test_value), 184805b261ecSmrg#endif 184905b261ecSmrg 1850f7df2e56Smrg .test_type = pTrigger->test_type, 1851f7df2e56Smrg .delta_hi = XSyncValueHigh32(pAlarm->delta), 1852f7df2e56Smrg .delta_lo = XSyncValueLow32(pAlarm->delta), 1853f7df2e56Smrg .events = pAlarm->events, 1854f7df2e56Smrg .state = pAlarm->state 1855f7df2e56Smrg }; 1856f7df2e56Smrg 1857f7df2e56Smrg if (client->swapped) { 1858f7df2e56Smrg swaps(&rep.sequenceNumber); 1859f7df2e56Smrg swapl(&rep.length); 1860f7df2e56Smrg swapl(&rep.counter); 1861f7df2e56Smrg swapl(&rep.wait_value_hi); 1862f7df2e56Smrg swapl(&rep.wait_value_lo); 1863f7df2e56Smrg swapl(&rep.test_type); 1864f7df2e56Smrg swapl(&rep.delta_hi); 1865f7df2e56Smrg swapl(&rep.delta_lo); 1866f7df2e56Smrg } 1867f7df2e56Smrg 1868f7df2e56Smrg WriteToClient(client, sizeof(xSyncQueryAlarmReply), &rep); 18694202a189Smrg return Success; 187005b261ecSmrg} 187105b261ecSmrg 18724202a189Smrgstatic int 18734202a189SmrgProcSyncDestroyAlarm(ClientPtr client) 187405b261ecSmrg{ 18754202a189Smrg SyncAlarm *pAlarm; 18764202a189Smrg int rc; 1877f7df2e56Smrg 187805b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 187905b261ecSmrg 188005b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 188105b261ecSmrg 1882f7df2e56Smrg rc = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm, 1883f7df2e56Smrg client, DixDestroyAccess); 18844202a189Smrg if (rc != Success) 1885f7df2e56Smrg return rc; 188605b261ecSmrg 188705b261ecSmrg FreeResource(stuff->alarm, RT_NONE); 18884202a189Smrg return Success; 188905b261ecSmrg} 189005b261ecSmrg 189165b04b38Smrgstatic int 189265b04b38SmrgProcSyncCreateFence(ClientPtr client) 189365b04b38Smrg{ 189465b04b38Smrg REQUEST(xSyncCreateFenceReq); 189565b04b38Smrg DrawablePtr pDraw; 189665b04b38Smrg SyncFence *pFence; 189765b04b38Smrg int rc; 189865b04b38Smrg 189965b04b38Smrg REQUEST_SIZE_MATCH(xSyncCreateFenceReq); 190065b04b38Smrg 190165b04b38Smrg rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess); 190265b04b38Smrg if (rc != Success) 1903f7df2e56Smrg return rc; 190465b04b38Smrg 190565b04b38Smrg LEGAL_NEW_RESOURCE(stuff->fid, client); 190665b04b38Smrg 1907f7df2e56Smrg if (!(pFence = (SyncFence *) SyncCreate(client, stuff->fid, SYNC_FENCE))) 1908f7df2e56Smrg return BadAlloc; 190965b04b38Smrg 191065b04b38Smrg miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered); 191165b04b38Smrg 1912f7df2e56Smrg if (!AddResource(stuff->fid, RTFence, (void *) pFence)) 1913f7df2e56Smrg return BadAlloc; 191465b04b38Smrg 191565b04b38Smrg return client->noClientException; 191665b04b38Smrg} 191765b04b38Smrg 191865b04b38Smrgstatic int 191965b04b38SmrgFreeFence(void *obj, XID id) 192065b04b38Smrg{ 192165b04b38Smrg SyncFence *pFence = (SyncFence *) obj; 192265b04b38Smrg 192365b04b38Smrg miSyncDestroyFence(pFence); 192465b04b38Smrg 192565b04b38Smrg return Success; 192665b04b38Smrg} 192765b04b38Smrg 1928f7df2e56Smrgint 1929f7df2e56SmrgSyncVerifyFence(SyncFence ** ppSyncFence, XID fid, ClientPtr client, Mask mode) 193065b04b38Smrg{ 1931f7df2e56Smrg int rc = dixLookupResourceByType((void **) ppSyncFence, fid, RTFence, 1932f7df2e56Smrg client, mode); 193365b04b38Smrg 193465b04b38Smrg if (rc != Success) 1935f7df2e56Smrg client->errorValue = fid; 193665b04b38Smrg 193765b04b38Smrg return rc; 193865b04b38Smrg} 193965b04b38Smrg 194065b04b38Smrgstatic int 194165b04b38SmrgProcSyncTriggerFence(ClientPtr client) 194265b04b38Smrg{ 194365b04b38Smrg REQUEST(xSyncTriggerFenceReq); 194465b04b38Smrg SyncFence *pFence; 194565b04b38Smrg int rc; 194665b04b38Smrg 194765b04b38Smrg REQUEST_SIZE_MATCH(xSyncTriggerFenceReq); 194865b04b38Smrg 1949f7df2e56Smrg rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence, 1950f7df2e56Smrg client, DixWriteAccess); 195165b04b38Smrg if (rc != Success) 1952f7df2e56Smrg return rc; 195365b04b38Smrg 195465b04b38Smrg miSyncTriggerFence(pFence); 195565b04b38Smrg 195665b04b38Smrg return client->noClientException; 195765b04b38Smrg} 195865b04b38Smrg 195965b04b38Smrgstatic int 196065b04b38SmrgProcSyncResetFence(ClientPtr client) 196165b04b38Smrg{ 196265b04b38Smrg REQUEST(xSyncResetFenceReq); 196365b04b38Smrg SyncFence *pFence; 196465b04b38Smrg int rc; 196565b04b38Smrg 196665b04b38Smrg REQUEST_SIZE_MATCH(xSyncResetFenceReq); 196765b04b38Smrg 1968f7df2e56Smrg rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence, 1969f7df2e56Smrg client, DixWriteAccess); 197065b04b38Smrg if (rc != Success) 1971f7df2e56Smrg return rc; 197265b04b38Smrg 197365b04b38Smrg if (pFence->funcs.CheckTriggered(pFence) != TRUE) 1974f7df2e56Smrg return BadMatch; 197565b04b38Smrg 197665b04b38Smrg pFence->funcs.Reset(pFence); 197765b04b38Smrg 197865b04b38Smrg return client->noClientException; 197965b04b38Smrg} 198065b04b38Smrg 198165b04b38Smrgstatic int 198265b04b38SmrgProcSyncDestroyFence(ClientPtr client) 198365b04b38Smrg{ 198465b04b38Smrg REQUEST(xSyncDestroyFenceReq); 198565b04b38Smrg SyncFence *pFence; 198665b04b38Smrg int rc; 198765b04b38Smrg 198865b04b38Smrg REQUEST_SIZE_MATCH(xSyncDestroyFenceReq); 198965b04b38Smrg 1990f7df2e56Smrg rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence, 1991f7df2e56Smrg client, DixDestroyAccess); 199265b04b38Smrg if (rc != Success) 1993f7df2e56Smrg return rc; 199465b04b38Smrg 199565b04b38Smrg FreeResource(stuff->fid, RT_NONE); 199665b04b38Smrg return client->noClientException; 199765b04b38Smrg} 199865b04b38Smrg 199965b04b38Smrgstatic int 200065b04b38SmrgProcSyncQueryFence(ClientPtr client) 200165b04b38Smrg{ 200265b04b38Smrg REQUEST(xSyncQueryFenceReq); 200365b04b38Smrg xSyncQueryFenceReply rep; 200465b04b38Smrg SyncFence *pFence; 200565b04b38Smrg int rc; 200665b04b38Smrg 200765b04b38Smrg REQUEST_SIZE_MATCH(xSyncQueryFenceReq); 200865b04b38Smrg 2009f7df2e56Smrg rc = dixLookupResourceByType((void **) &pFence, stuff->fid, 2010f7df2e56Smrg RTFence, client, DixReadAccess); 201165b04b38Smrg if (rc != Success) 2012f7df2e56Smrg return rc; 201365b04b38Smrg 2014f7df2e56Smrg rep = (xSyncQueryFenceReply) { 2015f7df2e56Smrg .type = X_Reply, 2016f7df2e56Smrg .sequenceNumber = client->sequence, 2017f7df2e56Smrg .length = 0, 201865b04b38Smrg 2019f7df2e56Smrg .triggered = pFence->funcs.CheckTriggered(pFence) 2020f7df2e56Smrg }; 202165b04b38Smrg 2022f7df2e56Smrg if (client->swapped) { 2023f7df2e56Smrg swaps(&rep.sequenceNumber); 2024f7df2e56Smrg swapl(&rep.length); 202565b04b38Smrg } 202665b04b38Smrg 2027f7df2e56Smrg WriteToClient(client, sizeof(xSyncQueryFenceReply), &rep); 202865b04b38Smrg return client->noClientException; 202965b04b38Smrg} 203065b04b38Smrg 203165b04b38Smrgstatic int 203265b04b38SmrgProcSyncAwaitFence(ClientPtr client) 203365b04b38Smrg{ 203465b04b38Smrg REQUEST(xSyncAwaitFenceReq); 203565b04b38Smrg SyncAwaitUnion *pAwaitUnion; 203665b04b38Smrg SyncAwait *pAwait; 2037f7df2e56Smrg 203865b04b38Smrg /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to 203965b04b38Smrg * CARD32 in protocol definitions */ 204065b04b38Smrg CARD32 *pProtocolFences; 204165b04b38Smrg int status; 204265b04b38Smrg int len; 204365b04b38Smrg int items; 204465b04b38Smrg int i; 204565b04b38Smrg 204665b04b38Smrg REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq); 204765b04b38Smrg 204865b04b38Smrg len = client->req_len << 2; 204965b04b38Smrg len -= sz_xSyncAwaitFenceReq; 205065b04b38Smrg items = len / sizeof(CARD32); 205165b04b38Smrg 2052f7df2e56Smrg if (items * sizeof(CARD32) != len) { 2053f7df2e56Smrg return BadLength; 205465b04b38Smrg } 2055f7df2e56Smrg if (items == 0) { 2056f7df2e56Smrg client->errorValue = items; 2057f7df2e56Smrg return BadValue; 205865b04b38Smrg } 205965b04b38Smrg 206065b04b38Smrg if (!(pAwaitUnion = SyncAwaitPrologue(client, items))) 2061f7df2e56Smrg return BadAlloc; 206265b04b38Smrg 206365b04b38Smrg /* don't need to do any more memory allocation for this request! */ 206465b04b38Smrg 2065f7df2e56Smrg pProtocolFences = (CARD32 *) &stuff[1]; 2066f7df2e56Smrg 2067f7df2e56Smrg pAwait = &(pAwaitUnion + 1)->await; /* skip over header */ 2068f7df2e56Smrg for (i = 0; i < items; i++, pProtocolFences++, pAwait++) { 2069f7df2e56Smrg if (*pProtocolFences == None) { 2070f7df2e56Smrg /* this should take care of removing any triggers created by 2071f7df2e56Smrg * this request that have already been registered on sync objects 2072f7df2e56Smrg */ 2073f7df2e56Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 2074f7df2e56Smrg client->errorValue = *pProtocolFences; 2075f7df2e56Smrg return SyncErrorBase + XSyncBadFence; 2076f7df2e56Smrg } 2077f7df2e56Smrg 2078f7df2e56Smrg pAwait->trigger.pSync = NULL; 2079f7df2e56Smrg /* Provide acceptable values for these unused fields to 2080f7df2e56Smrg * satisfy SyncInitTrigger's validation logic 2081f7df2e56Smrg */ 2082f7df2e56Smrg pAwait->trigger.value_type = XSyncAbsolute; 2083f7df2e56Smrg XSyncIntToValue(&pAwait->trigger.wait_value, 0); 2084f7df2e56Smrg pAwait->trigger.test_type = 0; 2085f7df2e56Smrg 2086f7df2e56Smrg status = SyncInitTrigger(client, &pAwait->trigger, 2087f7df2e56Smrg *pProtocolFences, RTFence, XSyncCAAllTrigger); 2088f7df2e56Smrg if (status != Success) { 2089f7df2e56Smrg /* this should take care of removing any triggers created by 2090f7df2e56Smrg * this request that have already been registered on sync objects 2091f7df2e56Smrg */ 2092f7df2e56Smrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 2093f7df2e56Smrg return status; 2094f7df2e56Smrg } 2095f7df2e56Smrg /* this is not a mistake -- same function works for both cases */ 2096f7df2e56Smrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 2097f7df2e56Smrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 2098f7df2e56Smrg /* event_threshold is unused for fence syncs */ 2099f7df2e56Smrg XSyncIntToValue(&pAwait->event_threshold, 0); 2100f7df2e56Smrg pAwait->pHeader = &pAwaitUnion->header; 2101f7df2e56Smrg pAwaitUnion->header.num_waitconditions++; 210265b04b38Smrg } 210365b04b38Smrg 210465b04b38Smrg SyncAwaitEpilogue(client, items, pAwaitUnion); 210565b04b38Smrg 210665b04b38Smrg return client->noClientException; 210765b04b38Smrg} 210865b04b38Smrg 210905b261ecSmrg/* 211005b261ecSmrg * ** Given an extension request, call the appropriate request procedure 211105b261ecSmrg */ 21124202a189Smrgstatic int 21134202a189SmrgProcSyncDispatch(ClientPtr client) 211405b261ecSmrg{ 211505b261ecSmrg REQUEST(xReq); 211605b261ecSmrg 2117f7df2e56Smrg switch (stuff->data) { 2118f7df2e56Smrg case X_SyncInitialize: 2119f7df2e56Smrg return ProcSyncInitialize(client); 2120f7df2e56Smrg case X_SyncListSystemCounters: 2121f7df2e56Smrg return ProcSyncListSystemCounters(client); 2122f7df2e56Smrg case X_SyncCreateCounter: 2123f7df2e56Smrg return ProcSyncCreateCounter(client); 2124f7df2e56Smrg case X_SyncSetCounter: 2125f7df2e56Smrg return ProcSyncSetCounter(client); 2126f7df2e56Smrg case X_SyncChangeCounter: 2127f7df2e56Smrg return ProcSyncChangeCounter(client); 2128f7df2e56Smrg case X_SyncQueryCounter: 2129f7df2e56Smrg return ProcSyncQueryCounter(client); 2130f7df2e56Smrg case X_SyncDestroyCounter: 2131f7df2e56Smrg return ProcSyncDestroyCounter(client); 2132f7df2e56Smrg case X_SyncAwait: 2133f7df2e56Smrg return ProcSyncAwait(client); 2134f7df2e56Smrg case X_SyncCreateAlarm: 2135f7df2e56Smrg return ProcSyncCreateAlarm(client); 2136f7df2e56Smrg case X_SyncChangeAlarm: 2137f7df2e56Smrg return ProcSyncChangeAlarm(client); 2138f7df2e56Smrg case X_SyncQueryAlarm: 2139f7df2e56Smrg return ProcSyncQueryAlarm(client); 2140f7df2e56Smrg case X_SyncDestroyAlarm: 2141f7df2e56Smrg return ProcSyncDestroyAlarm(client); 2142f7df2e56Smrg case X_SyncSetPriority: 2143f7df2e56Smrg return ProcSyncSetPriority(client); 2144f7df2e56Smrg case X_SyncGetPriority: 2145f7df2e56Smrg return ProcSyncGetPriority(client); 2146f7df2e56Smrg case X_SyncCreateFence: 2147f7df2e56Smrg return ProcSyncCreateFence(client); 2148f7df2e56Smrg case X_SyncTriggerFence: 2149f7df2e56Smrg return ProcSyncTriggerFence(client); 2150f7df2e56Smrg case X_SyncResetFence: 2151f7df2e56Smrg return ProcSyncResetFence(client); 2152f7df2e56Smrg case X_SyncDestroyFence: 2153f7df2e56Smrg return ProcSyncDestroyFence(client); 2154f7df2e56Smrg case X_SyncQueryFence: 2155f7df2e56Smrg return ProcSyncQueryFence(client); 2156f7df2e56Smrg case X_SyncAwaitFence: 2157f7df2e56Smrg return ProcSyncAwaitFence(client); 2158f7df2e56Smrg default: 2159f7df2e56Smrg return BadRequest; 216005b261ecSmrg } 216105b261ecSmrg} 216205b261ecSmrg 216305b261ecSmrg/* 216405b261ecSmrg * Boring Swapping stuff ... 216505b261ecSmrg */ 216605b261ecSmrg 21674202a189Smrgstatic int 21684202a189SmrgSProcSyncInitialize(ClientPtr client) 216905b261ecSmrg{ 217005b261ecSmrg REQUEST(xSyncInitializeReq); 2171f7df2e56Smrg swaps(&stuff->length); 2172f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 217305b261ecSmrg 217405b261ecSmrg return ProcSyncInitialize(client); 217505b261ecSmrg} 217605b261ecSmrg 21774202a189Smrgstatic int 21784202a189SmrgSProcSyncListSystemCounters(ClientPtr client) 217905b261ecSmrg{ 218005b261ecSmrg REQUEST(xSyncListSystemCountersReq); 2181f7df2e56Smrg swaps(&stuff->length); 2182f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 218305b261ecSmrg 218405b261ecSmrg return ProcSyncListSystemCounters(client); 218505b261ecSmrg} 218605b261ecSmrg 21874202a189Smrgstatic int 21884202a189SmrgSProcSyncCreateCounter(ClientPtr client) 218905b261ecSmrg{ 219005b261ecSmrg REQUEST(xSyncCreateCounterReq); 2191f7df2e56Smrg swaps(&stuff->length); 2192f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 2193f7df2e56Smrg swapl(&stuff->cid); 2194f7df2e56Smrg swapl(&stuff->initial_value_lo); 2195f7df2e56Smrg swapl(&stuff->initial_value_hi); 219605b261ecSmrg 219705b261ecSmrg return ProcSyncCreateCounter(client); 219805b261ecSmrg} 219905b261ecSmrg 22004202a189Smrgstatic int 22014202a189SmrgSProcSyncSetCounter(ClientPtr client) 220205b261ecSmrg{ 220305b261ecSmrg REQUEST(xSyncSetCounterReq); 2204f7df2e56Smrg swaps(&stuff->length); 2205f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 2206f7df2e56Smrg swapl(&stuff->cid); 2207f7df2e56Smrg swapl(&stuff->value_lo); 2208f7df2e56Smrg swapl(&stuff->value_hi); 220905b261ecSmrg 221005b261ecSmrg return ProcSyncSetCounter(client); 221105b261ecSmrg} 221205b261ecSmrg 22134202a189Smrgstatic int 22144202a189SmrgSProcSyncChangeCounter(ClientPtr client) 221505b261ecSmrg{ 221605b261ecSmrg REQUEST(xSyncChangeCounterReq); 2217f7df2e56Smrg swaps(&stuff->length); 2218f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 2219f7df2e56Smrg swapl(&stuff->cid); 2220f7df2e56Smrg swapl(&stuff->value_lo); 2221f7df2e56Smrg swapl(&stuff->value_hi); 222205b261ecSmrg 222305b261ecSmrg return ProcSyncChangeCounter(client); 222405b261ecSmrg} 222505b261ecSmrg 22264202a189Smrgstatic int 22274202a189SmrgSProcSyncQueryCounter(ClientPtr client) 222805b261ecSmrg{ 222905b261ecSmrg REQUEST(xSyncQueryCounterReq); 2230f7df2e56Smrg swaps(&stuff->length); 2231f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 2232f7df2e56Smrg swapl(&stuff->counter); 223305b261ecSmrg 223405b261ecSmrg return ProcSyncQueryCounter(client); 223505b261ecSmrg} 223605b261ecSmrg 22374202a189Smrgstatic int 22384202a189SmrgSProcSyncDestroyCounter(ClientPtr client) 223905b261ecSmrg{ 224005b261ecSmrg REQUEST(xSyncDestroyCounterReq); 2241f7df2e56Smrg swaps(&stuff->length); 2242f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 2243f7df2e56Smrg swapl(&stuff->counter); 224405b261ecSmrg 224505b261ecSmrg return ProcSyncDestroyCounter(client); 224605b261ecSmrg} 224705b261ecSmrg 22484202a189Smrgstatic int 22494202a189SmrgSProcSyncAwait(ClientPtr client) 225005b261ecSmrg{ 225105b261ecSmrg REQUEST(xSyncAwaitReq); 2252f7df2e56Smrg swaps(&stuff->length); 225305b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 225405b261ecSmrg SwapRestL(stuff); 225505b261ecSmrg 225605b261ecSmrg return ProcSyncAwait(client); 225705b261ecSmrg} 225805b261ecSmrg 22594202a189Smrgstatic int 22604202a189SmrgSProcSyncCreateAlarm(ClientPtr client) 226105b261ecSmrg{ 226205b261ecSmrg REQUEST(xSyncCreateAlarmReq); 2263f7df2e56Smrg swaps(&stuff->length); 226405b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 2265f7df2e56Smrg swapl(&stuff->id); 2266f7df2e56Smrg swapl(&stuff->valueMask); 226705b261ecSmrg SwapRestL(stuff); 226805b261ecSmrg 226905b261ecSmrg return ProcSyncCreateAlarm(client); 227005b261ecSmrg} 227105b261ecSmrg 22724202a189Smrgstatic int 22734202a189SmrgSProcSyncChangeAlarm(ClientPtr client) 227405b261ecSmrg{ 227505b261ecSmrg REQUEST(xSyncChangeAlarmReq); 2276f7df2e56Smrg swaps(&stuff->length); 227705b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 2278f7df2e56Smrg swapl(&stuff->alarm); 2279f7df2e56Smrg swapl(&stuff->valueMask); 228005b261ecSmrg SwapRestL(stuff); 228105b261ecSmrg return ProcSyncChangeAlarm(client); 228205b261ecSmrg} 228305b261ecSmrg 22844202a189Smrgstatic int 22854202a189SmrgSProcSyncQueryAlarm(ClientPtr client) 228605b261ecSmrg{ 228705b261ecSmrg REQUEST(xSyncQueryAlarmReq); 2288f7df2e56Smrg swaps(&stuff->length); 2289f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 2290f7df2e56Smrg swapl(&stuff->alarm); 229105b261ecSmrg 229205b261ecSmrg return ProcSyncQueryAlarm(client); 229305b261ecSmrg} 229405b261ecSmrg 22954202a189Smrgstatic int 22964202a189SmrgSProcSyncDestroyAlarm(ClientPtr client) 229705b261ecSmrg{ 229805b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 2299f7df2e56Smrg swaps(&stuff->length); 2300f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 2301f7df2e56Smrg swapl(&stuff->alarm); 230205b261ecSmrg 230305b261ecSmrg return ProcSyncDestroyAlarm(client); 230405b261ecSmrg} 230505b261ecSmrg 23064202a189Smrgstatic int 23074202a189SmrgSProcSyncSetPriority(ClientPtr client) 230805b261ecSmrg{ 230905b261ecSmrg REQUEST(xSyncSetPriorityReq); 2310f7df2e56Smrg swaps(&stuff->length); 2311f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 2312f7df2e56Smrg swapl(&stuff->id); 2313f7df2e56Smrg swapl(&stuff->priority); 231405b261ecSmrg 231505b261ecSmrg return ProcSyncSetPriority(client); 231605b261ecSmrg} 231705b261ecSmrg 23184202a189Smrgstatic int 23194202a189SmrgSProcSyncGetPriority(ClientPtr client) 232005b261ecSmrg{ 232105b261ecSmrg REQUEST(xSyncGetPriorityReq); 2322f7df2e56Smrg swaps(&stuff->length); 2323f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 2324f7df2e56Smrg swapl(&stuff->id); 232505b261ecSmrg 232605b261ecSmrg return ProcSyncGetPriority(client); 232705b261ecSmrg} 232805b261ecSmrg 232965b04b38Smrgstatic int 233065b04b38SmrgSProcSyncCreateFence(ClientPtr client) 233165b04b38Smrg{ 233265b04b38Smrg REQUEST(xSyncCreateFenceReq); 2333f7df2e56Smrg swaps(&stuff->length); 2334f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncCreateFenceReq); 2335f7df2e56Smrg swapl(&stuff->fid); 233665b04b38Smrg 233765b04b38Smrg return ProcSyncCreateFence(client); 233865b04b38Smrg} 233965b04b38Smrg 234065b04b38Smrgstatic int 234165b04b38SmrgSProcSyncTriggerFence(ClientPtr client) 234265b04b38Smrg{ 234365b04b38Smrg REQUEST(xSyncTriggerFenceReq); 2344f7df2e56Smrg swaps(&stuff->length); 2345f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncTriggerFenceReq); 2346f7df2e56Smrg swapl(&stuff->fid); 234765b04b38Smrg 234865b04b38Smrg return ProcSyncTriggerFence(client); 234965b04b38Smrg} 235065b04b38Smrg 235165b04b38Smrgstatic int 235265b04b38SmrgSProcSyncResetFence(ClientPtr client) 235365b04b38Smrg{ 235465b04b38Smrg REQUEST(xSyncResetFenceReq); 2355f7df2e56Smrg swaps(&stuff->length); 2356f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncResetFenceReq); 2357f7df2e56Smrg swapl(&stuff->fid); 235865b04b38Smrg 235965b04b38Smrg return ProcSyncResetFence(client); 236065b04b38Smrg} 236165b04b38Smrg 236265b04b38Smrgstatic int 236365b04b38SmrgSProcSyncDestroyFence(ClientPtr client) 236465b04b38Smrg{ 236565b04b38Smrg REQUEST(xSyncDestroyFenceReq); 2366f7df2e56Smrg swaps(&stuff->length); 2367f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncDestroyFenceReq); 2368f7df2e56Smrg swapl(&stuff->fid); 236965b04b38Smrg 237065b04b38Smrg return ProcSyncDestroyFence(client); 237165b04b38Smrg} 237265b04b38Smrg 237365b04b38Smrgstatic int 237465b04b38SmrgSProcSyncQueryFence(ClientPtr client) 237565b04b38Smrg{ 237665b04b38Smrg REQUEST(xSyncQueryFenceReq); 2377f7df2e56Smrg swaps(&stuff->length); 2378f7df2e56Smrg REQUEST_SIZE_MATCH(xSyncQueryFenceReq); 2379f7df2e56Smrg swapl(&stuff->fid); 238065b04b38Smrg 238165b04b38Smrg return ProcSyncQueryFence(client); 238265b04b38Smrg} 238365b04b38Smrg 238465b04b38Smrgstatic int 238565b04b38SmrgSProcSyncAwaitFence(ClientPtr client) 238665b04b38Smrg{ 238765b04b38Smrg REQUEST(xSyncAwaitFenceReq); 2388f7df2e56Smrg swaps(&stuff->length); 238965b04b38Smrg REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq); 239065b04b38Smrg SwapRestL(stuff); 239165b04b38Smrg 239265b04b38Smrg return ProcSyncAwaitFence(client); 239365b04b38Smrg} 239405b261ecSmrg 23954202a189Smrgstatic int 23964202a189SmrgSProcSyncDispatch(ClientPtr client) 239705b261ecSmrg{ 239805b261ecSmrg REQUEST(xReq); 239905b261ecSmrg 2400f7df2e56Smrg switch (stuff->data) { 2401f7df2e56Smrg case X_SyncInitialize: 2402f7df2e56Smrg return SProcSyncInitialize(client); 2403f7df2e56Smrg case X_SyncListSystemCounters: 2404f7df2e56Smrg return SProcSyncListSystemCounters(client); 2405f7df2e56Smrg case X_SyncCreateCounter: 2406f7df2e56Smrg return SProcSyncCreateCounter(client); 2407f7df2e56Smrg case X_SyncSetCounter: 2408f7df2e56Smrg return SProcSyncSetCounter(client); 2409f7df2e56Smrg case X_SyncChangeCounter: 2410f7df2e56Smrg return SProcSyncChangeCounter(client); 2411f7df2e56Smrg case X_SyncQueryCounter: 2412f7df2e56Smrg return SProcSyncQueryCounter(client); 2413f7df2e56Smrg case X_SyncDestroyCounter: 2414f7df2e56Smrg return SProcSyncDestroyCounter(client); 2415f7df2e56Smrg case X_SyncAwait: 2416f7df2e56Smrg return SProcSyncAwait(client); 2417f7df2e56Smrg case X_SyncCreateAlarm: 2418f7df2e56Smrg return SProcSyncCreateAlarm(client); 2419f7df2e56Smrg case X_SyncChangeAlarm: 2420f7df2e56Smrg return SProcSyncChangeAlarm(client); 2421f7df2e56Smrg case X_SyncQueryAlarm: 2422f7df2e56Smrg return SProcSyncQueryAlarm(client); 2423f7df2e56Smrg case X_SyncDestroyAlarm: 2424f7df2e56Smrg return SProcSyncDestroyAlarm(client); 2425f7df2e56Smrg case X_SyncSetPriority: 2426f7df2e56Smrg return SProcSyncSetPriority(client); 2427f7df2e56Smrg case X_SyncGetPriority: 2428f7df2e56Smrg return SProcSyncGetPriority(client); 2429f7df2e56Smrg case X_SyncCreateFence: 2430f7df2e56Smrg return SProcSyncCreateFence(client); 2431f7df2e56Smrg case X_SyncTriggerFence: 2432f7df2e56Smrg return SProcSyncTriggerFence(client); 2433f7df2e56Smrg case X_SyncResetFence: 2434f7df2e56Smrg return SProcSyncResetFence(client); 2435f7df2e56Smrg case X_SyncDestroyFence: 2436f7df2e56Smrg return SProcSyncDestroyFence(client); 2437f7df2e56Smrg case X_SyncQueryFence: 2438f7df2e56Smrg return SProcSyncQueryFence(client); 2439f7df2e56Smrg case X_SyncAwaitFence: 2440f7df2e56Smrg return SProcSyncAwaitFence(client); 2441f7df2e56Smrg default: 2442f7df2e56Smrg return BadRequest; 244305b261ecSmrg } 244405b261ecSmrg} 244505b261ecSmrg 244605b261ecSmrg/* 244705b261ecSmrg * Event Swapping 244805b261ecSmrg */ 244905b261ecSmrg 24504202a189Smrgstatic void 2451f7df2e56SmrgSCounterNotifyEvent(xSyncCounterNotifyEvent * from, 2452f7df2e56Smrg xSyncCounterNotifyEvent * to) 245305b261ecSmrg{ 245405b261ecSmrg to->type = from->type; 245505b261ecSmrg to->kind = from->kind; 245605b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 245705b261ecSmrg cpswapl(from->counter, to->counter); 245805b261ecSmrg cpswapl(from->wait_value_lo, to->wait_value_lo); 245905b261ecSmrg cpswapl(from->wait_value_hi, to->wait_value_hi); 246005b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 246105b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 246205b261ecSmrg cpswapl(from->time, to->time); 246305b261ecSmrg cpswaps(from->count, to->count); 246405b261ecSmrg to->destroyed = from->destroyed; 246505b261ecSmrg} 246605b261ecSmrg 24674202a189Smrgstatic void 2468f7df2e56SmrgSAlarmNotifyEvent(xSyncAlarmNotifyEvent * from, xSyncAlarmNotifyEvent * to) 246905b261ecSmrg{ 247005b261ecSmrg to->type = from->type; 247105b261ecSmrg to->kind = from->kind; 247205b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 247305b261ecSmrg cpswapl(from->alarm, to->alarm); 247405b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 247505b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 247605b261ecSmrg cpswapl(from->alarm_value_lo, to->alarm_value_lo); 247705b261ecSmrg cpswapl(from->alarm_value_hi, to->alarm_value_hi); 247805b261ecSmrg cpswapl(from->time, to->time); 247905b261ecSmrg to->state = from->state; 248005b261ecSmrg} 248105b261ecSmrg 248205b261ecSmrg/* 248305b261ecSmrg * ** Close everything down. ** This is fairly simple for now. 248405b261ecSmrg */ 248505b261ecSmrg/* ARGSUSED */ 24864202a189Smrgstatic void 2487f7df2e56SmrgSyncResetProc(ExtensionEntry * extEntry) 248805b261ecSmrg{ 248905b261ecSmrg RTCounter = 0; 249005b261ecSmrg} 249105b261ecSmrg 249205b261ecSmrg/* 249305b261ecSmrg * ** Initialise the extension. 249405b261ecSmrg */ 24954202a189Smrgvoid 24964202a189SmrgSyncExtensionInit(void) 249705b261ecSmrg{ 249805b261ecSmrg ExtensionEntry *extEntry; 2499f7df2e56Smrg int s; 250065b04b38Smrg 250165b04b38Smrg for (s = 0; s < screenInfo.numScreens; s++) 2502f7df2e56Smrg miSyncSetup(screenInfo.screens[s]); 250305b261ecSmrg 2504f7df2e56Smrg if (RTCounter == 0) { 2505f7df2e56Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 2506f7df2e56Smrg xorg_list_init(&SysCounterList); 250705b261ecSmrg } 25084202a189Smrg RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); 25094202a189Smrg RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); 251065b04b38Smrg RTFence = CreateNewResourceType(FreeFence, "SyncFence"); 25114202a189Smrg if (RTAwait) 2512f7df2e56Smrg RTAwait |= RC_NEVERRETAIN; 25134202a189Smrg RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); 25144202a189Smrg if (RTAlarmClient) 2515f7df2e56Smrg RTAlarmClient |= RC_NEVERRETAIN; 251605b261ecSmrg 251705b261ecSmrg if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 2518f7df2e56Smrg RTAlarmClient == 0 || 2519f7df2e56Smrg (extEntry = AddExtension(SYNC_NAME, 2520f7df2e56Smrg XSyncNumberEvents, XSyncNumberErrors, 2521f7df2e56Smrg ProcSyncDispatch, SProcSyncDispatch, 2522f7df2e56Smrg SyncResetProc, StandardMinorOpcode)) == NULL) { 2523f7df2e56Smrg ErrorF("Sync Extension %d.%d failed to Initialise\n", 2524f7df2e56Smrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 2525f7df2e56Smrg return; 252605b261ecSmrg } 252705b261ecSmrg 252805b261ecSmrg SyncEventBase = extEntry->eventBase; 252905b261ecSmrg SyncErrorBase = extEntry->errorBase; 2530f7df2e56Smrg EventSwapVector[SyncEventBase + XSyncCounterNotify] = 2531f7df2e56Smrg (EventSwapPtr) SCounterNotifyEvent; 2532f7df2e56Smrg EventSwapVector[SyncEventBase + XSyncAlarmNotify] = 2533f7df2e56Smrg (EventSwapPtr) SAlarmNotifyEvent; 253405b261ecSmrg 25354202a189Smrg SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter); 25364202a189Smrg SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm); 253765b04b38Smrg SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence); 25384202a189Smrg 253905b261ecSmrg /* 254005b261ecSmrg * Although SERVERTIME is implemented by the OS layer, we initialise it 254105b261ecSmrg * here because doing it in OsInit() is too early. The resource database 254205b261ecSmrg * is not initialised when OsInit() is called. This is just about OK 254305b261ecSmrg * because there is always a servertime counter. 254405b261ecSmrg */ 254505b261ecSmrg SyncInitServerTime(); 254605b261ecSmrg SyncInitIdleTime(); 254705b261ecSmrg 254805b261ecSmrg#ifdef DEBUG 254905b261ecSmrg fprintf(stderr, "Sync Extension %d.%d\n", 2550f7df2e56Smrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 255105b261ecSmrg#endif 255205b261ecSmrg} 255305b261ecSmrg 255405b261ecSmrg/* 255505b261ecSmrg * ***** SERVERTIME implementation - should go in its own file in OS directory? 255605b261ecSmrg */ 255705b261ecSmrg 2558f7df2e56Smrgstatic void *ServertimeCounter; 255905b261ecSmrgstatic XSyncValue Now; 256005b261ecSmrgstatic XSyncValue *pnext_time; 256105b261ecSmrg 256205b261ecSmrg#define GetTime()\ 256305b261ecSmrg{\ 256405b261ecSmrg unsigned long millis = GetTimeInMillis();\ 256505b261ecSmrg unsigned long maxis = XSyncValueHigh32(Now);\ 256605b261ecSmrg if (millis < XSyncValueLow32(Now)) maxis++;\ 256705b261ecSmrg XSyncIntsToValue(&Now, millis, maxis);\ 256805b261ecSmrg} 256905b261ecSmrg 257005b261ecSmrg/* 257105b261ecSmrg*** Server Block Handler 25724202a189Smrg*** code inspired by multibuffer extension (now deprecated) 257305b261ecSmrg */ 2574f7df2e56Smrg /*ARGSUSED*/ static void 25754202a189SmrgServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) 257605b261ecSmrg{ 257705b261ecSmrg XSyncValue delay; 257805b261ecSmrg unsigned long timeout; 257905b261ecSmrg 2580f7df2e56Smrg if (pnext_time) { 258105b261ecSmrg GetTime(); 258205b261ecSmrg 2583f7df2e56Smrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) { 258405b261ecSmrg timeout = 0; 25854202a189Smrg } 2586f7df2e56Smrg else { 2587f7df2e56Smrg Bool overflow; 2588f7df2e56Smrg 258905b261ecSmrg XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 2590f7df2e56Smrg (void) overflow; 259105b261ecSmrg timeout = XSyncValueLow32(delay); 259205b261ecSmrg } 2593f7df2e56Smrg AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 259405b261ecSmrg } 259505b261ecSmrg} 259605b261ecSmrg 259705b261ecSmrg/* 259805b261ecSmrg*** Wakeup Handler 259905b261ecSmrg */ 2600f7df2e56Smrg /*ARGSUSED*/ static void 26014202a189SmrgServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) 260205b261ecSmrg{ 2603f7df2e56Smrg if (pnext_time) { 260405b261ecSmrg GetTime(); 260505b261ecSmrg 2606f7df2e56Smrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) { 260705b261ecSmrg SyncChangeCounter(ServertimeCounter, Now); 260805b261ecSmrg } 260905b261ecSmrg } 261005b261ecSmrg} 261105b261ecSmrg 261205b261ecSmrgstatic void 2613f7df2e56SmrgServertimeQueryValue(void *pCounter, CARD64 * pValue_return) 261405b261ecSmrg{ 261505b261ecSmrg GetTime(); 261605b261ecSmrg *pValue_return = Now; 261705b261ecSmrg} 261805b261ecSmrg 261905b261ecSmrgstatic void 2620f7df2e56SmrgServertimeBracketValues(void *pCounter, CARD64 * pbracket_less, 2621f7df2e56Smrg CARD64 * pbracket_greater) 262205b261ecSmrg{ 2623f7df2e56Smrg if (!pnext_time && pbracket_greater) { 2624f7df2e56Smrg RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 2625f7df2e56Smrg ServertimeWakeupHandler, NULL); 262605b261ecSmrg } 2627f7df2e56Smrg else if (pnext_time && !pbracket_greater) { 2628f7df2e56Smrg RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 2629f7df2e56Smrg ServertimeWakeupHandler, NULL); 263005b261ecSmrg } 263105b261ecSmrg pnext_time = pbracket_greater; 263205b261ecSmrg} 263305b261ecSmrg 263405b261ecSmrgstatic void 263505b261ecSmrgSyncInitServerTime(void) 263605b261ecSmrg{ 263705b261ecSmrg CARD64 resolution; 263805b261ecSmrg 263905b261ecSmrg XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 264005b261ecSmrg XSyncIntToValue(&resolution, 4); 264105b261ecSmrg ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 2642f7df2e56Smrg XSyncCounterNeverDecreases, 2643f7df2e56Smrg ServertimeQueryValue, 2644f7df2e56Smrg ServertimeBracketValues); 264505b261ecSmrg pnext_time = NULL; 264605b261ecSmrg} 264705b261ecSmrg 264805b261ecSmrg/* 264905b261ecSmrg * IDLETIME implementation 265005b261ecSmrg */ 265105b261ecSmrg 2652f7df2e56Smrgtypedef struct { 2653f7df2e56Smrg XSyncValue *value_less; 2654f7df2e56Smrg XSyncValue *value_greater; 2655f7df2e56Smrg int deviceid; 2656f7df2e56Smrg} IdleCounterPriv; 265705b261ecSmrg 265805b261ecSmrgstatic void 2659f7df2e56SmrgIdleTimeQueryValue(void *pCounter, CARD64 * pValue_return) 266005b261ecSmrg{ 2661f7df2e56Smrg int deviceid; 2662f7df2e56Smrg CARD32 idle; 2663f7df2e56Smrg 2664f7df2e56Smrg if (pCounter) { 2665f7df2e56Smrg SyncCounter *counter = pCounter; 2666f7df2e56Smrg IdleCounterPriv *priv = SysCounterGetPrivate(counter); 2667f7df2e56Smrg deviceid = priv->deviceid; 2668f7df2e56Smrg } 2669f7df2e56Smrg else 2670f7df2e56Smrg deviceid = XIAllDevices; 2671f7df2e56Smrg idle = GetTimeInMillis() - LastEventTime(deviceid).milliseconds; 2672f7df2e56Smrg XSyncIntsToValue(pValue_return, idle, 0); 267305b261ecSmrg} 267405b261ecSmrg 267505b261ecSmrgstatic void 2676f7df2e56SmrgIdleTimeBlockHandler(void *pCounter, struct timeval **wt, void *LastSelectMask) 267705b261ecSmrg{ 2678f7df2e56Smrg SyncCounter *counter = pCounter; 2679f7df2e56Smrg IdleCounterPriv *priv = SysCounterGetPrivate(counter); 2680f7df2e56Smrg XSyncValue *less = priv->value_less, 2681f7df2e56Smrg *greater = priv->value_greater; 268245801275Sjmcneill XSyncValue idle, old_idle; 2683f7df2e56Smrg SyncTriggerList *list = counter->sync.pTriglist; 268445801275Sjmcneill SyncTrigger *trig; 268505b261ecSmrg 2686f7df2e56Smrg if (!less && !greater) 2687f7df2e56Smrg return; 2688f7df2e56Smrg 2689f7df2e56Smrg old_idle = counter->value; 2690f7df2e56Smrg IdleTimeQueryValue(counter, &idle); 2691f7df2e56Smrg counter->value = idle; /* push, so CheckTrigger works */ 2692f7df2e56Smrg 2693f7df2e56Smrg /** 2694f7df2e56Smrg * There's an indefinite amount of time between ProcessInputEvents() 2695f7df2e56Smrg * where the idle time is reset and the time we actually get here. idle 2696f7df2e56Smrg * may be past the lower bracket if we dawdled with the events, so 2697f7df2e56Smrg * check for whether we did reset and bomb out of select immediately. 2698f7df2e56Smrg */ 2699f7df2e56Smrg if (less && XSyncValueGreaterThan(idle, *less) && 2700f7df2e56Smrg LastEventTimeWasReset(priv->deviceid)) { 2701f7df2e56Smrg AdjustWaitForDelay(wt, 0); 2702f7df2e56Smrg } else if (less && XSyncValueLessOrEqual(idle, *less)) { 2703f7df2e56Smrg /* 2704f7df2e56Smrg * We've been idle for less than the threshold value, and someone 2705f7df2e56Smrg * wants to know about that, but now we need to know whether they 2706f7df2e56Smrg * want level or edge trigger. Check the trigger list against the 2707f7df2e56Smrg * current idle time, and if any succeed, bomb out of select() 2708f7df2e56Smrg * immediately so we can reschedule. 2709f7df2e56Smrg */ 2710f7df2e56Smrg 2711f7df2e56Smrg for (list = counter->sync.pTriglist; list; list = list->next) { 2712f7df2e56Smrg trig = list->pTrigger; 2713f7df2e56Smrg if (trig->CheckTrigger(trig, old_idle)) { 2714f7df2e56Smrg AdjustWaitForDelay(wt, 0); 2715f7df2e56Smrg break; 2716f7df2e56Smrg } 2717f7df2e56Smrg } 2718f7df2e56Smrg /* 2719f7df2e56Smrg * We've been called exactly on the idle time, but we have a 2720f7df2e56Smrg * NegativeTransition trigger which requires a transition from an 2721f7df2e56Smrg * idle time greater than this. Schedule a wakeup for the next 2722f7df2e56Smrg * millisecond so we won't miss a transition. 2723f7df2e56Smrg */ 2724f7df2e56Smrg if (XSyncValueEqual(idle, *less)) 2725f7df2e56Smrg AdjustWaitForDelay(wt, 1); 2726f7df2e56Smrg } 2727f7df2e56Smrg else if (greater) { 2728f7df2e56Smrg /* 2729f7df2e56Smrg * There's a threshold in the positive direction. If we've been 2730f7df2e56Smrg * idle less than it, schedule a wakeup for sometime in the future. 2731f7df2e56Smrg * If we've been idle more than it, and someone wants to know about 2732f7df2e56Smrg * that level-triggered, schedule an immediate wakeup. 2733f7df2e56Smrg */ 2734f7df2e56Smrg 2735f7df2e56Smrg if (XSyncValueLessThan(idle, *greater)) { 2736f7df2e56Smrg XSyncValue value; 2737f7df2e56Smrg Bool overflow; 2738f7df2e56Smrg 2739f7df2e56Smrg XSyncValueSubtract(&value, *greater, idle, &overflow); 2740f7df2e56Smrg AdjustWaitForDelay(wt, XSyncValueLow32(value)); 2741f7df2e56Smrg } 2742f7df2e56Smrg else { 2743f7df2e56Smrg for (list = counter->sync.pTriglist; list; 2744f7df2e56Smrg list = list->next) { 2745f7df2e56Smrg trig = list->pTrigger; 2746f7df2e56Smrg if (trig->CheckTrigger(trig, old_idle)) { 2747f7df2e56Smrg AdjustWaitForDelay(wt, 0); 2748f7df2e56Smrg break; 2749f7df2e56Smrg } 2750f7df2e56Smrg } 2751f7df2e56Smrg } 2752f7df2e56Smrg } 2753f7df2e56Smrg 2754f7df2e56Smrg counter->value = old_idle; /* pop */ 2755f7df2e56Smrg} 2756f7df2e56Smrg 2757f7df2e56Smrgstatic void 2758f7df2e56SmrgIdleTimeCheckBrackets(SyncCounter *counter, XSyncValue idle, XSyncValue *less, XSyncValue *greater) 2759f7df2e56Smrg{ 2760f7df2e56Smrg if ((greater && XSyncValueGreaterOrEqual(idle, *greater)) || 2761f7df2e56Smrg (less && XSyncValueLessOrEqual(idle, *less))) { 2762f7df2e56Smrg SyncChangeCounter(counter, idle); 2763f7df2e56Smrg } 2764f7df2e56Smrg else 2765f7df2e56Smrg SyncUpdateCounter(counter, idle); 276605b261ecSmrg} 276705b261ecSmrg 276805b261ecSmrgstatic void 2769f7df2e56SmrgIdleTimeWakeupHandler(void *pCounter, int rc, void *LastSelectMask) 277005b261ecSmrg{ 2771f7df2e56Smrg SyncCounter *counter = pCounter; 2772f7df2e56Smrg IdleCounterPriv *priv = SysCounterGetPrivate(counter); 2773f7df2e56Smrg XSyncValue *less = priv->value_less, 2774f7df2e56Smrg *greater = priv->value_greater; 277505b261ecSmrg XSyncValue idle; 277605b261ecSmrg 2777f7df2e56Smrg if (!less && !greater) 2778f7df2e56Smrg return; 277905b261ecSmrg 2780f7df2e56Smrg IdleTimeQueryValue(pCounter, &idle); 278105b261ecSmrg 2782f7df2e56Smrg /* 2783f7df2e56Smrg There is no guarantee for the WakeupHandler to be called within a specific 2784f7df2e56Smrg timeframe. Idletime may go to 0, but by the time we get here, it may be 2785f7df2e56Smrg non-zero and alarms for a pos. transition on 0 won't get triggered. 2786f7df2e56Smrg https://bugs.freedesktop.org/show_bug.cgi?id=70476 2787f7df2e56Smrg */ 2788f7df2e56Smrg if (LastEventTimeWasReset(priv->deviceid)) { 2789f7df2e56Smrg LastEventTimeToggleResetFlag(priv->deviceid, FALSE); 2790f7df2e56Smrg if (!XSyncValueIsZero(idle)) { 2791f7df2e56Smrg XSyncValue zero; 2792f7df2e56Smrg XSyncIntsToValue(&zero, 0, 0); 2793f7df2e56Smrg IdleTimeCheckBrackets(counter, zero, less, greater); 2794f7df2e56Smrg less = priv->value_less; 2795f7df2e56Smrg greater = priv->value_greater; 2796f7df2e56Smrg } 279705b261ecSmrg } 2798f7df2e56Smrg 2799f7df2e56Smrg IdleTimeCheckBrackets(counter, idle, less, greater); 280005b261ecSmrg} 280105b261ecSmrg 280205b261ecSmrgstatic void 2803f7df2e56SmrgIdleTimeBracketValues(void *pCounter, CARD64 * pbracket_less, 2804f7df2e56Smrg CARD64 * pbracket_greater) 280505b261ecSmrg{ 2806f7df2e56Smrg SyncCounter *counter = pCounter; 2807f7df2e56Smrg IdleCounterPriv *priv = SysCounterGetPrivate(counter); 2808f7df2e56Smrg XSyncValue *less = priv->value_less, 2809f7df2e56Smrg *greater = priv->value_greater; 2810f7df2e56Smrg Bool registered = (less || greater); 281105b261ecSmrg 2812f7df2e56Smrg if (registered && !pbracket_less && !pbracket_greater) { 2813f7df2e56Smrg RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 2814f7df2e56Smrg IdleTimeWakeupHandler, pCounter); 281505b261ecSmrg } 2816f7df2e56Smrg else if (!registered && (pbracket_less || pbracket_greater)) { 2817f7df2e56Smrg /* Reset flag must be zero so we don't force a idle timer reset on 2818f7df2e56Smrg the first wakeup */ 2819f7df2e56Smrg LastEventTimeToggleResetAll(FALSE); 2820f7df2e56Smrg RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 2821f7df2e56Smrg IdleTimeWakeupHandler, pCounter); 282205b261ecSmrg } 282305b261ecSmrg 2824f7df2e56Smrg priv->value_greater = pbracket_greater; 2825f7df2e56Smrg priv->value_less = pbracket_less; 282605b261ecSmrg} 282705b261ecSmrg 2828f7df2e56Smrgstatic SyncCounter* 2829f7df2e56Smrginit_system_idle_counter(const char *name, int deviceid) 283005b261ecSmrg{ 283105b261ecSmrg CARD64 resolution; 283205b261ecSmrg XSyncValue idle; 2833f7df2e56Smrg SyncCounter *idle_time_counter; 2834f7df2e56Smrg 2835f7df2e56Smrg IdleTimeQueryValue(NULL, &idle); 2836f7df2e56Smrg XSyncIntToValue(&resolution, 4); 283705b261ecSmrg 2838f7df2e56Smrg idle_time_counter = SyncCreateSystemCounter(name, idle, resolution, 2839f7df2e56Smrg XSyncCounterUnrestricted, 2840f7df2e56Smrg IdleTimeQueryValue, 2841f7df2e56Smrg IdleTimeBracketValues); 284205b261ecSmrg 2843f7df2e56Smrg if (idle_time_counter != NULL) { 2844f7df2e56Smrg IdleCounterPriv *priv = malloc(sizeof(IdleCounterPriv)); 284505b261ecSmrg 2846f7df2e56Smrg priv->value_less = priv->value_greater = NULL; 2847f7df2e56Smrg priv->deviceid = deviceid; 2848f7df2e56Smrg 2849f7df2e56Smrg idle_time_counter->pSysCounterInfo->private = priv; 2850f7df2e56Smrg } 2851f7df2e56Smrg 2852f7df2e56Smrg return idle_time_counter; 2853f7df2e56Smrg} 2854f7df2e56Smrg 2855f7df2e56Smrgstatic void 2856f7df2e56SmrgSyncInitIdleTime(void) 2857f7df2e56Smrg{ 2858f7df2e56Smrg init_system_idle_counter("IDLETIME", XIAllDevices); 2859f7df2e56Smrg} 2860f7df2e56Smrg 2861f7df2e56SmrgSyncCounter* 2862f7df2e56SmrgSyncInitDeviceIdleTime(DeviceIntPtr dev) 2863f7df2e56Smrg{ 2864f7df2e56Smrg char timer_name[64]; 2865f7df2e56Smrg sprintf(timer_name, "DEVICEIDLETIME %d", dev->id); 2866f7df2e56Smrg 2867f7df2e56Smrg return init_system_idle_counter(timer_name, dev->id); 2868f7df2e56Smrg} 2869f7df2e56Smrg 2870f7df2e56Smrgvoid SyncRemoveDeviceIdleTime(SyncCounter *counter) 2871f7df2e56Smrg{ 2872f7df2e56Smrg /* FreeAllResources() frees all system counters before the devices are 2873f7df2e56Smrg shut down, check if there are any left before freeing the device's 2874f7df2e56Smrg counter */ 2875f7df2e56Smrg if (counter && !xorg_list_is_empty(&SysCounterList)) 2876f7df2e56Smrg xorg_list_del(&counter->pSysCounterInfo->entry); 287705b261ecSmrg} 2878