sync.c revision 4202a189
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" 7005b261ecSmrg 7105b261ecSmrg#include <stdio.h> 72637ac9abSmrg#if !defined(WIN32) 7305b261ecSmrg#include <sys/time.h> 7405b261ecSmrg#endif 7505b261ecSmrg 7605b261ecSmrg#include "modinit.h" 7705b261ecSmrg 7805b261ecSmrg/* 7905b261ecSmrg * Local Global Variables 8005b261ecSmrg */ 8105b261ecSmrgstatic int SyncEventBase; 8205b261ecSmrgstatic int SyncErrorBase; 8305b261ecSmrgstatic RESTYPE RTCounter = 0; 8405b261ecSmrgstatic RESTYPE RTAwait; 8505b261ecSmrgstatic RESTYPE RTAlarm; 8605b261ecSmrgstatic RESTYPE RTAlarmClient; 8705b261ecSmrgstatic int SyncNumSystemCounters = 0; 8805b261ecSmrgstatic SyncCounter **SysCounterList = NULL; 8905b261ecSmrg 9005b261ecSmrg#define IsSystemCounter(pCounter) \ 9105b261ecSmrg (pCounter && (pCounter->client == NULL)) 9205b261ecSmrg 9305b261ecSmrg/* these are all the alarm attributes that pertain to the alarm's trigger */ 9405b261ecSmrg#define XSyncCAAllTrigger \ 9505b261ecSmrg (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) 9605b261ecSmrg 974202a189Smrgstatic void SyncComputeBracketValues(SyncCounter *); 9805b261ecSmrg 994202a189Smrgstatic void SyncInitServerTime(void); 10005b261ecSmrg 1014202a189Smrgstatic void SyncInitIdleTime(void); 10205b261ecSmrg 10305b261ecSmrgstatic DISPATCH_PROC(ProcSyncAwait); 10405b261ecSmrgstatic DISPATCH_PROC(ProcSyncChangeAlarm); 10505b261ecSmrgstatic DISPATCH_PROC(ProcSyncChangeCounter); 10605b261ecSmrgstatic DISPATCH_PROC(ProcSyncCreateAlarm); 10705b261ecSmrgstatic DISPATCH_PROC(ProcSyncCreateCounter); 10805b261ecSmrgstatic DISPATCH_PROC(ProcSyncDestroyAlarm); 10905b261ecSmrgstatic DISPATCH_PROC(ProcSyncDestroyCounter); 11005b261ecSmrgstatic DISPATCH_PROC(ProcSyncDispatch); 11105b261ecSmrgstatic DISPATCH_PROC(ProcSyncGetPriority); 11205b261ecSmrgstatic DISPATCH_PROC(ProcSyncInitialize); 11305b261ecSmrgstatic DISPATCH_PROC(ProcSyncListSystemCounters); 11405b261ecSmrgstatic DISPATCH_PROC(ProcSyncQueryAlarm); 11505b261ecSmrgstatic DISPATCH_PROC(ProcSyncQueryCounter); 11605b261ecSmrgstatic DISPATCH_PROC(ProcSyncSetCounter); 11705b261ecSmrgstatic DISPATCH_PROC(ProcSyncSetPriority); 11805b261ecSmrgstatic DISPATCH_PROC(SProcSyncAwait); 11905b261ecSmrgstatic DISPATCH_PROC(SProcSyncChangeAlarm); 12005b261ecSmrgstatic DISPATCH_PROC(SProcSyncChangeCounter); 12105b261ecSmrgstatic DISPATCH_PROC(SProcSyncCreateAlarm); 12205b261ecSmrgstatic DISPATCH_PROC(SProcSyncCreateCounter); 12305b261ecSmrgstatic DISPATCH_PROC(SProcSyncDestroyAlarm); 12405b261ecSmrgstatic DISPATCH_PROC(SProcSyncDestroyCounter); 12505b261ecSmrgstatic DISPATCH_PROC(SProcSyncDispatch); 12605b261ecSmrgstatic DISPATCH_PROC(SProcSyncGetPriority); 12705b261ecSmrgstatic DISPATCH_PROC(SProcSyncInitialize); 12805b261ecSmrgstatic DISPATCH_PROC(SProcSyncListSystemCounters); 12905b261ecSmrgstatic DISPATCH_PROC(SProcSyncQueryAlarm); 13005b261ecSmrgstatic DISPATCH_PROC(SProcSyncQueryCounter); 13105b261ecSmrgstatic DISPATCH_PROC(SProcSyncSetCounter); 13205b261ecSmrgstatic DISPATCH_PROC(SProcSyncSetPriority); 13305b261ecSmrg 13405b261ecSmrg/* Each counter maintains a simple linked list of triggers that are 13505b261ecSmrg * interested in the counter. The two functions below are used to 13605b261ecSmrg * delete and add triggers on this list. 13705b261ecSmrg */ 13805b261ecSmrgstatic void 1394202a189SmrgSyncDeleteTriggerFromCounter(SyncTrigger *pTrigger) 14005b261ecSmrg{ 14105b261ecSmrg SyncTriggerList *pCur; 14205b261ecSmrg SyncTriggerList *pPrev; 14305b261ecSmrg 14405b261ecSmrg /* pCounter needs to be stored in pTrigger before calling here. */ 14505b261ecSmrg 14605b261ecSmrg if (!pTrigger->pCounter) 14705b261ecSmrg return; 14805b261ecSmrg 14905b261ecSmrg pPrev = NULL; 15005b261ecSmrg pCur = pTrigger->pCounter->pTriglist; 15105b261ecSmrg 15205b261ecSmrg while (pCur) 15305b261ecSmrg { 15405b261ecSmrg if (pCur->pTrigger == pTrigger) 15505b261ecSmrg { 15605b261ecSmrg if (pPrev) 15705b261ecSmrg pPrev->next = pCur->next; 15805b261ecSmrg else 15905b261ecSmrg pTrigger->pCounter->pTriglist = pCur->next; 1604202a189Smrg 1614202a189Smrg free(pCur); 16205b261ecSmrg break; 16305b261ecSmrg } 16405b261ecSmrg 16505b261ecSmrg pPrev = pCur; 16605b261ecSmrg pCur = pCur->next; 16705b261ecSmrg } 1684202a189Smrg 16905b261ecSmrg if (IsSystemCounter(pTrigger->pCounter)) 1704202a189Smrg SyncComputeBracketValues(pTrigger->pCounter); 17105b261ecSmrg} 17205b261ecSmrg 17305b261ecSmrg 17405b261ecSmrgstatic int 1754202a189SmrgSyncAddTriggerToCounter(SyncTrigger *pTrigger) 17605b261ecSmrg{ 17705b261ecSmrg SyncTriggerList *pCur; 17805b261ecSmrg 17905b261ecSmrg if (!pTrigger->pCounter) 18005b261ecSmrg return Success; 18105b261ecSmrg 18205b261ecSmrg /* don't do anything if it's already there */ 18305b261ecSmrg for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) 18405b261ecSmrg { 18505b261ecSmrg if (pCur->pTrigger == pTrigger) 18605b261ecSmrg return Success; 18705b261ecSmrg } 18805b261ecSmrg 1894202a189Smrg if (!(pCur = malloc(sizeof(SyncTriggerList)))) 19005b261ecSmrg return BadAlloc; 19105b261ecSmrg 19205b261ecSmrg pCur->pTrigger = pTrigger; 19305b261ecSmrg pCur->next = pTrigger->pCounter->pTriglist; 19405b261ecSmrg pTrigger->pCounter->pTriglist = pCur; 19505b261ecSmrg 19605b261ecSmrg if (IsSystemCounter(pTrigger->pCounter)) 1974202a189Smrg SyncComputeBracketValues(pTrigger->pCounter); 19805b261ecSmrg 19905b261ecSmrg return Success; 20005b261ecSmrg} 20105b261ecSmrg 20205b261ecSmrg 2034202a189Smrg/* Below are four possible functions that can be plugged into 20405b261ecSmrg * pTrigger->CheckTrigger, corresponding to the four possible 20505b261ecSmrg * test-types. These functions are called after the counter's 20605b261ecSmrg * value changes but are also passed the old counter value 20705b261ecSmrg * so they can inspect both the old and new values. 20805b261ecSmrg * (PositiveTransition and NegativeTransition need to see both 20905b261ecSmrg * pieces of information.) These functions return the truth value 21005b261ecSmrg * of the trigger. 21105b261ecSmrg * 21205b261ecSmrg * All of them include the condition pTrigger->pCounter == NULL. 2134202a189Smrg * This is because the spec says that a trigger with a counter value 21405b261ecSmrg * of None is always TRUE. 21505b261ecSmrg */ 21605b261ecSmrg 21705b261ecSmrgstatic Bool 2184202a189SmrgSyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) 21905b261ecSmrg{ 22005b261ecSmrg return (pTrigger->pCounter == NULL || 22105b261ecSmrg XSyncValueGreaterOrEqual(pTrigger->pCounter->value, 22205b261ecSmrg pTrigger->test_value)); 22305b261ecSmrg} 22405b261ecSmrg 22505b261ecSmrgstatic Bool 2264202a189SmrgSyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) 22705b261ecSmrg{ 22805b261ecSmrg return (pTrigger->pCounter == NULL || 22905b261ecSmrg XSyncValueLessOrEqual(pTrigger->pCounter->value, 23005b261ecSmrg pTrigger->test_value)); 23105b261ecSmrg} 23205b261ecSmrg 23305b261ecSmrgstatic Bool 2344202a189SmrgSyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) 23505b261ecSmrg{ 23605b261ecSmrg return (pTrigger->pCounter == NULL || 23705b261ecSmrg (XSyncValueLessThan(oldval, pTrigger->test_value) && 23805b261ecSmrg XSyncValueGreaterOrEqual(pTrigger->pCounter->value, 23905b261ecSmrg pTrigger->test_value))); 24005b261ecSmrg} 24105b261ecSmrg 24205b261ecSmrgstatic Bool 2434202a189SmrgSyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) 24405b261ecSmrg{ 24505b261ecSmrg return (pTrigger->pCounter == NULL || 24605b261ecSmrg (XSyncValueGreaterThan(oldval, pTrigger->test_value) && 24705b261ecSmrg XSyncValueLessOrEqual(pTrigger->pCounter->value, 24805b261ecSmrg pTrigger->test_value))); 24905b261ecSmrg} 25005b261ecSmrg 2514202a189Smrgstatic int 2524202a189SmrgSyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter, 2534202a189Smrg Mask changes) 25405b261ecSmrg{ 25505b261ecSmrg SyncCounter *pCounter = pTrigger->pCounter; 256637ac9abSmrg int rc; 25705b261ecSmrg Bool newcounter = FALSE; 25805b261ecSmrg 25905b261ecSmrg if (changes & XSyncCACounter) 26005b261ecSmrg { 26105b261ecSmrg if (counter == None) 26205b261ecSmrg pCounter = NULL; 263f241d193Smrg else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, 264637ac9abSmrg counter, RTCounter, client, DixReadAccess))) 26505b261ecSmrg { 26605b261ecSmrg client->errorValue = counter; 2674202a189Smrg return rc; 26805b261ecSmrg } 26905b261ecSmrg if (pCounter != pTrigger->pCounter) 27005b261ecSmrg { /* new counter for trigger */ 27105b261ecSmrg SyncDeleteTriggerFromCounter(pTrigger); 27205b261ecSmrg pTrigger->pCounter = pCounter; 27305b261ecSmrg newcounter = TRUE; 27405b261ecSmrg } 27505b261ecSmrg } 27605b261ecSmrg 27705b261ecSmrg /* if system counter, ask it what the current value is */ 27805b261ecSmrg 27905b261ecSmrg if (IsSystemCounter(pCounter)) 28005b261ecSmrg { 28105b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 28205b261ecSmrg &pCounter->value); 28305b261ecSmrg } 28405b261ecSmrg 28505b261ecSmrg if (changes & XSyncCAValueType) 28605b261ecSmrg { 28705b261ecSmrg if (pTrigger->value_type != XSyncRelative && 28805b261ecSmrg pTrigger->value_type != XSyncAbsolute) 28905b261ecSmrg { 29005b261ecSmrg client->errorValue = pTrigger->value_type; 29105b261ecSmrg return BadValue; 29205b261ecSmrg } 29305b261ecSmrg } 29405b261ecSmrg 29505b261ecSmrg if (changes & XSyncCATestType) 29605b261ecSmrg { 29705b261ecSmrg if (pTrigger->test_type != XSyncPositiveTransition && 29805b261ecSmrg pTrigger->test_type != XSyncNegativeTransition && 29905b261ecSmrg pTrigger->test_type != XSyncPositiveComparison && 30005b261ecSmrg pTrigger->test_type != XSyncNegativeComparison) 30105b261ecSmrg { 30205b261ecSmrg client->errorValue = pTrigger->test_type; 30305b261ecSmrg return BadValue; 30405b261ecSmrg } 30505b261ecSmrg /* select appropriate CheckTrigger function */ 30605b261ecSmrg 30705b261ecSmrg switch (pTrigger->test_type) 30805b261ecSmrg { 3094202a189Smrg case XSyncPositiveTransition: 31005b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; 31105b261ecSmrg break; 3124202a189Smrg case XSyncNegativeTransition: 31305b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; 31405b261ecSmrg break; 3154202a189Smrg case XSyncPositiveComparison: 31605b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; 31705b261ecSmrg break; 3184202a189Smrg case XSyncNegativeComparison: 31905b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; 32005b261ecSmrg break; 32105b261ecSmrg } 32205b261ecSmrg } 32305b261ecSmrg 32405b261ecSmrg if (changes & (XSyncCAValueType | XSyncCAValue)) 32505b261ecSmrg { 32605b261ecSmrg if (pTrigger->value_type == XSyncAbsolute) 32705b261ecSmrg pTrigger->test_value = pTrigger->wait_value; 32805b261ecSmrg else /* relative */ 32905b261ecSmrg { 33005b261ecSmrg Bool overflow; 33105b261ecSmrg if (pCounter == NULL) 33205b261ecSmrg return BadMatch; 33305b261ecSmrg 3344202a189Smrg XSyncValueAdd(&pTrigger->test_value, pCounter->value, 33505b261ecSmrg pTrigger->wait_value, &overflow); 33605b261ecSmrg if (overflow) 33705b261ecSmrg { 33805b261ecSmrg client->errorValue = XSyncValueHigh32(pTrigger->wait_value); 33905b261ecSmrg return BadValue; 34005b261ecSmrg } 34105b261ecSmrg } 34205b261ecSmrg } 34305b261ecSmrg 34405b261ecSmrg /* we wait until we're sure there are no errors before registering 34505b261ecSmrg * a new counter on a trigger 34605b261ecSmrg */ 34705b261ecSmrg if (newcounter) 34805b261ecSmrg { 349637ac9abSmrg if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) 350637ac9abSmrg return rc; 35105b261ecSmrg } 35205b261ecSmrg else if (IsSystemCounter(pCounter)) 35305b261ecSmrg { 3544202a189Smrg SyncComputeBracketValues(pCounter); 35505b261ecSmrg } 3564202a189Smrg 35705b261ecSmrg return Success; 35805b261ecSmrg} 35905b261ecSmrg 36005b261ecSmrg/* AlarmNotify events happen in response to actions taken on an Alarm or 3614202a189Smrg * the counter used by the alarm. AlarmNotify may be sent to multiple 36205b261ecSmrg * clients. The alarm maintains a list of clients interested in events. 36305b261ecSmrg */ 36405b261ecSmrgstatic void 3654202a189SmrgSyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) 36605b261ecSmrg{ 36705b261ecSmrg SyncAlarmClientList *pcl; 36805b261ecSmrg xSyncAlarmNotifyEvent ane; 36905b261ecSmrg SyncTrigger *pTrigger = &pAlarm->trigger; 37005b261ecSmrg 37105b261ecSmrg UpdateCurrentTime(); 37205b261ecSmrg 37305b261ecSmrg ane.type = SyncEventBase + XSyncAlarmNotify; 37405b261ecSmrg ane.kind = XSyncAlarmNotify; 37505b261ecSmrg ane.alarm = pAlarm->alarm_id; 37605b261ecSmrg if (pTrigger->pCounter) 37705b261ecSmrg { 37805b261ecSmrg ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); 37905b261ecSmrg ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); 38005b261ecSmrg } 38105b261ecSmrg else 38205b261ecSmrg { /* XXX what else can we do if there's no counter? */ 38305b261ecSmrg ane.counter_value_hi = ane.counter_value_lo = 0; 38405b261ecSmrg } 38505b261ecSmrg 38605b261ecSmrg ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); 38705b261ecSmrg ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); 38805b261ecSmrg ane.time = currentTime.milliseconds; 38905b261ecSmrg ane.state = pAlarm->state; 39005b261ecSmrg 39105b261ecSmrg /* send to owner */ 3924202a189Smrg if (pAlarm->events) 39305b261ecSmrg WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); 39405b261ecSmrg 39505b261ecSmrg /* send to other interested clients */ 39605b261ecSmrg for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) 3974202a189Smrg WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); 39805b261ecSmrg} 39905b261ecSmrg 40005b261ecSmrg 4014202a189Smrg/* CounterNotify events only occur in response to an Await. The events 40205b261ecSmrg * go only to the Awaiting client. 40305b261ecSmrg */ 40405b261ecSmrgstatic void 4054202a189SmrgSyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, 4064202a189Smrg int num_events) 40705b261ecSmrg{ 40805b261ecSmrg xSyncCounterNotifyEvent *pEvents, *pev; 40905b261ecSmrg int i; 41005b261ecSmrg 41105b261ecSmrg if (client->clientGone) 41205b261ecSmrg return; 4134202a189Smrg pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent)); 4144202a189Smrg if (!pEvents) 41505b261ecSmrg return; 41605b261ecSmrg UpdateCurrentTime(); 41705b261ecSmrg for (i = 0; i < num_events; i++, ppAwait++, pev++) 41805b261ecSmrg { 41905b261ecSmrg SyncTrigger *pTrigger = &(*ppAwait)->trigger; 42005b261ecSmrg pev->type = SyncEventBase + XSyncCounterNotify; 42105b261ecSmrg pev->kind = XSyncCounterNotify; 42205b261ecSmrg pev->counter = pTrigger->pCounter->id; 42305b261ecSmrg pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); 42405b261ecSmrg pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 42505b261ecSmrg pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); 42605b261ecSmrg pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); 42705b261ecSmrg pev->time = currentTime.milliseconds; 42805b261ecSmrg pev->count = num_events - i - 1; /* events remaining */ 42905b261ecSmrg pev->destroyed = pTrigger->pCounter->beingDestroyed; 43005b261ecSmrg } 43105b261ecSmrg /* swapping will be taken care of by this */ 43205b261ecSmrg WriteEventsToClient(client, num_events, (xEvent *)pEvents); 4334202a189Smrg free(pEvents); 43405b261ecSmrg} 43505b261ecSmrg 43605b261ecSmrg 43705b261ecSmrg/* This function is called when an alarm's counter is destroyed. 43805b261ecSmrg * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). 43905b261ecSmrg */ 4404202a189Smrgstatic void 4414202a189SmrgSyncAlarmCounterDestroyed(SyncTrigger *pTrigger) 44205b261ecSmrg{ 44305b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 44405b261ecSmrg 44505b261ecSmrg pAlarm->state = XSyncAlarmInactive; 44605b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 44705b261ecSmrg pTrigger->pCounter = NULL; 44805b261ecSmrg} 44905b261ecSmrg 45005b261ecSmrg 4514202a189Smrg/* This function is called when an alarm "goes off." 45205b261ecSmrg * It is plugged into pTrigger->TriggerFired (for alarm triggers). 45305b261ecSmrg */ 45405b261ecSmrgstatic void 4554202a189SmrgSyncAlarmTriggerFired(SyncTrigger *pTrigger) 45605b261ecSmrg{ 45705b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 45805b261ecSmrg CARD64 new_test_value; 45905b261ecSmrg 46005b261ecSmrg /* no need to check alarm unless it's active */ 46105b261ecSmrg if (pAlarm->state != XSyncAlarmActive) 46205b261ecSmrg return; 46305b261ecSmrg 46405b261ecSmrg /* " if the counter value is None, or if the delta is 0 and 46505b261ecSmrg * the test-type is PositiveComparison or NegativeComparison, 46605b261ecSmrg * no change is made to value (test-value) and the alarm 46705b261ecSmrg * state is changed to Inactive before the event is generated." 46805b261ecSmrg */ 46905b261ecSmrg if (pAlarm->trigger.pCounter == NULL 47005b261ecSmrg || (XSyncValueIsZero(pAlarm->delta) 47105b261ecSmrg && (pAlarm->trigger.test_type == XSyncPositiveComparison 47205b261ecSmrg || pAlarm->trigger.test_type == XSyncNegativeComparison))) 47305b261ecSmrg pAlarm->state = XSyncAlarmInactive; 47405b261ecSmrg 47505b261ecSmrg new_test_value = pAlarm->trigger.test_value; 47605b261ecSmrg 47705b261ecSmrg if (pAlarm->state == XSyncAlarmActive) 47805b261ecSmrg { 47905b261ecSmrg Bool overflow; 48005b261ecSmrg CARD64 oldvalue; 48105b261ecSmrg SyncTrigger *paTrigger = &pAlarm->trigger; 48205b261ecSmrg 48305b261ecSmrg /* "The alarm is updated by repeatedly adding delta to the 48405b261ecSmrg * value of the trigger and re-initializing it until it 48505b261ecSmrg * becomes FALSE." 48605b261ecSmrg */ 48705b261ecSmrg oldvalue = paTrigger->test_value; 48805b261ecSmrg 48905b261ecSmrg /* XXX really should do something smarter here */ 49005b261ecSmrg 49105b261ecSmrg do 49205b261ecSmrg { 49305b261ecSmrg XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, 49405b261ecSmrg pAlarm->delta, &overflow); 4954202a189Smrg } while (!overflow && 49605b261ecSmrg (*paTrigger->CheckTrigger)(paTrigger, 49705b261ecSmrg paTrigger->pCounter->value)); 49805b261ecSmrg 49905b261ecSmrg new_test_value = paTrigger->test_value; 50005b261ecSmrg paTrigger->test_value = oldvalue; 50105b261ecSmrg 50205b261ecSmrg /* "If this update would cause value to fall outside the range 50305b261ecSmrg * for an INT64...no change is made to value (test-value) and 50405b261ecSmrg * the alarm state is changed to Inactive before the event is 50505b261ecSmrg * generated." 50605b261ecSmrg */ 50705b261ecSmrg if (overflow) 50805b261ecSmrg { 50905b261ecSmrg new_test_value = oldvalue; 51005b261ecSmrg pAlarm->state = XSyncAlarmInactive; 51105b261ecSmrg } 51205b261ecSmrg } 51305b261ecSmrg /* The AlarmNotify event has to have the "new state of the alarm" 51405b261ecSmrg * which we can't be sure of until this point. However, it has 51505b261ecSmrg * to have the "old" trigger test value. That's the reason for 51605b261ecSmrg * all the newvalue/oldvalue shuffling above. After we send the 51705b261ecSmrg * events, give the trigger its new test value. 51805b261ecSmrg */ 51905b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 52005b261ecSmrg pTrigger->test_value = new_test_value; 52105b261ecSmrg} 52205b261ecSmrg 52305b261ecSmrg 52405b261ecSmrg/* This function is called when an Await unblocks, either as a result 52505b261ecSmrg * of the trigger firing OR the counter being destroyed. 52605b261ecSmrg * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed 52705b261ecSmrg * (for Await triggers). 52805b261ecSmrg */ 52905b261ecSmrgstatic void 5304202a189SmrgSyncAwaitTriggerFired(SyncTrigger *pTrigger) 53105b261ecSmrg{ 53205b261ecSmrg SyncAwait *pAwait = (SyncAwait *)pTrigger; 53305b261ecSmrg int numwaits; 53405b261ecSmrg SyncAwaitUnion *pAwaitUnion; 53505b261ecSmrg SyncAwait **ppAwait; 53605b261ecSmrg int num_events = 0; 53705b261ecSmrg 53805b261ecSmrg pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; 53905b261ecSmrg numwaits = pAwaitUnion->header.num_waitconditions; 5404202a189Smrg ppAwait = malloc(numwaits * sizeof(SyncAwait *)); 54105b261ecSmrg if (!ppAwait) 54205b261ecSmrg goto bail; 54305b261ecSmrg 54405b261ecSmrg pAwait = &(pAwaitUnion+1)->await; 54505b261ecSmrg 54605b261ecSmrg /* "When a client is unblocked, all the CounterNotify events for 54705b261ecSmrg * the Await request are generated contiguously. If count is 0 54805b261ecSmrg * there are no more events to follow for this request. If 54905b261ecSmrg * count is n, there are at least n more events to follow." 55005b261ecSmrg * 55105b261ecSmrg * Thus, it is best to find all the counters for which events 55205b261ecSmrg * need to be sent first, so that an accurate count field can 55305b261ecSmrg * be stored in the events. 55405b261ecSmrg */ 55505b261ecSmrg for ( ; numwaits; numwaits--, pAwait++) 55605b261ecSmrg { 55705b261ecSmrg CARD64 diff; 55805b261ecSmrg Bool overflow, diffgreater, diffequal; 55905b261ecSmrg 56005b261ecSmrg /* "A CounterNotify event with the destroyed flag set to TRUE is 56105b261ecSmrg * always generated if the counter for one of the triggers is 56205b261ecSmrg * destroyed." 56305b261ecSmrg */ 56405b261ecSmrg if (pAwait->trigger.pCounter->beingDestroyed) 56505b261ecSmrg { 56605b261ecSmrg ppAwait[num_events++] = pAwait; 56705b261ecSmrg continue; 56805b261ecSmrg } 56905b261ecSmrg 57005b261ecSmrg /* "The difference between the counter and the test value is 57105b261ecSmrg * calculated by subtracting the test value from the value of 57205b261ecSmrg * the counter." 57305b261ecSmrg */ 57405b261ecSmrg XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, 57505b261ecSmrg pAwait->trigger.test_value, &overflow); 57605b261ecSmrg 57705b261ecSmrg /* "If the difference lies outside the range for an INT64, an 57805b261ecSmrg * event is not generated." 57905b261ecSmrg */ 58005b261ecSmrg if (overflow) 58105b261ecSmrg continue; 58205b261ecSmrg diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); 58305b261ecSmrg diffequal = XSyncValueEqual(diff, pAwait->event_threshold); 58405b261ecSmrg 58505b261ecSmrg /* "If the test-type is PositiveTransition or 58605b261ecSmrg * PositiveComparison, a CounterNotify event is generated if 58705b261ecSmrg * the difference is at least event-threshold. If the test-type 58805b261ecSmrg * is NegativeTransition or NegativeComparison, a CounterNotify 58905b261ecSmrg * event is generated if the difference is at most 59005b261ecSmrg * event-threshold." 59105b261ecSmrg */ 59205b261ecSmrg 59305b261ecSmrg if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || 59405b261ecSmrg pAwait->trigger.test_type == XSyncPositiveTransition) 59505b261ecSmrg && (diffgreater || diffequal)) 59605b261ecSmrg || 59705b261ecSmrg ((pAwait->trigger.test_type == XSyncNegativeComparison || 59805b261ecSmrg pAwait->trigger.test_type == XSyncNegativeTransition) 59905b261ecSmrg && (!diffgreater) /* less or equal */ 60005b261ecSmrg ) 60105b261ecSmrg ) 60205b261ecSmrg { 60305b261ecSmrg ppAwait[num_events++] = pAwait; 60405b261ecSmrg } 60505b261ecSmrg } 60605b261ecSmrg if (num_events) 60705b261ecSmrg SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, 60805b261ecSmrg num_events); 6094202a189Smrg free(ppAwait); 61005b261ecSmrg 61105b261ecSmrgbail: 61205b261ecSmrg /* unblock the client */ 61305b261ecSmrg AttendClient(pAwaitUnion->header.client); 61405b261ecSmrg /* delete the await */ 61505b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 61605b261ecSmrg} 61705b261ecSmrg 61805b261ecSmrg 61905b261ecSmrg/* This function should always be used to change a counter's value so that 62005b261ecSmrg * any triggers depending on the counter will be checked. 62105b261ecSmrg */ 62205b261ecSmrgvoid 6234202a189SmrgSyncChangeCounter(SyncCounter *pCounter, CARD64 newval) 62405b261ecSmrg{ 62505b261ecSmrg SyncTriggerList *ptl, *pnext; 62605b261ecSmrg CARD64 oldval; 62705b261ecSmrg 62805b261ecSmrg oldval = pCounter->value; 62905b261ecSmrg pCounter->value = newval; 63005b261ecSmrg 63105b261ecSmrg /* run through triggers to see if any become true */ 63205b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 63305b261ecSmrg { 63405b261ecSmrg pnext = ptl->next; 63505b261ecSmrg if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) 63605b261ecSmrg (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); 63705b261ecSmrg } 63805b261ecSmrg 63905b261ecSmrg if (IsSystemCounter(pCounter)) 64005b261ecSmrg { 6414202a189Smrg SyncComputeBracketValues(pCounter); 64205b261ecSmrg } 64305b261ecSmrg} 64405b261ecSmrg 64505b261ecSmrg 64605b261ecSmrg/* loosely based on dix/events.c/EventSelectForWindow */ 64705b261ecSmrgstatic Bool 6484202a189SmrgSyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) 64905b261ecSmrg{ 65005b261ecSmrg SyncAlarmClientList *pClients; 65105b261ecSmrg 65205b261ecSmrg if (client == pAlarm->client) /* alarm owner */ 65305b261ecSmrg { 65405b261ecSmrg pAlarm->events = wantevents; 65505b261ecSmrg return Success; 65605b261ecSmrg } 65705b261ecSmrg 65805b261ecSmrg /* see if the client is already on the list (has events selected) */ 65905b261ecSmrg 66005b261ecSmrg for (pClients = pAlarm->pEventClients; pClients; 66105b261ecSmrg pClients = pClients->next) 66205b261ecSmrg { 66305b261ecSmrg if (pClients->client == client) 66405b261ecSmrg { 6654202a189Smrg /* client's presence on the list indicates desire for 6664202a189Smrg * events. If the client doesn't want events, remove it 66705b261ecSmrg * from the list. If the client does want events, do 66805b261ecSmrg * nothing, since it's already got them. 66905b261ecSmrg */ 67005b261ecSmrg if (!wantevents) 67105b261ecSmrg { 67205b261ecSmrg FreeResource(pClients->delete_id, RT_NONE); 67305b261ecSmrg } 67405b261ecSmrg return Success; 67505b261ecSmrg } 67605b261ecSmrg } 67705b261ecSmrg 67805b261ecSmrg /* if we get here, this client does not currently have 67905b261ecSmrg * events selected on the alarm 68005b261ecSmrg */ 68105b261ecSmrg 68205b261ecSmrg if (!wantevents) 6834202a189Smrg /* client doesn't want events, and we just discovered that it 68405b261ecSmrg * doesn't have them, so there's nothing to do. 68505b261ecSmrg */ 68605b261ecSmrg return Success; 68705b261ecSmrg 68805b261ecSmrg /* add new client to pAlarm->pEventClients */ 68905b261ecSmrg 6904202a189Smrg pClients = malloc(sizeof(SyncAlarmClientList)); 69105b261ecSmrg if (!pClients) 69205b261ecSmrg return BadAlloc; 69305b261ecSmrg 6944202a189Smrg /* register it as a resource so it will be cleaned up 69505b261ecSmrg * if the client dies 69605b261ecSmrg */ 69705b261ecSmrg 69805b261ecSmrg pClients->delete_id = FakeClientID(client->index); 69905b261ecSmrg if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) 70005b261ecSmrg { 7014202a189Smrg free(pClients); 70205b261ecSmrg return BadAlloc; 70305b261ecSmrg } 70405b261ecSmrg 70505b261ecSmrg /* link it into list after we know all the allocations succeed */ 70605b261ecSmrg 70705b261ecSmrg pClients->next = pAlarm->pEventClients; 70805b261ecSmrg pAlarm->pEventClients = pClients; 70905b261ecSmrg pClients->client = client; 71005b261ecSmrg return Success; 71105b261ecSmrg} 71205b261ecSmrg 71305b261ecSmrg/* 71405b261ecSmrg * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm 71505b261ecSmrg */ 7164202a189Smrgstatic int 7174202a189SmrgSyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, 7184202a189Smrg CARD32 *values) 71905b261ecSmrg{ 72005b261ecSmrg int status; 72105b261ecSmrg XSyncCounter counter; 72205b261ecSmrg Mask origmask = mask; 72305b261ecSmrg 72405b261ecSmrg counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; 72505b261ecSmrg 72605b261ecSmrg while (mask) 72705b261ecSmrg { 72805b261ecSmrg int index2 = lowbit(mask); 72905b261ecSmrg mask &= ~index2; 73005b261ecSmrg switch (index2) 73105b261ecSmrg { 73205b261ecSmrg case XSyncCACounter: 73305b261ecSmrg mask &= ~XSyncCACounter; 73405b261ecSmrg /* sanity check in SyncInitTrigger */ 73505b261ecSmrg counter = *values++; 73605b261ecSmrg break; 73705b261ecSmrg 73805b261ecSmrg case XSyncCAValueType: 73905b261ecSmrg mask &= ~XSyncCAValueType; 74005b261ecSmrg /* sanity check in SyncInitTrigger */ 74105b261ecSmrg pAlarm->trigger.value_type = *values++; 74205b261ecSmrg break; 74305b261ecSmrg 74405b261ecSmrg case XSyncCAValue: 74505b261ecSmrg mask &= ~XSyncCAValue; 74605b261ecSmrg XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); 74705b261ecSmrg values += 2; 74805b261ecSmrg break; 74905b261ecSmrg 75005b261ecSmrg case XSyncCATestType: 75105b261ecSmrg mask &= ~XSyncCATestType; 75205b261ecSmrg /* sanity check in SyncInitTrigger */ 75305b261ecSmrg pAlarm->trigger.test_type = *values++; 75405b261ecSmrg break; 75505b261ecSmrg 75605b261ecSmrg case XSyncCADelta: 75705b261ecSmrg mask &= ~XSyncCADelta; 75805b261ecSmrg XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); 75905b261ecSmrg values += 2; 76005b261ecSmrg break; 76105b261ecSmrg 76205b261ecSmrg case XSyncCAEvents: 76305b261ecSmrg mask &= ~XSyncCAEvents; 76405b261ecSmrg if ((*values != xTrue) && (*values != xFalse)) 76505b261ecSmrg { 76605b261ecSmrg client->errorValue = *values; 76705b261ecSmrg return BadValue; 76805b261ecSmrg } 76905b261ecSmrg status = SyncEventSelectForAlarm(pAlarm, client, 77005b261ecSmrg (Bool)(*values++)); 77105b261ecSmrg if (status != Success) 77205b261ecSmrg return status; 77305b261ecSmrg break; 77405b261ecSmrg 77505b261ecSmrg default: 77605b261ecSmrg client->errorValue = mask; 77705b261ecSmrg return BadValue; 77805b261ecSmrg } 77905b261ecSmrg } 78005b261ecSmrg 78105b261ecSmrg /* "If the test-type is PositiveComparison or PositiveTransition 78205b261ecSmrg * and delta is less than zero, or if the test-type is 78305b261ecSmrg * NegativeComparison or NegativeTransition and delta is 78405b261ecSmrg * greater than zero, a Match error is generated." 78505b261ecSmrg */ 78605b261ecSmrg if (origmask & (XSyncCADelta|XSyncCATestType)) 78705b261ecSmrg { 78805b261ecSmrg CARD64 zero; 78905b261ecSmrg XSyncIntToValue(&zero, 0); 79005b261ecSmrg if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || 79105b261ecSmrg (pAlarm->trigger.test_type == XSyncPositiveTransition)) 79205b261ecSmrg && XSyncValueLessThan(pAlarm->delta, zero)) 79305b261ecSmrg || 79405b261ecSmrg (((pAlarm->trigger.test_type == XSyncNegativeComparison) || 79505b261ecSmrg (pAlarm->trigger.test_type == XSyncNegativeTransition)) 79605b261ecSmrg && XSyncValueGreaterThan(pAlarm->delta, zero)) 79705b261ecSmrg ) 79805b261ecSmrg { 79905b261ecSmrg return BadMatch; 80005b261ecSmrg } 80105b261ecSmrg } 80205b261ecSmrg 80305b261ecSmrg /* postpone this until now, when we're sure nothing else can go wrong */ 80405b261ecSmrg if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, 80505b261ecSmrg origmask & XSyncCAAllTrigger)) != Success) 80605b261ecSmrg return status; 80705b261ecSmrg 80805b261ecSmrg /* XXX spec does not really say to do this - needs clarification */ 80905b261ecSmrg pAlarm->state = XSyncAlarmActive; 81005b261ecSmrg return Success; 81105b261ecSmrg} 81205b261ecSmrg 81305b261ecSmrg 81405b261ecSmrgstatic SyncCounter * 8154202a189SmrgSyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) 81605b261ecSmrg{ 81705b261ecSmrg SyncCounter *pCounter; 81805b261ecSmrg 8194202a189Smrg if (!(pCounter = malloc(sizeof(SyncCounter)))) 8204202a189Smrg return NULL; 82105b261ecSmrg 82205b261ecSmrg if (!AddResource(id, RTCounter, (pointer) pCounter)) 82305b261ecSmrg { 8244202a189Smrg free(pCounter); 8254202a189Smrg return NULL; 82605b261ecSmrg } 82705b261ecSmrg 82805b261ecSmrg pCounter->client = client; 82905b261ecSmrg pCounter->id = id; 83005b261ecSmrg pCounter->value = initialvalue; 83105b261ecSmrg pCounter->pTriglist = NULL; 83205b261ecSmrg pCounter->beingDestroyed = FALSE; 83305b261ecSmrg pCounter->pSysCounterInfo = NULL; 83405b261ecSmrg return pCounter; 83505b261ecSmrg} 83605b261ecSmrg 8374202a189Smrgstatic int FreeCounter(void *, XID); 83805b261ecSmrg 83905b261ecSmrg/* 84005b261ecSmrg * ***** System Counter utilities 84105b261ecSmrg */ 84205b261ecSmrg 8434202a189Smrgpointer 8444202a189SmrgSyncCreateSystemCounter( 8454202a189Smrg char *name, 8464202a189Smrg CARD64 initial, 8474202a189Smrg CARD64 resolution, 8484202a189Smrg SyncCounterType counterType, 8494202a189Smrg void (*QueryValue)(pointer /* pCounter */, 8504202a189Smrg CARD64 * /* pValue_return */), 8514202a189Smrg void (*BracketValues)(pointer /* pCounter */, 8524202a189Smrg CARD64 * /* pbracket_less */, 8534202a189Smrg CARD64 * /* pbracket_greater */) 8544202a189Smrg ) 85505b261ecSmrg{ 85605b261ecSmrg SyncCounter *pCounter; 85705b261ecSmrg 8584202a189Smrg SysCounterList = realloc(SysCounterList, 85905b261ecSmrg (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); 86005b261ecSmrg if (!SysCounterList) 8614202a189Smrg return NULL; 86205b261ecSmrg 86305b261ecSmrg /* this function may be called before SYNC has been initialized, so we 86405b261ecSmrg * have to make sure RTCounter is created. 86505b261ecSmrg */ 86605b261ecSmrg if (RTCounter == 0) 86705b261ecSmrg { 8684202a189Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 86905b261ecSmrg if (RTCounter == 0) 87005b261ecSmrg { 8714202a189Smrg return NULL; 87205b261ecSmrg } 87305b261ecSmrg } 87405b261ecSmrg 8754202a189Smrg pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); 87605b261ecSmrg 87705b261ecSmrg if (pCounter) 87805b261ecSmrg { 87905b261ecSmrg SysCounterInfo *psci; 88005b261ecSmrg 8814202a189Smrg psci = malloc(sizeof(SysCounterInfo)); 88205b261ecSmrg if (!psci) 88305b261ecSmrg { 88405b261ecSmrg FreeResource(pCounter->id, RT_NONE); 8854202a189Smrg return pCounter; 88605b261ecSmrg } 88705b261ecSmrg pCounter->pSysCounterInfo = psci; 88805b261ecSmrg psci->name = name; 88905b261ecSmrg psci->resolution = resolution; 89005b261ecSmrg psci->counterType = counterType; 89105b261ecSmrg psci->QueryValue = QueryValue; 89205b261ecSmrg psci->BracketValues = BracketValues; 89305b261ecSmrg XSyncMaxValue(&psci->bracket_greater); 89405b261ecSmrg XSyncMinValue(&psci->bracket_less); 89505b261ecSmrg SysCounterList[SyncNumSystemCounters++] = pCounter; 89605b261ecSmrg } 8974202a189Smrg return pCounter; 89805b261ecSmrg} 89905b261ecSmrg 90005b261ecSmrgvoid 9014202a189SmrgSyncDestroySystemCounter(pointer pSysCounter) 90205b261ecSmrg{ 90305b261ecSmrg SyncCounter *pCounter = (SyncCounter *)pSysCounter; 90405b261ecSmrg FreeResource(pCounter->id, RT_NONE); 90505b261ecSmrg} 90605b261ecSmrg 90705b261ecSmrgstatic void 9084202a189SmrgSyncComputeBracketValues(SyncCounter *pCounter) 90905b261ecSmrg{ 91005b261ecSmrg SyncTriggerList *pCur; 91105b261ecSmrg SyncTrigger *pTrigger; 91205b261ecSmrg SysCounterInfo *psci; 91305b261ecSmrg CARD64 *pnewgtval = NULL; 91405b261ecSmrg CARD64 *pnewltval = NULL; 91505b261ecSmrg SyncCounterType ct; 91605b261ecSmrg 91705b261ecSmrg if (!pCounter) 91805b261ecSmrg return; 91905b261ecSmrg 92005b261ecSmrg psci = pCounter->pSysCounterInfo; 92105b261ecSmrg ct = pCounter->pSysCounterInfo->counterType; 92205b261ecSmrg if (ct == XSyncCounterNeverChanges) 92305b261ecSmrg return; 92405b261ecSmrg 9254202a189Smrg XSyncMaxValue(&psci->bracket_greater); 9264202a189Smrg XSyncMinValue(&psci->bracket_less); 92705b261ecSmrg 92805b261ecSmrg for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) 92905b261ecSmrg { 93005b261ecSmrg pTrigger = pCur->pTrigger; 93105b261ecSmrg 93205b261ecSmrg if (pTrigger->test_type == XSyncPositiveComparison && 93305b261ecSmrg ct != XSyncCounterNeverIncreases) 93405b261ecSmrg { 93505b261ecSmrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 93605b261ecSmrg XSyncValueLessThan(pTrigger->test_value, 93705b261ecSmrg psci->bracket_greater)) 93805b261ecSmrg { 93905b261ecSmrg psci->bracket_greater = pTrigger->test_value; 94005b261ecSmrg pnewgtval = &psci->bracket_greater; 94105b261ecSmrg } 94205b261ecSmrg } 94305b261ecSmrg else if (pTrigger->test_type == XSyncNegativeComparison && 94405b261ecSmrg ct != XSyncCounterNeverDecreases) 94505b261ecSmrg { 94605b261ecSmrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 94705b261ecSmrg XSyncValueGreaterThan(pTrigger->test_value, 94805b261ecSmrg psci->bracket_less)) 94905b261ecSmrg { 95005b261ecSmrg psci->bracket_less = pTrigger->test_value; 95105b261ecSmrg pnewltval = &psci->bracket_less; 95205b261ecSmrg } 95305b261ecSmrg } 954a0d10bb6Smrg else if (pTrigger->test_type == XSyncNegativeTransition && 95505b261ecSmrg ct != XSyncCounterNeverIncreases) 956a0d10bb6Smrg { 957a0d10bb6Smrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 958a0d10bb6Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) 959a0d10bb6Smrg { 960a0d10bb6Smrg psci->bracket_less = pTrigger->test_value; 961a0d10bb6Smrg pnewltval = &psci->bracket_less; 962a0d10bb6Smrg } 963a0d10bb6Smrg } 964a0d10bb6Smrg else if (pTrigger->test_type == XSyncPositiveTransition && 96505b261ecSmrg ct != XSyncCounterNeverDecreases) 96605b261ecSmrg { 967a0d10bb6Smrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 968a0d10bb6Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) 96905b261ecSmrg { 970a0d10bb6Smrg psci->bracket_greater = pTrigger->test_value; 971a0d10bb6Smrg pnewgtval = &psci->bracket_greater; 97205b261ecSmrg } 97305b261ecSmrg } 97405b261ecSmrg } /* end for each trigger */ 97505b261ecSmrg 97605b261ecSmrg if (pnewgtval || pnewltval) 97705b261ecSmrg { 97805b261ecSmrg (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); 97905b261ecSmrg } 98005b261ecSmrg} 98105b261ecSmrg 98205b261ecSmrg/* 98305b261ecSmrg * ***** Resource delete functions 98405b261ecSmrg */ 98505b261ecSmrg 98605b261ecSmrg/* ARGSUSED */ 98705b261ecSmrgstatic int 9884202a189SmrgFreeAlarm(void *addr, XID id) 98905b261ecSmrg{ 99005b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *) addr; 99105b261ecSmrg 99205b261ecSmrg pAlarm->state = XSyncAlarmDestroyed; 99305b261ecSmrg 99405b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 99505b261ecSmrg 99605b261ecSmrg /* delete event selections */ 99705b261ecSmrg 99805b261ecSmrg while (pAlarm->pEventClients) 99905b261ecSmrg FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 100005b261ecSmrg 100105b261ecSmrg SyncDeleteTriggerFromCounter(&pAlarm->trigger); 100205b261ecSmrg 10034202a189Smrg free(pAlarm); 100405b261ecSmrg return Success; 100505b261ecSmrg} 100605b261ecSmrg 100705b261ecSmrg 100805b261ecSmrg/* 100905b261ecSmrg * ** Cleanup after the destruction of a Counter 101005b261ecSmrg */ 101105b261ecSmrg/* ARGSUSED */ 101205b261ecSmrgstatic int 10134202a189SmrgFreeCounter(void *env, XID id) 101405b261ecSmrg{ 101505b261ecSmrg SyncCounter *pCounter = (SyncCounter *) env; 101605b261ecSmrg SyncTriggerList *ptl, *pnext; 101705b261ecSmrg 101805b261ecSmrg pCounter->beingDestroyed = TRUE; 101905b261ecSmrg /* tell all the counter's triggers that the counter has been destroyed */ 102005b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 102105b261ecSmrg { 102205b261ecSmrg (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); 102305b261ecSmrg pnext = ptl->next; 10244202a189Smrg free(ptl); /* destroy the trigger list as we go */ 102505b261ecSmrg } 102605b261ecSmrg if (IsSystemCounter(pCounter)) 102705b261ecSmrg { 102805b261ecSmrg int i, found = 0; 102905b261ecSmrg 10304202a189Smrg free(pCounter->pSysCounterInfo); 103105b261ecSmrg 103205b261ecSmrg /* find the counter in the list of system counters and remove it */ 103305b261ecSmrg 103405b261ecSmrg if (SysCounterList) 103505b261ecSmrg { 103605b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 103705b261ecSmrg { 103805b261ecSmrg if (SysCounterList[i] == pCounter) 103905b261ecSmrg { 104005b261ecSmrg found = i; 104105b261ecSmrg break; 104205b261ecSmrg } 104305b261ecSmrg } 104405b261ecSmrg if (found < (SyncNumSystemCounters-1)) 104505b261ecSmrg { 104605b261ecSmrg for (i = found; i < SyncNumSystemCounters-1; i++) 104705b261ecSmrg { 104805b261ecSmrg SysCounterList[i] = SysCounterList[i+1]; 104905b261ecSmrg } 105005b261ecSmrg } 105105b261ecSmrg } 105205b261ecSmrg SyncNumSystemCounters--; 105305b261ecSmrg } 10544202a189Smrg free(pCounter); 105505b261ecSmrg return Success; 105605b261ecSmrg} 105705b261ecSmrg 105805b261ecSmrg/* 105905b261ecSmrg * ** Cleanup after Await 106005b261ecSmrg */ 106105b261ecSmrg/* ARGSUSED */ 106205b261ecSmrgstatic int 10634202a189SmrgFreeAwait(void *addr, XID id) 106405b261ecSmrg{ 106505b261ecSmrg SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 106605b261ecSmrg SyncAwait *pAwait; 106705b261ecSmrg int numwaits; 106805b261ecSmrg 106905b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* first await on list */ 107005b261ecSmrg 107105b261ecSmrg /* remove triggers from counters */ 107205b261ecSmrg 107305b261ecSmrg for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 107405b261ecSmrg numwaits--, pAwait++) 107505b261ecSmrg { 10764202a189Smrg /* If the counter is being destroyed, FreeCounter will delete 107705b261ecSmrg * the trigger list itself, so don't do it here. 107805b261ecSmrg */ 107905b261ecSmrg SyncCounter *pCounter = pAwait->trigger.pCounter; 108005b261ecSmrg if (pCounter && !pCounter->beingDestroyed) 108105b261ecSmrg SyncDeleteTriggerFromCounter(&pAwait->trigger); 108205b261ecSmrg } 10834202a189Smrg free(pAwaitUnion); 108405b261ecSmrg return Success; 108505b261ecSmrg} 108605b261ecSmrg 108705b261ecSmrg/* loosely based on dix/events.c/OtherClientGone */ 108805b261ecSmrgstatic int 10894202a189SmrgFreeAlarmClient(void *value, XID id) 109005b261ecSmrg{ 109105b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)value; 109205b261ecSmrg SyncAlarmClientList *pCur, *pPrev; 109305b261ecSmrg 109405b261ecSmrg for (pPrev = NULL, pCur = pAlarm->pEventClients; 109505b261ecSmrg pCur; 109605b261ecSmrg pPrev = pCur, pCur = pCur->next) 109705b261ecSmrg { 109805b261ecSmrg if (pCur->delete_id == id) 109905b261ecSmrg { 110005b261ecSmrg if (pPrev) 110105b261ecSmrg pPrev->next = pCur->next; 110205b261ecSmrg else 110305b261ecSmrg pAlarm->pEventClients = pCur->next; 11044202a189Smrg free(pCur); 11054202a189Smrg return Success; 110605b261ecSmrg } 110705b261ecSmrg } 110805b261ecSmrg FatalError("alarm client not on event list"); 110905b261ecSmrg /*NOTREACHED*/ 111005b261ecSmrg} 111105b261ecSmrg 111205b261ecSmrg 111305b261ecSmrg/* 111405b261ecSmrg * ***** Proc functions 111505b261ecSmrg */ 111605b261ecSmrg 111705b261ecSmrg 111805b261ecSmrg/* 111905b261ecSmrg * ** Initialize the extension 112005b261ecSmrg */ 11214202a189Smrgstatic int 11224202a189SmrgProcSyncInitialize(ClientPtr client) 112305b261ecSmrg{ 112405b261ecSmrg xSyncInitializeReply rep; 112505b261ecSmrg int n; 112605b261ecSmrg 112705b261ecSmrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 112805b261ecSmrg 11294202a189Smrg memset(&rep, 0, sizeof(xSyncInitializeReply)); 113005b261ecSmrg rep.type = X_Reply; 113105b261ecSmrg rep.sequenceNumber = client->sequence; 113205b261ecSmrg rep.majorVersion = SYNC_MAJOR_VERSION; 113305b261ecSmrg rep.minorVersion = SYNC_MINOR_VERSION; 113405b261ecSmrg rep.length = 0; 113505b261ecSmrg 113605b261ecSmrg if (client->swapped) 113705b261ecSmrg { 113805b261ecSmrg swaps(&rep.sequenceNumber, n); 113905b261ecSmrg } 114005b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 11414202a189Smrg return Success; 114205b261ecSmrg} 114305b261ecSmrg 114405b261ecSmrg/* 114505b261ecSmrg * ** Get list of system counters available through the extension 114605b261ecSmrg */ 11474202a189Smrgstatic int 11484202a189SmrgProcSyncListSystemCounters(ClientPtr client) 114905b261ecSmrg{ 115005b261ecSmrg xSyncListSystemCountersReply rep; 115105b261ecSmrg int i, len; 115205b261ecSmrg xSyncSystemCounter *list = NULL, *walklist = NULL; 11534202a189Smrg 115405b261ecSmrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 115505b261ecSmrg 115605b261ecSmrg rep.type = X_Reply; 115705b261ecSmrg rep.sequenceNumber = client->sequence; 115805b261ecSmrg rep.nCounters = SyncNumSystemCounters; 115905b261ecSmrg 116005b261ecSmrg for (i = len = 0; i < SyncNumSystemCounters; i++) 116105b261ecSmrg { 116205b261ecSmrg char *name = SysCounterList[i]->pSysCounterInfo->name; 116305b261ecSmrg /* pad to 4 byte boundary */ 11644202a189Smrg len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); 116505b261ecSmrg } 116605b261ecSmrg 116705b261ecSmrg if (len) 116805b261ecSmrg { 11694202a189Smrg walklist = list = malloc(len); 117005b261ecSmrg if (!list) 117105b261ecSmrg return BadAlloc; 117205b261ecSmrg } 117305b261ecSmrg 11744202a189Smrg rep.length = bytes_to_int32(len); 117505b261ecSmrg 117605b261ecSmrg if (client->swapped) 117705b261ecSmrg { 1178637ac9abSmrg char n; 117905b261ecSmrg swaps(&rep.sequenceNumber, n); 118005b261ecSmrg swapl(&rep.length, n); 118105b261ecSmrg swapl(&rep.nCounters, n); 118205b261ecSmrg } 118305b261ecSmrg 118405b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 118505b261ecSmrg { 118605b261ecSmrg int namelen; 118705b261ecSmrg char *pname_in_reply; 118805b261ecSmrg SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; 118905b261ecSmrg 119005b261ecSmrg walklist->counter = SysCounterList[i]->id; 119105b261ecSmrg walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 119205b261ecSmrg walklist->resolution_lo = XSyncValueLow32(psci->resolution); 119305b261ecSmrg namelen = strlen(psci->name); 119405b261ecSmrg walklist->name_length = namelen; 119505b261ecSmrg 119605b261ecSmrg if (client->swapped) 119705b261ecSmrg { 1198637ac9abSmrg char n; 119905b261ecSmrg swapl(&walklist->counter, n); 120005b261ecSmrg swapl(&walklist->resolution_hi, n); 120105b261ecSmrg swapl(&walklist->resolution_lo, n); 120205b261ecSmrg swaps(&walklist->name_length, n); 120305b261ecSmrg } 120405b261ecSmrg 120505b261ecSmrg pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; 120605b261ecSmrg strncpy(pname_in_reply, psci->name, namelen); 12074202a189Smrg walklist = (xSyncSystemCounter *) (((char *)walklist) + 12084202a189Smrg pad_to_int32(sz_xSyncSystemCounter + namelen)); 120905b261ecSmrg } 121005b261ecSmrg 121105b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 12124202a189Smrg if (len) 121305b261ecSmrg { 121405b261ecSmrg WriteToClient(client, len, (char *) list); 12154202a189Smrg free(list); 121605b261ecSmrg } 121705b261ecSmrg 12184202a189Smrg return Success; 121905b261ecSmrg} 122005b261ecSmrg 122105b261ecSmrg/* 122205b261ecSmrg * ** Set client Priority 122305b261ecSmrg */ 12244202a189Smrgstatic int 12254202a189SmrgProcSyncSetPriority(ClientPtr client) 122605b261ecSmrg{ 122705b261ecSmrg REQUEST(xSyncSetPriorityReq); 122805b261ecSmrg ClientPtr priorityclient; 122905b261ecSmrg int rc; 123005b261ecSmrg 123105b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 123205b261ecSmrg 123305b261ecSmrg if (stuff->id == None) 123405b261ecSmrg priorityclient = client; 123505b261ecSmrg else { 123605b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1237637ac9abSmrg DixSetAttrAccess); 123805b261ecSmrg if (rc != Success) 123905b261ecSmrg return rc; 124005b261ecSmrg } 124105b261ecSmrg 124205b261ecSmrg if (priorityclient->priority != stuff->priority) 124305b261ecSmrg { 124405b261ecSmrg priorityclient->priority = stuff->priority; 124505b261ecSmrg 124605b261ecSmrg /* The following will force the server back into WaitForSomething 124705b261ecSmrg * so that the change in this client's priority is immediately 124805b261ecSmrg * reflected. 124905b261ecSmrg */ 125005b261ecSmrg isItTimeToYield = TRUE; 125105b261ecSmrg dispatchException |= DE_PRIORITYCHANGE; 125205b261ecSmrg } 125305b261ecSmrg return Success; 125405b261ecSmrg} 125505b261ecSmrg 125605b261ecSmrg/* 125705b261ecSmrg * ** Get client Priority 125805b261ecSmrg */ 12594202a189Smrgstatic int 12604202a189SmrgProcSyncGetPriority(ClientPtr client) 126105b261ecSmrg{ 126205b261ecSmrg REQUEST(xSyncGetPriorityReq); 126305b261ecSmrg xSyncGetPriorityReply rep; 126405b261ecSmrg ClientPtr priorityclient; 126505b261ecSmrg int rc; 126605b261ecSmrg 126705b261ecSmrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 126805b261ecSmrg 126905b261ecSmrg if (stuff->id == None) 127005b261ecSmrg priorityclient = client; 127105b261ecSmrg else { 127205b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1273637ac9abSmrg DixGetAttrAccess); 127405b261ecSmrg if (rc != Success) 127505b261ecSmrg return rc; 127605b261ecSmrg } 127705b261ecSmrg 127805b261ecSmrg rep.type = X_Reply; 127905b261ecSmrg rep.length = 0; 128005b261ecSmrg rep.sequenceNumber = client->sequence; 128105b261ecSmrg rep.priority = priorityclient->priority; 128205b261ecSmrg 128305b261ecSmrg if (client->swapped) 128405b261ecSmrg { 1285637ac9abSmrg char n; 128605b261ecSmrg swaps(&rep.sequenceNumber, n); 128705b261ecSmrg swapl(&rep.priority, n); 128805b261ecSmrg } 128905b261ecSmrg 129005b261ecSmrg WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); 129105b261ecSmrg 12924202a189Smrg return Success; 129305b261ecSmrg} 129405b261ecSmrg 129505b261ecSmrg/* 129605b261ecSmrg * ** Create a new counter 129705b261ecSmrg */ 12984202a189Smrgstatic int 12994202a189SmrgProcSyncCreateCounter(ClientPtr client) 130005b261ecSmrg{ 130105b261ecSmrg REQUEST(xSyncCreateCounterReq); 130205b261ecSmrg CARD64 initial; 130305b261ecSmrg 130405b261ecSmrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 130505b261ecSmrg 130605b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 130705b261ecSmrg 130805b261ecSmrg XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); 130905b261ecSmrg if (!SyncCreateCounter(client, stuff->cid, initial)) 131005b261ecSmrg return BadAlloc; 131105b261ecSmrg 13124202a189Smrg return Success; 131305b261ecSmrg} 131405b261ecSmrg 131505b261ecSmrg/* 131605b261ecSmrg * ** Set Counter value 131705b261ecSmrg */ 13184202a189Smrgstatic int 13194202a189SmrgProcSyncSetCounter(ClientPtr client) 132005b261ecSmrg{ 132105b261ecSmrg REQUEST(xSyncSetCounterReq); 132205b261ecSmrg SyncCounter *pCounter; 132305b261ecSmrg CARD64 newvalue; 13244202a189Smrg int rc; 132505b261ecSmrg 132605b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 132705b261ecSmrg 13284202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, 13294202a189Smrg client, DixWriteAccess); 13304202a189Smrg if (rc != Success) 13314202a189Smrg return rc; 133205b261ecSmrg 133305b261ecSmrg if (IsSystemCounter(pCounter)) 133405b261ecSmrg { 133505b261ecSmrg client->errorValue = stuff->cid; 133605b261ecSmrg return BadAccess; 133705b261ecSmrg } 133805b261ecSmrg 133905b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 134005b261ecSmrg SyncChangeCounter(pCounter, newvalue); 134105b261ecSmrg return Success; 134205b261ecSmrg} 134305b261ecSmrg 134405b261ecSmrg/* 134505b261ecSmrg * ** Change Counter value 134605b261ecSmrg */ 13474202a189Smrgstatic int 13484202a189SmrgProcSyncChangeCounter(ClientPtr client) 134905b261ecSmrg{ 135005b261ecSmrg REQUEST(xSyncChangeCounterReq); 135105b261ecSmrg SyncCounter *pCounter; 135205b261ecSmrg CARD64 newvalue; 135305b261ecSmrg Bool overflow; 13544202a189Smrg int rc; 135505b261ecSmrg 135605b261ecSmrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 135705b261ecSmrg 13584202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, 13594202a189Smrg client, DixWriteAccess); 13604202a189Smrg if (rc != Success) 13614202a189Smrg return rc; 136205b261ecSmrg 136305b261ecSmrg if (IsSystemCounter(pCounter)) 136405b261ecSmrg { 136505b261ecSmrg client->errorValue = stuff->cid; 136605b261ecSmrg return BadAccess; 136705b261ecSmrg } 136805b261ecSmrg 136905b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 137005b261ecSmrg XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 137105b261ecSmrg if (overflow) 137205b261ecSmrg { 137305b261ecSmrg /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 13744202a189Smrg client->errorValue = stuff->value_hi; 137505b261ecSmrg return BadValue; 137605b261ecSmrg } 137705b261ecSmrg SyncChangeCounter(pCounter, newvalue); 137805b261ecSmrg return Success; 137905b261ecSmrg} 138005b261ecSmrg 138105b261ecSmrg/* 138205b261ecSmrg * ** Destroy a counter 138305b261ecSmrg */ 13844202a189Smrgstatic int 13854202a189SmrgProcSyncDestroyCounter(ClientPtr client) 138605b261ecSmrg{ 138705b261ecSmrg REQUEST(xSyncDestroyCounterReq); 138805b261ecSmrg SyncCounter *pCounter; 13894202a189Smrg int rc; 139005b261ecSmrg 139105b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 139205b261ecSmrg 13934202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, 13944202a189Smrg client, DixDestroyAccess); 13954202a189Smrg if (rc != Success) 13964202a189Smrg return rc; 13974202a189Smrg 139805b261ecSmrg if (IsSystemCounter(pCounter)) 139905b261ecSmrg { 140005b261ecSmrg client->errorValue = stuff->counter; 140105b261ecSmrg return BadAccess; 140205b261ecSmrg } 140305b261ecSmrg FreeResource(pCounter->id, RT_NONE); 140405b261ecSmrg return Success; 140505b261ecSmrg} 140605b261ecSmrg 140705b261ecSmrg 140805b261ecSmrg/* 140905b261ecSmrg * ** Await 141005b261ecSmrg */ 14114202a189Smrgstatic int 14124202a189SmrgProcSyncAwait(ClientPtr client) 141305b261ecSmrg{ 141405b261ecSmrg REQUEST(xSyncAwaitReq); 141505b261ecSmrg int len, items; 141605b261ecSmrg int i; 141705b261ecSmrg xSyncWaitCondition *pProtocolWaitConds; 141805b261ecSmrg SyncAwaitUnion *pAwaitUnion; 141905b261ecSmrg SyncAwait *pAwait; 142005b261ecSmrg int status; 142105b261ecSmrg 142205b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 142305b261ecSmrg 142405b261ecSmrg len = client->req_len << 2; 142505b261ecSmrg len -= sz_xSyncAwaitReq; 142605b261ecSmrg items = len / sz_xSyncWaitCondition; 142705b261ecSmrg 142805b261ecSmrg if (items * sz_xSyncWaitCondition != len) 142905b261ecSmrg { 143005b261ecSmrg return BadLength; 143105b261ecSmrg } 143205b261ecSmrg if (items == 0) 143305b261ecSmrg { 143405b261ecSmrg client->errorValue = items; /* XXX protocol change */ 143505b261ecSmrg return BadValue; 143605b261ecSmrg } 143705b261ecSmrg 143805b261ecSmrg pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; 143905b261ecSmrg 14404202a189Smrg /* all the memory for the entire await list is allocated 144105b261ecSmrg * here in one chunk 144205b261ecSmrg */ 14434202a189Smrg pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion)); 144405b261ecSmrg if (!pAwaitUnion) 144505b261ecSmrg return BadAlloc; 144605b261ecSmrg 144705b261ecSmrg /* first item is the header, remainder are real wait conditions */ 144805b261ecSmrg 144905b261ecSmrg pAwaitUnion->header.delete_id = FakeClientID(client->index); 145005b261ecSmrg if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 145105b261ecSmrg { 14524202a189Smrg free(pAwaitUnion); 145305b261ecSmrg return BadAlloc; 145405b261ecSmrg } 145505b261ecSmrg 145605b261ecSmrg /* don't need to do any more memory allocation for this request! */ 145705b261ecSmrg 145805b261ecSmrg pAwaitUnion->header.client = client; 145905b261ecSmrg pAwaitUnion->header.num_waitconditions = 0; 146005b261ecSmrg 146105b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 146205b261ecSmrg for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) 146305b261ecSmrg { 146405b261ecSmrg if (pProtocolWaitConds->counter == None) /* XXX protocol change */ 146505b261ecSmrg { 146605b261ecSmrg /* this should take care of removing any triggers created by 146705b261ecSmrg * this request that have already been registered on counters 146805b261ecSmrg */ 146905b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 147005b261ecSmrg client->errorValue = pProtocolWaitConds->counter; 147105b261ecSmrg return SyncErrorBase + XSyncBadCounter; 147205b261ecSmrg } 147305b261ecSmrg 147405b261ecSmrg /* sanity checks are in SyncInitTrigger */ 147505b261ecSmrg pAwait->trigger.pCounter = NULL; 147605b261ecSmrg pAwait->trigger.value_type = pProtocolWaitConds->value_type; 147705b261ecSmrg XSyncIntsToValue(&pAwait->trigger.wait_value, 147805b261ecSmrg pProtocolWaitConds->wait_value_lo, 147905b261ecSmrg pProtocolWaitConds->wait_value_hi); 148005b261ecSmrg pAwait->trigger.test_type = pProtocolWaitConds->test_type; 148105b261ecSmrg 148205b261ecSmrg status = SyncInitTrigger(client, &pAwait->trigger, 148305b261ecSmrg pProtocolWaitConds->counter, XSyncCAAllTrigger); 148405b261ecSmrg if (status != Success) 148505b261ecSmrg { 148605b261ecSmrg /* this should take care of removing any triggers created by 148705b261ecSmrg * this request that have already been registered on counters 148805b261ecSmrg */ 148905b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 149005b261ecSmrg return status; 149105b261ecSmrg } 149205b261ecSmrg /* this is not a mistake -- same function works for both cases */ 149305b261ecSmrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 149405b261ecSmrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 149505b261ecSmrg XSyncIntsToValue(&pAwait->event_threshold, 149605b261ecSmrg pProtocolWaitConds->event_threshold_lo, 149705b261ecSmrg pProtocolWaitConds->event_threshold_hi); 149805b261ecSmrg pAwait->pHeader = &pAwaitUnion->header; 149905b261ecSmrg pAwaitUnion->header.num_waitconditions++; 150005b261ecSmrg } 150105b261ecSmrg 150205b261ecSmrg IgnoreClient(client); 150305b261ecSmrg 150405b261ecSmrg /* see if any of the triggers are already true */ 150505b261ecSmrg 150605b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 150705b261ecSmrg for (i = 0; i < items; i++, pAwait++) 150805b261ecSmrg { 150905b261ecSmrg /* don't have to worry about NULL counters because the request 151005b261ecSmrg * errors before we get here out if they occur 151105b261ecSmrg */ 151205b261ecSmrg if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, 151305b261ecSmrg pAwait->trigger.pCounter->value)) 151405b261ecSmrg { 151505b261ecSmrg (*pAwait->trigger.TriggerFired)(&pAwait->trigger); 151605b261ecSmrg break; /* once is enough */ 151705b261ecSmrg } 151805b261ecSmrg } 151905b261ecSmrg return Success; 152005b261ecSmrg} 152105b261ecSmrg 152205b261ecSmrg 152305b261ecSmrg/* 152405b261ecSmrg * ** Query a counter 152505b261ecSmrg */ 15264202a189Smrgstatic int 15274202a189SmrgProcSyncQueryCounter(ClientPtr client) 152805b261ecSmrg{ 152905b261ecSmrg REQUEST(xSyncQueryCounterReq); 153005b261ecSmrg xSyncQueryCounterReply rep; 153105b261ecSmrg SyncCounter *pCounter; 15324202a189Smrg int rc; 153305b261ecSmrg 153405b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 153505b261ecSmrg 15364202a189Smrg rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, 15374202a189Smrg RTCounter, client, DixReadAccess); 15384202a189Smrg if (rc != Success) 15394202a189Smrg return rc; 154005b261ecSmrg 154105b261ecSmrg rep.type = X_Reply; 154205b261ecSmrg rep.length = 0; 154305b261ecSmrg rep.sequenceNumber = client->sequence; 154405b261ecSmrg 154505b261ecSmrg /* if system counter, ask it what the current value is */ 154605b261ecSmrg 154705b261ecSmrg if (IsSystemCounter(pCounter)) 154805b261ecSmrg { 154905b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 155005b261ecSmrg &pCounter->value); 155105b261ecSmrg } 155205b261ecSmrg 155305b261ecSmrg rep.value_hi = XSyncValueHigh32(pCounter->value); 155405b261ecSmrg rep.value_lo = XSyncValueLow32(pCounter->value); 155505b261ecSmrg if (client->swapped) 155605b261ecSmrg { 1557637ac9abSmrg char n; 155805b261ecSmrg swaps(&rep.sequenceNumber, n); 155905b261ecSmrg swapl(&rep.length, n); 156005b261ecSmrg swapl(&rep.value_hi, n); 156105b261ecSmrg swapl(&rep.value_lo, n); 156205b261ecSmrg } 156305b261ecSmrg WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); 15644202a189Smrg return Success; 156505b261ecSmrg} 156605b261ecSmrg 156705b261ecSmrg 156805b261ecSmrg/* 156905b261ecSmrg * ** Create Alarm 157005b261ecSmrg */ 15714202a189Smrgstatic int 15724202a189SmrgProcSyncCreateAlarm(ClientPtr client) 157305b261ecSmrg{ 157405b261ecSmrg REQUEST(xSyncCreateAlarmReq); 157505b261ecSmrg SyncAlarm *pAlarm; 157605b261ecSmrg int status; 157705b261ecSmrg unsigned long len, vmask; 157805b261ecSmrg SyncTrigger *pTrigger; 157905b261ecSmrg 158005b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 158105b261ecSmrg 158205b261ecSmrg LEGAL_NEW_RESOURCE(stuff->id, client); 158305b261ecSmrg 158405b261ecSmrg vmask = stuff->valueMask; 15854202a189Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); 158605b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 158705b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 158805b261ecSmrg return BadLength; 158905b261ecSmrg 15904202a189Smrg if (!(pAlarm = malloc(sizeof(SyncAlarm)))) 159105b261ecSmrg { 159205b261ecSmrg return BadAlloc; 159305b261ecSmrg } 159405b261ecSmrg 159505b261ecSmrg /* set up defaults */ 159605b261ecSmrg 159705b261ecSmrg pTrigger = &pAlarm->trigger; 159805b261ecSmrg pTrigger->pCounter = NULL; 159905b261ecSmrg pTrigger->value_type = XSyncAbsolute; 160005b261ecSmrg XSyncIntToValue(&pTrigger->wait_value, 0L); 160105b261ecSmrg pTrigger->test_type = XSyncPositiveComparison; 160205b261ecSmrg pTrigger->TriggerFired = SyncAlarmTriggerFired; 160305b261ecSmrg pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 160405b261ecSmrg status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); 160505b261ecSmrg if (status != Success) 160605b261ecSmrg { 16074202a189Smrg free(pAlarm); 160805b261ecSmrg return status; 160905b261ecSmrg } 161005b261ecSmrg 161105b261ecSmrg pAlarm->client = client; 161205b261ecSmrg pAlarm->alarm_id = stuff->id; 161305b261ecSmrg XSyncIntToValue(&pAlarm->delta, 1L); 161405b261ecSmrg pAlarm->events = TRUE; 161505b261ecSmrg pAlarm->state = XSyncAlarmInactive; 161605b261ecSmrg pAlarm->pEventClients = NULL; 161705b261ecSmrg status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 161805b261ecSmrg (CARD32 *)&stuff[1]); 161905b261ecSmrg if (status != Success) 162005b261ecSmrg { 16214202a189Smrg free(pAlarm); 162205b261ecSmrg return status; 162305b261ecSmrg } 162405b261ecSmrg 162505b261ecSmrg if (!AddResource(stuff->id, RTAlarm, pAlarm)) 162605b261ecSmrg { 16274202a189Smrg free(pAlarm); 162805b261ecSmrg return BadAlloc; 162905b261ecSmrg } 163005b261ecSmrg 163105b261ecSmrg /* see if alarm already triggered. NULL counter will not trigger 163205b261ecSmrg * in CreateAlarm and sets alarm state to Inactive. 163305b261ecSmrg */ 163405b261ecSmrg 163505b261ecSmrg if (!pTrigger->pCounter) 163605b261ecSmrg { 163705b261ecSmrg pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 163805b261ecSmrg } 163905b261ecSmrg else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) 164005b261ecSmrg { 164105b261ecSmrg (*pTrigger->TriggerFired)(pTrigger); 164205b261ecSmrg } 164305b261ecSmrg 164405b261ecSmrg return Success; 164505b261ecSmrg} 164605b261ecSmrg 164705b261ecSmrg/* 164805b261ecSmrg * ** Change Alarm 164905b261ecSmrg */ 16504202a189Smrgstatic int 16514202a189SmrgProcSyncChangeAlarm(ClientPtr client) 165205b261ecSmrg{ 165305b261ecSmrg REQUEST(xSyncChangeAlarmReq); 165405b261ecSmrg SyncAlarm *pAlarm; 165505b261ecSmrg long vmask; 165605b261ecSmrg int len, status; 165705b261ecSmrg 165805b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 165905b261ecSmrg 16604202a189Smrg status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 16614202a189Smrg client, DixWriteAccess); 16624202a189Smrg if (status != Success) 16634202a189Smrg return status; 166405b261ecSmrg 166505b261ecSmrg vmask = stuff->valueMask; 16664202a189Smrg len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); 166705b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 166805b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 166905b261ecSmrg return BadLength; 167005b261ecSmrg 16714202a189Smrg if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 167205b261ecSmrg (CARD32 *)&stuff[1])) != Success) 167305b261ecSmrg return status; 167405b261ecSmrg 167505b261ecSmrg /* see if alarm already triggered. NULL counter WILL trigger 167605b261ecSmrg * in ChangeAlarm. 167705b261ecSmrg */ 167805b261ecSmrg 167905b261ecSmrg if (!pAlarm->trigger.pCounter || 168005b261ecSmrg (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, 168105b261ecSmrg pAlarm->trigger.pCounter->value)) 168205b261ecSmrg { 168305b261ecSmrg (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); 168405b261ecSmrg } 168505b261ecSmrg return Success; 168605b261ecSmrg} 168705b261ecSmrg 16884202a189Smrgstatic int 16894202a189SmrgProcSyncQueryAlarm(ClientPtr client) 169005b261ecSmrg{ 169105b261ecSmrg REQUEST(xSyncQueryAlarmReq); 169205b261ecSmrg SyncAlarm *pAlarm; 169305b261ecSmrg xSyncQueryAlarmReply rep; 169405b261ecSmrg SyncTrigger *pTrigger; 16954202a189Smrg int rc; 169605b261ecSmrg 169705b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 169805b261ecSmrg 16994202a189Smrg rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 17004202a189Smrg client, DixReadAccess); 17014202a189Smrg if (rc != Success) 17024202a189Smrg return rc; 170305b261ecSmrg 170405b261ecSmrg rep.type = X_Reply; 17054202a189Smrg rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); 170605b261ecSmrg rep.sequenceNumber = client->sequence; 170705b261ecSmrg 170805b261ecSmrg pTrigger = &pAlarm->trigger; 170905b261ecSmrg rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; 171005b261ecSmrg 171105b261ecSmrg#if 0 /* XXX unclear what to do, depends on whether relative value-types 171205b261ecSmrg * are "consumed" immediately and are considered absolute from then 171305b261ecSmrg * on. 171405b261ecSmrg */ 171505b261ecSmrg rep.value_type = pTrigger->value_type; 171605b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); 171705b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); 171805b261ecSmrg#else 171905b261ecSmrg rep.value_type = XSyncAbsolute; 172005b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 172105b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); 172205b261ecSmrg#endif 172305b261ecSmrg 172405b261ecSmrg rep.test_type = pTrigger->test_type; 172505b261ecSmrg rep.delta_hi = XSyncValueHigh32(pAlarm->delta); 172605b261ecSmrg rep.delta_lo = XSyncValueLow32(pAlarm->delta); 172705b261ecSmrg rep.events = pAlarm->events; 172805b261ecSmrg rep.state = pAlarm->state; 172905b261ecSmrg 173005b261ecSmrg if (client->swapped) 173105b261ecSmrg { 1732637ac9abSmrg char n; 173305b261ecSmrg swaps(&rep.sequenceNumber, n); 173405b261ecSmrg swapl(&rep.length, n); 173505b261ecSmrg swapl(&rep.counter, n); 173605b261ecSmrg swapl(&rep.wait_value_hi, n); 173705b261ecSmrg swapl(&rep.wait_value_lo, n); 173805b261ecSmrg swapl(&rep.test_type, n); 173905b261ecSmrg swapl(&rep.delta_hi, n); 174005b261ecSmrg swapl(&rep.delta_lo, n); 174105b261ecSmrg } 174205b261ecSmrg 174305b261ecSmrg WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); 17444202a189Smrg return Success; 174505b261ecSmrg} 174605b261ecSmrg 17474202a189Smrgstatic int 17484202a189SmrgProcSyncDestroyAlarm(ClientPtr client) 174905b261ecSmrg{ 17504202a189Smrg SyncAlarm *pAlarm; 17514202a189Smrg int rc; 175205b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 175305b261ecSmrg 175405b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 175505b261ecSmrg 17564202a189Smrg rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, 17574202a189Smrg client, DixDestroyAccess); 17584202a189Smrg if (rc != Success) 17594202a189Smrg return rc; 176005b261ecSmrg 176105b261ecSmrg FreeResource(stuff->alarm, RT_NONE); 17624202a189Smrg return Success; 176305b261ecSmrg} 176405b261ecSmrg 176505b261ecSmrg/* 176605b261ecSmrg * ** Given an extension request, call the appropriate request procedure 176705b261ecSmrg */ 17684202a189Smrgstatic int 17694202a189SmrgProcSyncDispatch(ClientPtr client) 177005b261ecSmrg{ 177105b261ecSmrg REQUEST(xReq); 177205b261ecSmrg 177305b261ecSmrg switch (stuff->data) 177405b261ecSmrg { 177505b261ecSmrg case X_SyncInitialize: 177605b261ecSmrg return ProcSyncInitialize(client); 177705b261ecSmrg case X_SyncListSystemCounters: 177805b261ecSmrg return ProcSyncListSystemCounters(client); 177905b261ecSmrg case X_SyncCreateCounter: 178005b261ecSmrg return ProcSyncCreateCounter(client); 178105b261ecSmrg case X_SyncSetCounter: 178205b261ecSmrg return ProcSyncSetCounter(client); 178305b261ecSmrg case X_SyncChangeCounter: 178405b261ecSmrg return ProcSyncChangeCounter(client); 178505b261ecSmrg case X_SyncQueryCounter: 178605b261ecSmrg return ProcSyncQueryCounter(client); 178705b261ecSmrg case X_SyncDestroyCounter: 178805b261ecSmrg return ProcSyncDestroyCounter(client); 178905b261ecSmrg case X_SyncAwait: 179005b261ecSmrg return ProcSyncAwait(client); 179105b261ecSmrg case X_SyncCreateAlarm: 179205b261ecSmrg return ProcSyncCreateAlarm(client); 179305b261ecSmrg case X_SyncChangeAlarm: 179405b261ecSmrg return ProcSyncChangeAlarm(client); 179505b261ecSmrg case X_SyncQueryAlarm: 179605b261ecSmrg return ProcSyncQueryAlarm(client); 179705b261ecSmrg case X_SyncDestroyAlarm: 179805b261ecSmrg return ProcSyncDestroyAlarm(client); 179905b261ecSmrg case X_SyncSetPriority: 180005b261ecSmrg return ProcSyncSetPriority(client); 180105b261ecSmrg case X_SyncGetPriority: 180205b261ecSmrg return ProcSyncGetPriority(client); 180305b261ecSmrg default: 180405b261ecSmrg return BadRequest; 180505b261ecSmrg } 180605b261ecSmrg} 180705b261ecSmrg 180805b261ecSmrg/* 180905b261ecSmrg * Boring Swapping stuff ... 181005b261ecSmrg */ 181105b261ecSmrg 18124202a189Smrgstatic int 18134202a189SmrgSProcSyncInitialize(ClientPtr client) 181405b261ecSmrg{ 181505b261ecSmrg REQUEST(xSyncInitializeReq); 1816637ac9abSmrg char n; 181705b261ecSmrg 181805b261ecSmrg swaps(&stuff->length, n); 181905b261ecSmrg REQUEST_SIZE_MATCH (xSyncInitializeReq); 182005b261ecSmrg 182105b261ecSmrg return ProcSyncInitialize(client); 182205b261ecSmrg} 182305b261ecSmrg 18244202a189Smrgstatic int 18254202a189SmrgSProcSyncListSystemCounters(ClientPtr client) 182605b261ecSmrg{ 182705b261ecSmrg REQUEST(xSyncListSystemCountersReq); 1828637ac9abSmrg char n; 182905b261ecSmrg 183005b261ecSmrg swaps(&stuff->length, n); 183105b261ecSmrg REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); 183205b261ecSmrg 183305b261ecSmrg return ProcSyncListSystemCounters(client); 183405b261ecSmrg} 183505b261ecSmrg 18364202a189Smrgstatic int 18374202a189SmrgSProcSyncCreateCounter(ClientPtr client) 183805b261ecSmrg{ 183905b261ecSmrg REQUEST(xSyncCreateCounterReq); 1840637ac9abSmrg char n; 184105b261ecSmrg 184205b261ecSmrg swaps(&stuff->length, n); 184305b261ecSmrg REQUEST_SIZE_MATCH (xSyncCreateCounterReq); 184405b261ecSmrg swapl(&stuff->cid, n); 184505b261ecSmrg swapl(&stuff->initial_value_lo, n); 184605b261ecSmrg swapl(&stuff->initial_value_hi, n); 184705b261ecSmrg 184805b261ecSmrg return ProcSyncCreateCounter(client); 184905b261ecSmrg} 185005b261ecSmrg 18514202a189Smrgstatic int 18524202a189SmrgSProcSyncSetCounter(ClientPtr client) 185305b261ecSmrg{ 185405b261ecSmrg REQUEST(xSyncSetCounterReq); 1855637ac9abSmrg char n; 185605b261ecSmrg 185705b261ecSmrg swaps(&stuff->length, n); 185805b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetCounterReq); 185905b261ecSmrg swapl(&stuff->cid, n); 186005b261ecSmrg swapl(&stuff->value_lo, n); 186105b261ecSmrg swapl(&stuff->value_hi, n); 186205b261ecSmrg 186305b261ecSmrg return ProcSyncSetCounter(client); 186405b261ecSmrg} 186505b261ecSmrg 18664202a189Smrgstatic int 18674202a189SmrgSProcSyncChangeCounter(ClientPtr client) 186805b261ecSmrg{ 186905b261ecSmrg REQUEST(xSyncChangeCounterReq); 1870637ac9abSmrg char n; 187105b261ecSmrg 187205b261ecSmrg swaps(&stuff->length, n); 187305b261ecSmrg REQUEST_SIZE_MATCH (xSyncChangeCounterReq); 187405b261ecSmrg swapl(&stuff->cid, n); 187505b261ecSmrg swapl(&stuff->value_lo, n); 187605b261ecSmrg swapl(&stuff->value_hi, n); 187705b261ecSmrg 187805b261ecSmrg return ProcSyncChangeCounter(client); 187905b261ecSmrg} 188005b261ecSmrg 18814202a189Smrgstatic int 18824202a189SmrgSProcSyncQueryCounter(ClientPtr client) 188305b261ecSmrg{ 188405b261ecSmrg REQUEST(xSyncQueryCounterReq); 1885637ac9abSmrg char n; 188605b261ecSmrg 188705b261ecSmrg swaps(&stuff->length, n); 188805b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryCounterReq); 188905b261ecSmrg swapl(&stuff->counter, n); 189005b261ecSmrg 189105b261ecSmrg return ProcSyncQueryCounter(client); 189205b261ecSmrg} 189305b261ecSmrg 18944202a189Smrgstatic int 18954202a189SmrgSProcSyncDestroyCounter(ClientPtr client) 189605b261ecSmrg{ 189705b261ecSmrg REQUEST(xSyncDestroyCounterReq); 1898637ac9abSmrg char n; 189905b261ecSmrg 190005b261ecSmrg swaps(&stuff->length, n); 190105b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); 190205b261ecSmrg swapl(&stuff->counter, n); 190305b261ecSmrg 190405b261ecSmrg return ProcSyncDestroyCounter(client); 190505b261ecSmrg} 190605b261ecSmrg 19074202a189Smrgstatic int 19084202a189SmrgSProcSyncAwait(ClientPtr client) 190905b261ecSmrg{ 191005b261ecSmrg REQUEST(xSyncAwaitReq); 1911637ac9abSmrg char n; 191205b261ecSmrg 191305b261ecSmrg swaps(&stuff->length, n); 191405b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 191505b261ecSmrg SwapRestL(stuff); 191605b261ecSmrg 191705b261ecSmrg return ProcSyncAwait(client); 191805b261ecSmrg} 191905b261ecSmrg 19204202a189Smrgstatic int 19214202a189SmrgSProcSyncCreateAlarm(ClientPtr client) 192205b261ecSmrg{ 192305b261ecSmrg REQUEST(xSyncCreateAlarmReq); 1924637ac9abSmrg char n; 192505b261ecSmrg 192605b261ecSmrg swaps(&stuff->length, n); 192705b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 192805b261ecSmrg swapl(&stuff->id, n); 192905b261ecSmrg swapl(&stuff->valueMask, n); 193005b261ecSmrg SwapRestL(stuff); 193105b261ecSmrg 193205b261ecSmrg return ProcSyncCreateAlarm(client); 193305b261ecSmrg} 193405b261ecSmrg 19354202a189Smrgstatic int 19364202a189SmrgSProcSyncChangeAlarm(ClientPtr client) 193705b261ecSmrg{ 193805b261ecSmrg REQUEST(xSyncChangeAlarmReq); 1939637ac9abSmrg char n; 194005b261ecSmrg 194105b261ecSmrg swaps(&stuff->length, n); 194205b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 194305b261ecSmrg swapl(&stuff->alarm, n); 194405b261ecSmrg swapl(&stuff->valueMask, n); 194505b261ecSmrg SwapRestL(stuff); 194605b261ecSmrg return ProcSyncChangeAlarm(client); 194705b261ecSmrg} 194805b261ecSmrg 19494202a189Smrgstatic int 19504202a189SmrgSProcSyncQueryAlarm(ClientPtr client) 195105b261ecSmrg{ 195205b261ecSmrg REQUEST(xSyncQueryAlarmReq); 1953637ac9abSmrg char n; 195405b261ecSmrg 195505b261ecSmrg swaps(&stuff->length, n); 195605b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); 195705b261ecSmrg swapl(&stuff->alarm, n); 195805b261ecSmrg 195905b261ecSmrg return ProcSyncQueryAlarm(client); 196005b261ecSmrg} 196105b261ecSmrg 19624202a189Smrgstatic int 19634202a189SmrgSProcSyncDestroyAlarm(ClientPtr client) 196405b261ecSmrg{ 196505b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 1966637ac9abSmrg char n; 196705b261ecSmrg 196805b261ecSmrg swaps(&stuff->length, n); 196905b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); 197005b261ecSmrg swapl(&stuff->alarm, n); 197105b261ecSmrg 197205b261ecSmrg return ProcSyncDestroyAlarm(client); 197305b261ecSmrg} 197405b261ecSmrg 19754202a189Smrgstatic int 19764202a189SmrgSProcSyncSetPriority(ClientPtr client) 197705b261ecSmrg{ 197805b261ecSmrg REQUEST(xSyncSetPriorityReq); 1979637ac9abSmrg char n; 198005b261ecSmrg 198105b261ecSmrg swaps(&stuff->length, n); 198205b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetPriorityReq); 198305b261ecSmrg swapl(&stuff->id, n); 198405b261ecSmrg swapl(&stuff->priority, n); 198505b261ecSmrg 198605b261ecSmrg return ProcSyncSetPriority(client); 198705b261ecSmrg} 198805b261ecSmrg 19894202a189Smrgstatic int 19904202a189SmrgSProcSyncGetPriority(ClientPtr client) 199105b261ecSmrg{ 199205b261ecSmrg REQUEST(xSyncGetPriorityReq); 1993637ac9abSmrg char n; 199405b261ecSmrg 199505b261ecSmrg swaps(&stuff->length, n); 199605b261ecSmrg REQUEST_SIZE_MATCH (xSyncGetPriorityReq); 199705b261ecSmrg swapl(&stuff->id, n); 199805b261ecSmrg 199905b261ecSmrg return ProcSyncGetPriority(client); 200005b261ecSmrg} 200105b261ecSmrg 200205b261ecSmrg 20034202a189Smrgstatic int 20044202a189SmrgSProcSyncDispatch(ClientPtr client) 200505b261ecSmrg{ 200605b261ecSmrg REQUEST(xReq); 200705b261ecSmrg 200805b261ecSmrg switch (stuff->data) 200905b261ecSmrg { 201005b261ecSmrg case X_SyncInitialize: 201105b261ecSmrg return SProcSyncInitialize(client); 201205b261ecSmrg case X_SyncListSystemCounters: 201305b261ecSmrg return SProcSyncListSystemCounters(client); 201405b261ecSmrg case X_SyncCreateCounter: 201505b261ecSmrg return SProcSyncCreateCounter(client); 201605b261ecSmrg case X_SyncSetCounter: 201705b261ecSmrg return SProcSyncSetCounter(client); 201805b261ecSmrg case X_SyncChangeCounter: 201905b261ecSmrg return SProcSyncChangeCounter(client); 202005b261ecSmrg case X_SyncQueryCounter: 202105b261ecSmrg return SProcSyncQueryCounter(client); 202205b261ecSmrg case X_SyncDestroyCounter: 202305b261ecSmrg return SProcSyncDestroyCounter(client); 202405b261ecSmrg case X_SyncAwait: 202505b261ecSmrg return SProcSyncAwait(client); 202605b261ecSmrg case X_SyncCreateAlarm: 202705b261ecSmrg return SProcSyncCreateAlarm(client); 202805b261ecSmrg case X_SyncChangeAlarm: 202905b261ecSmrg return SProcSyncChangeAlarm(client); 203005b261ecSmrg case X_SyncQueryAlarm: 203105b261ecSmrg return SProcSyncQueryAlarm(client); 203205b261ecSmrg case X_SyncDestroyAlarm: 203305b261ecSmrg return SProcSyncDestroyAlarm(client); 203405b261ecSmrg case X_SyncSetPriority: 203505b261ecSmrg return SProcSyncSetPriority(client); 203605b261ecSmrg case X_SyncGetPriority: 203705b261ecSmrg return SProcSyncGetPriority(client); 203805b261ecSmrg default: 203905b261ecSmrg return BadRequest; 204005b261ecSmrg } 204105b261ecSmrg} 204205b261ecSmrg 204305b261ecSmrg/* 204405b261ecSmrg * Event Swapping 204505b261ecSmrg */ 204605b261ecSmrg 20474202a189Smrgstatic void 20484202a189SmrgSCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) 204905b261ecSmrg{ 205005b261ecSmrg to->type = from->type; 205105b261ecSmrg to->kind = from->kind; 205205b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 205305b261ecSmrg cpswapl(from->counter, to->counter); 205405b261ecSmrg cpswapl(from->wait_value_lo, to->wait_value_lo); 205505b261ecSmrg cpswapl(from->wait_value_hi, to->wait_value_hi); 205605b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 205705b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 205805b261ecSmrg cpswapl(from->time, to->time); 205905b261ecSmrg cpswaps(from->count, to->count); 206005b261ecSmrg to->destroyed = from->destroyed; 206105b261ecSmrg} 206205b261ecSmrg 206305b261ecSmrg 20644202a189Smrgstatic void 20654202a189SmrgSAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) 206605b261ecSmrg{ 206705b261ecSmrg to->type = from->type; 206805b261ecSmrg to->kind = from->kind; 206905b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 207005b261ecSmrg cpswapl(from->alarm, to->alarm); 207105b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 207205b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 207305b261ecSmrg cpswapl(from->alarm_value_lo, to->alarm_value_lo); 207405b261ecSmrg cpswapl(from->alarm_value_hi, to->alarm_value_hi); 207505b261ecSmrg cpswapl(from->time, to->time); 207605b261ecSmrg to->state = from->state; 207705b261ecSmrg} 207805b261ecSmrg 207905b261ecSmrg/* 208005b261ecSmrg * ** Close everything down. ** This is fairly simple for now. 208105b261ecSmrg */ 208205b261ecSmrg/* ARGSUSED */ 20834202a189Smrgstatic void 20844202a189SmrgSyncResetProc(ExtensionEntry *extEntry) 208505b261ecSmrg{ 20864202a189Smrg free(SysCounterList); 208705b261ecSmrg SysCounterList = NULL; 208805b261ecSmrg RTCounter = 0; 208905b261ecSmrg} 209005b261ecSmrg 209105b261ecSmrg 209205b261ecSmrg/* 209305b261ecSmrg * ** Initialise the extension. 209405b261ecSmrg */ 20954202a189Smrgvoid 20964202a189SmrgSyncExtensionInit(void) 209705b261ecSmrg{ 209805b261ecSmrg ExtensionEntry *extEntry; 209905b261ecSmrg 210005b261ecSmrg if (RTCounter == 0) 210105b261ecSmrg { 21024202a189Smrg RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); 210305b261ecSmrg } 21044202a189Smrg RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); 21054202a189Smrg RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); 21064202a189Smrg if (RTAwait) 21074202a189Smrg RTAwait |= RC_NEVERRETAIN; 21084202a189Smrg RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); 21094202a189Smrg if (RTAlarmClient) 21104202a189Smrg RTAlarmClient |= RC_NEVERRETAIN; 211105b261ecSmrg 211205b261ecSmrg if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 211305b261ecSmrg RTAlarmClient == 0 || 211405b261ecSmrg (extEntry = AddExtension(SYNC_NAME, 211505b261ecSmrg XSyncNumberEvents, XSyncNumberErrors, 211605b261ecSmrg ProcSyncDispatch, SProcSyncDispatch, 211705b261ecSmrg SyncResetProc, 211805b261ecSmrg StandardMinorOpcode)) == NULL) 211905b261ecSmrg { 212005b261ecSmrg ErrorF("Sync Extension %d.%d failed to Initialise\n", 212105b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 212205b261ecSmrg return; 212305b261ecSmrg } 212405b261ecSmrg 212505b261ecSmrg SyncEventBase = extEntry->eventBase; 212605b261ecSmrg SyncErrorBase = extEntry->errorBase; 212705b261ecSmrg EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; 212805b261ecSmrg EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; 212905b261ecSmrg 21304202a189Smrg SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter); 21314202a189Smrg SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm); 21324202a189Smrg 213305b261ecSmrg /* 213405b261ecSmrg * Although SERVERTIME is implemented by the OS layer, we initialise it 213505b261ecSmrg * here because doing it in OsInit() is too early. The resource database 213605b261ecSmrg * is not initialised when OsInit() is called. This is just about OK 213705b261ecSmrg * because there is always a servertime counter. 213805b261ecSmrg */ 213905b261ecSmrg SyncInitServerTime(); 214005b261ecSmrg SyncInitIdleTime(); 214105b261ecSmrg 214205b261ecSmrg#ifdef DEBUG 214305b261ecSmrg fprintf(stderr, "Sync Extension %d.%d\n", 214405b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 214505b261ecSmrg#endif 214605b261ecSmrg} 214705b261ecSmrg 214805b261ecSmrg 214905b261ecSmrg/* 215005b261ecSmrg * ***** SERVERTIME implementation - should go in its own file in OS directory? 215105b261ecSmrg */ 215205b261ecSmrg 215305b261ecSmrg 215405b261ecSmrg 215505b261ecSmrgstatic pointer ServertimeCounter; 215605b261ecSmrgstatic XSyncValue Now; 215705b261ecSmrgstatic XSyncValue *pnext_time; 215805b261ecSmrg 215905b261ecSmrg#define GetTime()\ 216005b261ecSmrg{\ 216105b261ecSmrg unsigned long millis = GetTimeInMillis();\ 216205b261ecSmrg unsigned long maxis = XSyncValueHigh32(Now);\ 216305b261ecSmrg if (millis < XSyncValueLow32(Now)) maxis++;\ 216405b261ecSmrg XSyncIntsToValue(&Now, millis, maxis);\ 216505b261ecSmrg} 216605b261ecSmrg 216705b261ecSmrg/* 216805b261ecSmrg*** Server Block Handler 21694202a189Smrg*** code inspired by multibuffer extension (now deprecated) 217005b261ecSmrg */ 217105b261ecSmrg/*ARGSUSED*/ 21724202a189Smrgstatic void 21734202a189SmrgServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) 217405b261ecSmrg{ 217505b261ecSmrg XSyncValue delay; 217605b261ecSmrg unsigned long timeout; 217705b261ecSmrg 217805b261ecSmrg if (pnext_time) 217905b261ecSmrg { 218005b261ecSmrg GetTime(); 218105b261ecSmrg 218205b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 218305b261ecSmrg { 218405b261ecSmrg timeout = 0; 21854202a189Smrg } 218605b261ecSmrg else 218705b261ecSmrg { 218805b261ecSmrg Bool overflow; 218905b261ecSmrg XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 219005b261ecSmrg (void)overflow; 219105b261ecSmrg timeout = XSyncValueLow32(delay); 219205b261ecSmrg } 219305b261ecSmrg AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 219405b261ecSmrg } 219505b261ecSmrg} 219605b261ecSmrg 219705b261ecSmrg/* 219805b261ecSmrg*** Wakeup Handler 219905b261ecSmrg */ 220005b261ecSmrg/*ARGSUSED*/ 22014202a189Smrgstatic void 22024202a189SmrgServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) 220305b261ecSmrg{ 220405b261ecSmrg if (pnext_time) 220505b261ecSmrg { 220605b261ecSmrg GetTime(); 220705b261ecSmrg 220805b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 220905b261ecSmrg { 221005b261ecSmrg SyncChangeCounter(ServertimeCounter, Now); 221105b261ecSmrg } 221205b261ecSmrg } 221305b261ecSmrg} 221405b261ecSmrg 221505b261ecSmrgstatic void 22164202a189SmrgServertimeQueryValue(void *pCounter, CARD64 *pValue_return) 221705b261ecSmrg{ 221805b261ecSmrg GetTime(); 221905b261ecSmrg *pValue_return = Now; 222005b261ecSmrg} 222105b261ecSmrg 222205b261ecSmrgstatic void 22234202a189SmrgServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, 22244202a189Smrg CARD64 *pbracket_greater) 222505b261ecSmrg{ 222605b261ecSmrg if (!pnext_time && pbracket_greater) 222705b261ecSmrg { 222805b261ecSmrg RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 222905b261ecSmrg ServertimeWakeupHandler, 223005b261ecSmrg NULL); 223105b261ecSmrg } 223205b261ecSmrg else if (pnext_time && !pbracket_greater) 223305b261ecSmrg { 223405b261ecSmrg RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 223505b261ecSmrg ServertimeWakeupHandler, 223605b261ecSmrg NULL); 223705b261ecSmrg } 223805b261ecSmrg pnext_time = pbracket_greater; 223905b261ecSmrg} 224005b261ecSmrg 224105b261ecSmrgstatic void 224205b261ecSmrgSyncInitServerTime(void) 224305b261ecSmrg{ 224405b261ecSmrg CARD64 resolution; 224505b261ecSmrg 224605b261ecSmrg XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 224705b261ecSmrg XSyncIntToValue(&resolution, 4); 224805b261ecSmrg ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 224905b261ecSmrg XSyncCounterNeverDecreases, 225005b261ecSmrg ServertimeQueryValue, ServertimeBracketValues); 225105b261ecSmrg pnext_time = NULL; 225205b261ecSmrg} 225305b261ecSmrg 225405b261ecSmrg 225505b261ecSmrg 225605b261ecSmrg/* 225705b261ecSmrg * IDLETIME implementation 225805b261ecSmrg */ 225905b261ecSmrg 226045801275Sjmcneillstatic SyncCounter *IdleTimeCounter; 226105b261ecSmrgstatic XSyncValue *pIdleTimeValueLess; 226205b261ecSmrgstatic XSyncValue *pIdleTimeValueGreater; 226305b261ecSmrg 226405b261ecSmrgstatic void 226505b261ecSmrgIdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 226605b261ecSmrg{ 226705b261ecSmrg CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 226805b261ecSmrg XSyncIntsToValue (pValue_return, idle, 0); 226905b261ecSmrg} 227005b261ecSmrg 227105b261ecSmrgstatic void 227245801275SjmcneillIdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) 227305b261ecSmrg{ 227445801275Sjmcneill XSyncValue idle, old_idle; 227545801275Sjmcneill SyncTriggerList *list = IdleTimeCounter->pTriglist; 227645801275Sjmcneill SyncTrigger *trig; 227705b261ecSmrg 227805b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 227905b261ecSmrg return; 228005b261ecSmrg 228145801275Sjmcneill old_idle = IdleTimeCounter->value; 228205b261ecSmrg IdleTimeQueryValue (NULL, &idle); 228345801275Sjmcneill IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ 228405b261ecSmrg 228505b261ecSmrg if (pIdleTimeValueLess && 228605b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 228705b261ecSmrg { 228845801275Sjmcneill /* 228945801275Sjmcneill * We've been idle for less than the threshold value, and someone 229045801275Sjmcneill * wants to know about that, but now we need to know whether they 229145801275Sjmcneill * want level or edge trigger. Check the trigger list against the 229245801275Sjmcneill * current idle time, and if any succeed, bomb out of select() 229345801275Sjmcneill * immediately so we can reschedule. 229445801275Sjmcneill */ 229545801275Sjmcneill 229645801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 229745801275Sjmcneill trig = list->pTrigger; 229845801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 229945801275Sjmcneill AdjustWaitForDelay(wt, 0); 230045801275Sjmcneill break; 230145801275Sjmcneill } 230245801275Sjmcneill } 230305b261ecSmrg } 230405b261ecSmrg else if (pIdleTimeValueGreater) 230505b261ecSmrg { 230645801275Sjmcneill /* 230745801275Sjmcneill * There's a threshold in the positive direction. If we've been 230845801275Sjmcneill * idle less than it, schedule a wakeup for sometime in the future. 230945801275Sjmcneill * If we've been idle more than it, and someone wants to know about 231045801275Sjmcneill * that level-triggered, schedule an immediate wakeup. 231145801275Sjmcneill */ 231245801275Sjmcneill unsigned long timeout = -1; 231305b261ecSmrg 231445801275Sjmcneill if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { 231505b261ecSmrg XSyncValue value; 231605b261ecSmrg Bool overflow; 231705b261ecSmrg 231805b261ecSmrg XSyncValueSubtract (&value, *pIdleTimeValueGreater, 231905b261ecSmrg idle, &overflow); 232045801275Sjmcneill timeout = min(timeout, XSyncValueLow32 (value)); 232145801275Sjmcneill } else { 232245801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 232345801275Sjmcneill trig = list->pTrigger; 232445801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 232545801275Sjmcneill timeout = min(timeout, 0); 232645801275Sjmcneill break; 232745801275Sjmcneill } 232845801275Sjmcneill } 232905b261ecSmrg } 233005b261ecSmrg 233105b261ecSmrg AdjustWaitForDelay (wt, timeout); 233205b261ecSmrg } 233345801275Sjmcneill 233445801275Sjmcneill IdleTimeCounter->value = old_idle; /* pop */ 233505b261ecSmrg} 233605b261ecSmrg 233705b261ecSmrgstatic void 23384202a189SmrgIdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) 233905b261ecSmrg{ 234005b261ecSmrg XSyncValue idle; 234105b261ecSmrg 234205b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 234305b261ecSmrg return; 234405b261ecSmrg 234505b261ecSmrg IdleTimeQueryValue (NULL, &idle); 234605b261ecSmrg 234705b261ecSmrg if ((pIdleTimeValueGreater && 234805b261ecSmrg XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || 234905b261ecSmrg (pIdleTimeValueLess && 235005b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) 235105b261ecSmrg { 235205b261ecSmrg SyncChangeCounter (IdleTimeCounter, idle); 235305b261ecSmrg } 235405b261ecSmrg} 235505b261ecSmrg 235605b261ecSmrgstatic void 23574202a189SmrgIdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, 235805b261ecSmrg CARD64 *pbracket_greater) 235905b261ecSmrg{ 236005b261ecSmrg Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); 236105b261ecSmrg 236205b261ecSmrg if (registered && !pbracket_less && !pbracket_greater) 236305b261ecSmrg { 236405b261ecSmrg RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 236505b261ecSmrg IdleTimeWakeupHandler, 236605b261ecSmrg NULL); 236705b261ecSmrg } 236805b261ecSmrg else if (!registered && (pbracket_less || pbracket_greater)) 236905b261ecSmrg { 237005b261ecSmrg RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 237105b261ecSmrg IdleTimeWakeupHandler, 237205b261ecSmrg NULL); 237305b261ecSmrg } 237405b261ecSmrg 237505b261ecSmrg pIdleTimeValueGreater = pbracket_greater; 237605b261ecSmrg pIdleTimeValueLess = pbracket_less; 237705b261ecSmrg} 237805b261ecSmrg 237905b261ecSmrgstatic void 238005b261ecSmrgSyncInitIdleTime (void) 238105b261ecSmrg{ 238205b261ecSmrg CARD64 resolution; 238305b261ecSmrg XSyncValue idle; 238405b261ecSmrg 238505b261ecSmrg IdleTimeQueryValue (NULL, &idle); 238605b261ecSmrg XSyncIntToValue (&resolution, 4); 238705b261ecSmrg 238805b261ecSmrg IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, 238905b261ecSmrg XSyncCounterUnrestricted, 239005b261ecSmrg IdleTimeQueryValue, 239105b261ecSmrg IdleTimeBracketValues); 239205b261ecSmrg 239305b261ecSmrg pIdleTimeValueLess = pIdleTimeValueGreater = NULL; 239405b261ecSmrg} 2395