sync.c revision f241d193
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 3705b261ecSmrgsupporting 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#define NEED_REPLIES 5405b261ecSmrg#define NEED_EVENTS 5505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5605b261ecSmrg#include <dix-config.h> 5705b261ecSmrg#endif 5805b261ecSmrg 5905b261ecSmrg#include <string.h> 6005b261ecSmrg 6105b261ecSmrg#include <X11/X.h> 6205b261ecSmrg#include <X11/Xproto.h> 6305b261ecSmrg#include <X11/Xmd.h> 6405b261ecSmrg#include "misc.h" 6505b261ecSmrg#include "os.h" 6605b261ecSmrg#include "extnsionst.h" 6705b261ecSmrg#include "dixstruct.h" 6805b261ecSmrg#include "resource.h" 6905b261ecSmrg#include "opaque.h" 7005b261ecSmrg#define _SYNC_SERVER 7105b261ecSmrg#include <X11/extensions/sync.h> 7205b261ecSmrg#include <X11/extensions/syncstr.h> 7305b261ecSmrg 7405b261ecSmrg#include <stdio.h> 75637ac9abSmrg#if !defined(WIN32) 7605b261ecSmrg#include <sys/time.h> 7705b261ecSmrg#endif 7805b261ecSmrg 7905b261ecSmrg#include "modinit.h" 8005b261ecSmrg 8105b261ecSmrg/* 8205b261ecSmrg * Local Global Variables 8305b261ecSmrg */ 8405b261ecSmrgstatic int SyncEventBase; 8505b261ecSmrgstatic int SyncErrorBase; 8605b261ecSmrgstatic RESTYPE RTCounter = 0; 8705b261ecSmrgstatic RESTYPE RTAwait; 8805b261ecSmrgstatic RESTYPE RTAlarm; 8905b261ecSmrgstatic RESTYPE RTAlarmClient; 9005b261ecSmrgstatic int SyncNumSystemCounters = 0; 9105b261ecSmrgstatic SyncCounter **SysCounterList = NULL; 9205b261ecSmrg 9305b261ecSmrg#define IsSystemCounter(pCounter) \ 9405b261ecSmrg (pCounter && (pCounter->client == NULL)) 9505b261ecSmrg 9605b261ecSmrg/* these are all the alarm attributes that pertain to the alarm's trigger */ 9705b261ecSmrg#define XSyncCAAllTrigger \ 9805b261ecSmrg (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) 9905b261ecSmrg 10005b261ecSmrgstatic int 10105b261ecSmrgFreeAlarm( 10205b261ecSmrg pointer /* addr */, 10305b261ecSmrg XID /* id */ 10405b261ecSmrg); 10505b261ecSmrg 10605b261ecSmrgstatic int 10705b261ecSmrgFreeAlarmClient( 10805b261ecSmrg pointer /* value */, 10905b261ecSmrg XID /* id */ 11005b261ecSmrg); 11105b261ecSmrg 11205b261ecSmrgstatic int 11305b261ecSmrgFreeAwait( 11405b261ecSmrg pointer /* addr */, 11505b261ecSmrg XID /* id */ 11605b261ecSmrg); 11705b261ecSmrg 11805b261ecSmrgstatic void 11905b261ecSmrgServertimeBracketValues( 12005b261ecSmrg pointer /* pCounter */, 12105b261ecSmrg CARD64 * /* pbracket_less */, 12205b261ecSmrg CARD64 * /* pbracket_greater */ 12305b261ecSmrg); 12405b261ecSmrg 12505b261ecSmrgstatic void 12605b261ecSmrgServertimeQueryValue( 12705b261ecSmrg pointer /* pCounter */, 12805b261ecSmrg CARD64 * /* pValue_return */ 12905b261ecSmrg); 13005b261ecSmrg 13105b261ecSmrgstatic void 13205b261ecSmrgServertimeWakeupHandler( 13305b261ecSmrg pointer /* env */, 13405b261ecSmrg int /* rc */, 13505b261ecSmrg pointer /* LastSelectMask */ 13605b261ecSmrg); 13705b261ecSmrg 13805b261ecSmrgstatic int 13905b261ecSmrgSyncInitTrigger( 14005b261ecSmrg ClientPtr /* client */, 14105b261ecSmrg SyncTrigger * /* pTrigger */, 14205b261ecSmrg XSyncCounter /* counter */, 14305b261ecSmrg Mask /* changes */ 14405b261ecSmrg); 14505b261ecSmrg 14605b261ecSmrgstatic void 14705b261ecSmrgSAlarmNotifyEvent( 14805b261ecSmrg xSyncAlarmNotifyEvent * /* from */, 14905b261ecSmrg xSyncAlarmNotifyEvent * /* to */ 15005b261ecSmrg); 15105b261ecSmrg 15205b261ecSmrgstatic void 15305b261ecSmrgSCounterNotifyEvent( 15405b261ecSmrg xSyncCounterNotifyEvent * /* from */, 15505b261ecSmrg xSyncCounterNotifyEvent * /* to */ 15605b261ecSmrg); 15705b261ecSmrg 15805b261ecSmrgstatic void 15905b261ecSmrgServertimeBlockHandler( 16005b261ecSmrg pointer /* env */, 16105b261ecSmrg struct timeval ** /* wt */, 16205b261ecSmrg pointer /* LastSelectMask */ 16305b261ecSmrg); 16405b261ecSmrg 16505b261ecSmrgstatic int 16605b261ecSmrgSyncAddTriggerToCounter( 16705b261ecSmrg SyncTrigger * /* pTrigger */ 16805b261ecSmrg); 16905b261ecSmrg 17005b261ecSmrgextern void 17105b261ecSmrgSyncAlarmCounterDestroyed( 17205b261ecSmrg SyncTrigger * /* pTrigger */ 17305b261ecSmrg); 17405b261ecSmrg 17505b261ecSmrgstatic void 17605b261ecSmrgSyncAlarmTriggerFired( 17705b261ecSmrg SyncTrigger * /* pTrigger */ 17805b261ecSmrg); 17905b261ecSmrg 18005b261ecSmrgstatic void 18105b261ecSmrgSyncAwaitTriggerFired( 18205b261ecSmrg SyncTrigger * /* pTrigger */ 18305b261ecSmrg); 18405b261ecSmrg 18505b261ecSmrgstatic int 18605b261ecSmrgSyncChangeAlarmAttributes( 18705b261ecSmrg ClientPtr /* client */, 18805b261ecSmrg SyncAlarm * /* pAlarm */, 18905b261ecSmrg Mask /* mask */, 19005b261ecSmrg CARD32 * /* values */ 19105b261ecSmrg); 19205b261ecSmrg 19305b261ecSmrgstatic Bool 19405b261ecSmrgSyncCheckTriggerNegativeComparison( 19505b261ecSmrg SyncTrigger * /* pTrigger */, 19605b261ecSmrg CARD64 /* oldval */ 19705b261ecSmrg); 19805b261ecSmrg 19905b261ecSmrgstatic Bool 20005b261ecSmrgSyncCheckTriggerNegativeTransition( 20105b261ecSmrg SyncTrigger * /* pTrigger */, 20205b261ecSmrg CARD64 /* oldval */ 20305b261ecSmrg); 20405b261ecSmrg 20505b261ecSmrgstatic Bool 20605b261ecSmrgSyncCheckTriggerPositiveComparison( 20705b261ecSmrg SyncTrigger * /* pTrigger */, 20805b261ecSmrg CARD64 /* oldval */ 20905b261ecSmrg); 21005b261ecSmrg 21105b261ecSmrgstatic Bool 21205b261ecSmrgSyncCheckTriggerPositiveTransition( 21305b261ecSmrg SyncTrigger * /* pTrigger */, 21405b261ecSmrg CARD64 /* oldval */ 21505b261ecSmrg); 21605b261ecSmrg 21705b261ecSmrgstatic SyncCounter * 21805b261ecSmrgSyncCreateCounter( 21905b261ecSmrg ClientPtr /* client */, 22005b261ecSmrg XSyncCounter /* id */, 22105b261ecSmrg CARD64 /* initialvalue */ 22205b261ecSmrg); 22305b261ecSmrg 22405b261ecSmrgstatic void SyncComputeBracketValues( 22505b261ecSmrg SyncCounter * /* pCounter */, 22605b261ecSmrg Bool /* startOver */ 22705b261ecSmrg); 22805b261ecSmrg 22905b261ecSmrgstatic void 23005b261ecSmrgSyncDeleteTriggerFromCounter( 23105b261ecSmrg SyncTrigger * /* pTrigger */ 23205b261ecSmrg); 23305b261ecSmrg 23405b261ecSmrgstatic Bool 23505b261ecSmrgSyncEventSelectForAlarm( 23605b261ecSmrg SyncAlarm * /* pAlarm */, 23705b261ecSmrg ClientPtr /* client */, 23805b261ecSmrg Bool /* wantevents */ 23905b261ecSmrg); 24005b261ecSmrg 24105b261ecSmrgstatic void 24205b261ecSmrgSyncInitServerTime( 24305b261ecSmrg void 24405b261ecSmrg); 24505b261ecSmrg 24605b261ecSmrgstatic void 24705b261ecSmrgSyncInitIdleTime( 24805b261ecSmrg void 24905b261ecSmrg); 25005b261ecSmrg 25105b261ecSmrgstatic void 25205b261ecSmrgSyncResetProc( 25305b261ecSmrg ExtensionEntry * /* extEntry */ 25405b261ecSmrg); 25505b261ecSmrg 25605b261ecSmrgstatic void 25705b261ecSmrgSyncSendAlarmNotifyEvents( 25805b261ecSmrg SyncAlarm * /* pAlarm */ 25905b261ecSmrg); 26005b261ecSmrg 26105b261ecSmrgstatic void 26205b261ecSmrgSyncSendCounterNotifyEvents( 26305b261ecSmrg ClientPtr /* client */, 26405b261ecSmrg SyncAwait ** /* ppAwait */, 26505b261ecSmrg int /* num_events */ 26605b261ecSmrg); 26705b261ecSmrg 26805b261ecSmrgstatic DISPATCH_PROC(ProcSyncAwait); 26905b261ecSmrgstatic DISPATCH_PROC(ProcSyncChangeAlarm); 27005b261ecSmrgstatic DISPATCH_PROC(ProcSyncChangeCounter); 27105b261ecSmrgstatic DISPATCH_PROC(ProcSyncCreateAlarm); 27205b261ecSmrgstatic DISPATCH_PROC(ProcSyncCreateCounter); 27305b261ecSmrgstatic DISPATCH_PROC(ProcSyncDestroyAlarm); 27405b261ecSmrgstatic DISPATCH_PROC(ProcSyncDestroyCounter); 27505b261ecSmrgstatic DISPATCH_PROC(ProcSyncDispatch); 27605b261ecSmrgstatic DISPATCH_PROC(ProcSyncGetPriority); 27705b261ecSmrgstatic DISPATCH_PROC(ProcSyncInitialize); 27805b261ecSmrgstatic DISPATCH_PROC(ProcSyncListSystemCounters); 27905b261ecSmrgstatic DISPATCH_PROC(ProcSyncQueryAlarm); 28005b261ecSmrgstatic DISPATCH_PROC(ProcSyncQueryCounter); 28105b261ecSmrgstatic DISPATCH_PROC(ProcSyncSetCounter); 28205b261ecSmrgstatic DISPATCH_PROC(ProcSyncSetPriority); 28305b261ecSmrgstatic DISPATCH_PROC(SProcSyncAwait); 28405b261ecSmrgstatic DISPATCH_PROC(SProcSyncChangeAlarm); 28505b261ecSmrgstatic DISPATCH_PROC(SProcSyncChangeCounter); 28605b261ecSmrgstatic DISPATCH_PROC(SProcSyncCreateAlarm); 28705b261ecSmrgstatic DISPATCH_PROC(SProcSyncCreateCounter); 28805b261ecSmrgstatic DISPATCH_PROC(SProcSyncDestroyAlarm); 28905b261ecSmrgstatic DISPATCH_PROC(SProcSyncDestroyCounter); 29005b261ecSmrgstatic DISPATCH_PROC(SProcSyncDispatch); 29105b261ecSmrgstatic DISPATCH_PROC(SProcSyncGetPriority); 29205b261ecSmrgstatic DISPATCH_PROC(SProcSyncInitialize); 29305b261ecSmrgstatic DISPATCH_PROC(SProcSyncListSystemCounters); 29405b261ecSmrgstatic DISPATCH_PROC(SProcSyncQueryAlarm); 29505b261ecSmrgstatic DISPATCH_PROC(SProcSyncQueryCounter); 29605b261ecSmrgstatic DISPATCH_PROC(SProcSyncSetCounter); 29705b261ecSmrgstatic DISPATCH_PROC(SProcSyncSetPriority); 29805b261ecSmrg 29905b261ecSmrg/* Each counter maintains a simple linked list of triggers that are 30005b261ecSmrg * interested in the counter. The two functions below are used to 30105b261ecSmrg * delete and add triggers on this list. 30205b261ecSmrg */ 30305b261ecSmrgstatic void 30405b261ecSmrgSyncDeleteTriggerFromCounter(pTrigger) 30505b261ecSmrg SyncTrigger *pTrigger; 30605b261ecSmrg{ 30705b261ecSmrg SyncTriggerList *pCur; 30805b261ecSmrg SyncTriggerList *pPrev; 30905b261ecSmrg 31005b261ecSmrg /* pCounter needs to be stored in pTrigger before calling here. */ 31105b261ecSmrg 31205b261ecSmrg if (!pTrigger->pCounter) 31305b261ecSmrg return; 31405b261ecSmrg 31505b261ecSmrg pPrev = NULL; 31605b261ecSmrg pCur = pTrigger->pCounter->pTriglist; 31705b261ecSmrg 31805b261ecSmrg while (pCur) 31905b261ecSmrg { 32005b261ecSmrg if (pCur->pTrigger == pTrigger) 32105b261ecSmrg { 32205b261ecSmrg if (pPrev) 32305b261ecSmrg pPrev->next = pCur->next; 32405b261ecSmrg else 32505b261ecSmrg pTrigger->pCounter->pTriglist = pCur->next; 32605b261ecSmrg 32705b261ecSmrg xfree(pCur); 32805b261ecSmrg break; 32905b261ecSmrg } 33005b261ecSmrg 33105b261ecSmrg pPrev = pCur; 33205b261ecSmrg pCur = pCur->next; 33305b261ecSmrg } 33405b261ecSmrg 33505b261ecSmrg if (IsSystemCounter(pTrigger->pCounter)) 33605b261ecSmrg SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE); 33705b261ecSmrg} 33805b261ecSmrg 33905b261ecSmrg 34005b261ecSmrgstatic int 34105b261ecSmrgSyncAddTriggerToCounter(pTrigger) 34205b261ecSmrg SyncTrigger *pTrigger; 34305b261ecSmrg{ 34405b261ecSmrg SyncTriggerList *pCur; 34505b261ecSmrg 34605b261ecSmrg if (!pTrigger->pCounter) 34705b261ecSmrg return Success; 34805b261ecSmrg 34905b261ecSmrg /* don't do anything if it's already there */ 35005b261ecSmrg for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) 35105b261ecSmrg { 35205b261ecSmrg if (pCur->pTrigger == pTrigger) 35305b261ecSmrg return Success; 35405b261ecSmrg } 35505b261ecSmrg 35605b261ecSmrg if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList)))) 35705b261ecSmrg return BadAlloc; 35805b261ecSmrg 35905b261ecSmrg pCur->pTrigger = pTrigger; 36005b261ecSmrg pCur->next = pTrigger->pCounter->pTriglist; 36105b261ecSmrg pTrigger->pCounter->pTriglist = pCur; 36205b261ecSmrg 36305b261ecSmrg if (IsSystemCounter(pTrigger->pCounter)) 36405b261ecSmrg SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE); 36505b261ecSmrg 36605b261ecSmrg return Success; 36705b261ecSmrg} 36805b261ecSmrg 36905b261ecSmrg 37005b261ecSmrg/* Below are four possible functions that can be plugged into 37105b261ecSmrg * pTrigger->CheckTrigger, corresponding to the four possible 37205b261ecSmrg * test-types. These functions are called after the counter's 37305b261ecSmrg * value changes but are also passed the old counter value 37405b261ecSmrg * so they can inspect both the old and new values. 37505b261ecSmrg * (PositiveTransition and NegativeTransition need to see both 37605b261ecSmrg * pieces of information.) These functions return the truth value 37705b261ecSmrg * of the trigger. 37805b261ecSmrg * 37905b261ecSmrg * All of them include the condition pTrigger->pCounter == NULL. 38005b261ecSmrg * This is because the spec says that a trigger with a counter value 38105b261ecSmrg * of None is always TRUE. 38205b261ecSmrg */ 38305b261ecSmrg 38405b261ecSmrgstatic Bool 38505b261ecSmrgSyncCheckTriggerPositiveComparison(pTrigger, oldval) 38605b261ecSmrg SyncTrigger *pTrigger; 38705b261ecSmrg CARD64 oldval; 38805b261ecSmrg{ 38905b261ecSmrg return (pTrigger->pCounter == NULL || 39005b261ecSmrg XSyncValueGreaterOrEqual(pTrigger->pCounter->value, 39105b261ecSmrg pTrigger->test_value)); 39205b261ecSmrg} 39305b261ecSmrg 39405b261ecSmrgstatic Bool 39505b261ecSmrgSyncCheckTriggerNegativeComparison(pTrigger, oldval) 39605b261ecSmrg SyncTrigger *pTrigger; 39705b261ecSmrg CARD64 oldval; 39805b261ecSmrg{ 39905b261ecSmrg return (pTrigger->pCounter == NULL || 40005b261ecSmrg XSyncValueLessOrEqual(pTrigger->pCounter->value, 40105b261ecSmrg pTrigger->test_value)); 40205b261ecSmrg} 40305b261ecSmrg 40405b261ecSmrgstatic Bool 40505b261ecSmrgSyncCheckTriggerPositiveTransition(pTrigger, oldval) 40605b261ecSmrg SyncTrigger *pTrigger; 40705b261ecSmrg CARD64 oldval; 40805b261ecSmrg{ 40905b261ecSmrg return (pTrigger->pCounter == NULL || 41005b261ecSmrg (XSyncValueLessThan(oldval, pTrigger->test_value) && 41105b261ecSmrg XSyncValueGreaterOrEqual(pTrigger->pCounter->value, 41205b261ecSmrg pTrigger->test_value))); 41305b261ecSmrg} 41405b261ecSmrg 41505b261ecSmrgstatic Bool 41605b261ecSmrgSyncCheckTriggerNegativeTransition(pTrigger, oldval) 41705b261ecSmrg SyncTrigger *pTrigger; 41805b261ecSmrg CARD64 oldval; 41905b261ecSmrg{ 42005b261ecSmrg return (pTrigger->pCounter == NULL || 42105b261ecSmrg (XSyncValueGreaterThan(oldval, pTrigger->test_value) && 42205b261ecSmrg XSyncValueLessOrEqual(pTrigger->pCounter->value, 42305b261ecSmrg pTrigger->test_value))); 42405b261ecSmrg} 42505b261ecSmrg 42605b261ecSmrg 42705b261ecSmrg 42805b261ecSmrgstatic int 42905b261ecSmrgSyncInitTrigger(client, pTrigger, counter, changes) 43005b261ecSmrg ClientPtr client; /* so we can set errorValue */ 43105b261ecSmrg SyncTrigger *pTrigger; 43205b261ecSmrg XSyncCounter counter; 43305b261ecSmrg Mask changes; 43405b261ecSmrg{ 43505b261ecSmrg SyncCounter *pCounter = pTrigger->pCounter; 436637ac9abSmrg int rc; 43705b261ecSmrg Bool newcounter = FALSE; 43805b261ecSmrg 43905b261ecSmrg if (changes & XSyncCACounter) 44005b261ecSmrg { 44105b261ecSmrg if (counter == None) 44205b261ecSmrg pCounter = NULL; 443f241d193Smrg else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, 444637ac9abSmrg counter, RTCounter, client, DixReadAccess))) 44505b261ecSmrg { 44605b261ecSmrg client->errorValue = counter; 447637ac9abSmrg return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; 44805b261ecSmrg } 44905b261ecSmrg if (pCounter != pTrigger->pCounter) 45005b261ecSmrg { /* new counter for trigger */ 45105b261ecSmrg SyncDeleteTriggerFromCounter(pTrigger); 45205b261ecSmrg pTrigger->pCounter = pCounter; 45305b261ecSmrg newcounter = TRUE; 45405b261ecSmrg } 45505b261ecSmrg } 45605b261ecSmrg 45705b261ecSmrg /* if system counter, ask it what the current value is */ 45805b261ecSmrg 45905b261ecSmrg if (IsSystemCounter(pCounter)) 46005b261ecSmrg { 46105b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 46205b261ecSmrg &pCounter->value); 46305b261ecSmrg } 46405b261ecSmrg 46505b261ecSmrg if (changes & XSyncCAValueType) 46605b261ecSmrg { 46705b261ecSmrg if (pTrigger->value_type != XSyncRelative && 46805b261ecSmrg pTrigger->value_type != XSyncAbsolute) 46905b261ecSmrg { 47005b261ecSmrg client->errorValue = pTrigger->value_type; 47105b261ecSmrg return BadValue; 47205b261ecSmrg } 47305b261ecSmrg } 47405b261ecSmrg 47505b261ecSmrg if (changes & XSyncCATestType) 47605b261ecSmrg { 47705b261ecSmrg if (pTrigger->test_type != XSyncPositiveTransition && 47805b261ecSmrg pTrigger->test_type != XSyncNegativeTransition && 47905b261ecSmrg pTrigger->test_type != XSyncPositiveComparison && 48005b261ecSmrg pTrigger->test_type != XSyncNegativeComparison) 48105b261ecSmrg { 48205b261ecSmrg client->errorValue = pTrigger->test_type; 48305b261ecSmrg return BadValue; 48405b261ecSmrg } 48505b261ecSmrg /* select appropriate CheckTrigger function */ 48605b261ecSmrg 48705b261ecSmrg switch (pTrigger->test_type) 48805b261ecSmrg { 48905b261ecSmrg case XSyncPositiveTransition: 49005b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; 49105b261ecSmrg break; 49205b261ecSmrg case XSyncNegativeTransition: 49305b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; 49405b261ecSmrg break; 49505b261ecSmrg case XSyncPositiveComparison: 49605b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; 49705b261ecSmrg break; 49805b261ecSmrg case XSyncNegativeComparison: 49905b261ecSmrg pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; 50005b261ecSmrg break; 50105b261ecSmrg } 50205b261ecSmrg } 50305b261ecSmrg 50405b261ecSmrg if (changes & (XSyncCAValueType | XSyncCAValue)) 50505b261ecSmrg { 50605b261ecSmrg if (pTrigger->value_type == XSyncAbsolute) 50705b261ecSmrg pTrigger->test_value = pTrigger->wait_value; 50805b261ecSmrg else /* relative */ 50905b261ecSmrg { 51005b261ecSmrg Bool overflow; 51105b261ecSmrg if (pCounter == NULL) 51205b261ecSmrg return BadMatch; 51305b261ecSmrg 51405b261ecSmrg XSyncValueAdd(&pTrigger->test_value, pCounter->value, 51505b261ecSmrg pTrigger->wait_value, &overflow); 51605b261ecSmrg if (overflow) 51705b261ecSmrg { 51805b261ecSmrg client->errorValue = XSyncValueHigh32(pTrigger->wait_value); 51905b261ecSmrg return BadValue; 52005b261ecSmrg } 52105b261ecSmrg } 52205b261ecSmrg } 52305b261ecSmrg 52405b261ecSmrg /* we wait until we're sure there are no errors before registering 52505b261ecSmrg * a new counter on a trigger 52605b261ecSmrg */ 52705b261ecSmrg if (newcounter) 52805b261ecSmrg { 529637ac9abSmrg if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) 530637ac9abSmrg return rc; 53105b261ecSmrg } 53205b261ecSmrg else if (IsSystemCounter(pCounter)) 53305b261ecSmrg { 53405b261ecSmrg SyncComputeBracketValues(pCounter, /*startOver*/ TRUE); 53505b261ecSmrg } 53605b261ecSmrg 53705b261ecSmrg return Success; 53805b261ecSmrg} 53905b261ecSmrg 54005b261ecSmrg/* AlarmNotify events happen in response to actions taken on an Alarm or 54105b261ecSmrg * the counter used by the alarm. AlarmNotify may be sent to multiple 54205b261ecSmrg * clients. The alarm maintains a list of clients interested in events. 54305b261ecSmrg */ 54405b261ecSmrgstatic void 54505b261ecSmrgSyncSendAlarmNotifyEvents(pAlarm) 54605b261ecSmrg SyncAlarm *pAlarm; 54705b261ecSmrg{ 54805b261ecSmrg SyncAlarmClientList *pcl; 54905b261ecSmrg xSyncAlarmNotifyEvent ane; 55005b261ecSmrg SyncTrigger *pTrigger = &pAlarm->trigger; 55105b261ecSmrg 55205b261ecSmrg UpdateCurrentTime(); 55305b261ecSmrg 55405b261ecSmrg ane.type = SyncEventBase + XSyncAlarmNotify; 55505b261ecSmrg ane.kind = XSyncAlarmNotify; 55605b261ecSmrg ane.sequenceNumber = pAlarm->client->sequence; 55705b261ecSmrg ane.alarm = pAlarm->alarm_id; 55805b261ecSmrg if (pTrigger->pCounter) 55905b261ecSmrg { 56005b261ecSmrg ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); 56105b261ecSmrg ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); 56205b261ecSmrg } 56305b261ecSmrg else 56405b261ecSmrg { /* XXX what else can we do if there's no counter? */ 56505b261ecSmrg ane.counter_value_hi = ane.counter_value_lo = 0; 56605b261ecSmrg } 56705b261ecSmrg 56805b261ecSmrg ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); 56905b261ecSmrg ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); 57005b261ecSmrg ane.time = currentTime.milliseconds; 57105b261ecSmrg ane.state = pAlarm->state; 57205b261ecSmrg 57305b261ecSmrg /* send to owner */ 57405b261ecSmrg if (pAlarm->events && !pAlarm->client->clientGone) 57505b261ecSmrg WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); 57605b261ecSmrg 57705b261ecSmrg /* send to other interested clients */ 57805b261ecSmrg for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) 57905b261ecSmrg { 58005b261ecSmrg if (!pAlarm->client->clientGone) 58105b261ecSmrg { 58205b261ecSmrg ane.sequenceNumber = pcl->client->sequence; 58305b261ecSmrg WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); 58405b261ecSmrg } 58505b261ecSmrg } 58605b261ecSmrg} 58705b261ecSmrg 58805b261ecSmrg 58905b261ecSmrg/* CounterNotify events only occur in response to an Await. The events 59005b261ecSmrg * go only to the Awaiting client. 59105b261ecSmrg */ 59205b261ecSmrgstatic void 59305b261ecSmrgSyncSendCounterNotifyEvents(client, ppAwait, num_events) 59405b261ecSmrg ClientPtr client; 59505b261ecSmrg SyncAwait **ppAwait; 59605b261ecSmrg int num_events; 59705b261ecSmrg{ 59805b261ecSmrg xSyncCounterNotifyEvent *pEvents, *pev; 59905b261ecSmrg int i; 60005b261ecSmrg 60105b261ecSmrg if (client->clientGone) 60205b261ecSmrg return; 60305b261ecSmrg pev = pEvents = (xSyncCounterNotifyEvent *) 604637ac9abSmrg xalloc(num_events * sizeof(xSyncCounterNotifyEvent)); 60505b261ecSmrg if (!pEvents) 60605b261ecSmrg return; 60705b261ecSmrg UpdateCurrentTime(); 60805b261ecSmrg for (i = 0; i < num_events; i++, ppAwait++, pev++) 60905b261ecSmrg { 61005b261ecSmrg SyncTrigger *pTrigger = &(*ppAwait)->trigger; 61105b261ecSmrg pev->type = SyncEventBase + XSyncCounterNotify; 61205b261ecSmrg pev->kind = XSyncCounterNotify; 61305b261ecSmrg pev->sequenceNumber = client->sequence; 61405b261ecSmrg pev->counter = pTrigger->pCounter->id; 61505b261ecSmrg pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); 61605b261ecSmrg pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 61705b261ecSmrg pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); 61805b261ecSmrg pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); 61905b261ecSmrg pev->time = currentTime.milliseconds; 62005b261ecSmrg pev->count = num_events - i - 1; /* events remaining */ 62105b261ecSmrg pev->destroyed = pTrigger->pCounter->beingDestroyed; 62205b261ecSmrg } 62305b261ecSmrg /* swapping will be taken care of by this */ 62405b261ecSmrg WriteEventsToClient(client, num_events, (xEvent *)pEvents); 625637ac9abSmrg xfree(pEvents); 62605b261ecSmrg} 62705b261ecSmrg 62805b261ecSmrg 62905b261ecSmrg/* This function is called when an alarm's counter is destroyed. 63005b261ecSmrg * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). 63105b261ecSmrg */ 63205b261ecSmrgvoid 63305b261ecSmrgSyncAlarmCounterDestroyed(pTrigger) 63405b261ecSmrg SyncTrigger *pTrigger; 63505b261ecSmrg{ 63605b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 63705b261ecSmrg 63805b261ecSmrg pAlarm->state = XSyncAlarmInactive; 63905b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 64005b261ecSmrg pTrigger->pCounter = NULL; 64105b261ecSmrg} 64205b261ecSmrg 64305b261ecSmrg 64405b261ecSmrg/* This function is called when an alarm "goes off." 64505b261ecSmrg * It is plugged into pTrigger->TriggerFired (for alarm triggers). 64605b261ecSmrg */ 64705b261ecSmrgstatic void 64805b261ecSmrgSyncAlarmTriggerFired(pTrigger) 64905b261ecSmrg SyncTrigger *pTrigger; 65005b261ecSmrg{ 65105b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; 65205b261ecSmrg CARD64 new_test_value; 65305b261ecSmrg 65405b261ecSmrg /* no need to check alarm unless it's active */ 65505b261ecSmrg if (pAlarm->state != XSyncAlarmActive) 65605b261ecSmrg return; 65705b261ecSmrg 65805b261ecSmrg /* " if the counter value is None, or if the delta is 0 and 65905b261ecSmrg * the test-type is PositiveComparison or NegativeComparison, 66005b261ecSmrg * no change is made to value (test-value) and the alarm 66105b261ecSmrg * state is changed to Inactive before the event is generated." 66205b261ecSmrg */ 66305b261ecSmrg if (pAlarm->trigger.pCounter == NULL 66405b261ecSmrg || (XSyncValueIsZero(pAlarm->delta) 66505b261ecSmrg && (pAlarm->trigger.test_type == XSyncPositiveComparison 66605b261ecSmrg || pAlarm->trigger.test_type == XSyncNegativeComparison))) 66705b261ecSmrg pAlarm->state = XSyncAlarmInactive; 66805b261ecSmrg 66905b261ecSmrg new_test_value = pAlarm->trigger.test_value; 67005b261ecSmrg 67105b261ecSmrg if (pAlarm->state == XSyncAlarmActive) 67205b261ecSmrg { 67305b261ecSmrg Bool overflow; 67405b261ecSmrg CARD64 oldvalue; 67505b261ecSmrg SyncTrigger *paTrigger = &pAlarm->trigger; 67605b261ecSmrg 67705b261ecSmrg /* "The alarm is updated by repeatedly adding delta to the 67805b261ecSmrg * value of the trigger and re-initializing it until it 67905b261ecSmrg * becomes FALSE." 68005b261ecSmrg */ 68105b261ecSmrg oldvalue = paTrigger->test_value; 68205b261ecSmrg 68305b261ecSmrg /* XXX really should do something smarter here */ 68405b261ecSmrg 68505b261ecSmrg do 68605b261ecSmrg { 68705b261ecSmrg XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, 68805b261ecSmrg pAlarm->delta, &overflow); 68905b261ecSmrg } while (!overflow && 69005b261ecSmrg (*paTrigger->CheckTrigger)(paTrigger, 69105b261ecSmrg paTrigger->pCounter->value)); 69205b261ecSmrg 69305b261ecSmrg new_test_value = paTrigger->test_value; 69405b261ecSmrg paTrigger->test_value = oldvalue; 69505b261ecSmrg 69605b261ecSmrg /* "If this update would cause value to fall outside the range 69705b261ecSmrg * for an INT64...no change is made to value (test-value) and 69805b261ecSmrg * the alarm state is changed to Inactive before the event is 69905b261ecSmrg * generated." 70005b261ecSmrg */ 70105b261ecSmrg if (overflow) 70205b261ecSmrg { 70305b261ecSmrg new_test_value = oldvalue; 70405b261ecSmrg pAlarm->state = XSyncAlarmInactive; 70505b261ecSmrg } 70605b261ecSmrg } 70705b261ecSmrg /* The AlarmNotify event has to have the "new state of the alarm" 70805b261ecSmrg * which we can't be sure of until this point. However, it has 70905b261ecSmrg * to have the "old" trigger test value. That's the reason for 71005b261ecSmrg * all the newvalue/oldvalue shuffling above. After we send the 71105b261ecSmrg * events, give the trigger its new test value. 71205b261ecSmrg */ 71305b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 71405b261ecSmrg pTrigger->test_value = new_test_value; 71505b261ecSmrg} 71605b261ecSmrg 71705b261ecSmrg 71805b261ecSmrg/* This function is called when an Await unblocks, either as a result 71905b261ecSmrg * of the trigger firing OR the counter being destroyed. 72005b261ecSmrg * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed 72105b261ecSmrg * (for Await triggers). 72205b261ecSmrg */ 72305b261ecSmrgstatic void 72405b261ecSmrgSyncAwaitTriggerFired(pTrigger) 72505b261ecSmrg SyncTrigger *pTrigger; 72605b261ecSmrg{ 72705b261ecSmrg SyncAwait *pAwait = (SyncAwait *)pTrigger; 72805b261ecSmrg int numwaits; 72905b261ecSmrg SyncAwaitUnion *pAwaitUnion; 73005b261ecSmrg SyncAwait **ppAwait; 73105b261ecSmrg int num_events = 0; 73205b261ecSmrg 73305b261ecSmrg pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; 73405b261ecSmrg numwaits = pAwaitUnion->header.num_waitconditions; 735637ac9abSmrg ppAwait = (SyncAwait **)xalloc(numwaits * sizeof(SyncAwait *)); 73605b261ecSmrg if (!ppAwait) 73705b261ecSmrg goto bail; 73805b261ecSmrg 73905b261ecSmrg pAwait = &(pAwaitUnion+1)->await; 74005b261ecSmrg 74105b261ecSmrg /* "When a client is unblocked, all the CounterNotify events for 74205b261ecSmrg * the Await request are generated contiguously. If count is 0 74305b261ecSmrg * there are no more events to follow for this request. If 74405b261ecSmrg * count is n, there are at least n more events to follow." 74505b261ecSmrg * 74605b261ecSmrg * Thus, it is best to find all the counters for which events 74705b261ecSmrg * need to be sent first, so that an accurate count field can 74805b261ecSmrg * be stored in the events. 74905b261ecSmrg */ 75005b261ecSmrg for ( ; numwaits; numwaits--, pAwait++) 75105b261ecSmrg { 75205b261ecSmrg CARD64 diff; 75305b261ecSmrg Bool overflow, diffgreater, diffequal; 75405b261ecSmrg 75505b261ecSmrg /* "A CounterNotify event with the destroyed flag set to TRUE is 75605b261ecSmrg * always generated if the counter for one of the triggers is 75705b261ecSmrg * destroyed." 75805b261ecSmrg */ 75905b261ecSmrg if (pAwait->trigger.pCounter->beingDestroyed) 76005b261ecSmrg { 76105b261ecSmrg ppAwait[num_events++] = pAwait; 76205b261ecSmrg continue; 76305b261ecSmrg } 76405b261ecSmrg 76505b261ecSmrg /* "The difference between the counter and the test value is 76605b261ecSmrg * calculated by subtracting the test value from the value of 76705b261ecSmrg * the counter." 76805b261ecSmrg */ 76905b261ecSmrg XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, 77005b261ecSmrg pAwait->trigger.test_value, &overflow); 77105b261ecSmrg 77205b261ecSmrg /* "If the difference lies outside the range for an INT64, an 77305b261ecSmrg * event is not generated." 77405b261ecSmrg */ 77505b261ecSmrg if (overflow) 77605b261ecSmrg continue; 77705b261ecSmrg diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); 77805b261ecSmrg diffequal = XSyncValueEqual(diff, pAwait->event_threshold); 77905b261ecSmrg 78005b261ecSmrg /* "If the test-type is PositiveTransition or 78105b261ecSmrg * PositiveComparison, a CounterNotify event is generated if 78205b261ecSmrg * the difference is at least event-threshold. If the test-type 78305b261ecSmrg * is NegativeTransition or NegativeComparison, a CounterNotify 78405b261ecSmrg * event is generated if the difference is at most 78505b261ecSmrg * event-threshold." 78605b261ecSmrg */ 78705b261ecSmrg 78805b261ecSmrg if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || 78905b261ecSmrg pAwait->trigger.test_type == XSyncPositiveTransition) 79005b261ecSmrg && (diffgreater || diffequal)) 79105b261ecSmrg || 79205b261ecSmrg ((pAwait->trigger.test_type == XSyncNegativeComparison || 79305b261ecSmrg pAwait->trigger.test_type == XSyncNegativeTransition) 79405b261ecSmrg && (!diffgreater) /* less or equal */ 79505b261ecSmrg ) 79605b261ecSmrg ) 79705b261ecSmrg { 79805b261ecSmrg ppAwait[num_events++] = pAwait; 79905b261ecSmrg } 80005b261ecSmrg } 80105b261ecSmrg if (num_events) 80205b261ecSmrg SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, 80305b261ecSmrg num_events); 804637ac9abSmrg xfree(ppAwait); 80505b261ecSmrg 80605b261ecSmrgbail: 80705b261ecSmrg /* unblock the client */ 80805b261ecSmrg AttendClient(pAwaitUnion->header.client); 80905b261ecSmrg /* delete the await */ 81005b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 81105b261ecSmrg} 81205b261ecSmrg 81305b261ecSmrg 81405b261ecSmrg/* This function should always be used to change a counter's value so that 81505b261ecSmrg * any triggers depending on the counter will be checked. 81605b261ecSmrg */ 81705b261ecSmrgvoid 81805b261ecSmrgSyncChangeCounter(pCounter, newval) 81905b261ecSmrg SyncCounter *pCounter; 82005b261ecSmrg CARD64 newval; 82105b261ecSmrg{ 82205b261ecSmrg SyncTriggerList *ptl, *pnext; 82305b261ecSmrg CARD64 oldval; 82405b261ecSmrg 82505b261ecSmrg oldval = pCounter->value; 82605b261ecSmrg pCounter->value = newval; 82705b261ecSmrg 82805b261ecSmrg /* run through triggers to see if any become true */ 82905b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 83005b261ecSmrg { 83105b261ecSmrg pnext = ptl->next; 83205b261ecSmrg if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) 83305b261ecSmrg (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); 83405b261ecSmrg } 83505b261ecSmrg 83605b261ecSmrg if (IsSystemCounter(pCounter)) 83705b261ecSmrg { 83805b261ecSmrg SyncComputeBracketValues(pCounter, /* startOver */ FALSE); 83905b261ecSmrg } 84005b261ecSmrg} 84105b261ecSmrg 84205b261ecSmrg 84305b261ecSmrg/* loosely based on dix/events.c/EventSelectForWindow */ 84405b261ecSmrgstatic Bool 84505b261ecSmrgSyncEventSelectForAlarm(pAlarm, client, wantevents) 84605b261ecSmrg SyncAlarm *pAlarm; 84705b261ecSmrg ClientPtr client; 84805b261ecSmrg Bool wantevents; 84905b261ecSmrg{ 85005b261ecSmrg SyncAlarmClientList *pClients; 85105b261ecSmrg 85205b261ecSmrg if (client == pAlarm->client) /* alarm owner */ 85305b261ecSmrg { 85405b261ecSmrg pAlarm->events = wantevents; 85505b261ecSmrg return Success; 85605b261ecSmrg } 85705b261ecSmrg 85805b261ecSmrg /* see if the client is already on the list (has events selected) */ 85905b261ecSmrg 86005b261ecSmrg for (pClients = pAlarm->pEventClients; pClients; 86105b261ecSmrg pClients = pClients->next) 86205b261ecSmrg { 86305b261ecSmrg if (pClients->client == client) 86405b261ecSmrg { 86505b261ecSmrg /* client's presence on the list indicates desire for 86605b261ecSmrg * events. If the client doesn't want events, remove it 86705b261ecSmrg * from the list. If the client does want events, do 86805b261ecSmrg * nothing, since it's already got them. 86905b261ecSmrg */ 87005b261ecSmrg if (!wantevents) 87105b261ecSmrg { 87205b261ecSmrg FreeResource(pClients->delete_id, RT_NONE); 87305b261ecSmrg } 87405b261ecSmrg return Success; 87505b261ecSmrg } 87605b261ecSmrg } 87705b261ecSmrg 87805b261ecSmrg /* if we get here, this client does not currently have 87905b261ecSmrg * events selected on the alarm 88005b261ecSmrg */ 88105b261ecSmrg 88205b261ecSmrg if (!wantevents) 88305b261ecSmrg /* client doesn't want events, and we just discovered that it 88405b261ecSmrg * doesn't have them, so there's nothing to do. 88505b261ecSmrg */ 88605b261ecSmrg return Success; 88705b261ecSmrg 88805b261ecSmrg /* add new client to pAlarm->pEventClients */ 88905b261ecSmrg 89005b261ecSmrg pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList)); 89105b261ecSmrg if (!pClients) 89205b261ecSmrg return BadAlloc; 89305b261ecSmrg 89405b261ecSmrg /* register it as a resource so it will be cleaned up 89505b261ecSmrg * if the client dies 89605b261ecSmrg */ 89705b261ecSmrg 89805b261ecSmrg pClients->delete_id = FakeClientID(client->index); 89905b261ecSmrg if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) 90005b261ecSmrg { 90105b261ecSmrg xfree(pClients); 90205b261ecSmrg return BadAlloc; 90305b261ecSmrg } 90405b261ecSmrg 90505b261ecSmrg /* link it into list after we know all the allocations succeed */ 90605b261ecSmrg 90705b261ecSmrg pClients->next = pAlarm->pEventClients; 90805b261ecSmrg pAlarm->pEventClients = pClients; 90905b261ecSmrg pClients->client = client; 91005b261ecSmrg return Success; 91105b261ecSmrg} 91205b261ecSmrg 91305b261ecSmrg/* 91405b261ecSmrg * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm 91505b261ecSmrg */ 91605b261ecSmrgstatic int 91705b261ecSmrgSyncChangeAlarmAttributes(client, pAlarm, mask, values) 91805b261ecSmrg ClientPtr client; 91905b261ecSmrg SyncAlarm *pAlarm; 92005b261ecSmrg Mask mask; 92105b261ecSmrg CARD32 *values; 92205b261ecSmrg{ 92305b261ecSmrg int status; 92405b261ecSmrg XSyncCounter counter; 92505b261ecSmrg Mask origmask = mask; 92605b261ecSmrg 92705b261ecSmrg counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; 92805b261ecSmrg 92905b261ecSmrg while (mask) 93005b261ecSmrg { 93105b261ecSmrg int index2 = lowbit(mask); 93205b261ecSmrg mask &= ~index2; 93305b261ecSmrg switch (index2) 93405b261ecSmrg { 93505b261ecSmrg case XSyncCACounter: 93605b261ecSmrg mask &= ~XSyncCACounter; 93705b261ecSmrg /* sanity check in SyncInitTrigger */ 93805b261ecSmrg counter = *values++; 93905b261ecSmrg break; 94005b261ecSmrg 94105b261ecSmrg case XSyncCAValueType: 94205b261ecSmrg mask &= ~XSyncCAValueType; 94305b261ecSmrg /* sanity check in SyncInitTrigger */ 94405b261ecSmrg pAlarm->trigger.value_type = *values++; 94505b261ecSmrg break; 94605b261ecSmrg 94705b261ecSmrg case XSyncCAValue: 94805b261ecSmrg mask &= ~XSyncCAValue; 94905b261ecSmrg XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); 95005b261ecSmrg values += 2; 95105b261ecSmrg break; 95205b261ecSmrg 95305b261ecSmrg case XSyncCATestType: 95405b261ecSmrg mask &= ~XSyncCATestType; 95505b261ecSmrg /* sanity check in SyncInitTrigger */ 95605b261ecSmrg pAlarm->trigger.test_type = *values++; 95705b261ecSmrg break; 95805b261ecSmrg 95905b261ecSmrg case XSyncCADelta: 96005b261ecSmrg mask &= ~XSyncCADelta; 96105b261ecSmrg XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); 96205b261ecSmrg values += 2; 96305b261ecSmrg break; 96405b261ecSmrg 96505b261ecSmrg case XSyncCAEvents: 96605b261ecSmrg mask &= ~XSyncCAEvents; 96705b261ecSmrg if ((*values != xTrue) && (*values != xFalse)) 96805b261ecSmrg { 96905b261ecSmrg client->errorValue = *values; 97005b261ecSmrg return BadValue; 97105b261ecSmrg } 97205b261ecSmrg status = SyncEventSelectForAlarm(pAlarm, client, 97305b261ecSmrg (Bool)(*values++)); 97405b261ecSmrg if (status != Success) 97505b261ecSmrg return status; 97605b261ecSmrg break; 97705b261ecSmrg 97805b261ecSmrg default: 97905b261ecSmrg client->errorValue = mask; 98005b261ecSmrg return BadValue; 98105b261ecSmrg } 98205b261ecSmrg } 98305b261ecSmrg 98405b261ecSmrg /* "If the test-type is PositiveComparison or PositiveTransition 98505b261ecSmrg * and delta is less than zero, or if the test-type is 98605b261ecSmrg * NegativeComparison or NegativeTransition and delta is 98705b261ecSmrg * greater than zero, a Match error is generated." 98805b261ecSmrg */ 98905b261ecSmrg if (origmask & (XSyncCADelta|XSyncCATestType)) 99005b261ecSmrg { 99105b261ecSmrg CARD64 zero; 99205b261ecSmrg XSyncIntToValue(&zero, 0); 99305b261ecSmrg if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || 99405b261ecSmrg (pAlarm->trigger.test_type == XSyncPositiveTransition)) 99505b261ecSmrg && XSyncValueLessThan(pAlarm->delta, zero)) 99605b261ecSmrg || 99705b261ecSmrg (((pAlarm->trigger.test_type == XSyncNegativeComparison) || 99805b261ecSmrg (pAlarm->trigger.test_type == XSyncNegativeTransition)) 99905b261ecSmrg && XSyncValueGreaterThan(pAlarm->delta, zero)) 100005b261ecSmrg ) 100105b261ecSmrg { 100205b261ecSmrg return BadMatch; 100305b261ecSmrg } 100405b261ecSmrg } 100505b261ecSmrg 100605b261ecSmrg /* postpone this until now, when we're sure nothing else can go wrong */ 100705b261ecSmrg if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, 100805b261ecSmrg origmask & XSyncCAAllTrigger)) != Success) 100905b261ecSmrg return status; 101005b261ecSmrg 101105b261ecSmrg /* XXX spec does not really say to do this - needs clarification */ 101205b261ecSmrg pAlarm->state = XSyncAlarmActive; 101305b261ecSmrg return Success; 101405b261ecSmrg} 101505b261ecSmrg 101605b261ecSmrg 101705b261ecSmrgstatic SyncCounter * 101805b261ecSmrgSyncCreateCounter(client, id, initialvalue) 101905b261ecSmrg ClientPtr client; 102005b261ecSmrg XSyncCounter id; 102105b261ecSmrg CARD64 initialvalue; 102205b261ecSmrg{ 102305b261ecSmrg SyncCounter *pCounter; 102405b261ecSmrg 102505b261ecSmrg if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter)))) 102605b261ecSmrg return (SyncCounter *)NULL; 102705b261ecSmrg 102805b261ecSmrg if (!AddResource(id, RTCounter, (pointer) pCounter)) 102905b261ecSmrg { 103005b261ecSmrg xfree((pointer) pCounter); 103105b261ecSmrg return (SyncCounter *)NULL; 103205b261ecSmrg } 103305b261ecSmrg 103405b261ecSmrg pCounter->client = client; 103505b261ecSmrg pCounter->id = id; 103605b261ecSmrg pCounter->value = initialvalue; 103705b261ecSmrg pCounter->pTriglist = NULL; 103805b261ecSmrg pCounter->beingDestroyed = FALSE; 103905b261ecSmrg pCounter->pSysCounterInfo = NULL; 104005b261ecSmrg return pCounter; 104105b261ecSmrg} 104205b261ecSmrg 104305b261ecSmrgstatic int FreeCounter( 104405b261ecSmrg pointer /*env*/, 104505b261ecSmrg XID /*id*/ 104605b261ecSmrg); 104705b261ecSmrg 104805b261ecSmrg/* 104905b261ecSmrg * ***** System Counter utilities 105005b261ecSmrg */ 105105b261ecSmrg 105205b261ecSmrgpointer 105305b261ecSmrgSyncCreateSystemCounter(name, initial, resolution, counterType, 105405b261ecSmrg QueryValue, BracketValues) 105505b261ecSmrg char *name; 105605b261ecSmrg CARD64 initial; 105705b261ecSmrg CARD64 resolution; 105805b261ecSmrg SyncCounterType counterType; 105905b261ecSmrg void (*QueryValue) ( 106005b261ecSmrg pointer /* pCounter */, 106105b261ecSmrg CARD64 * /* pValue_return */); 106205b261ecSmrg void (*BracketValues) ( 106305b261ecSmrg pointer /* pCounter */, 106405b261ecSmrg CARD64 * /* pbracket_less */, 106505b261ecSmrg CARD64 * /* pbracket_greater */); 106605b261ecSmrg{ 106705b261ecSmrg SyncCounter *pCounter; 106805b261ecSmrg 106905b261ecSmrg SysCounterList = (SyncCounter **)xrealloc(SysCounterList, 107005b261ecSmrg (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); 107105b261ecSmrg if (!SysCounterList) 107205b261ecSmrg return (pointer)NULL; 107305b261ecSmrg 107405b261ecSmrg /* this function may be called before SYNC has been initialized, so we 107505b261ecSmrg * have to make sure RTCounter is created. 107605b261ecSmrg */ 107705b261ecSmrg if (RTCounter == 0) 107805b261ecSmrg { 107905b261ecSmrg RTCounter = CreateNewResourceType(FreeCounter); 108005b261ecSmrg if (RTCounter == 0) 108105b261ecSmrg { 108205b261ecSmrg return (pointer)NULL; 108305b261ecSmrg } 108405b261ecSmrg } 108505b261ecSmrg 108605b261ecSmrg pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial); 108705b261ecSmrg 108805b261ecSmrg if (pCounter) 108905b261ecSmrg { 109005b261ecSmrg SysCounterInfo *psci; 109105b261ecSmrg 109205b261ecSmrg psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo)); 109305b261ecSmrg if (!psci) 109405b261ecSmrg { 109505b261ecSmrg FreeResource(pCounter->id, RT_NONE); 109605b261ecSmrg return (pointer) pCounter; 109705b261ecSmrg } 109805b261ecSmrg pCounter->pSysCounterInfo = psci; 109905b261ecSmrg psci->name = name; 110005b261ecSmrg psci->resolution = resolution; 110105b261ecSmrg psci->counterType = counterType; 110205b261ecSmrg psci->QueryValue = QueryValue; 110305b261ecSmrg psci->BracketValues = BracketValues; 110405b261ecSmrg XSyncMaxValue(&psci->bracket_greater); 110505b261ecSmrg XSyncMinValue(&psci->bracket_less); 110605b261ecSmrg SysCounterList[SyncNumSystemCounters++] = pCounter; 110705b261ecSmrg } 110805b261ecSmrg return (pointer) pCounter; 110905b261ecSmrg} 111005b261ecSmrg 111105b261ecSmrgvoid 111205b261ecSmrgSyncDestroySystemCounter(pSysCounter) 111305b261ecSmrg pointer pSysCounter; 111405b261ecSmrg{ 111505b261ecSmrg SyncCounter *pCounter = (SyncCounter *)pSysCounter; 111605b261ecSmrg FreeResource(pCounter->id, RT_NONE); 111705b261ecSmrg} 111805b261ecSmrg 111905b261ecSmrgstatic void 112005b261ecSmrgSyncComputeBracketValues(pCounter, startOver) 112105b261ecSmrg SyncCounter *pCounter; 112205b261ecSmrg Bool startOver; 112305b261ecSmrg{ 112405b261ecSmrg SyncTriggerList *pCur; 112505b261ecSmrg SyncTrigger *pTrigger; 112605b261ecSmrg SysCounterInfo *psci; 112705b261ecSmrg CARD64 *pnewgtval = NULL; 112805b261ecSmrg CARD64 *pnewltval = NULL; 112905b261ecSmrg SyncCounterType ct; 113005b261ecSmrg 113105b261ecSmrg if (!pCounter) 113205b261ecSmrg return; 113305b261ecSmrg 113405b261ecSmrg psci = pCounter->pSysCounterInfo; 113505b261ecSmrg ct = pCounter->pSysCounterInfo->counterType; 113605b261ecSmrg if (ct == XSyncCounterNeverChanges) 113705b261ecSmrg return; 113805b261ecSmrg 113905b261ecSmrg if (startOver) 114005b261ecSmrg { 114105b261ecSmrg XSyncMaxValue(&psci->bracket_greater); 114205b261ecSmrg XSyncMinValue(&psci->bracket_less); 114305b261ecSmrg } 114405b261ecSmrg 114505b261ecSmrg for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) 114605b261ecSmrg { 114705b261ecSmrg pTrigger = pCur->pTrigger; 114805b261ecSmrg 114905b261ecSmrg if (pTrigger->test_type == XSyncPositiveComparison && 115005b261ecSmrg ct != XSyncCounterNeverIncreases) 115105b261ecSmrg { 115205b261ecSmrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 115305b261ecSmrg XSyncValueLessThan(pTrigger->test_value, 115405b261ecSmrg psci->bracket_greater)) 115505b261ecSmrg { 115605b261ecSmrg psci->bracket_greater = pTrigger->test_value; 115705b261ecSmrg pnewgtval = &psci->bracket_greater; 115805b261ecSmrg } 115905b261ecSmrg } 116005b261ecSmrg else if (pTrigger->test_type == XSyncNegativeComparison && 116105b261ecSmrg ct != XSyncCounterNeverDecreases) 116205b261ecSmrg { 116305b261ecSmrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 116405b261ecSmrg XSyncValueGreaterThan(pTrigger->test_value, 116505b261ecSmrg psci->bracket_less)) 116605b261ecSmrg { 116705b261ecSmrg psci->bracket_less = pTrigger->test_value; 116805b261ecSmrg pnewltval = &psci->bracket_less; 116905b261ecSmrg } 117005b261ecSmrg } 117105b261ecSmrg else if ( (pTrigger->test_type == XSyncPositiveTransition && 117205b261ecSmrg ct != XSyncCounterNeverIncreases) 117305b261ecSmrg || 117405b261ecSmrg (pTrigger->test_type == XSyncNegativeTransition && 117505b261ecSmrg ct != XSyncCounterNeverDecreases) 117605b261ecSmrg ) 117705b261ecSmrg { 117805b261ecSmrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value)) 117905b261ecSmrg { 118005b261ecSmrg if (XSyncValueLessThan(pTrigger->test_value, 118105b261ecSmrg psci->bracket_greater)) 118205b261ecSmrg { 118305b261ecSmrg psci->bracket_greater = pTrigger->test_value; 118405b261ecSmrg pnewgtval = &psci->bracket_greater; 118505b261ecSmrg } 118605b261ecSmrg else 118705b261ecSmrg if (XSyncValueGreaterThan(pTrigger->test_value, 118805b261ecSmrg psci->bracket_less)) 118905b261ecSmrg { 119005b261ecSmrg psci->bracket_less = pTrigger->test_value; 119105b261ecSmrg pnewltval = &psci->bracket_less; 119205b261ecSmrg } 119305b261ecSmrg } 119405b261ecSmrg } 119505b261ecSmrg } /* end for each trigger */ 119605b261ecSmrg 119705b261ecSmrg if (pnewgtval || pnewltval) 119805b261ecSmrg { 119905b261ecSmrg (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); 120005b261ecSmrg } 120105b261ecSmrg} 120205b261ecSmrg 120305b261ecSmrg/* 120405b261ecSmrg * ***** Resource delete functions 120505b261ecSmrg */ 120605b261ecSmrg 120705b261ecSmrg/* ARGSUSED */ 120805b261ecSmrgstatic int 120905b261ecSmrgFreeAlarm(addr, id) 121005b261ecSmrg pointer addr; 121105b261ecSmrg XID id; 121205b261ecSmrg{ 121305b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *) addr; 121405b261ecSmrg 121505b261ecSmrg pAlarm->state = XSyncAlarmDestroyed; 121605b261ecSmrg 121705b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 121805b261ecSmrg 121905b261ecSmrg /* delete event selections */ 122005b261ecSmrg 122105b261ecSmrg while (pAlarm->pEventClients) 122205b261ecSmrg FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 122305b261ecSmrg 122405b261ecSmrg SyncDeleteTriggerFromCounter(&pAlarm->trigger); 122505b261ecSmrg 122605b261ecSmrg xfree(pAlarm); 122705b261ecSmrg return Success; 122805b261ecSmrg} 122905b261ecSmrg 123005b261ecSmrg 123105b261ecSmrg/* 123205b261ecSmrg * ** Cleanup after the destruction of a Counter 123305b261ecSmrg */ 123405b261ecSmrg/* ARGSUSED */ 123505b261ecSmrgstatic int 123605b261ecSmrgFreeCounter(env, id) 123705b261ecSmrg pointer env; 123805b261ecSmrg XID id; 123905b261ecSmrg{ 124005b261ecSmrg SyncCounter *pCounter = (SyncCounter *) env; 124105b261ecSmrg SyncTriggerList *ptl, *pnext; 124205b261ecSmrg 124305b261ecSmrg pCounter->beingDestroyed = TRUE; 124405b261ecSmrg /* tell all the counter's triggers that the counter has been destroyed */ 124505b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 124605b261ecSmrg { 124705b261ecSmrg (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); 124805b261ecSmrg pnext = ptl->next; 124905b261ecSmrg xfree(ptl); /* destroy the trigger list as we go */ 125005b261ecSmrg } 125105b261ecSmrg if (IsSystemCounter(pCounter)) 125205b261ecSmrg { 125305b261ecSmrg int i, found = 0; 125405b261ecSmrg 125505b261ecSmrg xfree(pCounter->pSysCounterInfo); 125605b261ecSmrg 125705b261ecSmrg /* find the counter in the list of system counters and remove it */ 125805b261ecSmrg 125905b261ecSmrg if (SysCounterList) 126005b261ecSmrg { 126105b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 126205b261ecSmrg { 126305b261ecSmrg if (SysCounterList[i] == pCounter) 126405b261ecSmrg { 126505b261ecSmrg found = i; 126605b261ecSmrg break; 126705b261ecSmrg } 126805b261ecSmrg } 126905b261ecSmrg if (found < (SyncNumSystemCounters-1)) 127005b261ecSmrg { 127105b261ecSmrg for (i = found; i < SyncNumSystemCounters-1; i++) 127205b261ecSmrg { 127305b261ecSmrg SysCounterList[i] = SysCounterList[i+1]; 127405b261ecSmrg } 127505b261ecSmrg } 127605b261ecSmrg } 127705b261ecSmrg SyncNumSystemCounters--; 127805b261ecSmrg } 127905b261ecSmrg xfree(pCounter); 128005b261ecSmrg return Success; 128105b261ecSmrg} 128205b261ecSmrg 128305b261ecSmrg/* 128405b261ecSmrg * ** Cleanup after Await 128505b261ecSmrg */ 128605b261ecSmrg/* ARGSUSED */ 128705b261ecSmrgstatic int 128805b261ecSmrgFreeAwait(addr, id) 128905b261ecSmrg pointer addr; 129005b261ecSmrg XID id; 129105b261ecSmrg{ 129205b261ecSmrg SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 129305b261ecSmrg SyncAwait *pAwait; 129405b261ecSmrg int numwaits; 129505b261ecSmrg 129605b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* first await on list */ 129705b261ecSmrg 129805b261ecSmrg /* remove triggers from counters */ 129905b261ecSmrg 130005b261ecSmrg for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 130105b261ecSmrg numwaits--, pAwait++) 130205b261ecSmrg { 130305b261ecSmrg /* If the counter is being destroyed, FreeCounter will delete 130405b261ecSmrg * the trigger list itself, so don't do it here. 130505b261ecSmrg */ 130605b261ecSmrg SyncCounter *pCounter = pAwait->trigger.pCounter; 130705b261ecSmrg if (pCounter && !pCounter->beingDestroyed) 130805b261ecSmrg SyncDeleteTriggerFromCounter(&pAwait->trigger); 130905b261ecSmrg } 131005b261ecSmrg xfree(pAwaitUnion); 131105b261ecSmrg return Success; 131205b261ecSmrg} 131305b261ecSmrg 131405b261ecSmrg/* loosely based on dix/events.c/OtherClientGone */ 131505b261ecSmrgstatic int 131605b261ecSmrgFreeAlarmClient(value, id) 131705b261ecSmrg pointer value; /* must conform to DeleteType */ 131805b261ecSmrg XID id; 131905b261ecSmrg{ 132005b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)value; 132105b261ecSmrg SyncAlarmClientList *pCur, *pPrev; 132205b261ecSmrg 132305b261ecSmrg for (pPrev = NULL, pCur = pAlarm->pEventClients; 132405b261ecSmrg pCur; 132505b261ecSmrg pPrev = pCur, pCur = pCur->next) 132605b261ecSmrg { 132705b261ecSmrg if (pCur->delete_id == id) 132805b261ecSmrg { 132905b261ecSmrg if (pPrev) 133005b261ecSmrg pPrev->next = pCur->next; 133105b261ecSmrg else 133205b261ecSmrg pAlarm->pEventClients = pCur->next; 133305b261ecSmrg xfree(pCur); 133405b261ecSmrg return(Success); 133505b261ecSmrg } 133605b261ecSmrg } 133705b261ecSmrg FatalError("alarm client not on event list"); 133805b261ecSmrg /*NOTREACHED*/ 133905b261ecSmrg} 134005b261ecSmrg 134105b261ecSmrg 134205b261ecSmrg/* 134305b261ecSmrg * ***** Proc functions 134405b261ecSmrg */ 134505b261ecSmrg 134605b261ecSmrg 134705b261ecSmrg/* 134805b261ecSmrg * ** Initialize the extension 134905b261ecSmrg */ 135005b261ecSmrgstatic int 135105b261ecSmrgProcSyncInitialize(client) 135205b261ecSmrg ClientPtr client; 135305b261ecSmrg{ 135405b261ecSmrg xSyncInitializeReply rep; 135505b261ecSmrg int n; 135605b261ecSmrg 135705b261ecSmrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 135805b261ecSmrg 135905b261ecSmrg rep.type = X_Reply; 136005b261ecSmrg rep.sequenceNumber = client->sequence; 136105b261ecSmrg rep.majorVersion = SYNC_MAJOR_VERSION; 136205b261ecSmrg rep.minorVersion = SYNC_MINOR_VERSION; 136305b261ecSmrg rep.length = 0; 136405b261ecSmrg 136505b261ecSmrg if (client->swapped) 136605b261ecSmrg { 136705b261ecSmrg swaps(&rep.sequenceNumber, n); 136805b261ecSmrg } 136905b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 137005b261ecSmrg return (client->noClientException); 137105b261ecSmrg} 137205b261ecSmrg 137305b261ecSmrg/* 137405b261ecSmrg * ** Get list of system counters available through the extension 137505b261ecSmrg */ 137605b261ecSmrgstatic int 137705b261ecSmrgProcSyncListSystemCounters(client) 137805b261ecSmrg ClientPtr client; 137905b261ecSmrg{ 138005b261ecSmrg xSyncListSystemCountersReply rep; 138105b261ecSmrg int i, len; 138205b261ecSmrg xSyncSystemCounter *list = NULL, *walklist = NULL; 138305b261ecSmrg 138405b261ecSmrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 138505b261ecSmrg 138605b261ecSmrg rep.type = X_Reply; 138705b261ecSmrg rep.sequenceNumber = client->sequence; 138805b261ecSmrg rep.nCounters = SyncNumSystemCounters; 138905b261ecSmrg 139005b261ecSmrg for (i = len = 0; i < SyncNumSystemCounters; i++) 139105b261ecSmrg { 139205b261ecSmrg char *name = SysCounterList[i]->pSysCounterInfo->name; 139305b261ecSmrg /* pad to 4 byte boundary */ 139405b261ecSmrg len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3; 139505b261ecSmrg } 139605b261ecSmrg 139705b261ecSmrg if (len) 139805b261ecSmrg { 1399637ac9abSmrg walklist = list = (xSyncSystemCounter *) xalloc(len); 140005b261ecSmrg if (!list) 140105b261ecSmrg return BadAlloc; 140205b261ecSmrg } 140305b261ecSmrg 140405b261ecSmrg rep.length = len >> 2; 140505b261ecSmrg 140605b261ecSmrg if (client->swapped) 140705b261ecSmrg { 1408637ac9abSmrg char n; 140905b261ecSmrg swaps(&rep.sequenceNumber, n); 141005b261ecSmrg swapl(&rep.length, n); 141105b261ecSmrg swapl(&rep.nCounters, n); 141205b261ecSmrg } 141305b261ecSmrg 141405b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 141505b261ecSmrg { 141605b261ecSmrg int namelen; 141705b261ecSmrg char *pname_in_reply; 141805b261ecSmrg SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; 141905b261ecSmrg 142005b261ecSmrg walklist->counter = SysCounterList[i]->id; 142105b261ecSmrg walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 142205b261ecSmrg walklist->resolution_lo = XSyncValueLow32(psci->resolution); 142305b261ecSmrg namelen = strlen(psci->name); 142405b261ecSmrg walklist->name_length = namelen; 142505b261ecSmrg 142605b261ecSmrg if (client->swapped) 142705b261ecSmrg { 1428637ac9abSmrg char n; 142905b261ecSmrg swapl(&walklist->counter, n); 143005b261ecSmrg swapl(&walklist->resolution_hi, n); 143105b261ecSmrg swapl(&walklist->resolution_lo, n); 143205b261ecSmrg swaps(&walklist->name_length, n); 143305b261ecSmrg } 143405b261ecSmrg 143505b261ecSmrg pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; 143605b261ecSmrg strncpy(pname_in_reply, psci->name, namelen); 143705b261ecSmrg walklist = (xSyncSystemCounter *) (((char *)walklist) + 143805b261ecSmrg ((sz_xSyncSystemCounter + namelen + 3) & ~3)); 143905b261ecSmrg } 144005b261ecSmrg 144105b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 144205b261ecSmrg if (len) 144305b261ecSmrg { 144405b261ecSmrg WriteToClient(client, len, (char *) list); 1445637ac9abSmrg xfree(list); 144605b261ecSmrg } 144705b261ecSmrg 144805b261ecSmrg return (client->noClientException); 144905b261ecSmrg} 145005b261ecSmrg 145105b261ecSmrg/* 145205b261ecSmrg * ** Set client Priority 145305b261ecSmrg */ 145405b261ecSmrgstatic int 145505b261ecSmrgProcSyncSetPriority(client) 145605b261ecSmrg ClientPtr client; 145705b261ecSmrg{ 145805b261ecSmrg REQUEST(xSyncSetPriorityReq); 145905b261ecSmrg ClientPtr priorityclient; 146005b261ecSmrg int rc; 146105b261ecSmrg 146205b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 146305b261ecSmrg 146405b261ecSmrg if (stuff->id == None) 146505b261ecSmrg priorityclient = client; 146605b261ecSmrg else { 146705b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1468637ac9abSmrg DixSetAttrAccess); 146905b261ecSmrg if (rc != Success) 147005b261ecSmrg return rc; 147105b261ecSmrg } 147205b261ecSmrg 147305b261ecSmrg if (priorityclient->priority != stuff->priority) 147405b261ecSmrg { 147505b261ecSmrg priorityclient->priority = stuff->priority; 147605b261ecSmrg 147705b261ecSmrg /* The following will force the server back into WaitForSomething 147805b261ecSmrg * so that the change in this client's priority is immediately 147905b261ecSmrg * reflected. 148005b261ecSmrg */ 148105b261ecSmrg isItTimeToYield = TRUE; 148205b261ecSmrg dispatchException |= DE_PRIORITYCHANGE; 148305b261ecSmrg } 148405b261ecSmrg return Success; 148505b261ecSmrg} 148605b261ecSmrg 148705b261ecSmrg/* 148805b261ecSmrg * ** Get client Priority 148905b261ecSmrg */ 149005b261ecSmrgstatic int 149105b261ecSmrgProcSyncGetPriority(client) 149205b261ecSmrg ClientPtr client; 149305b261ecSmrg{ 149405b261ecSmrg REQUEST(xSyncGetPriorityReq); 149505b261ecSmrg xSyncGetPriorityReply rep; 149605b261ecSmrg ClientPtr priorityclient; 149705b261ecSmrg int rc; 149805b261ecSmrg 149905b261ecSmrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 150005b261ecSmrg 150105b261ecSmrg if (stuff->id == None) 150205b261ecSmrg priorityclient = client; 150305b261ecSmrg else { 150405b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1505637ac9abSmrg DixGetAttrAccess); 150605b261ecSmrg if (rc != Success) 150705b261ecSmrg return rc; 150805b261ecSmrg } 150905b261ecSmrg 151005b261ecSmrg rep.type = X_Reply; 151105b261ecSmrg rep.length = 0; 151205b261ecSmrg rep.sequenceNumber = client->sequence; 151305b261ecSmrg rep.priority = priorityclient->priority; 151405b261ecSmrg 151505b261ecSmrg if (client->swapped) 151605b261ecSmrg { 1517637ac9abSmrg char n; 151805b261ecSmrg swaps(&rep.sequenceNumber, n); 151905b261ecSmrg swapl(&rep.priority, n); 152005b261ecSmrg } 152105b261ecSmrg 152205b261ecSmrg WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); 152305b261ecSmrg 152405b261ecSmrg return (client->noClientException); 152505b261ecSmrg} 152605b261ecSmrg 152705b261ecSmrg/* 152805b261ecSmrg * ** Create a new counter 152905b261ecSmrg */ 153005b261ecSmrgstatic int 153105b261ecSmrgProcSyncCreateCounter(client) 153205b261ecSmrg ClientPtr client; 153305b261ecSmrg{ 153405b261ecSmrg REQUEST(xSyncCreateCounterReq); 153505b261ecSmrg CARD64 initial; 153605b261ecSmrg 153705b261ecSmrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 153805b261ecSmrg 153905b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 154005b261ecSmrg 154105b261ecSmrg XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); 154205b261ecSmrg if (!SyncCreateCounter(client, stuff->cid, initial)) 154305b261ecSmrg return BadAlloc; 154405b261ecSmrg 154505b261ecSmrg return (client->noClientException); 154605b261ecSmrg} 154705b261ecSmrg 154805b261ecSmrg/* 154905b261ecSmrg * ** Set Counter value 155005b261ecSmrg */ 155105b261ecSmrgstatic int 155205b261ecSmrgProcSyncSetCounter(client) 155305b261ecSmrg ClientPtr client; 155405b261ecSmrg{ 155505b261ecSmrg REQUEST(xSyncSetCounterReq); 155605b261ecSmrg SyncCounter *pCounter; 155705b261ecSmrg CARD64 newvalue; 155805b261ecSmrg 155905b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 156005b261ecSmrg 156105b261ecSmrg pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid, 156205b261ecSmrg RTCounter, DixWriteAccess); 156305b261ecSmrg if (pCounter == NULL) 156405b261ecSmrg { 156505b261ecSmrg client->errorValue = stuff->cid; 156605b261ecSmrg return SyncErrorBase + XSyncBadCounter; 156705b261ecSmrg } 156805b261ecSmrg 156905b261ecSmrg if (IsSystemCounter(pCounter)) 157005b261ecSmrg { 157105b261ecSmrg client->errorValue = stuff->cid; 157205b261ecSmrg return BadAccess; 157305b261ecSmrg } 157405b261ecSmrg 157505b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 157605b261ecSmrg SyncChangeCounter(pCounter, newvalue); 157705b261ecSmrg return Success; 157805b261ecSmrg} 157905b261ecSmrg 158005b261ecSmrg/* 158105b261ecSmrg * ** Change Counter value 158205b261ecSmrg */ 158305b261ecSmrgstatic int 158405b261ecSmrgProcSyncChangeCounter(client) 158505b261ecSmrg ClientPtr client; 158605b261ecSmrg{ 158705b261ecSmrg REQUEST(xSyncChangeCounterReq); 158805b261ecSmrg SyncCounter *pCounter; 158905b261ecSmrg CARD64 newvalue; 159005b261ecSmrg Bool overflow; 159105b261ecSmrg 159205b261ecSmrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 159305b261ecSmrg 159405b261ecSmrg pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, 159505b261ecSmrg RTCounter, DixWriteAccess); 159605b261ecSmrg if (pCounter == NULL) 159705b261ecSmrg { 159805b261ecSmrg client->errorValue = stuff->cid; 159905b261ecSmrg return SyncErrorBase + XSyncBadCounter; 160005b261ecSmrg } 160105b261ecSmrg 160205b261ecSmrg if (IsSystemCounter(pCounter)) 160305b261ecSmrg { 160405b261ecSmrg client->errorValue = stuff->cid; 160505b261ecSmrg return BadAccess; 160605b261ecSmrg } 160705b261ecSmrg 160805b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 160905b261ecSmrg XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 161005b261ecSmrg if (overflow) 161105b261ecSmrg { 161205b261ecSmrg /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 161305b261ecSmrg client->errorValue = stuff->value_hi; 161405b261ecSmrg return BadValue; 161505b261ecSmrg } 161605b261ecSmrg SyncChangeCounter(pCounter, newvalue); 161705b261ecSmrg return Success; 161805b261ecSmrg} 161905b261ecSmrg 162005b261ecSmrg/* 162105b261ecSmrg * ** Destroy a counter 162205b261ecSmrg */ 162305b261ecSmrgstatic int 162405b261ecSmrgProcSyncDestroyCounter(client) 162505b261ecSmrg ClientPtr client; 162605b261ecSmrg{ 162705b261ecSmrg REQUEST(xSyncDestroyCounterReq); 162805b261ecSmrg SyncCounter *pCounter; 162905b261ecSmrg 163005b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 163105b261ecSmrg 163205b261ecSmrg pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, 163305b261ecSmrg RTCounter, DixDestroyAccess); 163405b261ecSmrg if (pCounter == NULL) 163505b261ecSmrg { 163605b261ecSmrg client->errorValue = stuff->counter; 163705b261ecSmrg return SyncErrorBase + XSyncBadCounter; 163805b261ecSmrg } 163905b261ecSmrg if (IsSystemCounter(pCounter)) 164005b261ecSmrg { 164105b261ecSmrg client->errorValue = stuff->counter; 164205b261ecSmrg return BadAccess; 164305b261ecSmrg } 164405b261ecSmrg FreeResource(pCounter->id, RT_NONE); 164505b261ecSmrg return Success; 164605b261ecSmrg} 164705b261ecSmrg 164805b261ecSmrg 164905b261ecSmrg/* 165005b261ecSmrg * ** Await 165105b261ecSmrg */ 165205b261ecSmrgstatic int 165305b261ecSmrgProcSyncAwait(client) 165405b261ecSmrg ClientPtr client; 165505b261ecSmrg{ 165605b261ecSmrg REQUEST(xSyncAwaitReq); 165705b261ecSmrg int len, items; 165805b261ecSmrg int i; 165905b261ecSmrg xSyncWaitCondition *pProtocolWaitConds; 166005b261ecSmrg SyncAwaitUnion *pAwaitUnion; 166105b261ecSmrg SyncAwait *pAwait; 166205b261ecSmrg int status; 166305b261ecSmrg 166405b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 166505b261ecSmrg 166605b261ecSmrg len = client->req_len << 2; 166705b261ecSmrg len -= sz_xSyncAwaitReq; 166805b261ecSmrg items = len / sz_xSyncWaitCondition; 166905b261ecSmrg 167005b261ecSmrg if (items * sz_xSyncWaitCondition != len) 167105b261ecSmrg { 167205b261ecSmrg return BadLength; 167305b261ecSmrg } 167405b261ecSmrg if (items == 0) 167505b261ecSmrg { 167605b261ecSmrg client->errorValue = items; /* XXX protocol change */ 167705b261ecSmrg return BadValue; 167805b261ecSmrg } 167905b261ecSmrg 168005b261ecSmrg pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; 168105b261ecSmrg 168205b261ecSmrg /* all the memory for the entire await list is allocated 168305b261ecSmrg * here in one chunk 168405b261ecSmrg */ 168505b261ecSmrg pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion)); 168605b261ecSmrg if (!pAwaitUnion) 168705b261ecSmrg return BadAlloc; 168805b261ecSmrg 168905b261ecSmrg /* first item is the header, remainder are real wait conditions */ 169005b261ecSmrg 169105b261ecSmrg pAwaitUnion->header.delete_id = FakeClientID(client->index); 169205b261ecSmrg if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 169305b261ecSmrg { 169405b261ecSmrg xfree(pAwaitUnion); 169505b261ecSmrg return BadAlloc; 169605b261ecSmrg } 169705b261ecSmrg 169805b261ecSmrg /* don't need to do any more memory allocation for this request! */ 169905b261ecSmrg 170005b261ecSmrg pAwaitUnion->header.client = client; 170105b261ecSmrg pAwaitUnion->header.num_waitconditions = 0; 170205b261ecSmrg 170305b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 170405b261ecSmrg for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) 170505b261ecSmrg { 170605b261ecSmrg if (pProtocolWaitConds->counter == None) /* XXX protocol change */ 170705b261ecSmrg { 170805b261ecSmrg /* this should take care of removing any triggers created by 170905b261ecSmrg * this request that have already been registered on counters 171005b261ecSmrg */ 171105b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 171205b261ecSmrg client->errorValue = pProtocolWaitConds->counter; 171305b261ecSmrg return SyncErrorBase + XSyncBadCounter; 171405b261ecSmrg } 171505b261ecSmrg 171605b261ecSmrg /* sanity checks are in SyncInitTrigger */ 171705b261ecSmrg pAwait->trigger.pCounter = NULL; 171805b261ecSmrg pAwait->trigger.value_type = pProtocolWaitConds->value_type; 171905b261ecSmrg XSyncIntsToValue(&pAwait->trigger.wait_value, 172005b261ecSmrg pProtocolWaitConds->wait_value_lo, 172105b261ecSmrg pProtocolWaitConds->wait_value_hi); 172205b261ecSmrg pAwait->trigger.test_type = pProtocolWaitConds->test_type; 172305b261ecSmrg 172405b261ecSmrg status = SyncInitTrigger(client, &pAwait->trigger, 172505b261ecSmrg pProtocolWaitConds->counter, XSyncCAAllTrigger); 172605b261ecSmrg if (status != Success) 172705b261ecSmrg { 172805b261ecSmrg /* this should take care of removing any triggers created by 172905b261ecSmrg * this request that have already been registered on counters 173005b261ecSmrg */ 173105b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 173205b261ecSmrg return status; 173305b261ecSmrg } 173405b261ecSmrg /* this is not a mistake -- same function works for both cases */ 173505b261ecSmrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 173605b261ecSmrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 173705b261ecSmrg XSyncIntsToValue(&pAwait->event_threshold, 173805b261ecSmrg pProtocolWaitConds->event_threshold_lo, 173905b261ecSmrg pProtocolWaitConds->event_threshold_hi); 174005b261ecSmrg pAwait->pHeader = &pAwaitUnion->header; 174105b261ecSmrg pAwaitUnion->header.num_waitconditions++; 174205b261ecSmrg } 174305b261ecSmrg 174405b261ecSmrg IgnoreClient(client); 174505b261ecSmrg 174605b261ecSmrg /* see if any of the triggers are already true */ 174705b261ecSmrg 174805b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 174905b261ecSmrg for (i = 0; i < items; i++, pAwait++) 175005b261ecSmrg { 175105b261ecSmrg /* don't have to worry about NULL counters because the request 175205b261ecSmrg * errors before we get here out if they occur 175305b261ecSmrg */ 175405b261ecSmrg if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, 175505b261ecSmrg pAwait->trigger.pCounter->value)) 175605b261ecSmrg { 175705b261ecSmrg (*pAwait->trigger.TriggerFired)(&pAwait->trigger); 175805b261ecSmrg break; /* once is enough */ 175905b261ecSmrg } 176005b261ecSmrg } 176105b261ecSmrg return Success; 176205b261ecSmrg} 176305b261ecSmrg 176405b261ecSmrg 176505b261ecSmrg/* 176605b261ecSmrg * ** Query a counter 176705b261ecSmrg */ 176805b261ecSmrgstatic int 176905b261ecSmrgProcSyncQueryCounter(client) 177005b261ecSmrg ClientPtr client; 177105b261ecSmrg{ 177205b261ecSmrg REQUEST(xSyncQueryCounterReq); 177305b261ecSmrg xSyncQueryCounterReply rep; 177405b261ecSmrg SyncCounter *pCounter; 177505b261ecSmrg 177605b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 177705b261ecSmrg 177805b261ecSmrg pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, 177905b261ecSmrg RTCounter, DixReadAccess); 178005b261ecSmrg if (pCounter == NULL) 178105b261ecSmrg { 178205b261ecSmrg client->errorValue = stuff->counter; 178305b261ecSmrg return SyncErrorBase + XSyncBadCounter; 178405b261ecSmrg } 178505b261ecSmrg 178605b261ecSmrg rep.type = X_Reply; 178705b261ecSmrg rep.length = 0; 178805b261ecSmrg rep.sequenceNumber = client->sequence; 178905b261ecSmrg 179005b261ecSmrg /* if system counter, ask it what the current value is */ 179105b261ecSmrg 179205b261ecSmrg if (IsSystemCounter(pCounter)) 179305b261ecSmrg { 179405b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 179505b261ecSmrg &pCounter->value); 179605b261ecSmrg } 179705b261ecSmrg 179805b261ecSmrg rep.value_hi = XSyncValueHigh32(pCounter->value); 179905b261ecSmrg rep.value_lo = XSyncValueLow32(pCounter->value); 180005b261ecSmrg if (client->swapped) 180105b261ecSmrg { 1802637ac9abSmrg char n; 180305b261ecSmrg swaps(&rep.sequenceNumber, n); 180405b261ecSmrg swapl(&rep.length, n); 180505b261ecSmrg swapl(&rep.value_hi, n); 180605b261ecSmrg swapl(&rep.value_lo, n); 180705b261ecSmrg } 180805b261ecSmrg WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); 180905b261ecSmrg return (client->noClientException); 181005b261ecSmrg} 181105b261ecSmrg 181205b261ecSmrg 181305b261ecSmrg/* 181405b261ecSmrg * ** Create Alarm 181505b261ecSmrg */ 181605b261ecSmrgstatic int 181705b261ecSmrgProcSyncCreateAlarm(client) 181805b261ecSmrg ClientPtr client; 181905b261ecSmrg{ 182005b261ecSmrg REQUEST(xSyncCreateAlarmReq); 182105b261ecSmrg SyncAlarm *pAlarm; 182205b261ecSmrg int status; 182305b261ecSmrg unsigned long len, vmask; 182405b261ecSmrg SyncTrigger *pTrigger; 182505b261ecSmrg 182605b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 182705b261ecSmrg 182805b261ecSmrg LEGAL_NEW_RESOURCE(stuff->id, client); 182905b261ecSmrg 183005b261ecSmrg vmask = stuff->valueMask; 183105b261ecSmrg len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2); 183205b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 183305b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 183405b261ecSmrg return BadLength; 183505b261ecSmrg 183605b261ecSmrg if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm)))) 183705b261ecSmrg { 183805b261ecSmrg return BadAlloc; 183905b261ecSmrg } 184005b261ecSmrg 184105b261ecSmrg /* set up defaults */ 184205b261ecSmrg 184305b261ecSmrg pTrigger = &pAlarm->trigger; 184405b261ecSmrg pTrigger->pCounter = NULL; 184505b261ecSmrg pTrigger->value_type = XSyncAbsolute; 184605b261ecSmrg XSyncIntToValue(&pTrigger->wait_value, 0L); 184705b261ecSmrg pTrigger->test_type = XSyncPositiveComparison; 184805b261ecSmrg pTrigger->TriggerFired = SyncAlarmTriggerFired; 184905b261ecSmrg pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 185005b261ecSmrg status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); 185105b261ecSmrg if (status != Success) 185205b261ecSmrg { 185305b261ecSmrg xfree(pAlarm); 185405b261ecSmrg return status; 185505b261ecSmrg } 185605b261ecSmrg 185705b261ecSmrg pAlarm->client = client; 185805b261ecSmrg pAlarm->alarm_id = stuff->id; 185905b261ecSmrg XSyncIntToValue(&pAlarm->delta, 1L); 186005b261ecSmrg pAlarm->events = TRUE; 186105b261ecSmrg pAlarm->state = XSyncAlarmInactive; 186205b261ecSmrg pAlarm->pEventClients = NULL; 186305b261ecSmrg status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 186405b261ecSmrg (CARD32 *)&stuff[1]); 186505b261ecSmrg if (status != Success) 186605b261ecSmrg { 186705b261ecSmrg xfree(pAlarm); 186805b261ecSmrg return status; 186905b261ecSmrg } 187005b261ecSmrg 187105b261ecSmrg if (!AddResource(stuff->id, RTAlarm, pAlarm)) 187205b261ecSmrg { 187305b261ecSmrg xfree(pAlarm); 187405b261ecSmrg return BadAlloc; 187505b261ecSmrg } 187605b261ecSmrg 187705b261ecSmrg /* see if alarm already triggered. NULL counter will not trigger 187805b261ecSmrg * in CreateAlarm and sets alarm state to Inactive. 187905b261ecSmrg */ 188005b261ecSmrg 188105b261ecSmrg if (!pTrigger->pCounter) 188205b261ecSmrg { 188305b261ecSmrg pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 188405b261ecSmrg } 188505b261ecSmrg else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) 188605b261ecSmrg { 188705b261ecSmrg (*pTrigger->TriggerFired)(pTrigger); 188805b261ecSmrg } 188905b261ecSmrg 189005b261ecSmrg return Success; 189105b261ecSmrg} 189205b261ecSmrg 189305b261ecSmrg/* 189405b261ecSmrg * ** Change Alarm 189505b261ecSmrg */ 189605b261ecSmrgstatic int 189705b261ecSmrgProcSyncChangeAlarm(client) 189805b261ecSmrg ClientPtr client; 189905b261ecSmrg{ 190005b261ecSmrg REQUEST(xSyncChangeAlarmReq); 190105b261ecSmrg SyncAlarm *pAlarm; 190205b261ecSmrg long vmask; 190305b261ecSmrg int len, status; 190405b261ecSmrg 190505b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 190605b261ecSmrg 190705b261ecSmrg if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 190805b261ecSmrg RTAlarm, DixWriteAccess))) 190905b261ecSmrg { 191005b261ecSmrg client->errorValue = stuff->alarm; 191105b261ecSmrg return SyncErrorBase + XSyncBadAlarm; 191205b261ecSmrg } 191305b261ecSmrg 191405b261ecSmrg vmask = stuff->valueMask; 191505b261ecSmrg len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2); 191605b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 191705b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 191805b261ecSmrg return BadLength; 191905b261ecSmrg 192005b261ecSmrg if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 192105b261ecSmrg (CARD32 *)&stuff[1])) != Success) 192205b261ecSmrg return status; 192305b261ecSmrg 192405b261ecSmrg /* see if alarm already triggered. NULL counter WILL trigger 192505b261ecSmrg * in ChangeAlarm. 192605b261ecSmrg */ 192705b261ecSmrg 192805b261ecSmrg if (!pAlarm->trigger.pCounter || 192905b261ecSmrg (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, 193005b261ecSmrg pAlarm->trigger.pCounter->value)) 193105b261ecSmrg { 193205b261ecSmrg (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); 193305b261ecSmrg } 193405b261ecSmrg return Success; 193505b261ecSmrg} 193605b261ecSmrg 193705b261ecSmrgstatic int 193805b261ecSmrgProcSyncQueryAlarm(client) 193905b261ecSmrg ClientPtr client; 194005b261ecSmrg{ 194105b261ecSmrg REQUEST(xSyncQueryAlarmReq); 194205b261ecSmrg SyncAlarm *pAlarm; 194305b261ecSmrg xSyncQueryAlarmReply rep; 194405b261ecSmrg SyncTrigger *pTrigger; 194505b261ecSmrg 194605b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 194705b261ecSmrg 194805b261ecSmrg pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 194905b261ecSmrg RTAlarm, DixReadAccess); 195005b261ecSmrg if (!pAlarm) 195105b261ecSmrg { 195205b261ecSmrg client->errorValue = stuff->alarm; 195305b261ecSmrg return (SyncErrorBase + XSyncBadAlarm); 195405b261ecSmrg } 195505b261ecSmrg 195605b261ecSmrg rep.type = X_Reply; 195705b261ecSmrg rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2; 195805b261ecSmrg rep.sequenceNumber = client->sequence; 195905b261ecSmrg 196005b261ecSmrg pTrigger = &pAlarm->trigger; 196105b261ecSmrg rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; 196205b261ecSmrg 196305b261ecSmrg#if 0 /* XXX unclear what to do, depends on whether relative value-types 196405b261ecSmrg * are "consumed" immediately and are considered absolute from then 196505b261ecSmrg * on. 196605b261ecSmrg */ 196705b261ecSmrg rep.value_type = pTrigger->value_type; 196805b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); 196905b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); 197005b261ecSmrg#else 197105b261ecSmrg rep.value_type = XSyncAbsolute; 197205b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 197305b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); 197405b261ecSmrg#endif 197505b261ecSmrg 197605b261ecSmrg rep.test_type = pTrigger->test_type; 197705b261ecSmrg rep.delta_hi = XSyncValueHigh32(pAlarm->delta); 197805b261ecSmrg rep.delta_lo = XSyncValueLow32(pAlarm->delta); 197905b261ecSmrg rep.events = pAlarm->events; 198005b261ecSmrg rep.state = pAlarm->state; 198105b261ecSmrg 198205b261ecSmrg if (client->swapped) 198305b261ecSmrg { 1984637ac9abSmrg char n; 198505b261ecSmrg swaps(&rep.sequenceNumber, n); 198605b261ecSmrg swapl(&rep.length, n); 198705b261ecSmrg swapl(&rep.counter, n); 198805b261ecSmrg swapl(&rep.wait_value_hi, n); 198905b261ecSmrg swapl(&rep.wait_value_lo, n); 199005b261ecSmrg swapl(&rep.test_type, n); 199105b261ecSmrg swapl(&rep.delta_hi, n); 199205b261ecSmrg swapl(&rep.delta_lo, n); 199305b261ecSmrg } 199405b261ecSmrg 199505b261ecSmrg WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); 199605b261ecSmrg return (client->noClientException); 199705b261ecSmrg} 199805b261ecSmrg 199905b261ecSmrg 200005b261ecSmrgstatic int 200105b261ecSmrgProcSyncDestroyAlarm(client) 200205b261ecSmrg ClientPtr client; 200305b261ecSmrg{ 200405b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 200505b261ecSmrg 200605b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 200705b261ecSmrg 200805b261ecSmrg if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 200905b261ecSmrg RTAlarm, DixDestroyAccess))) 201005b261ecSmrg { 201105b261ecSmrg client->errorValue = stuff->alarm; 201205b261ecSmrg return SyncErrorBase + XSyncBadAlarm; 201305b261ecSmrg } 201405b261ecSmrg 201505b261ecSmrg FreeResource(stuff->alarm, RT_NONE); 201605b261ecSmrg return (client->noClientException); 201705b261ecSmrg} 201805b261ecSmrg 201905b261ecSmrg/* 202005b261ecSmrg * ** Given an extension request, call the appropriate request procedure 202105b261ecSmrg */ 202205b261ecSmrgstatic int 202305b261ecSmrgProcSyncDispatch(client) 202405b261ecSmrg ClientPtr client; 202505b261ecSmrg{ 202605b261ecSmrg REQUEST(xReq); 202705b261ecSmrg 202805b261ecSmrg switch (stuff->data) 202905b261ecSmrg { 203005b261ecSmrg 203105b261ecSmrg case X_SyncInitialize: 203205b261ecSmrg return ProcSyncInitialize(client); 203305b261ecSmrg case X_SyncListSystemCounters: 203405b261ecSmrg return ProcSyncListSystemCounters(client); 203505b261ecSmrg case X_SyncCreateCounter: 203605b261ecSmrg return ProcSyncCreateCounter(client); 203705b261ecSmrg case X_SyncSetCounter: 203805b261ecSmrg return ProcSyncSetCounter(client); 203905b261ecSmrg case X_SyncChangeCounter: 204005b261ecSmrg return ProcSyncChangeCounter(client); 204105b261ecSmrg case X_SyncQueryCounter: 204205b261ecSmrg return ProcSyncQueryCounter(client); 204305b261ecSmrg case X_SyncDestroyCounter: 204405b261ecSmrg return ProcSyncDestroyCounter(client); 204505b261ecSmrg case X_SyncAwait: 204605b261ecSmrg return ProcSyncAwait(client); 204705b261ecSmrg case X_SyncCreateAlarm: 204805b261ecSmrg return ProcSyncCreateAlarm(client); 204905b261ecSmrg case X_SyncChangeAlarm: 205005b261ecSmrg return ProcSyncChangeAlarm(client); 205105b261ecSmrg case X_SyncQueryAlarm: 205205b261ecSmrg return ProcSyncQueryAlarm(client); 205305b261ecSmrg case X_SyncDestroyAlarm: 205405b261ecSmrg return ProcSyncDestroyAlarm(client); 205505b261ecSmrg case X_SyncSetPriority: 205605b261ecSmrg return ProcSyncSetPriority(client); 205705b261ecSmrg case X_SyncGetPriority: 205805b261ecSmrg return ProcSyncGetPriority(client); 205905b261ecSmrg default: 206005b261ecSmrg return BadRequest; 206105b261ecSmrg } 206205b261ecSmrg} 206305b261ecSmrg 206405b261ecSmrg/* 206505b261ecSmrg * Boring Swapping stuff ... 206605b261ecSmrg */ 206705b261ecSmrg 206805b261ecSmrgstatic int 206905b261ecSmrgSProcSyncInitialize(client) 207005b261ecSmrg ClientPtr client; 207105b261ecSmrg{ 207205b261ecSmrg REQUEST(xSyncInitializeReq); 2073637ac9abSmrg char n; 207405b261ecSmrg 207505b261ecSmrg swaps(&stuff->length, n); 207605b261ecSmrg REQUEST_SIZE_MATCH (xSyncInitializeReq); 207705b261ecSmrg 207805b261ecSmrg return ProcSyncInitialize(client); 207905b261ecSmrg} 208005b261ecSmrg 208105b261ecSmrgstatic int 208205b261ecSmrgSProcSyncListSystemCounters(client) 208305b261ecSmrg ClientPtr client; 208405b261ecSmrg{ 208505b261ecSmrg REQUEST(xSyncListSystemCountersReq); 2086637ac9abSmrg char n; 208705b261ecSmrg 208805b261ecSmrg swaps(&stuff->length, n); 208905b261ecSmrg REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); 209005b261ecSmrg 209105b261ecSmrg return ProcSyncListSystemCounters(client); 209205b261ecSmrg} 209305b261ecSmrg 209405b261ecSmrgstatic int 209505b261ecSmrgSProcSyncCreateCounter(client) 209605b261ecSmrg ClientPtr client; 209705b261ecSmrg{ 209805b261ecSmrg REQUEST(xSyncCreateCounterReq); 2099637ac9abSmrg char n; 210005b261ecSmrg 210105b261ecSmrg swaps(&stuff->length, n); 210205b261ecSmrg REQUEST_SIZE_MATCH (xSyncCreateCounterReq); 210305b261ecSmrg swapl(&stuff->cid, n); 210405b261ecSmrg swapl(&stuff->initial_value_lo, n); 210505b261ecSmrg swapl(&stuff->initial_value_hi, n); 210605b261ecSmrg 210705b261ecSmrg return ProcSyncCreateCounter(client); 210805b261ecSmrg} 210905b261ecSmrg 211005b261ecSmrgstatic int 211105b261ecSmrgSProcSyncSetCounter(client) 211205b261ecSmrg ClientPtr client; 211305b261ecSmrg{ 211405b261ecSmrg REQUEST(xSyncSetCounterReq); 2115637ac9abSmrg char n; 211605b261ecSmrg 211705b261ecSmrg swaps(&stuff->length, n); 211805b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetCounterReq); 211905b261ecSmrg swapl(&stuff->cid, n); 212005b261ecSmrg swapl(&stuff->value_lo, n); 212105b261ecSmrg swapl(&stuff->value_hi, n); 212205b261ecSmrg 212305b261ecSmrg return ProcSyncSetCounter(client); 212405b261ecSmrg} 212505b261ecSmrg 212605b261ecSmrgstatic int 212705b261ecSmrgSProcSyncChangeCounter(client) 212805b261ecSmrg ClientPtr client; 212905b261ecSmrg{ 213005b261ecSmrg REQUEST(xSyncChangeCounterReq); 2131637ac9abSmrg char n; 213205b261ecSmrg 213305b261ecSmrg swaps(&stuff->length, n); 213405b261ecSmrg REQUEST_SIZE_MATCH (xSyncChangeCounterReq); 213505b261ecSmrg swapl(&stuff->cid, n); 213605b261ecSmrg swapl(&stuff->value_lo, n); 213705b261ecSmrg swapl(&stuff->value_hi, n); 213805b261ecSmrg 213905b261ecSmrg return ProcSyncChangeCounter(client); 214005b261ecSmrg} 214105b261ecSmrg 214205b261ecSmrgstatic int 214305b261ecSmrgSProcSyncQueryCounter(client) 214405b261ecSmrg ClientPtr client; 214505b261ecSmrg{ 214605b261ecSmrg REQUEST(xSyncQueryCounterReq); 2147637ac9abSmrg char n; 214805b261ecSmrg 214905b261ecSmrg swaps(&stuff->length, n); 215005b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryCounterReq); 215105b261ecSmrg swapl(&stuff->counter, n); 215205b261ecSmrg 215305b261ecSmrg return ProcSyncQueryCounter(client); 215405b261ecSmrg} 215505b261ecSmrg 215605b261ecSmrgstatic int 215705b261ecSmrgSProcSyncDestroyCounter(client) 215805b261ecSmrg ClientPtr client; 215905b261ecSmrg{ 216005b261ecSmrg REQUEST(xSyncDestroyCounterReq); 2161637ac9abSmrg char n; 216205b261ecSmrg 216305b261ecSmrg swaps(&stuff->length, n); 216405b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); 216505b261ecSmrg swapl(&stuff->counter, n); 216605b261ecSmrg 216705b261ecSmrg return ProcSyncDestroyCounter(client); 216805b261ecSmrg} 216905b261ecSmrg 217005b261ecSmrgstatic int 217105b261ecSmrgSProcSyncAwait(client) 217205b261ecSmrg ClientPtr client; 217305b261ecSmrg{ 217405b261ecSmrg REQUEST(xSyncAwaitReq); 2175637ac9abSmrg char n; 217605b261ecSmrg 217705b261ecSmrg swaps(&stuff->length, n); 217805b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 217905b261ecSmrg SwapRestL(stuff); 218005b261ecSmrg 218105b261ecSmrg return ProcSyncAwait(client); 218205b261ecSmrg} 218305b261ecSmrg 218405b261ecSmrg 218505b261ecSmrgstatic int 218605b261ecSmrgSProcSyncCreateAlarm(client) 218705b261ecSmrg ClientPtr client; 218805b261ecSmrg{ 218905b261ecSmrg REQUEST(xSyncCreateAlarmReq); 2190637ac9abSmrg char n; 219105b261ecSmrg 219205b261ecSmrg swaps(&stuff->length, n); 219305b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 219405b261ecSmrg swapl(&stuff->id, n); 219505b261ecSmrg swapl(&stuff->valueMask, n); 219605b261ecSmrg SwapRestL(stuff); 219705b261ecSmrg 219805b261ecSmrg return ProcSyncCreateAlarm(client); 219905b261ecSmrg} 220005b261ecSmrg 220105b261ecSmrgstatic int 220205b261ecSmrgSProcSyncChangeAlarm(client) 220305b261ecSmrg ClientPtr client; 220405b261ecSmrg{ 220505b261ecSmrg REQUEST(xSyncChangeAlarmReq); 2206637ac9abSmrg char n; 220705b261ecSmrg 220805b261ecSmrg swaps(&stuff->length, n); 220905b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 221005b261ecSmrg swapl(&stuff->alarm, n); 221105b261ecSmrg swapl(&stuff->valueMask, n); 221205b261ecSmrg SwapRestL(stuff); 221305b261ecSmrg return ProcSyncChangeAlarm(client); 221405b261ecSmrg} 221505b261ecSmrg 221605b261ecSmrgstatic int 221705b261ecSmrgSProcSyncQueryAlarm(client) 221805b261ecSmrg ClientPtr client; 221905b261ecSmrg{ 222005b261ecSmrg REQUEST(xSyncQueryAlarmReq); 2221637ac9abSmrg char n; 222205b261ecSmrg 222305b261ecSmrg swaps(&stuff->length, n); 222405b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); 222505b261ecSmrg swapl(&stuff->alarm, n); 222605b261ecSmrg 222705b261ecSmrg return ProcSyncQueryAlarm(client); 222805b261ecSmrg} 222905b261ecSmrg 223005b261ecSmrgstatic int 223105b261ecSmrgSProcSyncDestroyAlarm(client) 223205b261ecSmrg ClientPtr client; 223305b261ecSmrg{ 223405b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 2235637ac9abSmrg char n; 223605b261ecSmrg 223705b261ecSmrg swaps(&stuff->length, n); 223805b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); 223905b261ecSmrg swapl(&stuff->alarm, n); 224005b261ecSmrg 224105b261ecSmrg return ProcSyncDestroyAlarm(client); 224205b261ecSmrg} 224305b261ecSmrg 224405b261ecSmrgstatic int 224505b261ecSmrgSProcSyncSetPriority(client) 224605b261ecSmrg ClientPtr client; 224705b261ecSmrg{ 224805b261ecSmrg REQUEST(xSyncSetPriorityReq); 2249637ac9abSmrg char n; 225005b261ecSmrg 225105b261ecSmrg swaps(&stuff->length, n); 225205b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetPriorityReq); 225305b261ecSmrg swapl(&stuff->id, n); 225405b261ecSmrg swapl(&stuff->priority, n); 225505b261ecSmrg 225605b261ecSmrg return ProcSyncSetPriority(client); 225705b261ecSmrg} 225805b261ecSmrg 225905b261ecSmrgstatic int 226005b261ecSmrgSProcSyncGetPriority(client) 226105b261ecSmrg ClientPtr client; 226205b261ecSmrg{ 226305b261ecSmrg REQUEST(xSyncGetPriorityReq); 2264637ac9abSmrg char n; 226505b261ecSmrg 226605b261ecSmrg swaps(&stuff->length, n); 226705b261ecSmrg REQUEST_SIZE_MATCH (xSyncGetPriorityReq); 226805b261ecSmrg swapl(&stuff->id, n); 226905b261ecSmrg 227005b261ecSmrg return ProcSyncGetPriority(client); 227105b261ecSmrg} 227205b261ecSmrg 227305b261ecSmrg 227405b261ecSmrgstatic int 227505b261ecSmrgSProcSyncDispatch(client) 227605b261ecSmrg ClientPtr client; 227705b261ecSmrg{ 227805b261ecSmrg REQUEST(xReq); 227905b261ecSmrg 228005b261ecSmrg switch (stuff->data) 228105b261ecSmrg { 228205b261ecSmrg case X_SyncInitialize: 228305b261ecSmrg return SProcSyncInitialize(client); 228405b261ecSmrg case X_SyncListSystemCounters: 228505b261ecSmrg return SProcSyncListSystemCounters(client); 228605b261ecSmrg case X_SyncCreateCounter: 228705b261ecSmrg return SProcSyncCreateCounter(client); 228805b261ecSmrg case X_SyncSetCounter: 228905b261ecSmrg return SProcSyncSetCounter(client); 229005b261ecSmrg case X_SyncChangeCounter: 229105b261ecSmrg return SProcSyncChangeCounter(client); 229205b261ecSmrg case X_SyncQueryCounter: 229305b261ecSmrg return SProcSyncQueryCounter(client); 229405b261ecSmrg case X_SyncDestroyCounter: 229505b261ecSmrg return SProcSyncDestroyCounter(client); 229605b261ecSmrg case X_SyncAwait: 229705b261ecSmrg return SProcSyncAwait(client); 229805b261ecSmrg case X_SyncCreateAlarm: 229905b261ecSmrg return SProcSyncCreateAlarm(client); 230005b261ecSmrg case X_SyncChangeAlarm: 230105b261ecSmrg return SProcSyncChangeAlarm(client); 230205b261ecSmrg case X_SyncQueryAlarm: 230305b261ecSmrg return SProcSyncQueryAlarm(client); 230405b261ecSmrg case X_SyncDestroyAlarm: 230505b261ecSmrg return SProcSyncDestroyAlarm(client); 230605b261ecSmrg case X_SyncSetPriority: 230705b261ecSmrg return SProcSyncSetPriority(client); 230805b261ecSmrg case X_SyncGetPriority: 230905b261ecSmrg return SProcSyncGetPriority(client); 231005b261ecSmrg default: 231105b261ecSmrg return BadRequest; 231205b261ecSmrg } 231305b261ecSmrg} 231405b261ecSmrg 231505b261ecSmrg/* 231605b261ecSmrg * Event Swapping 231705b261ecSmrg */ 231805b261ecSmrg 231905b261ecSmrgstatic void 232005b261ecSmrgSCounterNotifyEvent(from, to) 232105b261ecSmrg xSyncCounterNotifyEvent *from, *to; 232205b261ecSmrg{ 232305b261ecSmrg to->type = from->type; 232405b261ecSmrg to->kind = from->kind; 232505b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 232605b261ecSmrg cpswapl(from->counter, to->counter); 232705b261ecSmrg cpswapl(from->wait_value_lo, to->wait_value_lo); 232805b261ecSmrg cpswapl(from->wait_value_hi, to->wait_value_hi); 232905b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 233005b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 233105b261ecSmrg cpswapl(from->time, to->time); 233205b261ecSmrg cpswaps(from->count, to->count); 233305b261ecSmrg to->destroyed = from->destroyed; 233405b261ecSmrg} 233505b261ecSmrg 233605b261ecSmrg 233705b261ecSmrgstatic void 233805b261ecSmrgSAlarmNotifyEvent(from, to) 233905b261ecSmrg xSyncAlarmNotifyEvent *from, *to; 234005b261ecSmrg{ 234105b261ecSmrg to->type = from->type; 234205b261ecSmrg to->kind = from->kind; 234305b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 234405b261ecSmrg cpswapl(from->alarm, to->alarm); 234505b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 234605b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 234705b261ecSmrg cpswapl(from->alarm_value_lo, to->alarm_value_lo); 234805b261ecSmrg cpswapl(from->alarm_value_hi, to->alarm_value_hi); 234905b261ecSmrg cpswapl(from->time, to->time); 235005b261ecSmrg to->state = from->state; 235105b261ecSmrg} 235205b261ecSmrg 235305b261ecSmrg/* 235405b261ecSmrg * ** Close everything down. ** This is fairly simple for now. 235505b261ecSmrg */ 235605b261ecSmrg/* ARGSUSED */ 235705b261ecSmrgstatic void 235805b261ecSmrgSyncResetProc(extEntry) 235905b261ecSmrg ExtensionEntry *extEntry; 236005b261ecSmrg{ 236105b261ecSmrg xfree(SysCounterList); 236205b261ecSmrg SysCounterList = NULL; 236305b261ecSmrg RTCounter = 0; 236405b261ecSmrg} 236505b261ecSmrg 236605b261ecSmrg 236705b261ecSmrg/* 236805b261ecSmrg * ** Initialise the extension. 236905b261ecSmrg */ 237005b261ecSmrgvoid 237105b261ecSmrgSyncExtensionInit(INITARGS) 237205b261ecSmrg{ 237305b261ecSmrg ExtensionEntry *extEntry; 237405b261ecSmrg 237505b261ecSmrg if (RTCounter == 0) 237605b261ecSmrg { 237705b261ecSmrg RTCounter = CreateNewResourceType(FreeCounter); 237805b261ecSmrg } 237905b261ecSmrg RTAlarm = CreateNewResourceType(FreeAlarm); 238005b261ecSmrg RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN; 238105b261ecSmrg RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN; 238205b261ecSmrg 238305b261ecSmrg if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 238405b261ecSmrg RTAlarmClient == 0 || 238505b261ecSmrg (extEntry = AddExtension(SYNC_NAME, 238605b261ecSmrg XSyncNumberEvents, XSyncNumberErrors, 238705b261ecSmrg ProcSyncDispatch, SProcSyncDispatch, 238805b261ecSmrg SyncResetProc, 238905b261ecSmrg StandardMinorOpcode)) == NULL) 239005b261ecSmrg { 239105b261ecSmrg ErrorF("Sync Extension %d.%d failed to Initialise\n", 239205b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 239305b261ecSmrg return; 239405b261ecSmrg } 239505b261ecSmrg 239605b261ecSmrg SyncEventBase = extEntry->eventBase; 239705b261ecSmrg SyncErrorBase = extEntry->errorBase; 239805b261ecSmrg EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; 239905b261ecSmrg EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; 240005b261ecSmrg 240105b261ecSmrg /* 240205b261ecSmrg * Although SERVERTIME is implemented by the OS layer, we initialise it 240305b261ecSmrg * here because doing it in OsInit() is too early. The resource database 240405b261ecSmrg * is not initialised when OsInit() is called. This is just about OK 240505b261ecSmrg * because there is always a servertime counter. 240605b261ecSmrg */ 240705b261ecSmrg SyncInitServerTime(); 240805b261ecSmrg SyncInitIdleTime(); 240905b261ecSmrg 241005b261ecSmrg#ifdef DEBUG 241105b261ecSmrg fprintf(stderr, "Sync Extension %d.%d\n", 241205b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 241305b261ecSmrg#endif 241405b261ecSmrg} 241505b261ecSmrg 241605b261ecSmrg 241705b261ecSmrg/* 241805b261ecSmrg * ***** SERVERTIME implementation - should go in its own file in OS directory? 241905b261ecSmrg */ 242005b261ecSmrg 242105b261ecSmrg 242205b261ecSmrg 242305b261ecSmrgstatic pointer ServertimeCounter; 242405b261ecSmrgstatic XSyncValue Now; 242505b261ecSmrgstatic XSyncValue *pnext_time; 242605b261ecSmrg 242705b261ecSmrg#define GetTime()\ 242805b261ecSmrg{\ 242905b261ecSmrg unsigned long millis = GetTimeInMillis();\ 243005b261ecSmrg unsigned long maxis = XSyncValueHigh32(Now);\ 243105b261ecSmrg if (millis < XSyncValueLow32(Now)) maxis++;\ 243205b261ecSmrg XSyncIntsToValue(&Now, millis, maxis);\ 243305b261ecSmrg} 243405b261ecSmrg 243505b261ecSmrg/* 243605b261ecSmrg*** Server Block Handler 243705b261ecSmrg*** code inspired by multibuffer extension 243805b261ecSmrg */ 243905b261ecSmrg/*ARGSUSED*/ 244005b261ecSmrgstatic void ServertimeBlockHandler(env, wt, LastSelectMask) 244105b261ecSmrgpointer env; 244205b261ecSmrgstruct timeval **wt; 244305b261ecSmrgpointer LastSelectMask; 244405b261ecSmrg{ 244505b261ecSmrg XSyncValue delay; 244605b261ecSmrg unsigned long timeout; 244705b261ecSmrg 244805b261ecSmrg if (pnext_time) 244905b261ecSmrg { 245005b261ecSmrg GetTime(); 245105b261ecSmrg 245205b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 245305b261ecSmrg { 245405b261ecSmrg timeout = 0; 245505b261ecSmrg } 245605b261ecSmrg else 245705b261ecSmrg { 245805b261ecSmrg Bool overflow; 245905b261ecSmrg XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 246005b261ecSmrg (void)overflow; 246105b261ecSmrg timeout = XSyncValueLow32(delay); 246205b261ecSmrg } 246305b261ecSmrg AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 246405b261ecSmrg } 246505b261ecSmrg} 246605b261ecSmrg 246705b261ecSmrg/* 246805b261ecSmrg*** Wakeup Handler 246905b261ecSmrg */ 247005b261ecSmrg/*ARGSUSED*/ 247105b261ecSmrgstatic void ServertimeWakeupHandler(env, rc, LastSelectMask) 247205b261ecSmrgpointer env; 247305b261ecSmrgint rc; 247405b261ecSmrgpointer LastSelectMask; 247505b261ecSmrg{ 247605b261ecSmrg if (pnext_time) 247705b261ecSmrg { 247805b261ecSmrg GetTime(); 247905b261ecSmrg 248005b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 248105b261ecSmrg { 248205b261ecSmrg SyncChangeCounter(ServertimeCounter, Now); 248305b261ecSmrg } 248405b261ecSmrg } 248505b261ecSmrg} 248605b261ecSmrg 248705b261ecSmrgstatic void 248805b261ecSmrgServertimeQueryValue(pCounter, pValue_return) 248905b261ecSmrg pointer pCounter; 249005b261ecSmrg CARD64 *pValue_return; 249105b261ecSmrg{ 249205b261ecSmrg GetTime(); 249305b261ecSmrg *pValue_return = Now; 249405b261ecSmrg} 249505b261ecSmrg 249605b261ecSmrgstatic void 249705b261ecSmrgServertimeBracketValues(pCounter, pbracket_less, pbracket_greater) 249805b261ecSmrg pointer pCounter; 249905b261ecSmrg CARD64 *pbracket_less; 250005b261ecSmrg CARD64 *pbracket_greater; 250105b261ecSmrg{ 250205b261ecSmrg if (!pnext_time && pbracket_greater) 250305b261ecSmrg { 250405b261ecSmrg RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 250505b261ecSmrg ServertimeWakeupHandler, 250605b261ecSmrg NULL); 250705b261ecSmrg } 250805b261ecSmrg else if (pnext_time && !pbracket_greater) 250905b261ecSmrg { 251005b261ecSmrg RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 251105b261ecSmrg ServertimeWakeupHandler, 251205b261ecSmrg NULL); 251305b261ecSmrg } 251405b261ecSmrg pnext_time = pbracket_greater; 251505b261ecSmrg} 251605b261ecSmrg 251705b261ecSmrgstatic void 251805b261ecSmrgSyncInitServerTime(void) 251905b261ecSmrg{ 252005b261ecSmrg CARD64 resolution; 252105b261ecSmrg 252205b261ecSmrg XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 252305b261ecSmrg XSyncIntToValue(&resolution, 4); 252405b261ecSmrg ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 252505b261ecSmrg XSyncCounterNeverDecreases, 252605b261ecSmrg ServertimeQueryValue, ServertimeBracketValues); 252705b261ecSmrg pnext_time = NULL; 252805b261ecSmrg} 252905b261ecSmrg 253005b261ecSmrg 253105b261ecSmrg 253205b261ecSmrg/* 253305b261ecSmrg * IDLETIME implementation 253405b261ecSmrg */ 253505b261ecSmrg 253645801275Sjmcneillstatic SyncCounter *IdleTimeCounter; 253705b261ecSmrgstatic XSyncValue *pIdleTimeValueLess; 253805b261ecSmrgstatic XSyncValue *pIdleTimeValueGreater; 253905b261ecSmrg 254005b261ecSmrgstatic void 254105b261ecSmrgIdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 254205b261ecSmrg{ 254305b261ecSmrg CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 254405b261ecSmrg XSyncIntsToValue (pValue_return, idle, 0); 254505b261ecSmrg} 254605b261ecSmrg 254705b261ecSmrgstatic void 254845801275SjmcneillIdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) 254905b261ecSmrg{ 255045801275Sjmcneill XSyncValue idle, old_idle; 255145801275Sjmcneill SyncTriggerList *list = IdleTimeCounter->pTriglist; 255245801275Sjmcneill SyncTrigger *trig; 255305b261ecSmrg 255405b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 255505b261ecSmrg return; 255605b261ecSmrg 255745801275Sjmcneill old_idle = IdleTimeCounter->value; 255805b261ecSmrg IdleTimeQueryValue (NULL, &idle); 255945801275Sjmcneill IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ 256005b261ecSmrg 256105b261ecSmrg if (pIdleTimeValueLess && 256205b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 256305b261ecSmrg { 256445801275Sjmcneill /* 256545801275Sjmcneill * We've been idle for less than the threshold value, and someone 256645801275Sjmcneill * wants to know about that, but now we need to know whether they 256745801275Sjmcneill * want level or edge trigger. Check the trigger list against the 256845801275Sjmcneill * current idle time, and if any succeed, bomb out of select() 256945801275Sjmcneill * immediately so we can reschedule. 257045801275Sjmcneill */ 257145801275Sjmcneill 257245801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 257345801275Sjmcneill trig = list->pTrigger; 257445801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 257545801275Sjmcneill AdjustWaitForDelay(wt, 0); 257645801275Sjmcneill break; 257745801275Sjmcneill } 257845801275Sjmcneill } 257905b261ecSmrg } 258005b261ecSmrg else if (pIdleTimeValueGreater) 258105b261ecSmrg { 258245801275Sjmcneill /* 258345801275Sjmcneill * There's a threshold in the positive direction. If we've been 258445801275Sjmcneill * idle less than it, schedule a wakeup for sometime in the future. 258545801275Sjmcneill * If we've been idle more than it, and someone wants to know about 258645801275Sjmcneill * that level-triggered, schedule an immediate wakeup. 258745801275Sjmcneill */ 258845801275Sjmcneill unsigned long timeout = -1; 258905b261ecSmrg 259045801275Sjmcneill if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { 259105b261ecSmrg XSyncValue value; 259205b261ecSmrg Bool overflow; 259305b261ecSmrg 259405b261ecSmrg XSyncValueSubtract (&value, *pIdleTimeValueGreater, 259505b261ecSmrg idle, &overflow); 259645801275Sjmcneill timeout = min(timeout, XSyncValueLow32 (value)); 259745801275Sjmcneill } else { 259845801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 259945801275Sjmcneill trig = list->pTrigger; 260045801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 260145801275Sjmcneill timeout = min(timeout, 0); 260245801275Sjmcneill break; 260345801275Sjmcneill } 260445801275Sjmcneill } 260505b261ecSmrg } 260605b261ecSmrg 260705b261ecSmrg AdjustWaitForDelay (wt, timeout); 260805b261ecSmrg } 260945801275Sjmcneill 261045801275Sjmcneill IdleTimeCounter->value = old_idle; /* pop */ 261105b261ecSmrg} 261205b261ecSmrg 261305b261ecSmrgstatic void 261405b261ecSmrgIdleTimeWakeupHandler (pointer env, 261505b261ecSmrg int rc, 261605b261ecSmrg pointer LastSelectMask) 261705b261ecSmrg{ 261805b261ecSmrg XSyncValue idle; 261905b261ecSmrg 262005b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 262105b261ecSmrg return; 262205b261ecSmrg 262305b261ecSmrg IdleTimeQueryValue (NULL, &idle); 262405b261ecSmrg 262505b261ecSmrg if ((pIdleTimeValueGreater && 262605b261ecSmrg XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || 262705b261ecSmrg (pIdleTimeValueLess && 262805b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) 262905b261ecSmrg { 263005b261ecSmrg SyncChangeCounter (IdleTimeCounter, idle); 263105b261ecSmrg } 263205b261ecSmrg} 263305b261ecSmrg 263405b261ecSmrgstatic void 263505b261ecSmrgIdleTimeBracketValues (pointer pCounter, 263605b261ecSmrg CARD64 *pbracket_less, 263705b261ecSmrg CARD64 *pbracket_greater) 263805b261ecSmrg{ 263905b261ecSmrg Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); 264005b261ecSmrg 264105b261ecSmrg if (registered && !pbracket_less && !pbracket_greater) 264205b261ecSmrg { 264305b261ecSmrg RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 264405b261ecSmrg IdleTimeWakeupHandler, 264505b261ecSmrg NULL); 264605b261ecSmrg } 264705b261ecSmrg else if (!registered && (pbracket_less || pbracket_greater)) 264805b261ecSmrg { 264905b261ecSmrg RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 265005b261ecSmrg IdleTimeWakeupHandler, 265105b261ecSmrg NULL); 265205b261ecSmrg } 265305b261ecSmrg 265405b261ecSmrg pIdleTimeValueGreater = pbracket_greater; 265505b261ecSmrg pIdleTimeValueLess = pbracket_less; 265605b261ecSmrg} 265705b261ecSmrg 265805b261ecSmrgstatic void 265905b261ecSmrgSyncInitIdleTime (void) 266005b261ecSmrg{ 266105b261ecSmrg CARD64 resolution; 266205b261ecSmrg XSyncValue idle; 266305b261ecSmrg 266405b261ecSmrg IdleTimeQueryValue (NULL, &idle); 266505b261ecSmrg XSyncIntToValue (&resolution, 4); 266605b261ecSmrg 266705b261ecSmrg IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, 266805b261ecSmrg XSyncCounterUnrestricted, 266905b261ecSmrg IdleTimeQueryValue, 267005b261ecSmrg IdleTimeBracketValues); 267105b261ecSmrg 267205b261ecSmrg pIdleTimeValueLess = pIdleTimeValueGreater = NULL; 267305b261ecSmrg} 2674