sync.c revision a0d10bb6
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 } 1171a0d10bb6Smrg else if (pTrigger->test_type == XSyncNegativeTransition && 117205b261ecSmrg ct != XSyncCounterNeverIncreases) 1173a0d10bb6Smrg { 1174a0d10bb6Smrg if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && 1175a0d10bb6Smrg XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) 1176a0d10bb6Smrg { 1177a0d10bb6Smrg psci->bracket_less = pTrigger->test_value; 1178a0d10bb6Smrg pnewltval = &psci->bracket_less; 1179a0d10bb6Smrg } 1180a0d10bb6Smrg } 1181a0d10bb6Smrg else if (pTrigger->test_type == XSyncPositiveTransition && 118205b261ecSmrg ct != XSyncCounterNeverDecreases) 118305b261ecSmrg { 1184a0d10bb6Smrg if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && 1185a0d10bb6Smrg XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) 118605b261ecSmrg { 1187a0d10bb6Smrg psci->bracket_greater = pTrigger->test_value; 1188a0d10bb6Smrg pnewgtval = &psci->bracket_greater; 118905b261ecSmrg } 119005b261ecSmrg } 119105b261ecSmrg } /* end for each trigger */ 119205b261ecSmrg 119305b261ecSmrg if (pnewgtval || pnewltval) 119405b261ecSmrg { 119505b261ecSmrg (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); 119605b261ecSmrg } 119705b261ecSmrg} 119805b261ecSmrg 119905b261ecSmrg/* 120005b261ecSmrg * ***** Resource delete functions 120105b261ecSmrg */ 120205b261ecSmrg 120305b261ecSmrg/* ARGSUSED */ 120405b261ecSmrgstatic int 120505b261ecSmrgFreeAlarm(addr, id) 120605b261ecSmrg pointer addr; 120705b261ecSmrg XID id; 120805b261ecSmrg{ 120905b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *) addr; 121005b261ecSmrg 121105b261ecSmrg pAlarm->state = XSyncAlarmDestroyed; 121205b261ecSmrg 121305b261ecSmrg SyncSendAlarmNotifyEvents(pAlarm); 121405b261ecSmrg 121505b261ecSmrg /* delete event selections */ 121605b261ecSmrg 121705b261ecSmrg while (pAlarm->pEventClients) 121805b261ecSmrg FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); 121905b261ecSmrg 122005b261ecSmrg SyncDeleteTriggerFromCounter(&pAlarm->trigger); 122105b261ecSmrg 122205b261ecSmrg xfree(pAlarm); 122305b261ecSmrg return Success; 122405b261ecSmrg} 122505b261ecSmrg 122605b261ecSmrg 122705b261ecSmrg/* 122805b261ecSmrg * ** Cleanup after the destruction of a Counter 122905b261ecSmrg */ 123005b261ecSmrg/* ARGSUSED */ 123105b261ecSmrgstatic int 123205b261ecSmrgFreeCounter(env, id) 123305b261ecSmrg pointer env; 123405b261ecSmrg XID id; 123505b261ecSmrg{ 123605b261ecSmrg SyncCounter *pCounter = (SyncCounter *) env; 123705b261ecSmrg SyncTriggerList *ptl, *pnext; 123805b261ecSmrg 123905b261ecSmrg pCounter->beingDestroyed = TRUE; 124005b261ecSmrg /* tell all the counter's triggers that the counter has been destroyed */ 124105b261ecSmrg for (ptl = pCounter->pTriglist; ptl; ptl = pnext) 124205b261ecSmrg { 124305b261ecSmrg (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); 124405b261ecSmrg pnext = ptl->next; 124505b261ecSmrg xfree(ptl); /* destroy the trigger list as we go */ 124605b261ecSmrg } 124705b261ecSmrg if (IsSystemCounter(pCounter)) 124805b261ecSmrg { 124905b261ecSmrg int i, found = 0; 125005b261ecSmrg 125105b261ecSmrg xfree(pCounter->pSysCounterInfo); 125205b261ecSmrg 125305b261ecSmrg /* find the counter in the list of system counters and remove it */ 125405b261ecSmrg 125505b261ecSmrg if (SysCounterList) 125605b261ecSmrg { 125705b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 125805b261ecSmrg { 125905b261ecSmrg if (SysCounterList[i] == pCounter) 126005b261ecSmrg { 126105b261ecSmrg found = i; 126205b261ecSmrg break; 126305b261ecSmrg } 126405b261ecSmrg } 126505b261ecSmrg if (found < (SyncNumSystemCounters-1)) 126605b261ecSmrg { 126705b261ecSmrg for (i = found; i < SyncNumSystemCounters-1; i++) 126805b261ecSmrg { 126905b261ecSmrg SysCounterList[i] = SysCounterList[i+1]; 127005b261ecSmrg } 127105b261ecSmrg } 127205b261ecSmrg } 127305b261ecSmrg SyncNumSystemCounters--; 127405b261ecSmrg } 127505b261ecSmrg xfree(pCounter); 127605b261ecSmrg return Success; 127705b261ecSmrg} 127805b261ecSmrg 127905b261ecSmrg/* 128005b261ecSmrg * ** Cleanup after Await 128105b261ecSmrg */ 128205b261ecSmrg/* ARGSUSED */ 128305b261ecSmrgstatic int 128405b261ecSmrgFreeAwait(addr, id) 128505b261ecSmrg pointer addr; 128605b261ecSmrg XID id; 128705b261ecSmrg{ 128805b261ecSmrg SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; 128905b261ecSmrg SyncAwait *pAwait; 129005b261ecSmrg int numwaits; 129105b261ecSmrg 129205b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* first await on list */ 129305b261ecSmrg 129405b261ecSmrg /* remove triggers from counters */ 129505b261ecSmrg 129605b261ecSmrg for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; 129705b261ecSmrg numwaits--, pAwait++) 129805b261ecSmrg { 129905b261ecSmrg /* If the counter is being destroyed, FreeCounter will delete 130005b261ecSmrg * the trigger list itself, so don't do it here. 130105b261ecSmrg */ 130205b261ecSmrg SyncCounter *pCounter = pAwait->trigger.pCounter; 130305b261ecSmrg if (pCounter && !pCounter->beingDestroyed) 130405b261ecSmrg SyncDeleteTriggerFromCounter(&pAwait->trigger); 130505b261ecSmrg } 130605b261ecSmrg xfree(pAwaitUnion); 130705b261ecSmrg return Success; 130805b261ecSmrg} 130905b261ecSmrg 131005b261ecSmrg/* loosely based on dix/events.c/OtherClientGone */ 131105b261ecSmrgstatic int 131205b261ecSmrgFreeAlarmClient(value, id) 131305b261ecSmrg pointer value; /* must conform to DeleteType */ 131405b261ecSmrg XID id; 131505b261ecSmrg{ 131605b261ecSmrg SyncAlarm *pAlarm = (SyncAlarm *)value; 131705b261ecSmrg SyncAlarmClientList *pCur, *pPrev; 131805b261ecSmrg 131905b261ecSmrg for (pPrev = NULL, pCur = pAlarm->pEventClients; 132005b261ecSmrg pCur; 132105b261ecSmrg pPrev = pCur, pCur = pCur->next) 132205b261ecSmrg { 132305b261ecSmrg if (pCur->delete_id == id) 132405b261ecSmrg { 132505b261ecSmrg if (pPrev) 132605b261ecSmrg pPrev->next = pCur->next; 132705b261ecSmrg else 132805b261ecSmrg pAlarm->pEventClients = pCur->next; 132905b261ecSmrg xfree(pCur); 133005b261ecSmrg return(Success); 133105b261ecSmrg } 133205b261ecSmrg } 133305b261ecSmrg FatalError("alarm client not on event list"); 133405b261ecSmrg /*NOTREACHED*/ 133505b261ecSmrg} 133605b261ecSmrg 133705b261ecSmrg 133805b261ecSmrg/* 133905b261ecSmrg * ***** Proc functions 134005b261ecSmrg */ 134105b261ecSmrg 134205b261ecSmrg 134305b261ecSmrg/* 134405b261ecSmrg * ** Initialize the extension 134505b261ecSmrg */ 134605b261ecSmrgstatic int 134705b261ecSmrgProcSyncInitialize(client) 134805b261ecSmrg ClientPtr client; 134905b261ecSmrg{ 135005b261ecSmrg xSyncInitializeReply rep; 135105b261ecSmrg int n; 135205b261ecSmrg 135305b261ecSmrg REQUEST_SIZE_MATCH(xSyncInitializeReq); 135405b261ecSmrg 135505b261ecSmrg rep.type = X_Reply; 135605b261ecSmrg rep.sequenceNumber = client->sequence; 135705b261ecSmrg rep.majorVersion = SYNC_MAJOR_VERSION; 135805b261ecSmrg rep.minorVersion = SYNC_MINOR_VERSION; 135905b261ecSmrg rep.length = 0; 136005b261ecSmrg 136105b261ecSmrg if (client->swapped) 136205b261ecSmrg { 136305b261ecSmrg swaps(&rep.sequenceNumber, n); 136405b261ecSmrg } 136505b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 136605b261ecSmrg return (client->noClientException); 136705b261ecSmrg} 136805b261ecSmrg 136905b261ecSmrg/* 137005b261ecSmrg * ** Get list of system counters available through the extension 137105b261ecSmrg */ 137205b261ecSmrgstatic int 137305b261ecSmrgProcSyncListSystemCounters(client) 137405b261ecSmrg ClientPtr client; 137505b261ecSmrg{ 137605b261ecSmrg xSyncListSystemCountersReply rep; 137705b261ecSmrg int i, len; 137805b261ecSmrg xSyncSystemCounter *list = NULL, *walklist = NULL; 137905b261ecSmrg 138005b261ecSmrg REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); 138105b261ecSmrg 138205b261ecSmrg rep.type = X_Reply; 138305b261ecSmrg rep.sequenceNumber = client->sequence; 138405b261ecSmrg rep.nCounters = SyncNumSystemCounters; 138505b261ecSmrg 138605b261ecSmrg for (i = len = 0; i < SyncNumSystemCounters; i++) 138705b261ecSmrg { 138805b261ecSmrg char *name = SysCounterList[i]->pSysCounterInfo->name; 138905b261ecSmrg /* pad to 4 byte boundary */ 139005b261ecSmrg len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3; 139105b261ecSmrg } 139205b261ecSmrg 139305b261ecSmrg if (len) 139405b261ecSmrg { 1395637ac9abSmrg walklist = list = (xSyncSystemCounter *) xalloc(len); 139605b261ecSmrg if (!list) 139705b261ecSmrg return BadAlloc; 139805b261ecSmrg } 139905b261ecSmrg 140005b261ecSmrg rep.length = len >> 2; 140105b261ecSmrg 140205b261ecSmrg if (client->swapped) 140305b261ecSmrg { 1404637ac9abSmrg char n; 140505b261ecSmrg swaps(&rep.sequenceNumber, n); 140605b261ecSmrg swapl(&rep.length, n); 140705b261ecSmrg swapl(&rep.nCounters, n); 140805b261ecSmrg } 140905b261ecSmrg 141005b261ecSmrg for (i = 0; i < SyncNumSystemCounters; i++) 141105b261ecSmrg { 141205b261ecSmrg int namelen; 141305b261ecSmrg char *pname_in_reply; 141405b261ecSmrg SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; 141505b261ecSmrg 141605b261ecSmrg walklist->counter = SysCounterList[i]->id; 141705b261ecSmrg walklist->resolution_hi = XSyncValueHigh32(psci->resolution); 141805b261ecSmrg walklist->resolution_lo = XSyncValueLow32(psci->resolution); 141905b261ecSmrg namelen = strlen(psci->name); 142005b261ecSmrg walklist->name_length = namelen; 142105b261ecSmrg 142205b261ecSmrg if (client->swapped) 142305b261ecSmrg { 1424637ac9abSmrg char n; 142505b261ecSmrg swapl(&walklist->counter, n); 142605b261ecSmrg swapl(&walklist->resolution_hi, n); 142705b261ecSmrg swapl(&walklist->resolution_lo, n); 142805b261ecSmrg swaps(&walklist->name_length, n); 142905b261ecSmrg } 143005b261ecSmrg 143105b261ecSmrg pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; 143205b261ecSmrg strncpy(pname_in_reply, psci->name, namelen); 143305b261ecSmrg walklist = (xSyncSystemCounter *) (((char *)walklist) + 143405b261ecSmrg ((sz_xSyncSystemCounter + namelen + 3) & ~3)); 143505b261ecSmrg } 143605b261ecSmrg 143705b261ecSmrg WriteToClient(client, sizeof(rep), (char *) &rep); 143805b261ecSmrg if (len) 143905b261ecSmrg { 144005b261ecSmrg WriteToClient(client, len, (char *) list); 1441637ac9abSmrg xfree(list); 144205b261ecSmrg } 144305b261ecSmrg 144405b261ecSmrg return (client->noClientException); 144505b261ecSmrg} 144605b261ecSmrg 144705b261ecSmrg/* 144805b261ecSmrg * ** Set client Priority 144905b261ecSmrg */ 145005b261ecSmrgstatic int 145105b261ecSmrgProcSyncSetPriority(client) 145205b261ecSmrg ClientPtr client; 145305b261ecSmrg{ 145405b261ecSmrg REQUEST(xSyncSetPriorityReq); 145505b261ecSmrg ClientPtr priorityclient; 145605b261ecSmrg int rc; 145705b261ecSmrg 145805b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetPriorityReq); 145905b261ecSmrg 146005b261ecSmrg if (stuff->id == None) 146105b261ecSmrg priorityclient = client; 146205b261ecSmrg else { 146305b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1464637ac9abSmrg DixSetAttrAccess); 146505b261ecSmrg if (rc != Success) 146605b261ecSmrg return rc; 146705b261ecSmrg } 146805b261ecSmrg 146905b261ecSmrg if (priorityclient->priority != stuff->priority) 147005b261ecSmrg { 147105b261ecSmrg priorityclient->priority = stuff->priority; 147205b261ecSmrg 147305b261ecSmrg /* The following will force the server back into WaitForSomething 147405b261ecSmrg * so that the change in this client's priority is immediately 147505b261ecSmrg * reflected. 147605b261ecSmrg */ 147705b261ecSmrg isItTimeToYield = TRUE; 147805b261ecSmrg dispatchException |= DE_PRIORITYCHANGE; 147905b261ecSmrg } 148005b261ecSmrg return Success; 148105b261ecSmrg} 148205b261ecSmrg 148305b261ecSmrg/* 148405b261ecSmrg * ** Get client Priority 148505b261ecSmrg */ 148605b261ecSmrgstatic int 148705b261ecSmrgProcSyncGetPriority(client) 148805b261ecSmrg ClientPtr client; 148905b261ecSmrg{ 149005b261ecSmrg REQUEST(xSyncGetPriorityReq); 149105b261ecSmrg xSyncGetPriorityReply rep; 149205b261ecSmrg ClientPtr priorityclient; 149305b261ecSmrg int rc; 149405b261ecSmrg 149505b261ecSmrg REQUEST_SIZE_MATCH(xSyncGetPriorityReq); 149605b261ecSmrg 149705b261ecSmrg if (stuff->id == None) 149805b261ecSmrg priorityclient = client; 149905b261ecSmrg else { 150005b261ecSmrg rc = dixLookupClient(&priorityclient, stuff->id, client, 1501637ac9abSmrg DixGetAttrAccess); 150205b261ecSmrg if (rc != Success) 150305b261ecSmrg return rc; 150405b261ecSmrg } 150505b261ecSmrg 150605b261ecSmrg rep.type = X_Reply; 150705b261ecSmrg rep.length = 0; 150805b261ecSmrg rep.sequenceNumber = client->sequence; 150905b261ecSmrg rep.priority = priorityclient->priority; 151005b261ecSmrg 151105b261ecSmrg if (client->swapped) 151205b261ecSmrg { 1513637ac9abSmrg char n; 151405b261ecSmrg swaps(&rep.sequenceNumber, n); 151505b261ecSmrg swapl(&rep.priority, n); 151605b261ecSmrg } 151705b261ecSmrg 151805b261ecSmrg WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); 151905b261ecSmrg 152005b261ecSmrg return (client->noClientException); 152105b261ecSmrg} 152205b261ecSmrg 152305b261ecSmrg/* 152405b261ecSmrg * ** Create a new counter 152505b261ecSmrg */ 152605b261ecSmrgstatic int 152705b261ecSmrgProcSyncCreateCounter(client) 152805b261ecSmrg ClientPtr client; 152905b261ecSmrg{ 153005b261ecSmrg REQUEST(xSyncCreateCounterReq); 153105b261ecSmrg CARD64 initial; 153205b261ecSmrg 153305b261ecSmrg REQUEST_SIZE_MATCH(xSyncCreateCounterReq); 153405b261ecSmrg 153505b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 153605b261ecSmrg 153705b261ecSmrg XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); 153805b261ecSmrg if (!SyncCreateCounter(client, stuff->cid, initial)) 153905b261ecSmrg return BadAlloc; 154005b261ecSmrg 154105b261ecSmrg return (client->noClientException); 154205b261ecSmrg} 154305b261ecSmrg 154405b261ecSmrg/* 154505b261ecSmrg * ** Set Counter value 154605b261ecSmrg */ 154705b261ecSmrgstatic int 154805b261ecSmrgProcSyncSetCounter(client) 154905b261ecSmrg ClientPtr client; 155005b261ecSmrg{ 155105b261ecSmrg REQUEST(xSyncSetCounterReq); 155205b261ecSmrg SyncCounter *pCounter; 155305b261ecSmrg CARD64 newvalue; 155405b261ecSmrg 155505b261ecSmrg REQUEST_SIZE_MATCH(xSyncSetCounterReq); 155605b261ecSmrg 155705b261ecSmrg pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid, 155805b261ecSmrg RTCounter, DixWriteAccess); 155905b261ecSmrg if (pCounter == NULL) 156005b261ecSmrg { 156105b261ecSmrg client->errorValue = stuff->cid; 156205b261ecSmrg return SyncErrorBase + XSyncBadCounter; 156305b261ecSmrg } 156405b261ecSmrg 156505b261ecSmrg if (IsSystemCounter(pCounter)) 156605b261ecSmrg { 156705b261ecSmrg client->errorValue = stuff->cid; 156805b261ecSmrg return BadAccess; 156905b261ecSmrg } 157005b261ecSmrg 157105b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 157205b261ecSmrg SyncChangeCounter(pCounter, newvalue); 157305b261ecSmrg return Success; 157405b261ecSmrg} 157505b261ecSmrg 157605b261ecSmrg/* 157705b261ecSmrg * ** Change Counter value 157805b261ecSmrg */ 157905b261ecSmrgstatic int 158005b261ecSmrgProcSyncChangeCounter(client) 158105b261ecSmrg ClientPtr client; 158205b261ecSmrg{ 158305b261ecSmrg REQUEST(xSyncChangeCounterReq); 158405b261ecSmrg SyncCounter *pCounter; 158505b261ecSmrg CARD64 newvalue; 158605b261ecSmrg Bool overflow; 158705b261ecSmrg 158805b261ecSmrg REQUEST_SIZE_MATCH(xSyncChangeCounterReq); 158905b261ecSmrg 159005b261ecSmrg pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, 159105b261ecSmrg RTCounter, DixWriteAccess); 159205b261ecSmrg if (pCounter == NULL) 159305b261ecSmrg { 159405b261ecSmrg client->errorValue = stuff->cid; 159505b261ecSmrg return SyncErrorBase + XSyncBadCounter; 159605b261ecSmrg } 159705b261ecSmrg 159805b261ecSmrg if (IsSystemCounter(pCounter)) 159905b261ecSmrg { 160005b261ecSmrg client->errorValue = stuff->cid; 160105b261ecSmrg return BadAccess; 160205b261ecSmrg } 160305b261ecSmrg 160405b261ecSmrg XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); 160505b261ecSmrg XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); 160605b261ecSmrg if (overflow) 160705b261ecSmrg { 160805b261ecSmrg /* XXX 64 bit value can't fit in 32 bits; do the best we can */ 160905b261ecSmrg client->errorValue = stuff->value_hi; 161005b261ecSmrg return BadValue; 161105b261ecSmrg } 161205b261ecSmrg SyncChangeCounter(pCounter, newvalue); 161305b261ecSmrg return Success; 161405b261ecSmrg} 161505b261ecSmrg 161605b261ecSmrg/* 161705b261ecSmrg * ** Destroy a counter 161805b261ecSmrg */ 161905b261ecSmrgstatic int 162005b261ecSmrgProcSyncDestroyCounter(client) 162105b261ecSmrg ClientPtr client; 162205b261ecSmrg{ 162305b261ecSmrg REQUEST(xSyncDestroyCounterReq); 162405b261ecSmrg SyncCounter *pCounter; 162505b261ecSmrg 162605b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); 162705b261ecSmrg 162805b261ecSmrg pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, 162905b261ecSmrg RTCounter, DixDestroyAccess); 163005b261ecSmrg if (pCounter == NULL) 163105b261ecSmrg { 163205b261ecSmrg client->errorValue = stuff->counter; 163305b261ecSmrg return SyncErrorBase + XSyncBadCounter; 163405b261ecSmrg } 163505b261ecSmrg if (IsSystemCounter(pCounter)) 163605b261ecSmrg { 163705b261ecSmrg client->errorValue = stuff->counter; 163805b261ecSmrg return BadAccess; 163905b261ecSmrg } 164005b261ecSmrg FreeResource(pCounter->id, RT_NONE); 164105b261ecSmrg return Success; 164205b261ecSmrg} 164305b261ecSmrg 164405b261ecSmrg 164505b261ecSmrg/* 164605b261ecSmrg * ** Await 164705b261ecSmrg */ 164805b261ecSmrgstatic int 164905b261ecSmrgProcSyncAwait(client) 165005b261ecSmrg ClientPtr client; 165105b261ecSmrg{ 165205b261ecSmrg REQUEST(xSyncAwaitReq); 165305b261ecSmrg int len, items; 165405b261ecSmrg int i; 165505b261ecSmrg xSyncWaitCondition *pProtocolWaitConds; 165605b261ecSmrg SyncAwaitUnion *pAwaitUnion; 165705b261ecSmrg SyncAwait *pAwait; 165805b261ecSmrg int status; 165905b261ecSmrg 166005b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 166105b261ecSmrg 166205b261ecSmrg len = client->req_len << 2; 166305b261ecSmrg len -= sz_xSyncAwaitReq; 166405b261ecSmrg items = len / sz_xSyncWaitCondition; 166505b261ecSmrg 166605b261ecSmrg if (items * sz_xSyncWaitCondition != len) 166705b261ecSmrg { 166805b261ecSmrg return BadLength; 166905b261ecSmrg } 167005b261ecSmrg if (items == 0) 167105b261ecSmrg { 167205b261ecSmrg client->errorValue = items; /* XXX protocol change */ 167305b261ecSmrg return BadValue; 167405b261ecSmrg } 167505b261ecSmrg 167605b261ecSmrg pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; 167705b261ecSmrg 167805b261ecSmrg /* all the memory for the entire await list is allocated 167905b261ecSmrg * here in one chunk 168005b261ecSmrg */ 168105b261ecSmrg pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion)); 168205b261ecSmrg if (!pAwaitUnion) 168305b261ecSmrg return BadAlloc; 168405b261ecSmrg 168505b261ecSmrg /* first item is the header, remainder are real wait conditions */ 168605b261ecSmrg 168705b261ecSmrg pAwaitUnion->header.delete_id = FakeClientID(client->index); 168805b261ecSmrg if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) 168905b261ecSmrg { 169005b261ecSmrg xfree(pAwaitUnion); 169105b261ecSmrg return BadAlloc; 169205b261ecSmrg } 169305b261ecSmrg 169405b261ecSmrg /* don't need to do any more memory allocation for this request! */ 169505b261ecSmrg 169605b261ecSmrg pAwaitUnion->header.client = client; 169705b261ecSmrg pAwaitUnion->header.num_waitconditions = 0; 169805b261ecSmrg 169905b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 170005b261ecSmrg for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) 170105b261ecSmrg { 170205b261ecSmrg if (pProtocolWaitConds->counter == None) /* XXX protocol change */ 170305b261ecSmrg { 170405b261ecSmrg /* this should take care of removing any triggers created by 170505b261ecSmrg * this request that have already been registered on counters 170605b261ecSmrg */ 170705b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 170805b261ecSmrg client->errorValue = pProtocolWaitConds->counter; 170905b261ecSmrg return SyncErrorBase + XSyncBadCounter; 171005b261ecSmrg } 171105b261ecSmrg 171205b261ecSmrg /* sanity checks are in SyncInitTrigger */ 171305b261ecSmrg pAwait->trigger.pCounter = NULL; 171405b261ecSmrg pAwait->trigger.value_type = pProtocolWaitConds->value_type; 171505b261ecSmrg XSyncIntsToValue(&pAwait->trigger.wait_value, 171605b261ecSmrg pProtocolWaitConds->wait_value_lo, 171705b261ecSmrg pProtocolWaitConds->wait_value_hi); 171805b261ecSmrg pAwait->trigger.test_type = pProtocolWaitConds->test_type; 171905b261ecSmrg 172005b261ecSmrg status = SyncInitTrigger(client, &pAwait->trigger, 172105b261ecSmrg pProtocolWaitConds->counter, XSyncCAAllTrigger); 172205b261ecSmrg if (status != Success) 172305b261ecSmrg { 172405b261ecSmrg /* this should take care of removing any triggers created by 172505b261ecSmrg * this request that have already been registered on counters 172605b261ecSmrg */ 172705b261ecSmrg FreeResource(pAwaitUnion->header.delete_id, RT_NONE); 172805b261ecSmrg return status; 172905b261ecSmrg } 173005b261ecSmrg /* this is not a mistake -- same function works for both cases */ 173105b261ecSmrg pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; 173205b261ecSmrg pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; 173305b261ecSmrg XSyncIntsToValue(&pAwait->event_threshold, 173405b261ecSmrg pProtocolWaitConds->event_threshold_lo, 173505b261ecSmrg pProtocolWaitConds->event_threshold_hi); 173605b261ecSmrg pAwait->pHeader = &pAwaitUnion->header; 173705b261ecSmrg pAwaitUnion->header.num_waitconditions++; 173805b261ecSmrg } 173905b261ecSmrg 174005b261ecSmrg IgnoreClient(client); 174105b261ecSmrg 174205b261ecSmrg /* see if any of the triggers are already true */ 174305b261ecSmrg 174405b261ecSmrg pAwait = &(pAwaitUnion+1)->await; /* skip over header */ 174505b261ecSmrg for (i = 0; i < items; i++, pAwait++) 174605b261ecSmrg { 174705b261ecSmrg /* don't have to worry about NULL counters because the request 174805b261ecSmrg * errors before we get here out if they occur 174905b261ecSmrg */ 175005b261ecSmrg if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, 175105b261ecSmrg pAwait->trigger.pCounter->value)) 175205b261ecSmrg { 175305b261ecSmrg (*pAwait->trigger.TriggerFired)(&pAwait->trigger); 175405b261ecSmrg break; /* once is enough */ 175505b261ecSmrg } 175605b261ecSmrg } 175705b261ecSmrg return Success; 175805b261ecSmrg} 175905b261ecSmrg 176005b261ecSmrg 176105b261ecSmrg/* 176205b261ecSmrg * ** Query a counter 176305b261ecSmrg */ 176405b261ecSmrgstatic int 176505b261ecSmrgProcSyncQueryCounter(client) 176605b261ecSmrg ClientPtr client; 176705b261ecSmrg{ 176805b261ecSmrg REQUEST(xSyncQueryCounterReq); 176905b261ecSmrg xSyncQueryCounterReply rep; 177005b261ecSmrg SyncCounter *pCounter; 177105b261ecSmrg 177205b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryCounterReq); 177305b261ecSmrg 177405b261ecSmrg pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter, 177505b261ecSmrg RTCounter, DixReadAccess); 177605b261ecSmrg if (pCounter == NULL) 177705b261ecSmrg { 177805b261ecSmrg client->errorValue = stuff->counter; 177905b261ecSmrg return SyncErrorBase + XSyncBadCounter; 178005b261ecSmrg } 178105b261ecSmrg 178205b261ecSmrg rep.type = X_Reply; 178305b261ecSmrg rep.length = 0; 178405b261ecSmrg rep.sequenceNumber = client->sequence; 178505b261ecSmrg 178605b261ecSmrg /* if system counter, ask it what the current value is */ 178705b261ecSmrg 178805b261ecSmrg if (IsSystemCounter(pCounter)) 178905b261ecSmrg { 179005b261ecSmrg (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, 179105b261ecSmrg &pCounter->value); 179205b261ecSmrg } 179305b261ecSmrg 179405b261ecSmrg rep.value_hi = XSyncValueHigh32(pCounter->value); 179505b261ecSmrg rep.value_lo = XSyncValueLow32(pCounter->value); 179605b261ecSmrg if (client->swapped) 179705b261ecSmrg { 1798637ac9abSmrg char n; 179905b261ecSmrg swaps(&rep.sequenceNumber, n); 180005b261ecSmrg swapl(&rep.length, n); 180105b261ecSmrg swapl(&rep.value_hi, n); 180205b261ecSmrg swapl(&rep.value_lo, n); 180305b261ecSmrg } 180405b261ecSmrg WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); 180505b261ecSmrg return (client->noClientException); 180605b261ecSmrg} 180705b261ecSmrg 180805b261ecSmrg 180905b261ecSmrg/* 181005b261ecSmrg * ** Create Alarm 181105b261ecSmrg */ 181205b261ecSmrgstatic int 181305b261ecSmrgProcSyncCreateAlarm(client) 181405b261ecSmrg ClientPtr client; 181505b261ecSmrg{ 181605b261ecSmrg REQUEST(xSyncCreateAlarmReq); 181705b261ecSmrg SyncAlarm *pAlarm; 181805b261ecSmrg int status; 181905b261ecSmrg unsigned long len, vmask; 182005b261ecSmrg SyncTrigger *pTrigger; 182105b261ecSmrg 182205b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 182305b261ecSmrg 182405b261ecSmrg LEGAL_NEW_RESOURCE(stuff->id, client); 182505b261ecSmrg 182605b261ecSmrg vmask = stuff->valueMask; 182705b261ecSmrg len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2); 182805b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 182905b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 183005b261ecSmrg return BadLength; 183105b261ecSmrg 183205b261ecSmrg if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm)))) 183305b261ecSmrg { 183405b261ecSmrg return BadAlloc; 183505b261ecSmrg } 183605b261ecSmrg 183705b261ecSmrg /* set up defaults */ 183805b261ecSmrg 183905b261ecSmrg pTrigger = &pAlarm->trigger; 184005b261ecSmrg pTrigger->pCounter = NULL; 184105b261ecSmrg pTrigger->value_type = XSyncAbsolute; 184205b261ecSmrg XSyncIntToValue(&pTrigger->wait_value, 0L); 184305b261ecSmrg pTrigger->test_type = XSyncPositiveComparison; 184405b261ecSmrg pTrigger->TriggerFired = SyncAlarmTriggerFired; 184505b261ecSmrg pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; 184605b261ecSmrg status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); 184705b261ecSmrg if (status != Success) 184805b261ecSmrg { 184905b261ecSmrg xfree(pAlarm); 185005b261ecSmrg return status; 185105b261ecSmrg } 185205b261ecSmrg 185305b261ecSmrg pAlarm->client = client; 185405b261ecSmrg pAlarm->alarm_id = stuff->id; 185505b261ecSmrg XSyncIntToValue(&pAlarm->delta, 1L); 185605b261ecSmrg pAlarm->events = TRUE; 185705b261ecSmrg pAlarm->state = XSyncAlarmInactive; 185805b261ecSmrg pAlarm->pEventClients = NULL; 185905b261ecSmrg status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 186005b261ecSmrg (CARD32 *)&stuff[1]); 186105b261ecSmrg if (status != Success) 186205b261ecSmrg { 186305b261ecSmrg xfree(pAlarm); 186405b261ecSmrg return status; 186505b261ecSmrg } 186605b261ecSmrg 186705b261ecSmrg if (!AddResource(stuff->id, RTAlarm, pAlarm)) 186805b261ecSmrg { 186905b261ecSmrg xfree(pAlarm); 187005b261ecSmrg return BadAlloc; 187105b261ecSmrg } 187205b261ecSmrg 187305b261ecSmrg /* see if alarm already triggered. NULL counter will not trigger 187405b261ecSmrg * in CreateAlarm and sets alarm state to Inactive. 187505b261ecSmrg */ 187605b261ecSmrg 187705b261ecSmrg if (!pTrigger->pCounter) 187805b261ecSmrg { 187905b261ecSmrg pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ 188005b261ecSmrg } 188105b261ecSmrg else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) 188205b261ecSmrg { 188305b261ecSmrg (*pTrigger->TriggerFired)(pTrigger); 188405b261ecSmrg } 188505b261ecSmrg 188605b261ecSmrg return Success; 188705b261ecSmrg} 188805b261ecSmrg 188905b261ecSmrg/* 189005b261ecSmrg * ** Change Alarm 189105b261ecSmrg */ 189205b261ecSmrgstatic int 189305b261ecSmrgProcSyncChangeAlarm(client) 189405b261ecSmrg ClientPtr client; 189505b261ecSmrg{ 189605b261ecSmrg REQUEST(xSyncChangeAlarmReq); 189705b261ecSmrg SyncAlarm *pAlarm; 189805b261ecSmrg long vmask; 189905b261ecSmrg int len, status; 190005b261ecSmrg 190105b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 190205b261ecSmrg 190305b261ecSmrg if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 190405b261ecSmrg RTAlarm, DixWriteAccess))) 190505b261ecSmrg { 190605b261ecSmrg client->errorValue = stuff->alarm; 190705b261ecSmrg return SyncErrorBase + XSyncBadAlarm; 190805b261ecSmrg } 190905b261ecSmrg 191005b261ecSmrg vmask = stuff->valueMask; 191105b261ecSmrg len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2); 191205b261ecSmrg /* the "extra" call to Ones accounts for the presence of 64 bit values */ 191305b261ecSmrg if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) 191405b261ecSmrg return BadLength; 191505b261ecSmrg 191605b261ecSmrg if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 191705b261ecSmrg (CARD32 *)&stuff[1])) != Success) 191805b261ecSmrg return status; 191905b261ecSmrg 192005b261ecSmrg /* see if alarm already triggered. NULL counter WILL trigger 192105b261ecSmrg * in ChangeAlarm. 192205b261ecSmrg */ 192305b261ecSmrg 192405b261ecSmrg if (!pAlarm->trigger.pCounter || 192505b261ecSmrg (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, 192605b261ecSmrg pAlarm->trigger.pCounter->value)) 192705b261ecSmrg { 192805b261ecSmrg (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); 192905b261ecSmrg } 193005b261ecSmrg return Success; 193105b261ecSmrg} 193205b261ecSmrg 193305b261ecSmrgstatic int 193405b261ecSmrgProcSyncQueryAlarm(client) 193505b261ecSmrg ClientPtr client; 193605b261ecSmrg{ 193705b261ecSmrg REQUEST(xSyncQueryAlarmReq); 193805b261ecSmrg SyncAlarm *pAlarm; 193905b261ecSmrg xSyncQueryAlarmReply rep; 194005b261ecSmrg SyncTrigger *pTrigger; 194105b261ecSmrg 194205b261ecSmrg REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); 194305b261ecSmrg 194405b261ecSmrg pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 194505b261ecSmrg RTAlarm, DixReadAccess); 194605b261ecSmrg if (!pAlarm) 194705b261ecSmrg { 194805b261ecSmrg client->errorValue = stuff->alarm; 194905b261ecSmrg return (SyncErrorBase + XSyncBadAlarm); 195005b261ecSmrg } 195105b261ecSmrg 195205b261ecSmrg rep.type = X_Reply; 195305b261ecSmrg rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2; 195405b261ecSmrg rep.sequenceNumber = client->sequence; 195505b261ecSmrg 195605b261ecSmrg pTrigger = &pAlarm->trigger; 195705b261ecSmrg rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; 195805b261ecSmrg 195905b261ecSmrg#if 0 /* XXX unclear what to do, depends on whether relative value-types 196005b261ecSmrg * are "consumed" immediately and are considered absolute from then 196105b261ecSmrg * on. 196205b261ecSmrg */ 196305b261ecSmrg rep.value_type = pTrigger->value_type; 196405b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); 196505b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); 196605b261ecSmrg#else 196705b261ecSmrg rep.value_type = XSyncAbsolute; 196805b261ecSmrg rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); 196905b261ecSmrg rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); 197005b261ecSmrg#endif 197105b261ecSmrg 197205b261ecSmrg rep.test_type = pTrigger->test_type; 197305b261ecSmrg rep.delta_hi = XSyncValueHigh32(pAlarm->delta); 197405b261ecSmrg rep.delta_lo = XSyncValueLow32(pAlarm->delta); 197505b261ecSmrg rep.events = pAlarm->events; 197605b261ecSmrg rep.state = pAlarm->state; 197705b261ecSmrg 197805b261ecSmrg if (client->swapped) 197905b261ecSmrg { 1980637ac9abSmrg char n; 198105b261ecSmrg swaps(&rep.sequenceNumber, n); 198205b261ecSmrg swapl(&rep.length, n); 198305b261ecSmrg swapl(&rep.counter, n); 198405b261ecSmrg swapl(&rep.wait_value_hi, n); 198505b261ecSmrg swapl(&rep.wait_value_lo, n); 198605b261ecSmrg swapl(&rep.test_type, n); 198705b261ecSmrg swapl(&rep.delta_hi, n); 198805b261ecSmrg swapl(&rep.delta_lo, n); 198905b261ecSmrg } 199005b261ecSmrg 199105b261ecSmrg WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); 199205b261ecSmrg return (client->noClientException); 199305b261ecSmrg} 199405b261ecSmrg 199505b261ecSmrg 199605b261ecSmrgstatic int 199705b261ecSmrgProcSyncDestroyAlarm(client) 199805b261ecSmrg ClientPtr client; 199905b261ecSmrg{ 200005b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 200105b261ecSmrg 200205b261ecSmrg REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); 200305b261ecSmrg 200405b261ecSmrg if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm, 200505b261ecSmrg RTAlarm, DixDestroyAccess))) 200605b261ecSmrg { 200705b261ecSmrg client->errorValue = stuff->alarm; 200805b261ecSmrg return SyncErrorBase + XSyncBadAlarm; 200905b261ecSmrg } 201005b261ecSmrg 201105b261ecSmrg FreeResource(stuff->alarm, RT_NONE); 201205b261ecSmrg return (client->noClientException); 201305b261ecSmrg} 201405b261ecSmrg 201505b261ecSmrg/* 201605b261ecSmrg * ** Given an extension request, call the appropriate request procedure 201705b261ecSmrg */ 201805b261ecSmrgstatic int 201905b261ecSmrgProcSyncDispatch(client) 202005b261ecSmrg ClientPtr client; 202105b261ecSmrg{ 202205b261ecSmrg REQUEST(xReq); 202305b261ecSmrg 202405b261ecSmrg switch (stuff->data) 202505b261ecSmrg { 202605b261ecSmrg 202705b261ecSmrg case X_SyncInitialize: 202805b261ecSmrg return ProcSyncInitialize(client); 202905b261ecSmrg case X_SyncListSystemCounters: 203005b261ecSmrg return ProcSyncListSystemCounters(client); 203105b261ecSmrg case X_SyncCreateCounter: 203205b261ecSmrg return ProcSyncCreateCounter(client); 203305b261ecSmrg case X_SyncSetCounter: 203405b261ecSmrg return ProcSyncSetCounter(client); 203505b261ecSmrg case X_SyncChangeCounter: 203605b261ecSmrg return ProcSyncChangeCounter(client); 203705b261ecSmrg case X_SyncQueryCounter: 203805b261ecSmrg return ProcSyncQueryCounter(client); 203905b261ecSmrg case X_SyncDestroyCounter: 204005b261ecSmrg return ProcSyncDestroyCounter(client); 204105b261ecSmrg case X_SyncAwait: 204205b261ecSmrg return ProcSyncAwait(client); 204305b261ecSmrg case X_SyncCreateAlarm: 204405b261ecSmrg return ProcSyncCreateAlarm(client); 204505b261ecSmrg case X_SyncChangeAlarm: 204605b261ecSmrg return ProcSyncChangeAlarm(client); 204705b261ecSmrg case X_SyncQueryAlarm: 204805b261ecSmrg return ProcSyncQueryAlarm(client); 204905b261ecSmrg case X_SyncDestroyAlarm: 205005b261ecSmrg return ProcSyncDestroyAlarm(client); 205105b261ecSmrg case X_SyncSetPriority: 205205b261ecSmrg return ProcSyncSetPriority(client); 205305b261ecSmrg case X_SyncGetPriority: 205405b261ecSmrg return ProcSyncGetPriority(client); 205505b261ecSmrg default: 205605b261ecSmrg return BadRequest; 205705b261ecSmrg } 205805b261ecSmrg} 205905b261ecSmrg 206005b261ecSmrg/* 206105b261ecSmrg * Boring Swapping stuff ... 206205b261ecSmrg */ 206305b261ecSmrg 206405b261ecSmrgstatic int 206505b261ecSmrgSProcSyncInitialize(client) 206605b261ecSmrg ClientPtr client; 206705b261ecSmrg{ 206805b261ecSmrg REQUEST(xSyncInitializeReq); 2069637ac9abSmrg char n; 207005b261ecSmrg 207105b261ecSmrg swaps(&stuff->length, n); 207205b261ecSmrg REQUEST_SIZE_MATCH (xSyncInitializeReq); 207305b261ecSmrg 207405b261ecSmrg return ProcSyncInitialize(client); 207505b261ecSmrg} 207605b261ecSmrg 207705b261ecSmrgstatic int 207805b261ecSmrgSProcSyncListSystemCounters(client) 207905b261ecSmrg ClientPtr client; 208005b261ecSmrg{ 208105b261ecSmrg REQUEST(xSyncListSystemCountersReq); 2082637ac9abSmrg char n; 208305b261ecSmrg 208405b261ecSmrg swaps(&stuff->length, n); 208505b261ecSmrg REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); 208605b261ecSmrg 208705b261ecSmrg return ProcSyncListSystemCounters(client); 208805b261ecSmrg} 208905b261ecSmrg 209005b261ecSmrgstatic int 209105b261ecSmrgSProcSyncCreateCounter(client) 209205b261ecSmrg ClientPtr client; 209305b261ecSmrg{ 209405b261ecSmrg REQUEST(xSyncCreateCounterReq); 2095637ac9abSmrg char n; 209605b261ecSmrg 209705b261ecSmrg swaps(&stuff->length, n); 209805b261ecSmrg REQUEST_SIZE_MATCH (xSyncCreateCounterReq); 209905b261ecSmrg swapl(&stuff->cid, n); 210005b261ecSmrg swapl(&stuff->initial_value_lo, n); 210105b261ecSmrg swapl(&stuff->initial_value_hi, n); 210205b261ecSmrg 210305b261ecSmrg return ProcSyncCreateCounter(client); 210405b261ecSmrg} 210505b261ecSmrg 210605b261ecSmrgstatic int 210705b261ecSmrgSProcSyncSetCounter(client) 210805b261ecSmrg ClientPtr client; 210905b261ecSmrg{ 211005b261ecSmrg REQUEST(xSyncSetCounterReq); 2111637ac9abSmrg char n; 211205b261ecSmrg 211305b261ecSmrg swaps(&stuff->length, n); 211405b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetCounterReq); 211505b261ecSmrg swapl(&stuff->cid, n); 211605b261ecSmrg swapl(&stuff->value_lo, n); 211705b261ecSmrg swapl(&stuff->value_hi, n); 211805b261ecSmrg 211905b261ecSmrg return ProcSyncSetCounter(client); 212005b261ecSmrg} 212105b261ecSmrg 212205b261ecSmrgstatic int 212305b261ecSmrgSProcSyncChangeCounter(client) 212405b261ecSmrg ClientPtr client; 212505b261ecSmrg{ 212605b261ecSmrg REQUEST(xSyncChangeCounterReq); 2127637ac9abSmrg char n; 212805b261ecSmrg 212905b261ecSmrg swaps(&stuff->length, n); 213005b261ecSmrg REQUEST_SIZE_MATCH (xSyncChangeCounterReq); 213105b261ecSmrg swapl(&stuff->cid, n); 213205b261ecSmrg swapl(&stuff->value_lo, n); 213305b261ecSmrg swapl(&stuff->value_hi, n); 213405b261ecSmrg 213505b261ecSmrg return ProcSyncChangeCounter(client); 213605b261ecSmrg} 213705b261ecSmrg 213805b261ecSmrgstatic int 213905b261ecSmrgSProcSyncQueryCounter(client) 214005b261ecSmrg ClientPtr client; 214105b261ecSmrg{ 214205b261ecSmrg REQUEST(xSyncQueryCounterReq); 2143637ac9abSmrg char n; 214405b261ecSmrg 214505b261ecSmrg swaps(&stuff->length, n); 214605b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryCounterReq); 214705b261ecSmrg swapl(&stuff->counter, n); 214805b261ecSmrg 214905b261ecSmrg return ProcSyncQueryCounter(client); 215005b261ecSmrg} 215105b261ecSmrg 215205b261ecSmrgstatic int 215305b261ecSmrgSProcSyncDestroyCounter(client) 215405b261ecSmrg ClientPtr client; 215505b261ecSmrg{ 215605b261ecSmrg REQUEST(xSyncDestroyCounterReq); 2157637ac9abSmrg char n; 215805b261ecSmrg 215905b261ecSmrg swaps(&stuff->length, n); 216005b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); 216105b261ecSmrg swapl(&stuff->counter, n); 216205b261ecSmrg 216305b261ecSmrg return ProcSyncDestroyCounter(client); 216405b261ecSmrg} 216505b261ecSmrg 216605b261ecSmrgstatic int 216705b261ecSmrgSProcSyncAwait(client) 216805b261ecSmrg ClientPtr client; 216905b261ecSmrg{ 217005b261ecSmrg REQUEST(xSyncAwaitReq); 2171637ac9abSmrg char n; 217205b261ecSmrg 217305b261ecSmrg swaps(&stuff->length, n); 217405b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); 217505b261ecSmrg SwapRestL(stuff); 217605b261ecSmrg 217705b261ecSmrg return ProcSyncAwait(client); 217805b261ecSmrg} 217905b261ecSmrg 218005b261ecSmrg 218105b261ecSmrgstatic int 218205b261ecSmrgSProcSyncCreateAlarm(client) 218305b261ecSmrg ClientPtr client; 218405b261ecSmrg{ 218505b261ecSmrg REQUEST(xSyncCreateAlarmReq); 2186637ac9abSmrg char n; 218705b261ecSmrg 218805b261ecSmrg swaps(&stuff->length, n); 218905b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); 219005b261ecSmrg swapl(&stuff->id, n); 219105b261ecSmrg swapl(&stuff->valueMask, n); 219205b261ecSmrg SwapRestL(stuff); 219305b261ecSmrg 219405b261ecSmrg return ProcSyncCreateAlarm(client); 219505b261ecSmrg} 219605b261ecSmrg 219705b261ecSmrgstatic int 219805b261ecSmrgSProcSyncChangeAlarm(client) 219905b261ecSmrg ClientPtr client; 220005b261ecSmrg{ 220105b261ecSmrg REQUEST(xSyncChangeAlarmReq); 2202637ac9abSmrg char n; 220305b261ecSmrg 220405b261ecSmrg swaps(&stuff->length, n); 220505b261ecSmrg REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); 220605b261ecSmrg swapl(&stuff->alarm, n); 220705b261ecSmrg swapl(&stuff->valueMask, n); 220805b261ecSmrg SwapRestL(stuff); 220905b261ecSmrg return ProcSyncChangeAlarm(client); 221005b261ecSmrg} 221105b261ecSmrg 221205b261ecSmrgstatic int 221305b261ecSmrgSProcSyncQueryAlarm(client) 221405b261ecSmrg ClientPtr client; 221505b261ecSmrg{ 221605b261ecSmrg REQUEST(xSyncQueryAlarmReq); 2217637ac9abSmrg char n; 221805b261ecSmrg 221905b261ecSmrg swaps(&stuff->length, n); 222005b261ecSmrg REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); 222105b261ecSmrg swapl(&stuff->alarm, n); 222205b261ecSmrg 222305b261ecSmrg return ProcSyncQueryAlarm(client); 222405b261ecSmrg} 222505b261ecSmrg 222605b261ecSmrgstatic int 222705b261ecSmrgSProcSyncDestroyAlarm(client) 222805b261ecSmrg ClientPtr client; 222905b261ecSmrg{ 223005b261ecSmrg REQUEST(xSyncDestroyAlarmReq); 2231637ac9abSmrg char n; 223205b261ecSmrg 223305b261ecSmrg swaps(&stuff->length, n); 223405b261ecSmrg REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); 223505b261ecSmrg swapl(&stuff->alarm, n); 223605b261ecSmrg 223705b261ecSmrg return ProcSyncDestroyAlarm(client); 223805b261ecSmrg} 223905b261ecSmrg 224005b261ecSmrgstatic int 224105b261ecSmrgSProcSyncSetPriority(client) 224205b261ecSmrg ClientPtr client; 224305b261ecSmrg{ 224405b261ecSmrg REQUEST(xSyncSetPriorityReq); 2245637ac9abSmrg char n; 224605b261ecSmrg 224705b261ecSmrg swaps(&stuff->length, n); 224805b261ecSmrg REQUEST_SIZE_MATCH (xSyncSetPriorityReq); 224905b261ecSmrg swapl(&stuff->id, n); 225005b261ecSmrg swapl(&stuff->priority, n); 225105b261ecSmrg 225205b261ecSmrg return ProcSyncSetPriority(client); 225305b261ecSmrg} 225405b261ecSmrg 225505b261ecSmrgstatic int 225605b261ecSmrgSProcSyncGetPriority(client) 225705b261ecSmrg ClientPtr client; 225805b261ecSmrg{ 225905b261ecSmrg REQUEST(xSyncGetPriorityReq); 2260637ac9abSmrg char n; 226105b261ecSmrg 226205b261ecSmrg swaps(&stuff->length, n); 226305b261ecSmrg REQUEST_SIZE_MATCH (xSyncGetPriorityReq); 226405b261ecSmrg swapl(&stuff->id, n); 226505b261ecSmrg 226605b261ecSmrg return ProcSyncGetPriority(client); 226705b261ecSmrg} 226805b261ecSmrg 226905b261ecSmrg 227005b261ecSmrgstatic int 227105b261ecSmrgSProcSyncDispatch(client) 227205b261ecSmrg ClientPtr client; 227305b261ecSmrg{ 227405b261ecSmrg REQUEST(xReq); 227505b261ecSmrg 227605b261ecSmrg switch (stuff->data) 227705b261ecSmrg { 227805b261ecSmrg case X_SyncInitialize: 227905b261ecSmrg return SProcSyncInitialize(client); 228005b261ecSmrg case X_SyncListSystemCounters: 228105b261ecSmrg return SProcSyncListSystemCounters(client); 228205b261ecSmrg case X_SyncCreateCounter: 228305b261ecSmrg return SProcSyncCreateCounter(client); 228405b261ecSmrg case X_SyncSetCounter: 228505b261ecSmrg return SProcSyncSetCounter(client); 228605b261ecSmrg case X_SyncChangeCounter: 228705b261ecSmrg return SProcSyncChangeCounter(client); 228805b261ecSmrg case X_SyncQueryCounter: 228905b261ecSmrg return SProcSyncQueryCounter(client); 229005b261ecSmrg case X_SyncDestroyCounter: 229105b261ecSmrg return SProcSyncDestroyCounter(client); 229205b261ecSmrg case X_SyncAwait: 229305b261ecSmrg return SProcSyncAwait(client); 229405b261ecSmrg case X_SyncCreateAlarm: 229505b261ecSmrg return SProcSyncCreateAlarm(client); 229605b261ecSmrg case X_SyncChangeAlarm: 229705b261ecSmrg return SProcSyncChangeAlarm(client); 229805b261ecSmrg case X_SyncQueryAlarm: 229905b261ecSmrg return SProcSyncQueryAlarm(client); 230005b261ecSmrg case X_SyncDestroyAlarm: 230105b261ecSmrg return SProcSyncDestroyAlarm(client); 230205b261ecSmrg case X_SyncSetPriority: 230305b261ecSmrg return SProcSyncSetPriority(client); 230405b261ecSmrg case X_SyncGetPriority: 230505b261ecSmrg return SProcSyncGetPriority(client); 230605b261ecSmrg default: 230705b261ecSmrg return BadRequest; 230805b261ecSmrg } 230905b261ecSmrg} 231005b261ecSmrg 231105b261ecSmrg/* 231205b261ecSmrg * Event Swapping 231305b261ecSmrg */ 231405b261ecSmrg 231505b261ecSmrgstatic void 231605b261ecSmrgSCounterNotifyEvent(from, to) 231705b261ecSmrg xSyncCounterNotifyEvent *from, *to; 231805b261ecSmrg{ 231905b261ecSmrg to->type = from->type; 232005b261ecSmrg to->kind = from->kind; 232105b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 232205b261ecSmrg cpswapl(from->counter, to->counter); 232305b261ecSmrg cpswapl(from->wait_value_lo, to->wait_value_lo); 232405b261ecSmrg cpswapl(from->wait_value_hi, to->wait_value_hi); 232505b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 232605b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 232705b261ecSmrg cpswapl(from->time, to->time); 232805b261ecSmrg cpswaps(from->count, to->count); 232905b261ecSmrg to->destroyed = from->destroyed; 233005b261ecSmrg} 233105b261ecSmrg 233205b261ecSmrg 233305b261ecSmrgstatic void 233405b261ecSmrgSAlarmNotifyEvent(from, to) 233505b261ecSmrg xSyncAlarmNotifyEvent *from, *to; 233605b261ecSmrg{ 233705b261ecSmrg to->type = from->type; 233805b261ecSmrg to->kind = from->kind; 233905b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 234005b261ecSmrg cpswapl(from->alarm, to->alarm); 234105b261ecSmrg cpswapl(from->counter_value_lo, to->counter_value_lo); 234205b261ecSmrg cpswapl(from->counter_value_hi, to->counter_value_hi); 234305b261ecSmrg cpswapl(from->alarm_value_lo, to->alarm_value_lo); 234405b261ecSmrg cpswapl(from->alarm_value_hi, to->alarm_value_hi); 234505b261ecSmrg cpswapl(from->time, to->time); 234605b261ecSmrg to->state = from->state; 234705b261ecSmrg} 234805b261ecSmrg 234905b261ecSmrg/* 235005b261ecSmrg * ** Close everything down. ** This is fairly simple for now. 235105b261ecSmrg */ 235205b261ecSmrg/* ARGSUSED */ 235305b261ecSmrgstatic void 235405b261ecSmrgSyncResetProc(extEntry) 235505b261ecSmrg ExtensionEntry *extEntry; 235605b261ecSmrg{ 235705b261ecSmrg xfree(SysCounterList); 235805b261ecSmrg SysCounterList = NULL; 235905b261ecSmrg RTCounter = 0; 236005b261ecSmrg} 236105b261ecSmrg 236205b261ecSmrg 236305b261ecSmrg/* 236405b261ecSmrg * ** Initialise the extension. 236505b261ecSmrg */ 236605b261ecSmrgvoid 236705b261ecSmrgSyncExtensionInit(INITARGS) 236805b261ecSmrg{ 236905b261ecSmrg ExtensionEntry *extEntry; 237005b261ecSmrg 237105b261ecSmrg if (RTCounter == 0) 237205b261ecSmrg { 237305b261ecSmrg RTCounter = CreateNewResourceType(FreeCounter); 237405b261ecSmrg } 237505b261ecSmrg RTAlarm = CreateNewResourceType(FreeAlarm); 237605b261ecSmrg RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN; 237705b261ecSmrg RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN; 237805b261ecSmrg 237905b261ecSmrg if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || 238005b261ecSmrg RTAlarmClient == 0 || 238105b261ecSmrg (extEntry = AddExtension(SYNC_NAME, 238205b261ecSmrg XSyncNumberEvents, XSyncNumberErrors, 238305b261ecSmrg ProcSyncDispatch, SProcSyncDispatch, 238405b261ecSmrg SyncResetProc, 238505b261ecSmrg StandardMinorOpcode)) == NULL) 238605b261ecSmrg { 238705b261ecSmrg ErrorF("Sync Extension %d.%d failed to Initialise\n", 238805b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 238905b261ecSmrg return; 239005b261ecSmrg } 239105b261ecSmrg 239205b261ecSmrg SyncEventBase = extEntry->eventBase; 239305b261ecSmrg SyncErrorBase = extEntry->errorBase; 239405b261ecSmrg EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; 239505b261ecSmrg EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; 239605b261ecSmrg 239705b261ecSmrg /* 239805b261ecSmrg * Although SERVERTIME is implemented by the OS layer, we initialise it 239905b261ecSmrg * here because doing it in OsInit() is too early. The resource database 240005b261ecSmrg * is not initialised when OsInit() is called. This is just about OK 240105b261ecSmrg * because there is always a servertime counter. 240205b261ecSmrg */ 240305b261ecSmrg SyncInitServerTime(); 240405b261ecSmrg SyncInitIdleTime(); 240505b261ecSmrg 240605b261ecSmrg#ifdef DEBUG 240705b261ecSmrg fprintf(stderr, "Sync Extension %d.%d\n", 240805b261ecSmrg SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); 240905b261ecSmrg#endif 241005b261ecSmrg} 241105b261ecSmrg 241205b261ecSmrg 241305b261ecSmrg/* 241405b261ecSmrg * ***** SERVERTIME implementation - should go in its own file in OS directory? 241505b261ecSmrg */ 241605b261ecSmrg 241705b261ecSmrg 241805b261ecSmrg 241905b261ecSmrgstatic pointer ServertimeCounter; 242005b261ecSmrgstatic XSyncValue Now; 242105b261ecSmrgstatic XSyncValue *pnext_time; 242205b261ecSmrg 242305b261ecSmrg#define GetTime()\ 242405b261ecSmrg{\ 242505b261ecSmrg unsigned long millis = GetTimeInMillis();\ 242605b261ecSmrg unsigned long maxis = XSyncValueHigh32(Now);\ 242705b261ecSmrg if (millis < XSyncValueLow32(Now)) maxis++;\ 242805b261ecSmrg XSyncIntsToValue(&Now, millis, maxis);\ 242905b261ecSmrg} 243005b261ecSmrg 243105b261ecSmrg/* 243205b261ecSmrg*** Server Block Handler 243305b261ecSmrg*** code inspired by multibuffer extension 243405b261ecSmrg */ 243505b261ecSmrg/*ARGSUSED*/ 243605b261ecSmrgstatic void ServertimeBlockHandler(env, wt, LastSelectMask) 243705b261ecSmrgpointer env; 243805b261ecSmrgstruct timeval **wt; 243905b261ecSmrgpointer LastSelectMask; 244005b261ecSmrg{ 244105b261ecSmrg XSyncValue delay; 244205b261ecSmrg unsigned long timeout; 244305b261ecSmrg 244405b261ecSmrg if (pnext_time) 244505b261ecSmrg { 244605b261ecSmrg GetTime(); 244705b261ecSmrg 244805b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 244905b261ecSmrg { 245005b261ecSmrg timeout = 0; 245105b261ecSmrg } 245205b261ecSmrg else 245305b261ecSmrg { 245405b261ecSmrg Bool overflow; 245505b261ecSmrg XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); 245605b261ecSmrg (void)overflow; 245705b261ecSmrg timeout = XSyncValueLow32(delay); 245805b261ecSmrg } 245905b261ecSmrg AdjustWaitForDelay(wt, timeout); /* os/utils.c */ 246005b261ecSmrg } 246105b261ecSmrg} 246205b261ecSmrg 246305b261ecSmrg/* 246405b261ecSmrg*** Wakeup Handler 246505b261ecSmrg */ 246605b261ecSmrg/*ARGSUSED*/ 246705b261ecSmrgstatic void ServertimeWakeupHandler(env, rc, LastSelectMask) 246805b261ecSmrgpointer env; 246905b261ecSmrgint rc; 247005b261ecSmrgpointer LastSelectMask; 247105b261ecSmrg{ 247205b261ecSmrg if (pnext_time) 247305b261ecSmrg { 247405b261ecSmrg GetTime(); 247505b261ecSmrg 247605b261ecSmrg if (XSyncValueGreaterOrEqual(Now, *pnext_time)) 247705b261ecSmrg { 247805b261ecSmrg SyncChangeCounter(ServertimeCounter, Now); 247905b261ecSmrg } 248005b261ecSmrg } 248105b261ecSmrg} 248205b261ecSmrg 248305b261ecSmrgstatic void 248405b261ecSmrgServertimeQueryValue(pCounter, pValue_return) 248505b261ecSmrg pointer pCounter; 248605b261ecSmrg CARD64 *pValue_return; 248705b261ecSmrg{ 248805b261ecSmrg GetTime(); 248905b261ecSmrg *pValue_return = Now; 249005b261ecSmrg} 249105b261ecSmrg 249205b261ecSmrgstatic void 249305b261ecSmrgServertimeBracketValues(pCounter, pbracket_less, pbracket_greater) 249405b261ecSmrg pointer pCounter; 249505b261ecSmrg CARD64 *pbracket_less; 249605b261ecSmrg CARD64 *pbracket_greater; 249705b261ecSmrg{ 249805b261ecSmrg if (!pnext_time && pbracket_greater) 249905b261ecSmrg { 250005b261ecSmrg RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, 250105b261ecSmrg ServertimeWakeupHandler, 250205b261ecSmrg NULL); 250305b261ecSmrg } 250405b261ecSmrg else if (pnext_time && !pbracket_greater) 250505b261ecSmrg { 250605b261ecSmrg RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, 250705b261ecSmrg ServertimeWakeupHandler, 250805b261ecSmrg NULL); 250905b261ecSmrg } 251005b261ecSmrg pnext_time = pbracket_greater; 251105b261ecSmrg} 251205b261ecSmrg 251305b261ecSmrgstatic void 251405b261ecSmrgSyncInitServerTime(void) 251505b261ecSmrg{ 251605b261ecSmrg CARD64 resolution; 251705b261ecSmrg 251805b261ecSmrg XSyncIntsToValue(&Now, GetTimeInMillis(), 0); 251905b261ecSmrg XSyncIntToValue(&resolution, 4); 252005b261ecSmrg ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 252105b261ecSmrg XSyncCounterNeverDecreases, 252205b261ecSmrg ServertimeQueryValue, ServertimeBracketValues); 252305b261ecSmrg pnext_time = NULL; 252405b261ecSmrg} 252505b261ecSmrg 252605b261ecSmrg 252705b261ecSmrg 252805b261ecSmrg/* 252905b261ecSmrg * IDLETIME implementation 253005b261ecSmrg */ 253105b261ecSmrg 253245801275Sjmcneillstatic SyncCounter *IdleTimeCounter; 253305b261ecSmrgstatic XSyncValue *pIdleTimeValueLess; 253405b261ecSmrgstatic XSyncValue *pIdleTimeValueGreater; 253505b261ecSmrg 253605b261ecSmrgstatic void 253705b261ecSmrgIdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 253805b261ecSmrg{ 253905b261ecSmrg CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 254005b261ecSmrg XSyncIntsToValue (pValue_return, idle, 0); 254105b261ecSmrg} 254205b261ecSmrg 254305b261ecSmrgstatic void 254445801275SjmcneillIdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) 254505b261ecSmrg{ 254645801275Sjmcneill XSyncValue idle, old_idle; 254745801275Sjmcneill SyncTriggerList *list = IdleTimeCounter->pTriglist; 254845801275Sjmcneill SyncTrigger *trig; 254905b261ecSmrg 255005b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 255105b261ecSmrg return; 255205b261ecSmrg 255345801275Sjmcneill old_idle = IdleTimeCounter->value; 255405b261ecSmrg IdleTimeQueryValue (NULL, &idle); 255545801275Sjmcneill IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ 255605b261ecSmrg 255705b261ecSmrg if (pIdleTimeValueLess && 255805b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 255905b261ecSmrg { 256045801275Sjmcneill /* 256145801275Sjmcneill * We've been idle for less than the threshold value, and someone 256245801275Sjmcneill * wants to know about that, but now we need to know whether they 256345801275Sjmcneill * want level or edge trigger. Check the trigger list against the 256445801275Sjmcneill * current idle time, and if any succeed, bomb out of select() 256545801275Sjmcneill * immediately so we can reschedule. 256645801275Sjmcneill */ 256745801275Sjmcneill 256845801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 256945801275Sjmcneill trig = list->pTrigger; 257045801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 257145801275Sjmcneill AdjustWaitForDelay(wt, 0); 257245801275Sjmcneill break; 257345801275Sjmcneill } 257445801275Sjmcneill } 257505b261ecSmrg } 257605b261ecSmrg else if (pIdleTimeValueGreater) 257705b261ecSmrg { 257845801275Sjmcneill /* 257945801275Sjmcneill * There's a threshold in the positive direction. If we've been 258045801275Sjmcneill * idle less than it, schedule a wakeup for sometime in the future. 258145801275Sjmcneill * If we've been idle more than it, and someone wants to know about 258245801275Sjmcneill * that level-triggered, schedule an immediate wakeup. 258345801275Sjmcneill */ 258445801275Sjmcneill unsigned long timeout = -1; 258505b261ecSmrg 258645801275Sjmcneill if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { 258705b261ecSmrg XSyncValue value; 258805b261ecSmrg Bool overflow; 258905b261ecSmrg 259005b261ecSmrg XSyncValueSubtract (&value, *pIdleTimeValueGreater, 259105b261ecSmrg idle, &overflow); 259245801275Sjmcneill timeout = min(timeout, XSyncValueLow32 (value)); 259345801275Sjmcneill } else { 259445801275Sjmcneill for (list = IdleTimeCounter->pTriglist; list; list = list->next) { 259545801275Sjmcneill trig = list->pTrigger; 259645801275Sjmcneill if (trig->CheckTrigger(trig, old_idle)) { 259745801275Sjmcneill timeout = min(timeout, 0); 259845801275Sjmcneill break; 259945801275Sjmcneill } 260045801275Sjmcneill } 260105b261ecSmrg } 260205b261ecSmrg 260305b261ecSmrg AdjustWaitForDelay (wt, timeout); 260405b261ecSmrg } 260545801275Sjmcneill 260645801275Sjmcneill IdleTimeCounter->value = old_idle; /* pop */ 260705b261ecSmrg} 260805b261ecSmrg 260905b261ecSmrgstatic void 261005b261ecSmrgIdleTimeWakeupHandler (pointer env, 261105b261ecSmrg int rc, 261205b261ecSmrg pointer LastSelectMask) 261305b261ecSmrg{ 261405b261ecSmrg XSyncValue idle; 261505b261ecSmrg 261605b261ecSmrg if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 261705b261ecSmrg return; 261805b261ecSmrg 261905b261ecSmrg IdleTimeQueryValue (NULL, &idle); 262005b261ecSmrg 262105b261ecSmrg if ((pIdleTimeValueGreater && 262205b261ecSmrg XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || 262305b261ecSmrg (pIdleTimeValueLess && 262405b261ecSmrg XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) 262505b261ecSmrg { 262605b261ecSmrg SyncChangeCounter (IdleTimeCounter, idle); 262705b261ecSmrg } 262805b261ecSmrg} 262905b261ecSmrg 263005b261ecSmrgstatic void 263105b261ecSmrgIdleTimeBracketValues (pointer pCounter, 263205b261ecSmrg CARD64 *pbracket_less, 263305b261ecSmrg CARD64 *pbracket_greater) 263405b261ecSmrg{ 263505b261ecSmrg Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); 263605b261ecSmrg 263705b261ecSmrg if (registered && !pbracket_less && !pbracket_greater) 263805b261ecSmrg { 263905b261ecSmrg RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, 264005b261ecSmrg IdleTimeWakeupHandler, 264105b261ecSmrg NULL); 264205b261ecSmrg } 264305b261ecSmrg else if (!registered && (pbracket_less || pbracket_greater)) 264405b261ecSmrg { 264505b261ecSmrg RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, 264605b261ecSmrg IdleTimeWakeupHandler, 264705b261ecSmrg NULL); 264805b261ecSmrg } 264905b261ecSmrg 265005b261ecSmrg pIdleTimeValueGreater = pbracket_greater; 265105b261ecSmrg pIdleTimeValueLess = pbracket_less; 265205b261ecSmrg} 265305b261ecSmrg 265405b261ecSmrgstatic void 265505b261ecSmrgSyncInitIdleTime (void) 265605b261ecSmrg{ 265705b261ecSmrg CARD64 resolution; 265805b261ecSmrg XSyncValue idle; 265905b261ecSmrg 266005b261ecSmrg IdleTimeQueryValue (NULL, &idle); 266105b261ecSmrg XSyncIntToValue (&resolution, 4); 266205b261ecSmrg 266305b261ecSmrg IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, 266405b261ecSmrg XSyncCounterUnrestricted, 266505b261ecSmrg IdleTimeQueryValue, 266605b261ecSmrg IdleTimeBracketValues); 266705b261ecSmrg 266805b261ecSmrg pIdleTimeValueLess = pIdleTimeValueGreater = NULL; 266905b261ecSmrg} 2670