sync.c revision 1b684552
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 2705b261ecSmrg 2805b261ecSmrgCopyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, 2905b261ecSmrgand Olivetti Research Limited, Cambridge, England. 3005b261ecSmrg 3105b261ecSmrg All Rights Reserved 3205b261ecSmrg 3305b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3405b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3505b261ecSmrgprovided that the above copyright notice appear in all copies and that 3605b261ecSmrgboth that copyright notice and this permission notice appear in 374202a189Smrgsupporting documentation, and that the names of Digital or Olivetti 3805b261ecSmrgnot be used in advertising or publicity pertaining to distribution of the 3905b261ecSmrgsoftware without specific, written prior permission. Digital and Olivetti 4005b261ecSmrgmake no representations about the suitability of this software 4105b261ecSmrgfor any purpose. It is provided "as is" without express or implied warranty. 4205b261ecSmrg 4305b261ecSmrgDIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 4405b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 4505b261ecSmrgFITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR 4605b261ecSmrgCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 4705b261ecSmrgUSE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 4805b261ecSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 4905b261ecSmrgPERFORMANCE OF THIS SOFTWARE. 5005b261ecSmrg 5105b261ecSmrg*/ 5205b261ecSmrg 5305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5405b261ecSmrg#include <dix-config.h> 5505b261ecSmrg#endif 5605b261ecSmrg 5705b261ecSmrg#include <string.h> 5805b261ecSmrg 5905b261ecSmrg#include <X11/X.h> 6005b261ecSmrg#include <X11/Xproto.h> 6105b261ecSmrg#include <X11/Xmd.h> 6205b261ecSmrg#include "misc.h" 6305b261ecSmrg#include "os.h" 6405b261ecSmrg#include "extnsionst.h" 6505b261ecSmrg#include "dixstruct.h" 6605b261ecSmrg#include "resource.h" 6705b261ecSmrg#include "opaque.h" 684202a189Smrg#include <X11/extensions/syncproto.h> 694202a189Smrg#include "syncsrv.h" 701b684552Smrg#include "protocol-versions.h" 7105b261ecSmrg 7205b261ecSmrg#include <stdio.h> 73637ac9abSmrg#if !defined(WIN32) 7405b261ecSmrg#include <sys/time.h> 7505b261ecSmrg#endif 7605b261ecSmrg 7705b261ecSmrg#include "modinit.h" 7805b261ecSmrg 7905b261ecSmrg/* 8005b261ecSmrg * Local Global Variables 8105b261ecSmrg */ 8205b261ecSmrgstatic int SyncEventBase; 8305b261ecSmrgstatic int SyncErrorBase; 8405b261ecSmrgstatic RESTYPE RTCounter = 0; 8505b261ecSmrgstatic RESTYPE RTAwait; 8605b261ecSmrgstatic RESTYPE RTAlarm; 8705b261ecSmrgstatic RESTYPE RTAlarmClient; 8805b261ecSmrgstatic int SyncNumSystemCounters = 0; 8905b261ecSmrgstatic SyncCounter **SysCounterList = NULL; 9005b261ecSmrg 9105b261ecSmrg#define IsSystemCounter(pCounter) \ 9205b261ecSmrg (pCounter && (pCounter->client == NULL)) 9305b261ecSmrg 9405b261ecSmrg/* these are all the alarm attributes that pertain to the alarm's trigger */ 9505b261ecSmrg#define XSyncCAAllTrigger \ 9605b261ecSmrg (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) 9705b261ecSmrg 984202a189Smrgstatic void SyncComputeBracketValues(SyncCounter *); 9905b261ecSmrg 1004202a189Smrgstatic void SyncInitServerTime(void); 10105b261ecSmrg 1024202a189Smrgstatic void SyncInitIdleTime(void); 10305b261ecSmrg 10405b261ecSmrgstatic DISPATCH_PROC(ProcSyncAwait); 10505b261ecSmrgstatic DISPATCH_PROC(ProcSyncChangeAlarm); 10605b261ecSmrgstatic DISPATCH_PROC(ProcSyncChangeCounter); 10705b261ecSmrgstatic DISPATCH_PROC(ProcSyncCreateAlarm); 10805b261ecSmrgstatic DISPATCH_PROC(ProcSyncCreateCounter); 10905b261ecSmrgstatic DISPATCH_PROC(ProcSyncDestroyAlarm); 11005b261ecSmrgstatic DISPATCH_PROC(ProcSyncDestroyCounter); 11105b261ecSmrgstatic DISPATCH_PROC(ProcSyncDispatch); 11205b261ecSmrgstatic DISPATCH_PROC(ProcSyncGetPriority); 11305b261ecSmrgstatic DISPATCH_PROC(ProcSyncInitialize); 11405b261ecSmrgstatic DISPATCH_PROC(ProcSyncListSystemCounters); 11505b261ecSmrgstatic DISPATCH_PROC(ProcSyncQueryAlarm); 11605b261ecSmrgstatic DISPATCH_PROC(ProcSyncQueryCounter); 11705b261ecSmrgstatic DISPATCH_PROC(ProcSyncSetCounter); 11805b261ecSmrgstatic DISPATCH_PROC(ProcSyncSetPriority); 11905b261ecSmrgstatic DISPATCH_PROC(SProcSyncAwait); 12005b261ecSmrgstatic DISPATCH_PROC(SProcSyncChangeAlarm); 12105b261ecSmrgstatic DISPATCH_PROC(SProcSyncChangeCounter); 12205b261ecSmrgstatic DISPATCH_PROC(SProcSyncCreateAlarm); 12305b261ecSmrgstatic DISPATCH_PROC(SProcSyncCreateCounter); 12405b261ecSmrgstatic DISPATCH_PROC(SProcSyncDestroyAlarm); 12505b261ecSmrgstatic DISPATCH_PROC(SProcSyncDestroyCounter); 12605b261ecSmrgstatic DISPATCH_PROC(SProcSyncDispatch); 12705b261ecSmrgstatic DISPATCH_PROC(SProcSyncGetPriority); 12805b261ecSmrgstatic DISPATCH_PROC(SProcSyncInitialize); 12905b261ecSmrgstatic DISPATCH_PROC(SProcSyncListSystemCounters); 13005b261ecSmrgstatic DISPATCH_PROC(SProcSyncQueryAlarm); 13105b261ecSmrgstatic DISPATCH_PROC(SProcSyncQueryCounter); 13205b261ecSmrgstatic DISPATCH_PROC(SProcSyncSetCounter); 13305b261ecSmrgstatic DISPATCH_PROC(SProcSyncSetPriority); 13405b261ecSmrg 13505b261ecSmrg/* Each counter maintains a simple linked list of triggers that are 13605b261ecSmrg * interested in the counter. The two functions below are used to 13705b261ecSmrg * delete and add triggers on this list. 13805b261ecSmrg */ 13905b261ecSmrgstatic void 1404202a189SmrgSyncDeleteTriggerFromCounter(SyncTrigger *pTrigger) 14105b261ecSmrg{ 14205b261ecSmrg SyncTriggerList *pCur; 14305b261ecSmrg SyncTriggerList *pPrev; 14405b261ecSmrg 14505b261ecSmrg /* pCounter needs to be stored in pTrigger before calling here. */ 14605b261ecSmrg 14705b261ecSmrg if (!pTrigger->pCounter) 14805b261ecSmrg return; 14905b261ecSmrg 15005b261ecSmrg pPrev = NULL; 15105b261ecSmrg pCur = pTrigger->pCounter->pTriglist; 15205b261ecSmrg 15305b261ecSmrg while (pCur) 15405b261ecSmrg { 15505b261ecSmrg if (pCur->pTrigger == pTrigger) 15605b261ecSmrg { 15705b261ecSmrg if (pPrev) 15805b261ecSmrg pPrev->next = pCur->next; 15905b261ecSmrg else 16005b261ecSmrg pTrigger->pCounter->pTriglist = pCur->next; 1614202a189Smrg 1624202a189Smrg free(pCur); 16305b261ecSmrg break; 16405b261ecSmrg } 16505b261ecSmrg 16605b261ecSmrg pPrev = pCur; 16705b261ecSmrg pCur = pCur->next; 16805b261ecSmrg } 1694202a189Smrg 17005b261ecSmrg if (IsSystemCounter(pTrigger->pCounter)) 1714202a189Smrg SyncComputeBracketValues(pTrigger->pCounter); 17205b261ecSmrg} 17305b261ecSmrg 17405b261ecSmrg 17505b261ecSmrgstatic int 1764202a189SmrgSyncAddTriggerToCounter(SyncTrigger *pTrigger) 17705b261ecSmrg{ 17805b261ecSmrg SyncTriggerList *pCur; 17905b261ecSmrg 18005b261ecSmrg if (!pTrigger->pCounter) 18105b261ecSmrg return Success; 18205b261ecSmrg 18305b261ecSmrg /* don't do anything if it's already there */ 18405b261ecSmrg for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) 18505b261ecSmrg { 18605b261ecSmrg if (pCur->pTrigger == pTrigger) 18705b261ecSmrg return Success; 18805b261ecSmrg } 18905b261ecSmrg 1904202a189Smrg if (!(pCur = malloc(sizeof(SyncTriggerList)))) 19105b261ecSmrg return BadAlloc; 19205b261ecSmrg 19305b261ecSmrg pCur->pTrigger = pTrigger; 19405b261ecSmrg pCur->next = pTrigger->pCounter->pTriglist; 19505b261ecSmrg pTrigger->pCounter->pTriglist = pCur; 19605b261ecSmrg 19705b261ecSmrg if (IsSystemCounter(pTrigger->pCounter)) 1984202a189Smrg SyncComputeBracketValues(pTrigger->pCounter); 19905b261ecSmrg 20005b261ecSmrg return Success; 20105b261ecSmrg} 20205b261ecSmrg 20305b261ecSmrg 2044202a189Smrg/* Below are four possible functions that can be plugged into 20505b261ecSmrg * pTrigger->CheckTrigger, corresponding to the four possible 20605b261ecSmrg * test-types. These functions are called after the counter's 20705b261ecSmrg * value changes but are also passed the old counter value 20805b261ecSmrg * so they can inspect both the old and new values. 20905b261ecSmrg * (PositiveTransition and NegativeTransition need to see both 21005b261ecSmrg * pieces of information.) These functions return the truth value 21105b261ecSmrg * of the trigger. 21205b261ecSmrg * 21305b261ecSmrg * All of them include the condition pTrigger->pCounter == NULL. 2144202a189Smrg * This is because the spec says that a trigger with a counter value 21505b261ecSmrg * of None is always TRUE. 21605b261ecSmrg */ 21705b261ecSmrg 21805b261ecSmrgstatic Bool 2194202a189SmrgSyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) 22005b261ecSmrg{ 22105b261ecSmrg return (pTrigger->pCounter == NULL || 22205b261ecSmrg XSyncValueGreaterOrEqual(pTrigger->pCounter->value, 22305b261ecSmrg pTrigger->test_value)); 22405b261ecSmrg} 22505b261ecSmrg 22605b261ecSmrgstatic Bool 2274202a189SmrgSyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) 22805b261ecSmrg{ 22905b261ecSmrg return (pTrigger->pCounter == NULL || 23005b261ecSmrg XSyncValueLessOrEqual(pTrigger->pCounter->value, 23105b261ecSmrg pTrigger->test_value)); 23205b261ecSmrg} 23305b261ecSmrg 23405b261ecSmrgstatic Bool 2354202a189SmrgSyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) 23605b261ecSmrg{ 23705b261ecSmrg return (pTrigger->pCounter == NULL || 23805b261ecSmrg (XSyncValueLessThan(oldval, pTrigger->test_value) && 23905b261ecSmrg XSyncValueGreaterOrEqual(pTrigger->pCounter->value, 24005b261ecSmrg pTrigger->test_value))); 24105b261ecSmrg} 24205b261ecSmrg 24305b261ecSmrgstatic Bool 2444202a189SmrgSyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) 24505b261ecSmrg{ 24605b261ecSmrg return (pTrigger->pCounter == NULL || 24705b261ecSmrg (XSyncValueGreaterThan(oldval, pTrigger->test_value) && 24805b261ecSmrg XSyncValueLessOrEqual(pTrigger->pCounter->value, 24905b261ecSmrg pTrigger->test_value))); 25005b261ecSmrg} 25105b261ecSmrg 2524202a189Smrgstatic int 2534202a189SmrgSyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter, 2544202a189Smrg Mask changes) 25505b261ecSmrg{ 25605b261ecSmrg SyncCounter *pCounter = pTrigger->pCounter; 257637ac9abSmrg int rc; 25805b261ecSmrg Bool newcounter = FALSE; 25905b261ecSmrg 26005b261ecSmrg if (changes & XSyncCACounter) 26105b261ecSmrg { 26205b261ecSmrg if (counter == None) 26305b261ecSmrg pCounter = NULL; 264f241d193Smrg else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, 265637ac9abSmrg counter, RTCounter, client, DixReadAccess))) 26605b261ecSmrg { 26705b261ecSmrg client->errorValue = counter; 2684202a189Smrg return rc; 26905b261ecSmrg } 27005b261ecSmrg if (pCounter != pTrigger->pCounter) 27105b261ecSmrg { /* new counter for trigger */ 27205b261ecSmrg SyncDeleteTriggerFromCounter(pTrigger); 27305b261ecSmrg pTrigger->pCounter = pCounter; 27405b261ecSmrg newcounter = TRUE; 27505b261ecSmrg } 27605b261ecSmrg } 27705b261ecSmrg 27805b261ecSmrg /* if system counter, ask it what the current value is */ 27905b261ecSmrg 28005b261ecSmrg if (IsSystemCounter(pCounter)) 28105b261ecSmrg { 28205b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 28305b261ecSmrg &pCounter->value); 28405b261ecSmrg } 28505b261ecSmrg 28605b261ecSmrg if (changes & XSyncCAValueType) 28705b261ecSmrg { 28805b261ecSmrg if (pTrigger->value_type != XSyncRelative && 28905b261ecSmrg pTrigger->value_type != XSyncAbsolute) 29005b261ecSmrg { 29105b261ecSmrg client->errorValue = pTrigger->value_type; 29205b261ecSmrg return BadValue; 29305b261ecSmrg } 29405b261ecSmrg } 29505b261ecSmrg 29605b261ecSmrg if (changes & XSyncCATestType) 29705b261ecSmrg { 29805b261ecSmrg if (pTrigger->test_type != XSyncPositiveTransition && 29905b261ecSmrg pTrigger->test_type != XSyncNegativeTransition && 30005b261ecSmrg pTrigger->test_type != XSyncPositiveComparison && 30105b261ecSmrg pTrigger->test_type != XSyncNegativeComparison) 30205b261ecSmrg { 30305b261ecSmrg client->errorValue = pTrigger->test_type; 30405b261ecSmrg return BadValue; 30505b261ecSmrg } 30605b261ecSmrg /* select appropriate CheckTrigger function */ 30705b261ecSmrg 30805b261ecSmrg switch (pTrigger->test_type) 30905b261ecSmrg { 3104202a189Smrg case XSyncPositiveTransition: 31105b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; 31205b261ecSmrg break; 3134202a189Smrg case XSyncNegativeTransition: 31405b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; 31505b261ecSmrg break; 3164202a189Smrg case XSyncPositiveComparison: 31705b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; 31805b261ecSmrg break; 3194202a189Smrg case XSyncNegativeComparison: 32005b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; 32105b261ecSmrg break; 32205b261ecSmrg } 32305b261ecSmrg } 32405b261ecSmrg 32505b261ecSmrg if (changes & (XSyncCAValueType | XSyncCAValue)) 32605b261ecSmrg { 32705b261ecSmrg if (pTrigger->value_type == XSyncAbsolute) 32805b261ecSmrg pTrigger->test_value = pTrigger->wait_value; 32905b261ecSmrg else /* relative */ 33005b261ecSmrg { 33105b261ecSmrg Bool overflow; 33205b261ecSmrg if (pCounter == NULL) 33305b261ecSmrg return BadMatch; 33405b261ecSmrg 3354202a189Smrg XSyncValueAdd(&pTrigger->test_value, pCounter->value, 33605b261ecSmrg pTrigger->wait_value, &overflow); 33705b261ecSmrg if (overflow) 33805b261ecSmrg { 33905b261ecSmrg client->errorValue = XSyncValueHigh32(pTrigger->wait_value); 34005b261ecSmrg return BadValue; 34105b261ecSmrg } 34205b261ecSmrg } 34305b261ecSmrg } 34405b261ecSmrg 34505b261ecSmrg /* we wait until we're sure there are no errors before registering 34605b261ecSmrg * a new counter on a trigger 34705b261ecSmrg */ 34805b261ecSmrg if (newcounter) 34905b261ecSmrg { 350637ac9abSmrg if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) 351637ac9abSmrg return rc; 35205b261ecSmrg } 35305b261ecSmrg else if (IsSystemCounter(pCounter)) 35405b261ecSmrg { 3554202a189Smrg SyncComputeBracketValues(pCounter); 35605b261ecSmrg } 3574202a189Smrg 35805b261ecSmrg return Success; 35905b261ecSmrg} 36005b261ecSmrg 36105b261ecSmrg/* AlarmNotify events happen in response to actions taken on an Alarm or 3624202a189Smrg * the counter used by the alarm. AlarmNotify may be sent to multiple 36305b261ecSmrg * clients. The alarm maintains a list of clients interested in events. 36405b261ecSmrg */ 36505b261ecSmrgstatic void 3664202a189SmrgSyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) 36705b261ecSmrg{ 36805b261ecSmrg SyncAlarmClientList *pcl; 36905b261ecSmrg xSyncAlarmNotifyEvent ane; 37005b261ecSmrg SyncTrigger *pTrigger = &pAlarm->trigger; 37105b261ecSmrg 37205b261ecSmrg UpdateCurrentTime(); 37305b261ecSmrg 37405b261ecSmrg ane.type = SyncEventBase + XSyncAlarmNotify; 37505b261ecSmrg ane.kind = XSyncAlarmNotify; 37605b261ecSmrg ane.alarm = pAlarm->alarm_id; 37705b261ecSmrg if (pTrigger->pCounter) 37805b261ecSmrg { 37905b261ecSmrg ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); 38005b261ecSmrg ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); 38105b261ecSmrg } 38205b261ecSmrg else 38305b261ecSmrg { /* XXX what else can we do if there's no counter? */ 38405b261ecSmrg ane.counter_value_hi = ane.counter_value_lo = 0; 38505b261ecSmrg } 38605b261ecSmrg 38705b261ecSmrg ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); 38805b261ecSmrg ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); 38905b261ecSmrg ane.time = currentTime.milliseconds; 39005b261ecSmrg ane.state = pAlarm->state; 39105b261ecSmrg 39205b261ecSmrg /* send to owner */ 3934202a189Smrg if (pAlarm->events) 39405b261ecSmrg WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); 39505b261ecSmrg 39605b261ecSmrg /* send to other interested clients */ 39705b261ecSmrg for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) 3984202a189Smrg WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); 39905b261ecSmrg} 40005b261ecSmrg 40105b261ecSmrg 4024202a189Smrg/* CounterNotify events only occur in response to an Await. The events 40305b261ecSmrg * go only to the Awaiting client. 40405b261ecSmrg */ 40505b261ecSmrgstatic void 4064202a189SmrgSyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, 4074202a189Smrg int num_events) 40805b261ecSmrg{ 40905b261ecSmrg xSyncCounterNotifyEvent *pEvents, *pev; 41005b261ecSmrg int i; 41105b261ecSmrg 41205b261ecSmrg if (client->clientGone) 41305b261ecSmrg return; 4144202a189Smrg pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent)); 4154202a189Smrg if (!pEvents) 41605b261ecSmrg return; 41705b261ecSmrg UpdateCurrentTime(); 41805b261ecSmrg for (i = 0; i < num_events; i++, ppAwait++, pev++) 41905b261ecSmrg { 42005b261ecSmrg SyncTrigger *pTrigger = &(*ppAwait)->trigger; 42105b261ecSmrg pev->type = SyncEventBase + XSyncCounterNotify; 42205b261ecSmrg pev->kind = XSyncCounterNotify; 42305b261ecSmrg pev->counter = pTrigger->pCounter->id; 42405b261ecSmrg pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); 42505b261ecSmrg pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 42605b261ecSmrg pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); 42705b261ecSmrg pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); 42805b261ecSmrg pev->time = currentTime.milliseconds; 42905b261ecSmrg pev->count = num_events - i - 1; /* events remaining */ 43005b261ecSmrg pev->destroyed = pTrigger->pCounter->beingDestroyed; 43105b261ecSmrg } 43205b261ecSmrg /* swapping will be taken care of by this */ 43305b261ecSmrg WriteEventsToClient(client, num_events, (xEvent *)pEvents); 4344202a189Smrg free(pEvents); 43505b261ecSmrg} 43605b261ecSmrg 43705b261ecSmrg 43805b261ecSmrg/* This function is called when an alarm's counter is destroyed. 43905b261ecSmrg * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). 44005b261ecSmrg */ 4414202a189Smrgstatic void 4424202a189SmrgSyncAlarmCounterDestroyed(SyncTrigger *pTrigger) 44305b261ecSmrg{ 44405b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 44505b261ecSmrg 44605b261ecSmrg pAlarm->state = XSyncAlarmInactive; 44705b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 44805b261ecSmrg pTrigger->pCounter = NULL; 44905b261ecSmrg} 45005b261ecSmrg 45105b261ecSmrg 4524202a189Smrg/* This function is called when an alarm "goes off." 45305b261ecSmrg * It is plugged into pTrigger->TriggerFired (for alarm triggers). 45405b261ecSmrg */ 45505b261ecSmrgstatic void 4564202a189SmrgSyncAlarmTriggerFired(SyncTrigger *pTrigger) 45705b261ecSmrg{ 45805b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 45905b261ecSmrg CARD64 new_test_value; 46005b261ecSmrg 46105b261ecSmrg /* no need to check alarm unless it's active */ 46205b261ecSmrg if (pAlarm->state != XSyncAlarmActive) 46305b261ecSmrg return; 46405b261ecSmrg 46505b261ecSmrg /* " if the counter value is None, or if the delta is 0 and 46605b261ecSmrg * the test-type is PositiveComparison or NegativeComparison, 46705b261ecSmrg * no change is made to value (test-value) and the alarm 46805b261ecSmrg * state is changed to Inactive before the event is generated." 46905b261ecSmrg */ 47005b261ecSmrg if (pAlarm->trigger.pCounter == NULL 47105b261ecSmrg || (XSyncValueIsZero(pAlarm->delta) 47205b261ecSmrg && (pAlarm->trigger.test_type == XSyncPositiveComparison 47305b261ecSmrg || pAlarm->trigger.test_type == XSyncNegativeComparison))) 47405b261ecSmrg pAlarm->state = XSyncAlarmInactive; 47505b261ecSmrg 47605b261ecSmrg new_test_value = pAlarm->trigger.test_value; 47705b261ecSmrg 47805b261ecSmrg if (pAlarm->state == XSyncAlarmActive) 47905b261ecSmrg { 48005b261ecSmrg Bool overflow; 48105b261ecSmrg CARD64 oldvalue; 48205b261ecSmrg SyncTrigger *paTrigger = &pAlarm->trigger; 48305b261ecSmrg 48405b261ecSmrg /* "The alarm is updated by repeatedly adding delta to the 48505b261ecSmrg * value of the trigger and re-initializing it until it 48605b261ecSmrg * becomes FALSE." 48705b261ecSmrg */ 48805b261ecSmrg oldvalue = paTrigger->test_value; 48905b261ecSmrg 49005b261ecSmrg /* XXX really should do something smarter here */ 49105b261ecSmrg 49205b261ecSmrg do 49305b261ecSmrg { 49405b261ecSmrg XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, 49505b261ecSmrg pAlarm->delta, &overflow); 4964202a189Smrg } while (!overflow && 49705b261ecSmrg (*paTrigger->CheckTrigger)(paTrigger, 49805b261ecSmrg paTrigger->pCounter->value)); 49905b261ecSmrg 50005b261ecSmrg new_test_value = paTrigger->test_value; 50105b261ecSmrg paTrigger->test_value = oldvalue; 50205b261ecSmrg 50305b261ecSmrg /* "If this update would cause value to fall outside the range 50405b261ecSmrg * for an INT64...no change is made to value (test-value) and 50505b261ecSmrg * the alarm state is changed to Inactive before the event is 50605b261ecSmrg * generated." 50705b261ecSmrg */ 50805b261ecSmrg if (overflow) 50905b261ecSmrg { 51005b261ecSmrg new_test_value = oldvalue; 51105b261ecSmrg pAlarm->state = XSyncAlarmInactive; 51205b261ecSmrg } 51305b261ecSmrg } 51405b261ecSmrg /* The AlarmNotify event has to have the "new state of the alarm" 51505b261ecSmrg * which we can't be sure of until this point. However, it has 51605b261ecSmrg * to have the "old" trigger test value. That's the reason for 51705b261ecSmrg * all the newvalue/oldvalue shuffling above. After we send the 51805b261ecSmrg * events, give the trigger its new test value. 51905b261ecSmrg */ 52005b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 52105b261ecSmrg pTrigger->test_value = new_test_value; 52205b261ecSmrg} 52305b261ecSmrg 52405b261ecSmrg 52505b261ecSmrg/* This function is called when an Await unblocks, either as a result 52605b261ecSmrg * of the trigger firing OR the counter being destroyed. 52705b261ecSmrg * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed 52805b261ecSmrg * (for Await triggers). 52905b261ecSmrg */ 53005b261ecSmrgstatic void 5314202a189SmrgSyncAwaitTriggerFired(SyncTrigger *pTrigger) 53205b261ecSmrg{ 53305b261ecSmrg SyncAwait *pAwait = (SyncAwait *)pTrigger; 53405b261ecSmrg int numwaits; 53505b261ecSmrg SyncAwaitUnion *pAwaitUnion; 53605b261ecSmrg SyncAwait **ppAwait; 53705b261ecSmrg int num_events = 0; 53805b261ecSmrg 53905b261ecSmrg pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; 54005b261ecSmrg numwaits = pAwaitUnion->header.num_waitconditions; 5414202a189Smrg ppAwait = malloc(numwaits * sizeof(SyncAwait *)); 54205b261ecSmrg if (!ppAwait) 54305b261ecSmrg goto bail; 54405b261ecSmrg 54505b261ecSmrg pAwait = &(pAwaitUnion+1)->await; 54605b261ecSmrg 54705b261ecSmrg /* "When a client is unblocked, all the CounterNotify events for 54805b261ecSmrg * the Await request are generated contiguously. If count is 0 54905b261ecSmrg * there are no more events to follow for this request. If 55005b261ecSmrg * count is n, there are at least n more events to follow." 55105b261ecSmrg * 55205b261ecSmrg * Thus, it is best to find all the counters for which events 55305b261ecSmrg * need to be sent first, so that an accurate count field can 55405b261ecSmrg * be stored in the events. 55505b261ecSmrg */ 55605b261ecSmrg for ( ; numwaits; numwaits--, pAwait++) 55705b261ecSmrg { 55805b261ecSmrg CARD64 diff; 55905b261ecSmrg Bool overflow, diffgreater, diffequal; 56005b261ecSmrg 56105b261ecSmrg /* "A CounterNotify event with the destroyed flag set to TRUE is 56205b261ecSmrg * always generated if the counter for one of the triggers is 56305b261ecSmrg * destroyed." 56405b261ecSmrg */ 56505b261ecSmrg if (pAwait->trigger.pCounter->beingDestroyed) 56605b261ecSmrg { 56705b261ecSmrg ppAwait[num_events++] = pAwait; 56805b261ecSmrg continue; 56905b261ecSmrg } 57005b261ecSmrg 57105b261ecSmrg /* "The difference between the counter and the test value is 57205b261ecSmrg * calculated by subtracting the test value from the value of 57305b261ecSmrg * the counter." 57405b261ecSmrg */ 57505b261ecSmrg XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, 57605b261ecSmrg pAwait->trigger.test_value, &overflow); 57705b261ecSmrg 57805b261ecSmrg /* "If the difference lies outside the range for an INT64, an 57905b261ecSmrg * event is not generated." 58005b261ecSmrg */ 58105b261ecSmrg if (overflow) 58205b261ecSmrg continue; 58305b261ecSmrg diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); 58405b261ecSmrg diffequal = XSyncValueEqual(diff, pAwait->event_threshold); 58505b261ecSmrg 58605b261ecSmrg /* "If the test-type is PositiveTransition or 58705b261ecSmrg * PositiveComparison, a CounterNotify event is generated if 58805b261ecSmrg * the difference is at least event-threshold. If the test-type 58905b261ecSmrg * is NegativeTransition or NegativeComparison, a CounterNotify 59005b261ecSmrg * event is generated if the difference is at most 59105b261ecSmrg * event-threshold." 59205b261ecSmrg */ 59305b261ecSmrg 59405b261ecSmrg if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || 59505b261ecSmrg pAwait->trigger.test_type == XSyncPositiveTransition) 59605b261ecSmrg && (diffgreater || diffequal)) 59705b261ecSmrg || 59805b261ecSmrg ((pAwait->trigger.test_type == XSyncNegativeComparison || 59905b261ecSmrg pAwait->trigger.test_type == XSyncNegativeTransition) 60005b261ecSmrg && (!diffgreater) /* less or equal */ 60105b261ecSmrg ) 60205b261ecSmrg ) 60305b261ecSmrg { 60405b261ecSmrg ppAwait[num_events++] = pAwait; 60505b261ecSmrg } 60605b261ecSmrg } 60705b261ecSmrg if (num_events) 60805b261ecSmrg SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, 60905b261ecSmrg num_events); 6104202a189Smrg free(ppAwait); 61105b261ecSmrg 61205b261ecSmrgbail: 61305b261ecSmrg /* unblock the client */ 61405b261ecSmrg AttendClient(pAwaitUnion->header.client); 61505b261ecSmrg /* delete the await */ 61605b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 61705b261ecSmrg} 61805b261ecSmrg 61905b261ecSmrg 62005b261ecSmrg/* This function should always be used to change a counter's value so that 62105b261ecSmrg * any triggers depending on the counter will be checked. 62205b261ecSmrg */ 62305b261ecSmrgvoid 6244202a189SmrgSyncChangeCounter(SyncCounter *pCounter, CARD64 newval) 62505b261ecSmrg{ 62605b261ecSmrg SyncTriggerList *ptl, *pnext; 62705b261ecSmrg CARD64 oldval; 62805b261ecSmrg 62905b261ecSmrg oldval = pCounter->value; 63005b261ecSmrg pCounter->value = newval; 63105b261ecSmrg 63205b261ecSmrg /* run through triggers to see if any become true */ 63305b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 63405b261ecSmrg { 63505b261ecSmrg pnext = ptl->next; 63605b261ecSmrg if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) 63705b261ecSmrg (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); 63805b261ecSmrg } 63905b261ecSmrg 64005b261ecSmrg if (IsSystemCounter(pCounter)) 64105b261ecSmrg { 6424202a189Smrg SyncComputeBracketValues(pCounter); 64305b261ecSmrg } 64405b261ecSmrg} 64505b261ecSmrg 64605b261ecSmrg 64705b261ecSmrg/* loosely based on dix/events.c/EventSelectForWindow */ 64805b261ecSmrgstatic Bool 6494202a189SmrgSyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) 65005b261ecSmrg{ 65105b261ecSmrg SyncAlarmClientList *pClients; 65205b261ecSmrg 65305b261ecSmrg if (client == pAlarm->client) /* alarm owner */ 65405b261ecSmrg { 65505b261ecSmrg pAlarm->events = wantevents; 65605b261ecSmrg return Success; 65705b261ecSmrg } 65805b261ecSmrg 65905b261ecSmrg /* see if the client is already on the list (has events selected) */ 66005b261ecSmrg 66105b261ecSmrg for (pClients = pAlarm->pEventClients; pClients; 66205b261ecSmrg pClients = pClients->next) 66305b261ecSmrg { 66405b261ecSmrg if (pClients->client == client) 66505b261ecSmrg { 6664202a189Smrg /* client's presence on the list indicates desire for 6674202a189Smrg * events. If the client doesn't want events, remove it 66805b261ecSmrg * from the list. If the client does want events, do 66905b261ecSmrg * nothing, since it's already got them. 67005b261ecSmrg */ 67105b261ecSmrg if (!wantevents) 67205b261ecSmrg { 67305b261ecSmrg FreeResource(pClients->delete_id, RT_NONE); 67405b261ecSmrg } 67505b261ecSmrg return Success; 67605b261ecSmrg } 67705b261ecSmrg } 67805b261ecSmrg 67905b261ecSmrg /* if we get here, this client does not currently have 68005b261ecSmrg * events selected on the alarm 68105b261ecSmrg */ 68205b261ecSmrg 68305b261ecSmrg if (!wantevents) 6844202a189Smrg /* client doesn't want events, and we just discovered that it 68505b261ecSmrg * doesn't have them, so there's nothing to do. 68605b261ecSmrg */ 68705b261ecSmrg return Success; 68805b261ecSmrg 68905b261ecSmrg /* add new client to pAlarm->pEventClients */ 69005b261ecSmrg 6914202a189Smrg pClients = malloc(sizeof(SyncAlarmClientList)); 69205b261ecSmrg if (!pClients) 69305b261ecSmrg return BadAlloc; 69405b261ecSmrg 6954202a189Smrg /* register it as a resource so it will be cleaned up 69605b261ecSmrg * if the client dies 69705b261ecSmrg */ 69805b261ecSmrg 69905b261ecSmrg pClients->delete_id = FakeClientID(client->index); 70005b261ecSmrg if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) 70105b261ecSmrg { 7024202a189Smrg free(pClients); 70305b261ecSmrg return BadAlloc; 70405b261ecSmrg } 70505b261ecSmrg 70605b261ecSmrg /* link it into list after we know all the allocations succeed */ 70705b261ecSmrg 70805b261ecSmrg pClients->next = pAlarm->pEventClients; 70905b261ecSmrg pAlarm->pEventClients = pClients; 71005b261ecSmrg pClients->client = client; 71105b261ecSmrg return Success; 71205b261ecSmrg} 71305b261ecSmrg 71405b261ecSmrg/* 71505b261ecSmrg * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm 71605b261ecSmrg */ 7174202a189Smrgstatic int 7184202a189SmrgSyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, 7194202a189Smrg CARD32 *values) 72005b261ecSmrg{ 72105b261ecSmrg int status; 72205b261ecSmrg XSyncCounter counter; 72305b261ecSmrg Mask origmask = mask; 72405b261ecSmrg 72505b261ecSmrg counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; 72605b261ecSmrg 72705b261ecSmrg while (mask) 72805b261ecSmrg { 72905b261ecSmrg int index2 = lowbit(mask); 73005b261ecSmrg mask &= ~index2; 73105b261ecSmrg switch (index2) 73205b261ecSmrg { 73305b261ecSmrg case XSyncCACounter: 73405b261ecSmrg mask &= ~XSyncCACounter; 73505b261ecSmrg /* sanity check in SyncInitTrigger */ 73605b261ecSmrg counter = *values++; 73705b261ecSmrg break; 73805b261ecSmrg 73905b261ecSmrg case XSyncCAValueType: 74005b261ecSmrg mask &= ~XSyncCAValueType; 74105b261ecSmrg /* sanity check in SyncInitTrigger */ 74205b261ecSmrg pAlarm->trigger.value_type = *values++; 74305b261ecSmrg break; 74405b261ecSmrg 74505b261ecSmrg case XSyncCAValue: 74605b261ecSmrg mask &= ~XSyncCAValue; 74705b261ecSmrg XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); 74805b261ecSmrg values += 2; 74905b261ecSmrg break; 75005b261ecSmrg 75105b261ecSmrg case XSyncCATestType: 75205b261ecSmrg mask &= ~XSyncCATestType; 75305b261ecSmrg /* sanity check in SyncInitTrigger */ 75405b261ecSmrg pAlarm->trigger.test_type = *values++; 75505b261ecSmrg break; 75605b261ecSmrg 75705b261ecSmrg case XSyncCADelta: 75805b261ecSmrg mask &= ~XSyncCADelta; 75905b261ecSmrg XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); 76005b261ecSmrg values += 2; 76105b261ecSmrg break; 76205b261ecSmrg 76305b261ecSmrg case XSyncCAEvents: 76405b261ecSmrg mask &= ~XSyncCAEvents; 76505b261ecSmrg if ((*values != xTrue) && (*values != xFalse)) 76605b261ecSmrg { 76705b261ecSmrg client->errorValue = *values; 76805b261ecSmrg return BadValue; 76905b261ecSmrg } 77005b261ecSmrg status = SyncEventSelectForAlarm(pAlarm, client, 77105b261ecSmrg (Bool)(*values++)); 77205b261ecSmrg if (status != Success) 77305b261ecSmrg return status; 77405b261ecSmrg break; 77505b261ecSmrg 77605b261ecSmrg default: 77705b261ecSmrg client->errorValue = mask; 77805b261ecSmrg return BadValue; 77905b261ecSmrg } 78005b261ecSmrg } 78105b261ecSmrg 78205b261ecSmrg /* "If the test-type is PositiveComparison or PositiveTransition 78305b261ecSmrg * and delta is less than zero, or if the test-type is 78405b261ecSmrg * NegativeComparison or NegativeTransition and delta is 78505b261ecSmrg * greater than zero, a Match error is generated." 78605b261ecSmrg */ 78705b261ecSmrg if (origmask & (XSyncCADelta|XSyncCATestType)) 78805b261ecSmrg { 78905b261ecSmrg CARD64 zero; 79005b261ecSmrg XSyncIntToValue(&zero, 0); 79105b261ecSmrg if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || 79205b261ecSmrg (pAlarm->trigger.test_type == XSyncPositiveTransition)) 79305b261ecSmrg && XSyncValueLessThan(pAlarm->delta, zero)) 79405b261ecSmrg || 79505b261ecSmrg (((pAlarm->trigger.test_type == XSyncNegativeComparison) || 79605b261ecSmrg (pAlarm->trigger.test_type == XSyncNegativeTransition)) 79705b261ecSmrg && XSyncValueGreaterThan(pAlarm->delta, zero)) 79805b261ecSmrg ) 79905b261ecSmrg { 80005b261ecSmrg return BadMatch; 80105b261ecSmrg } 80205b261ecSmrg } 80305b261ecSmrg 80405b261ecSmrg /* postpone this until now, when we're sure nothing else can go wrong */ 80505b261ecSmrg if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, 80605b261ecSmrg origmask & XSyncCAAllTrigger)) != Success) 80705b261ecSmrg return status; 80805b261ecSmrg 80905b261ecSmrg /* XXX spec does not really say to do this - needs clarification */ 81005b261ecSmrg pAlarm->state = XSyncAlarmActive; 81105b261ecSmrg return Success; 81205b261ecSmrg} 81305b261ecSmrg 81405b261ecSmrg 81505b261ecSmrgstatic SyncCounter * 8164202a189SmrgSyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) 81705b261ecSmrg{ 81805b261ecSmrg SyncCounter *pCounter; 81905b261ecSmrg 8204202a189Smrg if (!(pCounter = malloc(sizeof(SyncCounter)))) 8214202a189Smrg return NULL; 82205b261ecSmrg 82305b261ecSmrg if (!AddResource(id, RTCounter, (pointer) pCounter)) 82405b261ecSmrg { 8254202a189Smrg free(pCounter); 8264202a189Smrg return NULL; 82705b261ecSmrg } 82805b261ecSmrg 82905b261ecSmrg pCounter->client = client; 83005b261ecSmrg pCounter->id = id; 83105b261ecSmrg pCounter->value = initialvalue; 83205b261ecSmrg pCounter->pTriglist = NULL; 83305b261ecSmrg pCounter->beingDestroyed = FALSE; 83405b261ecSmrg pCounter->pSysCounterInfo = NULL; 83505b261ecSmrg return pCounter; 83605b261ecSmrg} 83705b261ecSmrg 8384202a189Smrgstatic int FreeCounter(void *, XID); 83905b261ecSmrg 84005b261ecSmrg/* 84105b261ecSmrg * ***** System Counter utilities 84205b261ecSmrg */ 84305b261ecSmrg 8444202a189Smrgpointer 8454202a189SmrgSyncCreateSystemCounter( 8464202a189Smrg char *name, 8474202a189Smrg CARD64 initial, 8484202a189Smrg CARD64 resolution, 8494202a189Smrg SyncCounterType counterType, 8504202a189Smrg void (*QueryValue)(pointer /* pCounter */, 8514202a189Smrg CARD64 * /* pValue_return */), 8524202a189Smrg void (*BracketValues)(pointer /* pCounter */, 8534202a189Smrg CARD64 * /* pbracket_less */, 8544202a189Smrg CARD64 * /* pbracket_greater */) 8554202a189Smrg ) 85605b261ecSmrg{ 85705b261ecSmrg SyncCounter *pCounter; 85805b261ecSmrg 8594202a189Smrg SysCounterList = realloc(SysCounterList, 86005b261ecSmrg (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); 86105b261ecSmrg if (!SysCounterList) 8624202a189Smrg return NULL; 86305b261ecSmrg 86405b261ecSmrg /* this function may be called before SYNC has been initialized, so we 86505b261ecSmrg * have to make sure RTCounter is created. 86605b261ecSmrg */ 86705b261ecSmrg if (RTCounter == 0) 86805b261ecSmrg { 8694202a189Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 87005b261ecSmrg if (RTCounter == 0) 87105b261ecSmrg { 8724202a189Smrg return NULL; 87305b261ecSmrg } 87405b261ecSmrg } 87505b261ecSmrg 8764202a189Smrg pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); 87705b261ecSmrg 87805b261ecSmrg if (pCounter) 87905b261ecSmrg { 88005b261ecSmrg SysCounterInfo *psci; 88105b261ecSmrg 8824202a189Smrg psci = malloc(sizeof(SysCounterInfo)); 88305b261ecSmrg if (!psci) 88405b261ecSmrg { 88505b261ecSmrg FreeResource(pCounter->id, RT_NONE); 8864202a189Smrg return pCounter; 88705b261ecSmrg } 88805b261ecSmrg pCounter->pSysCounterInfo = psci; 88905b261ecSmrg psci->name = name; 89005b261ecSmrg psci->resolution = resolution; 89105b261ecSmrg psci->counterType = counterType; 89205b261ecSmrg psci->QueryValue = QueryValue; 89305b261ecSmrg psci->BracketValues = BracketValues; 89405b261ecSmrg XSyncMaxValue(&psci->bracket_greater); 89505b261ecSmrg XSyncMinValue(&psci->bracket_less); 89605b261ecSmrg SysCounterList[SyncNumSystemCounters++] = pCounter; 89705b261ecSmrg } 8984202a189Smrg return pCounter; 89905b261ecSmrg} 90005b261ecSmrg 90105b261ecSmrgvoid 9024202a189SmrgSyncDestroySystemCounter(pointer pSysCounter) 90305b261ecSmrg{ 90405b261ecSmrg SyncCounter *pCounter = (SyncCounter *)pSysCounter; 90505b261ecSmrg FreeResource(pCounter->id, RT_NONE); 90605b261ecSmrg} 90705b261ecSmrg 90805b261ecSmrgstatic void 9094202a189SmrgSyncComputeBracketValues(SyncCounter *pCounter) 91005b261ecSmrg{ 91105b261ecSmrg SyncTriggerList *pCur; 91205b261ecSmrg SyncTrigger *pTrigger; 91305b261ecSmrg SysCounterInfo *psci; 91405b261ecSmrg CARD64 *pnewgtval = NULL; 91505b261ecSmrg CARD64 *pnewltval = NULL; 91605b261ecSmrg SyncCounterType ct; 91705b261ecSmrg 91805b261ecSmrg if (!pCounter) 91905b261ecSmrg return; 92005b261ecSmrg 92105b261ecSmrg psci = pCounter->pSysCounterInfo; 92205b261ecSmrg ct = pCounter->pSysCounterInfo->counterType; 92305b261ecSmrg if (ct == XSyncCounterNeverChanges) 92405b261ecSmrg return; 92505b261ecSmrg 9264202a189Smrg XSyncMaxValue(&psci->bracket_greater); 9274202a189Smrg XSyncMinValue(&psci->bracket_less); 92805b261ecSmrg 92905b261ecSmrg for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) 93005b261ecSmrg { 93105b261ecSmrg pTrigger = pCur->pTrigger; 93205b261ecSmrg 93305b261ecSmrg if (pTrigger->test_type == XSyncPositiveComparison && 93405b261ecSmrg ct != XSyncCounterNeverIncreases) 93505b261ecSmrg { 93605b261ecSmrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 93705b261ecSmrg XSyncValueLessThan(pTrigger->test_value, 93805b261ecSmrg psci->bracket_greater)) 93905b261ecSmrg { 94005b261ecSmrg psci->bracket_greater = pTrigger->test_value; 94105b261ecSmrg pnewgtval = &psci->bracket_greater; 94205b261ecSmrg } 94305b261ecSmrg } 94405b261ecSmrg else if (pTrigger->test_type == XSyncNegativeComparison && 94505b261ecSmrg ct != XSyncCounterNeverDecreases) 94605b261ecSmrg { 94705b261ecSmrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 94805b261ecSmrg XSyncValueGreaterThan(pTrigger->test_value, 94905b261ecSmrg psci->bracket_less)) 95005b261ecSmrg { 95105b261ecSmrg psci->bracket_less = pTrigger->test_value; 95205b261ecSmrg pnewltval = &psci->bracket_less; 95305b261ecSmrg } 95405b261ecSmrg } 955a0d10bb6Smrg else if (pTrigger->test_type == XSyncNegativeTransition && 95605b261ecSmrg ct != XSyncCounterNeverIncreases) 957a0d10bb6Smrg { 958a0d10bb6Smrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 959a0d10bb6Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) 960a0d10bb6Smrg { 961a0d10bb6Smrg psci->bracket_less = pTrigger->test_value; 962a0d10bb6Smrg pnewltval = &psci->bracket_less; 9631b684552Smrg } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) && 9641b684552Smrg XSyncValueLessThan(pTrigger->test_value, 9651b684552Smrg psci->bracket_greater)) 9661b684552Smrg { 9671b684552Smrg /* 9681b684552Smrg * The value is exactly equal to our threshold. We want one 9691b684552Smrg * more event in the positive direction to ensure we pick up 9701b684552Smrg * when the value *exceeds* this threshold. 9711b684552Smrg */ 9721b684552Smrg psci->bracket_greater = pTrigger->test_value; 9731b684552Smrg pnewgtval = &psci->bracket_greater; 974a0d10bb6Smrg } 975a0d10bb6Smrg } 976a0d10bb6Smrg else if (pTrigger->test_type == XSyncPositiveTransition && 97705b261ecSmrg ct != XSyncCounterNeverDecreases) 97805b261ecSmrg { 979a0d10bb6Smrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 980a0d10bb6Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) 98105b261ecSmrg { 982a0d10bb6Smrg psci->bracket_greater = pTrigger->test_value; 983a0d10bb6Smrg pnewgtval = &psci->bracket_greater; 9841b684552Smrg } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) && 9851b684552Smrg XSyncValueGreaterThan(pTrigger->test_value, 9861b684552Smrg psci->bracket_less)) 9871b684552Smrg { 9881b684552Smrg /* 9891b684552Smrg * The value is exactly equal to our threshold. We want one 9901b684552Smrg * more event in the negative direction to ensure we pick up 9911b684552Smrg * when the value is less than this threshold. 9921b684552Smrg */ 9931b684552Smrg psci->bracket_less = pTrigger->test_value; 9941b684552Smrg pnewltval = &psci->bracket_less; 99505b261ecSmrg } 99605b261ecSmrg } 99705b261ecSmrg } /* end for each trigger */ 99805b261ecSmrg 99905b261ecSmrg if (pnewgtval || pnewltval) 100005b261ecSmrg { 100105b261ecSmrg (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); 100205b261ecSmrg } 100305b261ecSmrg} 100405b261ecSmrg 100505b261ecSmrg/* 100605b261ecSmrg * ***** Resource delete functions 100705b261ecSmrg */ 100805b261ecSmrg 100905b261ecSmrg/* ARGSUSED */ 101005b261ecSmrgstatic int 10114202a189SmrgFreeAlarm(void *addr, XID id) 101205b261ecSmrg{ 101305b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *) addr; 101405b261ecSmrg 101505b261ecSmrg pAlarm->state = XSyncAlarmDestroyed; 101605b261ecSmrg 101705b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 101805b261ecSmrg 101905b261ecSmrg /* delete event selections */ 102005b261ecSmrg 102105b261ecSmrg while (pAlarm->pEventClients) 102205b261ecSmrg FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 102305b261ecSmrg 102405b261ecSmrg SyncDeleteTriggerFromCounter(&pAlarm->trigger); 102505b261ecSmrg 10264202a189Smrg free(pAlarm); 102705b261ecSmrg return Success; 102805b261ecSmrg} 102905b261ecSmrg 103005b261ecSmrg 103105b261ecSmrg/* 103205b261ecSmrg * ** Cleanup after the destruction of a Counter 103305b261ecSmrg */ 103405b261ecSmrg/* ARGSUSED */ 103505b261ecSmrgstatic int 10364202a189SmrgFreeCounter(void *env, XID id) 103705b261ecSmrg{ 103805b261ecSmrg SyncCounter *pCounter = (SyncCounter *) env; 103905b261ecSmrg SyncTriggerList *ptl, *pnext; 104005b261ecSmrg 104105b261ecSmrg pCounter->beingDestroyed = TRUE; 104205b261ecSmrg /* tell all the counter's triggers that the counter has been destroyed */ 104305b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 104405b261ecSmrg { 104505b261ecSmrg (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); 104605b261ecSmrg pnext = ptl->next; 10474202a189Smrg free(ptl); /* destroy the trigger list as we go */ 104805b261ecSmrg } 104905b261ecSmrg if (IsSystemCounter(pCounter)) 105005b261ecSmrg { 105105b261ecSmrg int i, found = 0; 105205b261ecSmrg 10534202a189Smrg free(pCounter->pSysCounterInfo); 105405b261ecSmrg 105505b261ecSmrg /* find the counter in the list of system counters and remove it */ 105605b261ecSmrg 105705b261ecSmrg if (SysCounterList) 105805b261ecSmrg { 105905b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 106005b261ecSmrg { 106105b261ecSmrg if (SysCounterList[i] == pCounter) 106205b261ecSmrg { 106305b261ecSmrg found = i; 106405b261ecSmrg break; 106505b261ecSmrg } 106605b261ecSmrg } 106705b261ecSmrg if (found < (SyncNumSystemCounters-1)) 106805b261ecSmrg { 106905b261ecSmrg for (i = found; i < SyncNumSystemCounters-1; i++) 107005b261ecSmrg { 107105b261ecSmrg SysCounterList[i] = SysCounterList[i+1]; 107205b261ecSmrg } 107305b261ecSmrg } 107405b261ecSmrg } 107505b261ecSmrg SyncNumSystemCounters--; 107605b261ecSmrg } 10774202a189Smrg free(pCounter); 107805b261ecSmrg return Success; 107905b261ecSmrg} 108005b261ecSmrg 108105b261ecSmrg/* 108205b261ecSmrg * ** Cleanup after Await 108305b261ecSmrg */ 108405b261ecSmrg/* ARGSUSED */ 108505b261ecSmrgstatic int 10864202a189SmrgFreeAwait(void *addr, XID id) 108705b261ecSmrg{ 108805b261ecSmrg SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 108905b261ecSmrg SyncAwait *pAwait; 109005b261ecSmrg int numwaits; 109105b261ecSmrg 109205b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* first await on list */ 109305b261ecSmrg 109405b261ecSmrg /* remove triggers from counters */ 109505b261ecSmrg 109605b261ecSmrg for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 109705b261ecSmrg numwaits--, pAwait++) 109805b261ecSmrg { 10994202a189Smrg /* If the counter is being destroyed, FreeCounter will delete 110005b261ecSmrg * the trigger list itself, so don't do it here. 110105b261ecSmrg */ 110205b261ecSmrg SyncCounter *pCounter = pAwait->trigger.pCounter; 110305b261ecSmrg if (pCounter && !pCounter->beingDestroyed) 110405b261ecSmrg SyncDeleteTriggerFromCounter(&pAwait->trigger); 110505b261ecSmrg } 11064202a189Smrg free(pAwaitUnion); 110705b261ecSmrg return Success; 110805b261ecSmrg} 110905b261ecSmrg 111005b261ecSmrg/* loosely based on dix/events.c/OtherClientGone */ 111105b261ecSmrgstatic int 11124202a189SmrgFreeAlarmClient(void *value, XID id) 111305b261ecSmrg{ 111405b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)value; 111505b261ecSmrg SyncAlarmClientList *pCur, *pPrev; 111605b261ecSmrg 111705b261ecSmrg for (pPrev = NULL, pCur = pAlarm->pEventClients; 111805b261ecSmrg pCur; 111905b261ecSmrg pPrev = pCur, pCur = pCur->next) 112005b261ecSmrg { 112105b261ecSmrg if (pCur->delete_id == id) 112205b261ecSmrg { 112305b261ecSmrg if (pPrev) 112405b261ecSmrg pPrev->next = pCur->next; 112505b261ecSmrg else 112605b261ecSmrg pAlarm->pEventClients = pCur->next; 11274202a189Smrg free(pCur); 11284202a189Smrg return Success; 112905b261ecSmrg } 113005b261ecSmrg } 113105b261ecSmrg FatalError("alarm client not on event list"); 113205b261ecSmrg /*NOTREACHED*/ 113305b261ecSmrg} 113405b261ecSmrg 113505b261ecSmrg 113605b261ecSmrg/* 113705b261ecSmrg * ***** Proc functions 113805b261ecSmrg */ 113905b261ecSmrg 114005b261ecSmrg 114105b261ecSmrg/* 114205b261ecSmrg * ** Initialize the extension 114305b261ecSmrg */ 11444202a189Smrgstatic int 11454202a189SmrgProcSyncInitialize(ClientPtr client) 114605b261ecSmrg{ 114705b261ecSmrg xSyncInitializeReply rep; 114805b261ecSmrg int n; 114905b261ecSmrg 115005b261ecSmrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 115105b261ecSmrg 11524202a189Smrg memset(&rep, 0, sizeof(xSyncInitializeReply)); 115305b261ecSmrg rep.type = X_Reply; 115405b261ecSmrg rep.sequenceNumber = client->sequence; 11551b684552Smrg rep.majorVersion = SERVER_SYNC_MAJOR_VERSION; 11561b684552Smrg rep.minorVersion = SERVER_SYNC_MINOR_VERSION; 115705b261ecSmrg rep.length = 0; 115805b261ecSmrg 115905b261ecSmrg if (client->swapped) 116005b261ecSmrg { 116105b261ecSmrg swaps(&rep.sequenceNumber, n); 116205b261ecSmrg } 116305b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 11644202a189Smrg return Success; 116505b261ecSmrg} 116605b261ecSmrg 116705b261ecSmrg/* 116805b261ecSmrg * ** Get list of system counters available through the extension 116905b261ecSmrg */ 11704202a189Smrgstatic int 11714202a189SmrgProcSyncListSystemCounters(ClientPtr client) 117205b261ecSmrg{ 117305b261ecSmrg xSyncListSystemCountersReply rep; 117405b261ecSmrg int i, len; 117505b261ecSmrg xSyncSystemCounter *list = NULL, *walklist = NULL; 11764202a189Smrg 117705b261ecSmrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 117805b261ecSmrg 117905b261ecSmrg rep.type = X_Reply; 118005b261ecSmrg rep.sequenceNumber = client->sequence; 118105b261ecSmrg rep.nCounters = SyncNumSystemCounters; 118205b261ecSmrg 118305b261ecSmrg for (i = len = 0; i < SyncNumSystemCounters; i++) 118405b261ecSmrg { 118505b261ecSmrg char *name = SysCounterList[i]->pSysCounterInfo->name; 118605b261ecSmrg /* pad to 4 byte boundary */ 11874202a189Smrg len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); 118805b261ecSmrg } 118905b261ecSmrg 119005b261ecSmrg if (len) 119105b261ecSmrg { 11924202a189Smrg walklist = list = malloc(len); 119305b261ecSmrg if (!list) 119405b261ecSmrg return BadAlloc; 119505b261ecSmrg } 119605b261ecSmrg 11974202a189Smrg rep.length = bytes_to_int32(len); 119805b261ecSmrg 119905b261ecSmrg if (client->swapped) 120005b261ecSmrg { 1201637ac9abSmrg char n; 120205b261ecSmrg swaps(&rep.sequenceNumber, n); 120305b261ecSmrg swapl(&rep.length, n); 120405b261ecSmrg swapl(&rep.nCounters, n); 120505b261ecSmrg } 120605b261ecSmrg 120705b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 120805b261ecSmrg { 120905b261ecSmrg int namelen; 121005b261ecSmrg char *pname_in_reply; 121105b261ecSmrg SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; 121205b261ecSmrg 121305b261ecSmrg walklist->counter = SysCounterList[i]->id; 121405b261ecSmrg walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 121505b261ecSmrg walklist->resolution_lo = XSyncValueLow32(psci->resolution); 121605b261ecSmrg namelen = strlen(psci->name); 121705b261ecSmrg walklist->name_length = namelen; 121805b261ecSmrg 121905b261ecSmrg if (client->swapped) 122005b261ecSmrg { 1221637ac9abSmrg char n; 122205b261ecSmrg swapl(&walklist->counter, n); 122305b261ecSmrg swapl(&walklist->resolution_hi, n); 122405b261ecSmrg swapl(&walklist->resolution_lo, n); 122505b261ecSmrg swaps(&walklist->name_length, n); 122605b261ecSmrg } 122705b261ecSmrg 122805b261ecSmrg pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; 122905b261ecSmrg strncpy(pname_in_reply, psci->name, namelen); 12304202a189Smrg walklist = (xSyncSystemCounter *) (((char *)walklist) + 12314202a189Smrg pad_to_int32(sz_xSyncSystemCounter + namelen)); 123205b261ecSmrg } 123305b261ecSmrg 123405b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 12354202a189Smrg if (len) 123605b261ecSmrg { 123705b261ecSmrg WriteToClient(client, len, (char *) list); 12384202a189Smrg free(list); 123905b261ecSmrg } 124005b261ecSmrg 12414202a189Smrg return Success; 124205b261ecSmrg} 124305b261ecSmrg 124405b261ecSmrg/* 124505b261ecSmrg * ** Set client Priority 124605b261ecSmrg */ 12474202a189Smrgstatic int 12484202a189SmrgProcSyncSetPriority(ClientPtr client) 124905b261ecSmrg{ 125005b261ecSmrg REQUEST(xSyncSetPriorityReq); 125105b261ecSmrg ClientPtr priorityclient; 125205b261ecSmrg int rc; 125305b261ecSmrg 125405b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 125505b261ecSmrg 125605b261ecSmrg if (stuff->id == None) 125705b261ecSmrg priorityclient = client; 125805b261ecSmrg else { 125905b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1260637ac9abSmrg DixSetAttrAccess); 126105b261ecSmrg if (rc != Success) 126205b261ecSmrg return rc; 126305b261ecSmrg } 126405b261ecSmrg 126505b261ecSmrg if (priorityclient->priority != stuff->priority) 126605b261ecSmrg { 126705b261ecSmrg priorityclient->priority = stuff->priority; 126805b261ecSmrg 126905b261ecSmrg /* The following will force the server back into WaitForSomething 127005b261ecSmrg * so that the change in this client's priority is immediately 127105b261ecSmrg * reflected. 127205b261ecSmrg */ 127305b261ecSmrg isItTimeToYield = TRUE; 127405b261ecSmrg dispatchException |= DE_PRIORITYCHANGE; 127505b261ecSmrg } 127605b261ecSmrg return Success; 127705b261ecSmrg} 127805b261ecSmrg 127905b261ecSmrg/* 128005b261ecSmrg * ** Get client Priority 128105b261ecSmrg */ 12824202a189Smrgstatic int 12834202a189SmrgProcSyncGetPriority(ClientPtr client) 128405b261ecSmrg{ 128505b261ecSmrg REQUEST(xSyncGetPriorityReq); 128605b261ecSmrg xSyncGetPriorityReply rep; 128705b261ecSmrg ClientPtr priorityclient; 128805b261ecSmrg int rc; 128905b261ecSmrg 129005b261ecSmrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 129105b261ecSmrg 129205b261ecSmrg if (stuff->id == None) 129305b261ecSmrg priorityclient = client; 129405b261ecSmrg else { 129505b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1296637ac9abSmrg DixGetAttrAccess); 129705b261ecSmrg if (rc != Success) 129805b261ecSmrg return rc; 129905b261ecSmrg } 130005b261ecSmrg 130105b261ecSmrg rep.type = X_Reply; 130205b261ecSmrg rep.length = 0; 130305b261ecSmrg rep.sequenceNumber = client->sequence; 130405b261ecSmrg rep.priority = priorityclient->priority; 130505b261ecSmrg 130605b261ecSmrg if (client->swapped) 130705b261ecSmrg { 1308637ac9abSmrg char n; 130905b261ecSmrg swaps(&rep.sequenceNumber, n); 131005b261ecSmrg swapl(&rep.priority, n); 131105b261ecSmrg } 131205b261ecSmrg 131305b261ecSmrg WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); 131405b261ecSmrg 13154202a189Smrg return Success; 131605b261ecSmrg} 131705b261ecSmrg 131805b261ecSmrg/* 131905b261ecSmrg * ** Create a new counter 132005b261ecSmrg */ 13214202a189Smrgstatic int 13224202a189SmrgProcSyncCreateCounter(ClientPtr client) 132305b261ecSmrg{ 132405b261ecSmrg REQUEST(xSyncCreateCounterReq); 132505b261ecSmrg CARD64 initial; 132605b261ecSmrg 132705b261ecSmrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 132805b261ecSmrg 132905b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 133005b261ecSmrg 133105b261ecSmrg XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); 133205b261ecSmrg if (!SyncCreateCounter(client, stuff->cid, initial)) 133305b261ecSmrg return BadAlloc; 133405b261ecSmrg 13354202a189Smrg return Success; 133605b261ecSmrg} 133705b261ecSmrg 133805b261ecSmrg/* 133905b261ecSmrg * ** Set Counter value 134005b261ecSmrg */ 13414202a189Smrgstatic int 13424202a189SmrgProcSyncSetCounter(ClientPtr client) 134305b261ecSmrg{ 134405b261ecSmrg REQUEST(xSyncSetCounterReq); 134505b261ecSmrg SyncCounter *pCounter; 134605b261ecSmrg CARD64 newvalue; 13474202a189Smrg int rc; 134805b261ecSmrg 134905b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 135005b261ecSmrg 13514202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, 13524202a189Smrg client, DixWriteAccess); 13534202a189Smrg if (rc != Success) 13544202a189Smrg return rc; 135505b261ecSmrg 135605b261ecSmrg if (IsSystemCounter(pCounter)) 135705b261ecSmrg { 135805b261ecSmrg client->errorValue = stuff->cid; 135905b261ecSmrg return BadAccess; 136005b261ecSmrg } 136105b261ecSmrg 136205b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 136305b261ecSmrg SyncChangeCounter(pCounter, newvalue); 136405b261ecSmrg return Success; 136505b261ecSmrg} 136605b261ecSmrg 136705b261ecSmrg/* 136805b261ecSmrg * ** Change Counter value 136905b261ecSmrg */ 13704202a189Smrgstatic int 13714202a189SmrgProcSyncChangeCounter(ClientPtr client) 137205b261ecSmrg{ 137305b261ecSmrg REQUEST(xSyncChangeCounterReq); 137405b261ecSmrg SyncCounter *pCounter; 137505b261ecSmrg CARD64 newvalue; 137605b261ecSmrg Bool overflow; 13774202a189Smrg int rc; 137805b261ecSmrg 137905b261ecSmrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 138005b261ecSmrg 13814202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, 13824202a189Smrg client, DixWriteAccess); 13834202a189Smrg if (rc != Success) 13844202a189Smrg return rc; 138505b261ecSmrg 138605b261ecSmrg if (IsSystemCounter(pCounter)) 138705b261ecSmrg { 138805b261ecSmrg client->errorValue = stuff->cid; 138905b261ecSmrg return BadAccess; 139005b261ecSmrg } 139105b261ecSmrg 139205b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 139305b261ecSmrg XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 139405b261ecSmrg if (overflow) 139505b261ecSmrg { 139605b261ecSmrg /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 13974202a189Smrg client->errorValue = stuff->value_hi; 139805b261ecSmrg return BadValue; 139905b261ecSmrg } 140005b261ecSmrg SyncChangeCounter(pCounter, newvalue); 140105b261ecSmrg return Success; 140205b261ecSmrg} 140305b261ecSmrg 140405b261ecSmrg/* 140505b261ecSmrg * ** Destroy a counter 140605b261ecSmrg */ 14074202a189Smrgstatic int 14084202a189SmrgProcSyncDestroyCounter(ClientPtr client) 140905b261ecSmrg{ 141005b261ecSmrg REQUEST(xSyncDestroyCounterReq); 141105b261ecSmrg SyncCounter *pCounter; 14124202a189Smrg int rc; 141305b261ecSmrg 141405b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 141505b261ecSmrg 14164202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, 14174202a189Smrg client, DixDestroyAccess); 14184202a189Smrg if (rc != Success) 14194202a189Smrg return rc; 14204202a189Smrg 142105b261ecSmrg if (IsSystemCounter(pCounter)) 142205b261ecSmrg { 142305b261ecSmrg client->errorValue = stuff->counter; 142405b261ecSmrg return BadAccess; 142505b261ecSmrg } 142605b261ecSmrg FreeResource(pCounter->id, RT_NONE); 142705b261ecSmrg return Success; 142805b261ecSmrg} 142905b261ecSmrg 143005b261ecSmrg 143105b261ecSmrg/* 143205b261ecSmrg * ** Await 143305b261ecSmrg */ 14344202a189Smrgstatic int 14354202a189SmrgProcSyncAwait(ClientPtr client) 143605b261ecSmrg{ 143705b261ecSmrg REQUEST(xSyncAwaitReq); 143805b261ecSmrg int len, items; 143905b261ecSmrg int i; 144005b261ecSmrg xSyncWaitCondition *pProtocolWaitConds; 144105b261ecSmrg SyncAwaitUnion *pAwaitUnion; 144205b261ecSmrg SyncAwait *pAwait; 144305b261ecSmrg int status; 144405b261ecSmrg 144505b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 144605b261ecSmrg 144705b261ecSmrg len = client->req_len << 2; 144805b261ecSmrg len -= sz_xSyncAwaitReq; 144905b261ecSmrg items = len / sz_xSyncWaitCondition; 145005b261ecSmrg 145105b261ecSmrg if (items * sz_xSyncWaitCondition != len) 145205b261ecSmrg { 145305b261ecSmrg return BadLength; 145405b261ecSmrg } 145505b261ecSmrg if (items == 0) 145605b261ecSmrg { 145705b261ecSmrg client->errorValue = items; /* XXX protocol change */ 145805b261ecSmrg return BadValue; 145905b261ecSmrg } 146005b261ecSmrg 146105b261ecSmrg pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; 146205b261ecSmrg 14634202a189Smrg /* all the memory for the entire await list is allocated 146405b261ecSmrg * here in one chunk 146505b261ecSmrg */ 14664202a189Smrg pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion)); 146705b261ecSmrg if (!pAwaitUnion) 146805b261ecSmrg return BadAlloc; 146905b261ecSmrg 147005b261ecSmrg /* first item is the header, remainder are real wait conditions */ 147105b261ecSmrg 147205b261ecSmrg pAwaitUnion->header.delete_id = FakeClientID(client->index); 147305b261ecSmrg if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 147405b261ecSmrg { 14754202a189Smrg free(pAwaitUnion); 147605b261ecSmrg return BadAlloc; 147705b261ecSmrg } 147805b261ecSmrg 147905b261ecSmrg /* don't need to do any more memory allocation for this request! */ 148005b261ecSmrg 148105b261ecSmrg pAwaitUnion->header.client = client; 148205b261ecSmrg pAwaitUnion->header.num_waitconditions = 0; 148305b261ecSmrg 148405b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 148505b261ecSmrg for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) 148605b261ecSmrg { 148705b261ecSmrg if (pProtocolWaitConds->counter == None) /* XXX protocol change */ 148805b261ecSmrg { 148905b261ecSmrg /* this should take care of removing any triggers created by 149005b261ecSmrg * this request that have already been registered on counters 149105b261ecSmrg */ 149205b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 149305b261ecSmrg client->errorValue = pProtocolWaitConds->counter; 149405b261ecSmrg return SyncErrorBase + XSyncBadCounter; 149505b261ecSmrg } 149605b261ecSmrg 149705b261ecSmrg /* sanity checks are in SyncInitTrigger */ 149805b261ecSmrg pAwait->trigger.pCounter = NULL; 149905b261ecSmrg pAwait->trigger.value_type = pProtocolWaitConds->value_type; 150005b261ecSmrg XSyncIntsToValue(&pAwait->trigger.wait_value, 150105b261ecSmrg pProtocolWaitConds->wait_value_lo, 150205b261ecSmrg pProtocolWaitConds->wait_value_hi); 150305b261ecSmrg pAwait->trigger.test_type = pProtocolWaitConds->test_type; 150405b261ecSmrg 150505b261ecSmrg status = SyncInitTrigger(client, &pAwait->trigger, 150605b261ecSmrg pProtocolWaitConds->counter, XSyncCAAllTrigger); 150705b261ecSmrg if (status != Success) 150805b261ecSmrg { 150905b261ecSmrg /* this should take care of removing any triggers created by 151005b261ecSmrg * this request that have already been registered on counters 151105b261ecSmrg */ 151205b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 151305b261ecSmrg return status; 151405b261ecSmrg } 151505b261ecSmrg /* this is not a mistake -- same function works for both cases */ 151605b261ecSmrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 151705b261ecSmrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 151805b261ecSmrg XSyncIntsToValue(&pAwait->event_threshold, 151905b261ecSmrg pProtocolWaitConds->event_threshold_lo, 152005b261ecSmrg pProtocolWaitConds->event_threshold_hi); 152105b261ecSmrg pAwait->pHeader = &pAwaitUnion->header; 152205b261ecSmrg pAwaitUnion->header.num_waitconditions++; 152305b261ecSmrg } 152405b261ecSmrg 152505b261ecSmrg IgnoreClient(client); 152605b261ecSmrg 152705b261ecSmrg /* see if any of the triggers are already true */ 152805b261ecSmrg 152905b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 153005b261ecSmrg for (i = 0; i < items; i++, pAwait++) 153105b261ecSmrg { 153205b261ecSmrg /* don't have to worry about NULL counters because the request 153305b261ecSmrg * errors before we get here out if they occur 153405b261ecSmrg */ 153505b261ecSmrg if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, 153605b261ecSmrg pAwait->trigger.pCounter->value)) 153705b261ecSmrg { 153805b261ecSmrg (*pAwait->trigger.TriggerFired)(&pAwait->trigger); 153905b261ecSmrg break; /* once is enough */ 154005b261ecSmrg } 154105b261ecSmrg } 154205b261ecSmrg return Success; 154305b261ecSmrg} 154405b261ecSmrg 154505b261ecSmrg 154605b261ecSmrg/* 154705b261ecSmrg * ** Query a counter 154805b261ecSmrg */ 15494202a189Smrgstatic int 15504202a189SmrgProcSyncQueryCounter(ClientPtr client) 155105b261ecSmrg{ 155205b261ecSmrg REQUEST(xSyncQueryCounterReq); 155305b261ecSmrg xSyncQueryCounterReply rep; 155405b261ecSmrg SyncCounter *pCounter; 15554202a189Smrg int rc; 155605b261ecSmrg 155705b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 155805b261ecSmrg 15594202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, 15604202a189Smrg RTCounter, client, DixReadAccess); 15614202a189Smrg if (rc != Success) 15624202a189Smrg return rc; 156305b261ecSmrg 156405b261ecSmrg rep.type = X_Reply; 156505b261ecSmrg rep.length = 0; 156605b261ecSmrg rep.sequenceNumber = client->sequence; 156705b261ecSmrg 156805b261ecSmrg /* if system counter, ask it what the current value is */ 156905b261ecSmrg 157005b261ecSmrg if (IsSystemCounter(pCounter)) 157105b261ecSmrg { 157205b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 157305b261ecSmrg &pCounter->value); 157405b261ecSmrg } 157505b261ecSmrg 157605b261ecSmrg rep.value_hi = XSyncValueHigh32(pCounter->value); 157705b261ecSmrg rep.value_lo = XSyncValueLow32(pCounter->value); 157805b261ecSmrg if (client->swapped) 157905b261ecSmrg { 1580637ac9abSmrg char n; 158105b261ecSmrg swaps(&rep.sequenceNumber, n); 158205b261ecSmrg swapl(&rep.length, n); 158305b261ecSmrg swapl(&rep.value_hi, n); 158405b261ecSmrg swapl(&rep.value_lo, n); 158505b261ecSmrg } 158605b261ecSmrg WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); 15874202a189Smrg return Success; 158805b261ecSmrg} 158905b261ecSmrg 159005b261ecSmrg 159105b261ecSmrg/* 159205b261ecSmrg * ** Create Alarm 159305b261ecSmrg */ 15944202a189Smrgstatic int 15954202a189SmrgProcSyncCreateAlarm(ClientPtr client) 159605b261ecSmrg{ 159705b261ecSmrg REQUEST(xSyncCreateAlarmReq); 159805b261ecSmrg SyncAlarm *pAlarm; 159905b261ecSmrg int status; 160005b261ecSmrg unsigned long len, vmask; 160105b261ecSmrg SyncTrigger *pTrigger; 160205b261ecSmrg 160305b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 160405b261ecSmrg 160505b261ecSmrg LEGAL_NEW_RESOURCE(stuff->id, client); 160605b261ecSmrg 160705b261ecSmrg vmask = stuff->valueMask; 16084202a189Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); 160905b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 161005b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 161105b261ecSmrg return BadLength; 161205b261ecSmrg 16134202a189Smrg if (!(pAlarm = malloc(sizeof(SyncAlarm)))) 161405b261ecSmrg { 161505b261ecSmrg return BadAlloc; 161605b261ecSmrg } 161705b261ecSmrg 161805b261ecSmrg /* set up defaults */ 161905b261ecSmrg 162005b261ecSmrg pTrigger = &pAlarm->trigger; 162105b261ecSmrg pTrigger->pCounter = NULL; 162205b261ecSmrg pTrigger->value_type = XSyncAbsolute; 162305b261ecSmrg XSyncIntToValue(&pTrigger->wait_value, 0L); 162405b261ecSmrg pTrigger->test_type = XSyncPositiveComparison; 162505b261ecSmrg pTrigger->TriggerFired = SyncAlarmTriggerFired; 162605b261ecSmrg pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 162705b261ecSmrg status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); 162805b261ecSmrg if (status != Success) 162905b261ecSmrg { 16304202a189Smrg free(pAlarm); 163105b261ecSmrg return status; 163205b261ecSmrg } 163305b261ecSmrg 163405b261ecSmrg pAlarm->client = client; 163505b261ecSmrg pAlarm->alarm_id = stuff->id; 163605b261ecSmrg XSyncIntToValue(&pAlarm->delta, 1L); 163705b261ecSmrg pAlarm->events = TRUE; 163805b261ecSmrg pAlarm->state = XSyncAlarmInactive; 163905b261ecSmrg pAlarm->pEventClients = NULL; 164005b261ecSmrg status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 164105b261ecSmrg (CARD32 *)&stuff[1]); 164205b261ecSmrg if (status != Success) 164305b261ecSmrg { 16444202a189Smrg free(pAlarm); 164505b261ecSmrg return status; 164605b261ecSmrg } 164705b261ecSmrg 164805b261ecSmrg if (!AddResource(stuff->id, RTAlarm, pAlarm)) 164905b261ecSmrg { 16504202a189Smrg free(pAlarm); 165105b261ecSmrg return BadAlloc; 165205b261ecSmrg } 165305b261ecSmrg 165405b261ecSmrg /* see if alarm already triggered. NULL counter will not trigger 165505b261ecSmrg * in CreateAlarm and sets alarm state to Inactive. 165605b261ecSmrg */ 165705b261ecSmrg 165805b261ecSmrg if (!pTrigger->pCounter) 165905b261ecSmrg { 166005b261ecSmrg pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 166105b261ecSmrg } 166205b261ecSmrg else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) 166305b261ecSmrg { 166405b261ecSmrg (*pTrigger->TriggerFired)(pTrigger); 166505b261ecSmrg } 166605b261ecSmrg 166705b261ecSmrg return Success; 166805b261ecSmrg} 166905b261ecSmrg 167005b261ecSmrg/* 167105b261ecSmrg * ** Change Alarm 167205b261ecSmrg */ 16734202a189Smrgstatic int 16744202a189SmrgProcSyncChangeAlarm(ClientPtr client) 167505b261ecSmrg{ 167605b261ecSmrg REQUEST(xSyncChangeAlarmReq); 167705b261ecSmrg SyncAlarm *pAlarm; 167805b261ecSmrg long vmask; 167905b261ecSmrg int len, status; 168005b261ecSmrg 168105b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 168205b261ecSmrg 16834202a189Smrg status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 16844202a189Smrg client, DixWriteAccess); 16854202a189Smrg if (status != Success) 16864202a189Smrg return status; 168705b261ecSmrg 168805b261ecSmrg vmask = stuff->valueMask; 16894202a189Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); 169005b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 169105b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 169205b261ecSmrg return BadLength; 169305b261ecSmrg 16944202a189Smrg if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 169505b261ecSmrg (CARD32 *)&stuff[1])) != Success) 169605b261ecSmrg return status; 169705b261ecSmrg 169805b261ecSmrg /* see if alarm already triggered. NULL counter WILL trigger 169905b261ecSmrg * in ChangeAlarm. 170005b261ecSmrg */ 170105b261ecSmrg 170205b261ecSmrg if (!pAlarm->trigger.pCounter || 170305b261ecSmrg (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, 170405b261ecSmrg pAlarm->trigger.pCounter->value)) 170505b261ecSmrg { 170605b261ecSmrg (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); 170705b261ecSmrg } 170805b261ecSmrg return Success; 170905b261ecSmrg} 171005b261ecSmrg 17114202a189Smrgstatic int 17124202a189SmrgProcSyncQueryAlarm(ClientPtr client) 171305b261ecSmrg{ 171405b261ecSmrg REQUEST(xSyncQueryAlarmReq); 171505b261ecSmrg SyncAlarm *pAlarm; 171605b261ecSmrg xSyncQueryAlarmReply rep; 171705b261ecSmrg SyncTrigger *pTrigger; 17184202a189Smrg int rc; 171905b261ecSmrg 172005b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 172105b261ecSmrg 17224202a189Smrg rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 17234202a189Smrg client, DixReadAccess); 17244202a189Smrg if (rc != Success) 17254202a189Smrg return rc; 172605b261ecSmrg 172705b261ecSmrg rep.type = X_Reply; 17284202a189Smrg rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); 172905b261ecSmrg rep.sequenceNumber = client->sequence; 173005b261ecSmrg 173105b261ecSmrg pTrigger = &pAlarm->trigger; 173205b261ecSmrg rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; 173305b261ecSmrg 173405b261ecSmrg#if 0 /* XXX unclear what to do, depends on whether relative value-types 173505b261ecSmrg * are "consumed" immediately and are considered absolute from then 173605b261ecSmrg * on. 173705b261ecSmrg */ 173805b261ecSmrg rep.value_type = pTrigger->value_type; 173905b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); 174005b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); 174105b261ecSmrg#else 174205b261ecSmrg rep.value_type = XSyncAbsolute; 174305b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 174405b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); 174505b261ecSmrg#endif 174605b261ecSmrg 174705b261ecSmrg rep.test_type = pTrigger->test_type; 174805b261ecSmrg rep.delta_hi = XSyncValueHigh32(pAlarm->delta); 174905b261ecSmrg rep.delta_lo = XSyncValueLow32(pAlarm->delta); 175005b261ecSmrg rep.events = pAlarm->events; 175105b261ecSmrg rep.state = pAlarm->state; 175205b261ecSmrg 175305b261ecSmrg if (client->swapped) 175405b261ecSmrg { 1755637ac9abSmrg char n; 175605b261ecSmrg swaps(&rep.sequenceNumber, n); 175705b261ecSmrg swapl(&rep.length, n); 175805b261ecSmrg swapl(&rep.counter, n); 175905b261ecSmrg swapl(&rep.wait_value_hi, n); 176005b261ecSmrg swapl(&rep.wait_value_lo, n); 176105b261ecSmrg swapl(&rep.test_type, n); 176205b261ecSmrg swapl(&rep.delta_hi, n); 176305b261ecSmrg swapl(&rep.delta_lo, n); 176405b261ecSmrg } 176505b261ecSmrg 176605b261ecSmrg WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); 17674202a189Smrg return Success; 176805b261ecSmrg} 176905b261ecSmrg 17704202a189Smrgstatic int 17714202a189SmrgProcSyncDestroyAlarm(ClientPtr client) 177205b261ecSmrg{ 17734202a189Smrg SyncAlarm *pAlarm; 17744202a189Smrg int rc; 177505b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 177605b261ecSmrg 177705b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 177805b261ecSmrg 17794202a189Smrg rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 17804202a189Smrg client, DixDestroyAccess); 17814202a189Smrg if (rc != Success) 17824202a189Smrg return rc; 178305b261ecSmrg 178405b261ecSmrg FreeResource(stuff->alarm, RT_NONE); 17854202a189Smrg return Success; 178605b261ecSmrg} 178705b261ecSmrg 178805b261ecSmrg/* 178905b261ecSmrg * ** Given an extension request, call the appropriate request procedure 179005b261ecSmrg */ 17914202a189Smrgstatic int 17924202a189SmrgProcSyncDispatch(ClientPtr client) 179305b261ecSmrg{ 179405b261ecSmrg REQUEST(xReq); 179505b261ecSmrg 179605b261ecSmrg switch (stuff->data) 179705b261ecSmrg { 179805b261ecSmrg case X_SyncInitialize: 179905b261ecSmrg return ProcSyncInitialize(client); 180005b261ecSmrg case X_SyncListSystemCounters: 180105b261ecSmrg return ProcSyncListSystemCounters(client); 180205b261ecSmrg case X_SyncCreateCounter: 180305b261ecSmrg return ProcSyncCreateCounter(client); 180405b261ecSmrg case X_SyncSetCounter: 180505b261ecSmrg return ProcSyncSetCounter(client); 180605b261ecSmrg case X_SyncChangeCounter: 180705b261ecSmrg return ProcSyncChangeCounter(client); 180805b261ecSmrg case X_SyncQueryCounter: 180905b261ecSmrg return ProcSyncQueryCounter(client); 181005b261ecSmrg case X_SyncDestroyCounter: 181105b261ecSmrg return ProcSyncDestroyCounter(client); 181205b261ecSmrg case X_SyncAwait: 181305b261ecSmrg return ProcSyncAwait(client); 181405b261ecSmrg case X_SyncCreateAlarm: 181505b261ecSmrg return ProcSyncCreateAlarm(client); 181605b261ecSmrg case X_SyncChangeAlarm: 181705b261ecSmrg return ProcSyncChangeAlarm(client); 181805b261ecSmrg case X_SyncQueryAlarm: 181905b261ecSmrg return ProcSyncQueryAlarm(client); 182005b261ecSmrg case X_SyncDestroyAlarm: 182105b261ecSmrg return ProcSyncDestroyAlarm(client); 182205b261ecSmrg case X_SyncSetPriority: 182305b261ecSmrg return ProcSyncSetPriority(client); 182405b261ecSmrg case X_SyncGetPriority: 182505b261ecSmrg return ProcSyncGetPriority(client); 182605b261ecSmrg default: 182705b261ecSmrg return BadRequest; 182805b261ecSmrg } 182905b261ecSmrg} 183005b261ecSmrg 183105b261ecSmrg/* 183205b261ecSmrg * Boring Swapping stuff ... 183305b261ecSmrg */ 183405b261ecSmrg 18354202a189Smrgstatic int 18364202a189SmrgSProcSyncInitialize(ClientPtr client) 183705b261ecSmrg{ 183805b261ecSmrg REQUEST(xSyncInitializeReq); 1839637ac9abSmrg char n; 184005b261ecSmrg 184105b261ecSmrg swaps(&stuff->length, n); 184205b261ecSmrg REQUEST_SIZE_MATCH (xSyncInitializeReq); 184305b261ecSmrg 184405b261ecSmrg return ProcSyncInitialize(client); 184505b261ecSmrg} 184605b261ecSmrg 18474202a189Smrgstatic int 18484202a189SmrgSProcSyncListSystemCounters(ClientPtr client) 184905b261ecSmrg{ 185005b261ecSmrg REQUEST(xSyncListSystemCountersReq); 1851637ac9abSmrg char n; 185205b261ecSmrg 185305b261ecSmrg swaps(&stuff->length, n); 185405b261ecSmrg REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); 185505b261ecSmrg 185605b261ecSmrg return ProcSyncListSystemCounters(client); 185705b261ecSmrg} 185805b261ecSmrg 18594202a189Smrgstatic int 18604202a189SmrgSProcSyncCreateCounter(ClientPtr client) 186105b261ecSmrg{ 186205b261ecSmrg REQUEST(xSyncCreateCounterReq); 1863637ac9abSmrg char n; 186405b261ecSmrg 186505b261ecSmrg swaps(&stuff->length, n); 186605b261ecSmrg REQUEST_SIZE_MATCH (xSyncCreateCounterReq); 186705b261ecSmrg swapl(&stuff->cid, n); 186805b261ecSmrg swapl(&stuff->initial_value_lo, n); 186905b261ecSmrg swapl(&stuff->initial_value_hi, n); 187005b261ecSmrg 187105b261ecSmrg return ProcSyncCreateCounter(client); 187205b261ecSmrg} 187305b261ecSmrg 18744202a189Smrgstatic int 18754202a189SmrgSProcSyncSetCounter(ClientPtr client) 187605b261ecSmrg{ 187705b261ecSmrg REQUEST(xSyncSetCounterReq); 1878637ac9abSmrg char n; 187905b261ecSmrg 188005b261ecSmrg swaps(&stuff->length, n); 188105b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetCounterReq); 188205b261ecSmrg swapl(&stuff->cid, n); 188305b261ecSmrg swapl(&stuff->value_lo, n); 188405b261ecSmrg swapl(&stuff->value_hi, n); 188505b261ecSmrg 188605b261ecSmrg return ProcSyncSetCounter(client); 188705b261ecSmrg} 188805b261ecSmrg 18894202a189Smrgstatic int 18904202a189SmrgSProcSyncChangeCounter(ClientPtr client) 189105b261ecSmrg{ 189205b261ecSmrg REQUEST(xSyncChangeCounterReq); 1893637ac9abSmrg char n; 189405b261ecSmrg 189505b261ecSmrg swaps(&stuff->length, n); 189605b261ecSmrg REQUEST_SIZE_MATCH (xSyncChangeCounterReq); 189705b261ecSmrg swapl(&stuff->cid, n); 189805b261ecSmrg swapl(&stuff->value_lo, n); 189905b261ecSmrg swapl(&stuff->value_hi, n); 190005b261ecSmrg 190105b261ecSmrg return ProcSyncChangeCounter(client); 190205b261ecSmrg} 190305b261ecSmrg 19044202a189Smrgstatic int 19054202a189SmrgSProcSyncQueryCounter(ClientPtr client) 190605b261ecSmrg{ 190705b261ecSmrg REQUEST(xSyncQueryCounterReq); 1908637ac9abSmrg char n; 190905b261ecSmrg 191005b261ecSmrg swaps(&stuff->length, n); 191105b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryCounterReq); 191205b261ecSmrg swapl(&stuff->counter, n); 191305b261ecSmrg 191405b261ecSmrg return ProcSyncQueryCounter(client); 191505b261ecSmrg} 191605b261ecSmrg 19174202a189Smrgstatic int 19184202a189SmrgSProcSyncDestroyCounter(ClientPtr client) 191905b261ecSmrg{ 192005b261ecSmrg REQUEST(xSyncDestroyCounterReq); 1921637ac9abSmrg char n; 192205b261ecSmrg 192305b261ecSmrg swaps(&stuff->length, n); 192405b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); 192505b261ecSmrg swapl(&stuff->counter, n); 192605b261ecSmrg 192705b261ecSmrg return ProcSyncDestroyCounter(client); 192805b261ecSmrg} 192905b261ecSmrg 19304202a189Smrgstatic int 19314202a189SmrgSProcSyncAwait(ClientPtr client) 193205b261ecSmrg{ 193305b261ecSmrg REQUEST(xSyncAwaitReq); 1934637ac9abSmrg char n; 193505b261ecSmrg 193605b261ecSmrg swaps(&stuff->length, n); 193705b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 193805b261ecSmrg SwapRestL(stuff); 193905b261ecSmrg 194005b261ecSmrg return ProcSyncAwait(client); 194105b261ecSmrg} 194205b261ecSmrg 19434202a189Smrgstatic int 19444202a189SmrgSProcSyncCreateAlarm(ClientPtr client) 194505b261ecSmrg{ 194605b261ecSmrg REQUEST(xSyncCreateAlarmReq); 1947637ac9abSmrg char n; 194805b261ecSmrg 194905b261ecSmrg swaps(&stuff->length, n); 195005b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 195105b261ecSmrg swapl(&stuff->id, n); 195205b261ecSmrg swapl(&stuff->valueMask, n); 195305b261ecSmrg SwapRestL(stuff); 195405b261ecSmrg 195505b261ecSmrg return ProcSyncCreateAlarm(client); 195605b261ecSmrg} 195705b261ecSmrg 19584202a189Smrgstatic int 19594202a189SmrgSProcSyncChangeAlarm(ClientPtr client) 196005b261ecSmrg{ 196105b261ecSmrg REQUEST(xSyncChangeAlarmReq); 1962637ac9abSmrg char n; 196305b261ecSmrg 196405b261ecSmrg swaps(&stuff->length, n); 196505b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 196605b261ecSmrg swapl(&stuff->alarm, n); 196705b261ecSmrg swapl(&stuff->valueMask, n); 196805b261ecSmrg SwapRestL(stuff); 196905b261ecSmrg return ProcSyncChangeAlarm(client); 197005b261ecSmrg} 197105b261ecSmrg 19724202a189Smrgstatic int 19734202a189SmrgSProcSyncQueryAlarm(ClientPtr client) 197405b261ecSmrg{ 197505b261ecSmrg REQUEST(xSyncQueryAlarmReq); 1976637ac9abSmrg char n; 197705b261ecSmrg 197805b261ecSmrg swaps(&stuff->length, n); 197905b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); 198005b261ecSmrg swapl(&stuff->alarm, n); 198105b261ecSmrg 198205b261ecSmrg return ProcSyncQueryAlarm(client); 198305b261ecSmrg} 198405b261ecSmrg 19854202a189Smrgstatic int 19864202a189SmrgSProcSyncDestroyAlarm(ClientPtr client) 198705b261ecSmrg{ 198805b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 1989637ac9abSmrg char n; 199005b261ecSmrg 199105b261ecSmrg swaps(&stuff->length, n); 199205b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); 199305b261ecSmrg swapl(&stuff->alarm, n); 199405b261ecSmrg 199505b261ecSmrg return ProcSyncDestroyAlarm(client); 199605b261ecSmrg} 199705b261ecSmrg 19984202a189Smrgstatic int 19994202a189SmrgSProcSyncSetPriority(ClientPtr client) 200005b261ecSmrg{ 200105b261ecSmrg REQUEST(xSyncSetPriorityReq); 2002637ac9abSmrg char n; 200305b261ecSmrg 200405b261ecSmrg swaps(&stuff->length, n); 200505b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetPriorityReq); 200605b261ecSmrg swapl(&stuff->id, n); 200705b261ecSmrg swapl(&stuff->priority, n); 200805b261ecSmrg 200905b261ecSmrg return ProcSyncSetPriority(client); 201005b261ecSmrg} 201105b261ecSmrg 20124202a189Smrgstatic int 20134202a189SmrgSProcSyncGetPriority(ClientPtr client) 201405b261ecSmrg{ 201505b261ecSmrg REQUEST(xSyncGetPriorityReq); 2016637ac9abSmrg char n; 201705b261ecSmrg 201805b261ecSmrg swaps(&stuff->length, n); 201905b261ecSmrg REQUEST_SIZE_MATCH (xSyncGetPriorityReq); 202005b261ecSmrg swapl(&stuff->id, n); 202105b261ecSmrg 202205b261ecSmrg return ProcSyncGetPriority(client); 202305b261ecSmrg} 202405b261ecSmrg 202505b261ecSmrg 20264202a189Smrgstatic int 20274202a189SmrgSProcSyncDispatch(ClientPtr client) 202805b261ecSmrg{ 202905b261ecSmrg REQUEST(xReq); 203005b261ecSmrg 203105b261ecSmrg switch (stuff->data) 203205b261ecSmrg { 203305b261ecSmrg case X_SyncInitialize: 203405b261ecSmrg return SProcSyncInitialize(client); 203505b261ecSmrg case X_SyncListSystemCounters: 203605b261ecSmrg return SProcSyncListSystemCounters(client); 203705b261ecSmrg case X_SyncCreateCounter: 203805b261ecSmrg return SProcSyncCreateCounter(client); 203905b261ecSmrg case X_SyncSetCounter: 204005b261ecSmrg return SProcSyncSetCounter(client); 204105b261ecSmrg case X_SyncChangeCounter: 204205b261ecSmrg return SProcSyncChangeCounter(client); 204305b261ecSmrg case X_SyncQueryCounter: 204405b261ecSmrg return SProcSyncQueryCounter(client); 204505b261ecSmrg case X_SyncDestroyCounter: 204605b261ecSmrg return SProcSyncDestroyCounter(client); 204705b261ecSmrg case X_SyncAwait: 204805b261ecSmrg return SProcSyncAwait(client); 204905b261ecSmrg case X_SyncCreateAlarm: 205005b261ecSmrg return SProcSyncCreateAlarm(client); 205105b261ecSmrg case X_SyncChangeAlarm: 205205b261ecSmrg return SProcSyncChangeAlarm(client); 205305b261ecSmrg case X_SyncQueryAlarm: 205405b261ecSmrg return SProcSyncQueryAlarm(client); 205505b261ecSmrg case X_SyncDestroyAlarm: 205605b261ecSmrg return SProcSyncDestroyAlarm(client); 205705b261ecSmrg case X_SyncSetPriority: 205805b261ecSmrg return SProcSyncSetPriority(client); 205905b261ecSmrg case X_SyncGetPriority: 206005b261ecSmrg return SProcSyncGetPriority(client); 206105b261ecSmrg default: 206205b261ecSmrg return BadRequest; 206305b261ecSmrg } 206405b261ecSmrg} 206505b261ecSmrg 206605b261ecSmrg/* 206705b261ecSmrg * Event Swapping 206805b261ecSmrg */ 206905b261ecSmrg 20704202a189Smrgstatic void 20714202a189SmrgSCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) 207205b261ecSmrg{ 207305b261ecSmrg to->type = from->type; 207405b261ecSmrg to->kind = from->kind; 207505b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 207605b261ecSmrg cpswapl(from->counter, to->counter); 207705b261ecSmrg cpswapl(from->wait_value_lo, to->wait_value_lo); 207805b261ecSmrg cpswapl(from->wait_value_hi, to->wait_value_hi); 207905b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 208005b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 208105b261ecSmrg cpswapl(from->time, to->time); 208205b261ecSmrg cpswaps(from->count, to->count); 208305b261ecSmrg to->destroyed = from->destroyed; 208405b261ecSmrg} 208505b261ecSmrg 208605b261ecSmrg 20874202a189Smrgstatic void 20884202a189SmrgSAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) 208905b261ecSmrg{ 209005b261ecSmrg to->type = from->type; 209105b261ecSmrg to->kind = from->kind; 209205b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 209305b261ecSmrg cpswapl(from->alarm, to->alarm); 209405b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 209505b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 209605b261ecSmrg cpswapl(from->alarm_value_lo, to->alarm_value_lo); 209705b261ecSmrg cpswapl(from->alarm_value_hi, to->alarm_value_hi); 209805b261ecSmrg cpswapl(from->time, to->time); 209905b261ecSmrg to->state = from->state; 210005b261ecSmrg} 210105b261ecSmrg 210205b261ecSmrg/* 210305b261ecSmrg * ** Close everything down. ** This is fairly simple for now. 210405b261ecSmrg */ 210505b261ecSmrg/* ARGSUSED */ 21064202a189Smrgstatic void 21074202a189SmrgSyncResetProc(ExtensionEntry *extEntry) 210805b261ecSmrg{ 21094202a189Smrg free(SysCounterList); 211005b261ecSmrg SysCounterList = NULL; 211105b261ecSmrg RTCounter = 0; 211205b261ecSmrg} 211305b261ecSmrg 211405b261ecSmrg 211505b261ecSmrg/* 211605b261ecSmrg * ** Initialise the extension. 211705b261ecSmrg */ 21184202a189Smrgvoid 21194202a189SmrgSyncExtensionInit(void) 212005b261ecSmrg{ 212105b261ecSmrg ExtensionEntry *extEntry; 212205b261ecSmrg 212305b261ecSmrg if (RTCounter == 0) 212405b261ecSmrg { 21254202a189Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 212605b261ecSmrg } 21274202a189Smrg RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); 21284202a189Smrg RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); 21294202a189Smrg if (RTAwait) 21304202a189Smrg RTAwait |= RC_NEVERRETAIN; 21314202a189Smrg RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); 21324202a189Smrg if (RTAlarmClient) 21334202a189Smrg RTAlarmClient |= RC_NEVERRETAIN; 213405b261ecSmrg 213505b261ecSmrg if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 213605b261ecSmrg RTAlarmClient == 0 || 213705b261ecSmrg (extEntry = AddExtension(SYNC_NAME, 213805b261ecSmrg XSyncNumberEvents, XSyncNumberErrors, 213905b261ecSmrg ProcSyncDispatch, SProcSyncDispatch, 214005b261ecSmrg SyncResetProc, 214105b261ecSmrg StandardMinorOpcode)) == NULL) 214205b261ecSmrg { 214305b261ecSmrg ErrorF("Sync Extension %d.%d failed to Initialise\n", 214405b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 214505b261ecSmrg return; 214605b261ecSmrg } 214705b261ecSmrg 214805b261ecSmrg SyncEventBase = extEntry->eventBase; 214905b261ecSmrg SyncErrorBase = extEntry->errorBase; 215005b261ecSmrg EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; 215105b261ecSmrg EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; 215205b261ecSmrg 21534202a189Smrg SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter); 21544202a189Smrg SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm); 21554202a189Smrg 215605b261ecSmrg /* 215705b261ecSmrg * Although SERVERTIME is implemented by the OS layer, we initialise it 215805b261ecSmrg * here because doing it in OsInit() is too early. The resource database 215905b261ecSmrg * is not initialised when OsInit() is called. This is just about OK 216005b261ecSmrg * because there is always a servertime counter. 216105b261ecSmrg */ 216205b261ecSmrg SyncInitServerTime(); 216305b261ecSmrg SyncInitIdleTime(); 216405b261ecSmrg 216505b261ecSmrg#ifdef DEBUG 216605b261ecSmrg fprintf(stderr, "Sync Extension %d.%d\n", 216705b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 216805b261ecSmrg#endif 216905b261ecSmrg} 217005b261ecSmrg 217105b261ecSmrg 217205b261ecSmrg/* 217305b261ecSmrg * ***** SERVERTIME implementation - should go in its own file in OS directory? 217405b261ecSmrg */ 217505b261ecSmrg 217605b261ecSmrg 217705b261ecSmrg 217805b261ecSmrgstatic pointer ServertimeCounter; 217905b261ecSmrgstatic XSyncValue Now; 218005b261ecSmrgstatic XSyncValue *pnext_time; 218105b261ecSmrg 218205b261ecSmrg#define GetTime()\ 218305b261ecSmrg{\ 218405b261ecSmrg unsigned long millis = GetTimeInMillis();\ 218505b261ecSmrg unsigned long maxis = XSyncValueHigh32(Now);\ 218605b261ecSmrg if (millis < XSyncValueLow32(Now)) maxis++;\ 218705b261ecSmrg XSyncIntsToValue(&Now, millis, maxis);\ 218805b261ecSmrg} 218905b261ecSmrg 219005b261ecSmrg/* 219105b261ecSmrg*** Server Block Handler 21924202a189Smrg*** code inspired by multibuffer extension (now deprecated) 219305b261ecSmrg */ 219405b261ecSmrg/*ARGSUSED*/ 21954202a189Smrgstatic void 21964202a189SmrgServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) 219705b261ecSmrg{ 219805b261ecSmrg XSyncValue delay; 219905b261ecSmrg unsigned long timeout; 220005b261ecSmrg 220105b261ecSmrg if (pnext_time) 220205b261ecSmrg { 220305b261ecSmrg GetTime(); 220405b261ecSmrg 220505b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 220605b261ecSmrg { 220705b261ecSmrg timeout = 0; 22084202a189Smrg } 220905b261ecSmrg else 221005b261ecSmrg { 221105b261ecSmrg Bool overflow; 221205b261ecSmrg XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 221305b261ecSmrg (void)overflow; 221405b261ecSmrg timeout = XSyncValueLow32(delay); 221505b261ecSmrg } 221605b261ecSmrg AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 221705b261ecSmrg } 221805b261ecSmrg} 221905b261ecSmrg 222005b261ecSmrg/* 222105b261ecSmrg*** Wakeup Handler 222205b261ecSmrg */ 222305b261ecSmrg/*ARGSUSED*/ 22244202a189Smrgstatic void 22254202a189SmrgServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) 222605b261ecSmrg{ 222705b261ecSmrg if (pnext_time) 222805b261ecSmrg { 222905b261ecSmrg GetTime(); 223005b261ecSmrg 223105b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 223205b261ecSmrg { 223305b261ecSmrg SyncChangeCounter(ServertimeCounter, Now); 223405b261ecSmrg } 223505b261ecSmrg } 223605b261ecSmrg} 223705b261ecSmrg 223805b261ecSmrgstatic void 22394202a189SmrgServertimeQueryValue(void *pCounter, CARD64 *pValue_return) 224005b261ecSmrg{ 224105b261ecSmrg GetTime(); 224205b261ecSmrg *pValue_return = Now; 224305b261ecSmrg} 224405b261ecSmrg 224505b261ecSmrgstatic void 22464202a189SmrgServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, 22474202a189Smrg CARD64 *pbracket_greater) 224805b261ecSmrg{ 224905b261ecSmrg if (!pnext_time && pbracket_greater) 225005b261ecSmrg { 225105b261ecSmrg RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 225205b261ecSmrg ServertimeWakeupHandler, 225305b261ecSmrg NULL); 225405b261ecSmrg } 225505b261ecSmrg else if (pnext_time && !pbracket_greater) 225605b261ecSmrg { 225705b261ecSmrg RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 225805b261ecSmrg ServertimeWakeupHandler, 225905b261ecSmrg NULL); 226005b261ecSmrg } 226105b261ecSmrg pnext_time = pbracket_greater; 226205b261ecSmrg} 226305b261ecSmrg 226405b261ecSmrgstatic void 226505b261ecSmrgSyncInitServerTime(void) 226605b261ecSmrg{ 226705b261ecSmrg CARD64 resolution; 226805b261ecSmrg 226905b261ecSmrg XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 227005b261ecSmrg XSyncIntToValue(&resolution, 4); 227105b261ecSmrg ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 227205b261ecSmrg XSyncCounterNeverDecreases, 227305b261ecSmrg ServertimeQueryValue, ServertimeBracketValues); 227405b261ecSmrg pnext_time = NULL; 227505b261ecSmrg} 227605b261ecSmrg 227705b261ecSmrg 227805b261ecSmrg 227905b261ecSmrg/* 228005b261ecSmrg * IDLETIME implementation 228105b261ecSmrg */ 228205b261ecSmrg 228345801275Sjmcneillstatic SyncCounter *IdleTimeCounter; 228405b261ecSmrgstatic XSyncValue *pIdleTimeValueLess; 228505b261ecSmrgstatic XSyncValue *pIdleTimeValueGreater; 228605b261ecSmrg 228705b261ecSmrgstatic void 228805b261ecSmrgIdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 228905b261ecSmrg{ 229005b261ecSmrg CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 229105b261ecSmrg XSyncIntsToValue (pValue_return, idle, 0); 229205b261ecSmrg} 229305b261ecSmrg 229405b261ecSmrgstatic void 229545801275SjmcneillIdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) 229605b261ecSmrg{ 229745801275Sjmcneill XSyncValue idle, old_idle; 229845801275Sjmcneill SyncTriggerList *list = IdleTimeCounter->pTriglist; 229945801275Sjmcneill SyncTrigger *trig; 230005b261ecSmrg 230105b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 230205b261ecSmrg return; 230305b261ecSmrg 230445801275Sjmcneill old_idle = IdleTimeCounter->value; 230505b261ecSmrg IdleTimeQueryValue (NULL, &idle); 230645801275Sjmcneill IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ 230705b261ecSmrg 230805b261ecSmrg if (pIdleTimeValueLess && 230905b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 231005b261ecSmrg { 231145801275Sjmcneill /* 231245801275Sjmcneill * We've been idle for less than the threshold value, and someone 231345801275Sjmcneill * wants to know about that, but now we need to know whether they 231445801275Sjmcneill * want level or edge trigger. Check the trigger list against the 231545801275Sjmcneill * current idle time, and if any succeed, bomb out of select() 231645801275Sjmcneill * immediately so we can reschedule. 231745801275Sjmcneill */ 231845801275Sjmcneill 231945801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 232045801275Sjmcneill trig = list->pTrigger; 232145801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 232245801275Sjmcneill AdjustWaitForDelay(wt, 0); 232345801275Sjmcneill break; 232445801275Sjmcneill } 232545801275Sjmcneill } 23261b684552Smrg /* 23271b684552Smrg * We've been called exactly on the idle time, but we have a 23281b684552Smrg * NegativeTransition trigger which requires a transition from an 23291b684552Smrg * idle time greater than this. Schedule a wakeup for the next 23301b684552Smrg * millisecond so we won't miss a transition. 23311b684552Smrg */ 23321b684552Smrg if (XSyncValueEqual (idle, *pIdleTimeValueLess)) 23331b684552Smrg AdjustWaitForDelay(wt, 1); 233405b261ecSmrg } 233505b261ecSmrg else if (pIdleTimeValueGreater) 233605b261ecSmrg { 233745801275Sjmcneill /* 233845801275Sjmcneill * There's a threshold in the positive direction. If we've been 233945801275Sjmcneill * idle less than it, schedule a wakeup for sometime in the future. 234045801275Sjmcneill * If we've been idle more than it, and someone wants to know about 234145801275Sjmcneill * that level-triggered, schedule an immediate wakeup. 234245801275Sjmcneill */ 234345801275Sjmcneill unsigned long timeout = -1; 234405b261ecSmrg 234545801275Sjmcneill if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { 234605b261ecSmrg XSyncValue value; 234705b261ecSmrg Bool overflow; 234805b261ecSmrg 234905b261ecSmrg XSyncValueSubtract (&value, *pIdleTimeValueGreater, 235005b261ecSmrg idle, &overflow); 235145801275Sjmcneill timeout = min(timeout, XSyncValueLow32 (value)); 235245801275Sjmcneill } else { 235345801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 235445801275Sjmcneill trig = list->pTrigger; 235545801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 235645801275Sjmcneill timeout = min(timeout, 0); 235745801275Sjmcneill break; 235845801275Sjmcneill } 235945801275Sjmcneill } 236005b261ecSmrg } 236105b261ecSmrg 236205b261ecSmrg AdjustWaitForDelay (wt, timeout); 236305b261ecSmrg } 236445801275Sjmcneill 236545801275Sjmcneill IdleTimeCounter->value = old_idle; /* pop */ 236605b261ecSmrg} 236705b261ecSmrg 236805b261ecSmrgstatic void 23694202a189SmrgIdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) 237005b261ecSmrg{ 237105b261ecSmrg XSyncValue idle; 237205b261ecSmrg 237305b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 237405b261ecSmrg return; 237505b261ecSmrg 237605b261ecSmrg IdleTimeQueryValue (NULL, &idle); 237705b261ecSmrg 237805b261ecSmrg if ((pIdleTimeValueGreater && 237905b261ecSmrg XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || 238005b261ecSmrg (pIdleTimeValueLess && 238105b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) 238205b261ecSmrg { 238305b261ecSmrg SyncChangeCounter (IdleTimeCounter, idle); 238405b261ecSmrg } 238505b261ecSmrg} 238605b261ecSmrg 238705b261ecSmrgstatic void 23884202a189SmrgIdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, 238905b261ecSmrg CARD64 *pbracket_greater) 239005b261ecSmrg{ 239105b261ecSmrg Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); 239205b261ecSmrg 239305b261ecSmrg if (registered && !pbracket_less && !pbracket_greater) 239405b261ecSmrg { 239505b261ecSmrg RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 239605b261ecSmrg IdleTimeWakeupHandler, 239705b261ecSmrg NULL); 239805b261ecSmrg } 239905b261ecSmrg else if (!registered && (pbracket_less || pbracket_greater)) 240005b261ecSmrg { 240105b261ecSmrg RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 240205b261ecSmrg IdleTimeWakeupHandler, 240305b261ecSmrg NULL); 240405b261ecSmrg } 240505b261ecSmrg 240605b261ecSmrg pIdleTimeValueGreater = pbracket_greater; 240705b261ecSmrg pIdleTimeValueLess = pbracket_less; 240805b261ecSmrg} 240905b261ecSmrg 241005b261ecSmrgstatic void 241105b261ecSmrgSyncInitIdleTime (void) 241205b261ecSmrg{ 241305b261ecSmrg CARD64 resolution; 241405b261ecSmrg XSyncValue idle; 241505b261ecSmrg 241605b261ecSmrg IdleTimeQueryValue (NULL, &idle); 241705b261ecSmrg XSyncIntToValue (&resolution, 4); 241805b261ecSmrg 241905b261ecSmrg IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, 242005b261ecSmrg XSyncCounterUnrestricted, 242105b261ecSmrg IdleTimeQueryValue, 242205b261ecSmrg IdleTimeBracketValues); 242305b261ecSmrg 242405b261ecSmrg pIdleTimeValueLess = pIdleTimeValueGreater = NULL; 242505b261ecSmrg} 2426