/nx-3.5.0/nx-X11/programs/Xserver/Xext/sync.c
C | 2513 lines | 1832 code | 357 blank | 324 comment | 254 complexity | f9585f0aec1bc54673ad60f6a7788a43 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
- /*
- Copyright 1991, 1993, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall
- not be used in advertising or otherwise to promote the sale, use or
- other dealings in this Software without prior written authorization
- from The Open Group.
- Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
- and Olivetti Research Limited, Cambridge, England.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Digital or Olivetti
- not be used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission. Digital and Olivetti
- make no representations about the suitability of this software
- for any purpose. It is provided "as is" without express or implied warranty.
- DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
- */
- /* $XFree86: xc/programs/Xserver/Xext/sync.c,v 3.13 2003/09/02 18:19:01 tsi Exp $ */
- #define NEED_REPLIES
- #define NEED_EVENTS
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <X11/X.h>
- #include <X11/Xproto.h>
- #include <X11/Xmd.h>
- #include "misc.h"
- #include "os.h"
- #include "extnsionst.h"
- #include "dixstruct.h"
- #include "resource.h"
- #include "opaque.h"
- #define _SYNC_SERVER
- #include <X11/extensions/sync.h>
- #include <X11/extensions/syncstr.h>
- #ifdef EXTMODULE
- #include "xf86_ansic.h"
- #else
- #include <stdio.h>
- #if !defined(WIN32) && !defined(Lynx)
- #include <sys/time.h>
- #endif
- #endif
- #include "modinit.h"
- /*
- * Local Global Variables
- */
- static int SyncEventBase;
- static int SyncErrorBase;
- static RESTYPE RTCounter = 0;
- static RESTYPE RTAwait;
- static RESTYPE RTAlarm;
- static RESTYPE RTAlarmClient;
- static int SyncNumSystemCounters = 0;
- static SyncCounter **SysCounterList = NULL;
- #define IsSystemCounter(pCounter) \
- (pCounter && (pCounter->client == NULL))
- /* these are all the alarm attributes that pertain to the alarm's trigger */
- #define XSyncCAAllTrigger \
- (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
- static int
- FreeAlarm(
- pointer /* addr */,
- XID /* id */
- );
- static int
- FreeAlarmClient(
- pointer /* value */,
- XID /* id */
- );
- static int
- FreeAwait(
- pointer /* addr */,
- XID /* id */
- );
- static void
- ServertimeBracketValues(
- pointer /* pCounter */,
- CARD64 * /* pbracket_less */,
- CARD64 * /* pbracket_greater */
- );
- static void
- ServertimeQueryValue(
- pointer /* pCounter */,
- CARD64 * /* pValue_return */
- );
- static void
- ServertimeWakeupHandler(
- pointer /* env */,
- int /* rc */,
- pointer /* LastSelectMask */
- );
- static int
- SyncInitTrigger(
- ClientPtr /* client */,
- SyncTrigger * /* pTrigger */,
- XSyncCounter /* counter */,
- Mask /* changes */
- );
- static void
- SAlarmNotifyEvent(
- xSyncAlarmNotifyEvent * /* from */,
- xSyncAlarmNotifyEvent * /* to */
- );
- static void
- SCounterNotifyEvent(
- xSyncCounterNotifyEvent * /* from */,
- xSyncCounterNotifyEvent * /* to */
- );
- static void
- ServertimeBlockHandler(
- pointer /* env */,
- struct timeval ** /* wt */,
- pointer /* LastSelectMask */
- );
- static int
- SyncAddTriggerToCounter(
- SyncTrigger * /* pTrigger */
- );
- extern void
- SyncAlarmCounterDestroyed(
- SyncTrigger * /* pTrigger */
- );
- static void
- SyncAlarmTriggerFired(
- SyncTrigger * /* pTrigger */
- );
- static void
- SyncAwaitTriggerFired(
- SyncTrigger * /* pTrigger */
- );
- static int
- SyncChangeAlarmAttributes(
- ClientPtr /* client */,
- SyncAlarm * /* pAlarm */,
- Mask /* mask */,
- CARD32 * /* values */
- );
- static Bool
- SyncCheckTriggerNegativeComparison(
- SyncTrigger * /* pTrigger */,
- CARD64 /* oldval */
- );
- static Bool
- SyncCheckTriggerNegativeTransition(
- SyncTrigger * /* pTrigger */,
- CARD64 /* oldval */
- );
- static Bool
- SyncCheckTriggerPositiveComparison(
- SyncTrigger * /* pTrigger */,
- CARD64 /* oldval */
- );
- static Bool
- SyncCheckTriggerPositiveTransition(
- SyncTrigger * /* pTrigger */,
- CARD64 /* oldval */
- );
- static SyncCounter *
- SyncCreateCounter(
- ClientPtr /* client */,
- XSyncCounter /* id */,
- CARD64 /* initialvalue */
- );
- static void SyncComputeBracketValues(
- SyncCounter * /* pCounter */,
- Bool /* startOver */
- );
- static void
- SyncDeleteTriggerFromCounter(
- SyncTrigger * /* pTrigger */
- );
- static Bool
- SyncEventSelectForAlarm(
- SyncAlarm * /* pAlarm */,
- ClientPtr /* client */,
- Bool /* wantevents */
- );
- static void
- SyncInitServerTime(
- void
- );
- static void
- SyncResetProc(
- ExtensionEntry * /* extEntry */
- );
- static void
- SyncSendAlarmNotifyEvents(
- SyncAlarm * /* pAlarm */
- );
- static void
- SyncSendCounterNotifyEvents(
- ClientPtr /* client */,
- SyncAwait ** /* ppAwait */,
- int /* num_events */
- );
- static DISPATCH_PROC(ProcSyncAwait);
- static DISPATCH_PROC(ProcSyncChangeAlarm);
- static DISPATCH_PROC(ProcSyncChangeCounter);
- static DISPATCH_PROC(ProcSyncCreateAlarm);
- static DISPATCH_PROC(ProcSyncCreateCounter);
- static DISPATCH_PROC(ProcSyncDestroyAlarm);
- static DISPATCH_PROC(ProcSyncDestroyCounter);
- static DISPATCH_PROC(ProcSyncDispatch);
- static DISPATCH_PROC(ProcSyncGetPriority);
- static DISPATCH_PROC(ProcSyncInitialize);
- static DISPATCH_PROC(ProcSyncListSystemCounters);
- static DISPATCH_PROC(ProcSyncQueryAlarm);
- static DISPATCH_PROC(ProcSyncQueryCounter);
- static DISPATCH_PROC(ProcSyncSetCounter);
- static DISPATCH_PROC(ProcSyncSetPriority);
- static DISPATCH_PROC(SProcSyncAwait);
- static DISPATCH_PROC(SProcSyncChangeAlarm);
- static DISPATCH_PROC(SProcSyncChangeCounter);
- static DISPATCH_PROC(SProcSyncCreateAlarm);
- static DISPATCH_PROC(SProcSyncCreateCounter);
- static DISPATCH_PROC(SProcSyncDestroyAlarm);
- static DISPATCH_PROC(SProcSyncDestroyCounter);
- static DISPATCH_PROC(SProcSyncDispatch);
- static DISPATCH_PROC(SProcSyncGetPriority);
- static DISPATCH_PROC(SProcSyncInitialize);
- static DISPATCH_PROC(SProcSyncListSystemCounters);
- static DISPATCH_PROC(SProcSyncQueryAlarm);
- static DISPATCH_PROC(SProcSyncQueryCounter);
- static DISPATCH_PROC(SProcSyncSetCounter);
- static DISPATCH_PROC(SProcSyncSetPriority);
- /* Each counter maintains a simple linked list of triggers that are
- * interested in the counter. The two functions below are used to
- * delete and add triggers on this list.
- */
- static void
- SyncDeleteTriggerFromCounter(pTrigger)
- SyncTrigger *pTrigger;
- {
- SyncTriggerList *pCur, *pPrev = NULL;
- /* pCounter needs to be stored in pTrigger before calling here. */
- if (!pTrigger->pCounter)
- return;
- for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
- {
- if (pCur->pTrigger == pTrigger)
- {
- if (pPrev)
- pPrev->next = pCur->next;
- else
- pTrigger->pCounter->pTriglist = pCur->next;
- xfree(pCur);
- break;
- }
- }
- if (IsSystemCounter(pTrigger->pCounter))
- SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
- }
- static int
- SyncAddTriggerToCounter(pTrigger)
- SyncTrigger *pTrigger;
- {
- SyncTriggerList *pCur;
- if (!pTrigger->pCounter)
- return Success;
- /* don't do anything if it's already there */
- for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
- {
- if (pCur->pTrigger == pTrigger)
- return Success;
- }
- if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
- return BadAlloc;
- pCur->pTrigger = pTrigger;
- pCur->next = pTrigger->pCounter->pTriglist;
- pTrigger->pCounter->pTriglist = pCur;
- if (IsSystemCounter(pTrigger->pCounter))
- SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
- return Success;
- }
- /* Below are four possible functions that can be plugged into
- * pTrigger->CheckTrigger, corresponding to the four possible
- * test-types. These functions are called after the counter's
- * value changes but are also passed the old counter value
- * so they can inspect both the old and new values.
- * (PositiveTransition and NegativeTransition need to see both
- * pieces of information.) These functions return the truth value
- * of the trigger.
- *
- * All of them include the condition pTrigger->pCounter == NULL.
- * This is because the spec says that a trigger with a counter value
- * of None is always TRUE.
- */
- static Bool
- SyncCheckTriggerPositiveComparison(pTrigger, oldval)
- SyncTrigger *pTrigger;
- CARD64 oldval;
- {
- return (pTrigger->pCounter == NULL ||
- XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
- pTrigger->test_value));
- }
- static Bool
- SyncCheckTriggerNegativeComparison(pTrigger, oldval)
- SyncTrigger *pTrigger;
- CARD64 oldval;
- {
- return (pTrigger->pCounter == NULL ||
- XSyncValueLessOrEqual(pTrigger->pCounter->value,
- pTrigger->test_value));
- }
- static Bool
- SyncCheckTriggerPositiveTransition(pTrigger, oldval)
- SyncTrigger *pTrigger;
- CARD64 oldval;
- {
- return (pTrigger->pCounter == NULL ||
- (XSyncValueLessThan(oldval, pTrigger->test_value) &&
- XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
- pTrigger->test_value)));
- }
- static Bool
- SyncCheckTriggerNegativeTransition(pTrigger, oldval)
- SyncTrigger *pTrigger;
- CARD64 oldval;
- {
- return (pTrigger->pCounter == NULL ||
- (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
- XSyncValueLessOrEqual(pTrigger->pCounter->value,
- pTrigger->test_value)));
- }
- static int
- SyncInitTrigger(client, pTrigger, counter, changes)
- ClientPtr client; /* so we can set errorValue */
- SyncTrigger *pTrigger;
- XSyncCounter counter;
- Mask changes;
- {
- SyncCounter *pCounter = pTrigger->pCounter;
- int status;
- Bool newcounter = FALSE;
- if (changes & XSyncCACounter)
- {
- if (counter == None)
- pCounter = NULL;
- else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
- client, counter, RTCounter, SecurityReadAccess)))
- {
- client->errorValue = counter;
- return SyncErrorBase + XSyncBadCounter;
- }
- if (pCounter != pTrigger->pCounter)
- { /* new counter for trigger */
- SyncDeleteTriggerFromCounter(pTrigger);
- pTrigger->pCounter = pCounter;
- newcounter = TRUE;
- }
- }
- /* if system counter, ask it what the current value is */
- if (IsSystemCounter(pCounter))
- {
- (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
- &pCounter->value);
- }
- if (changes & XSyncCAValueType)
- {
- if (pTrigger->value_type != XSyncRelative &&
- pTrigger->value_type != XSyncAbsolute)
- {
- client->errorValue = pTrigger->value_type;
- return BadValue;
- }
- }
- if (changes & XSyncCATestType)
- {
- if (pTrigger->test_type != XSyncPositiveTransition &&
- pTrigger->test_type != XSyncNegativeTransition &&
- pTrigger->test_type != XSyncPositiveComparison &&
- pTrigger->test_type != XSyncNegativeComparison)
- {
- client->errorValue = pTrigger->test_type;
- return BadValue;
- }
- /* select appropriate CheckTrigger function */
- switch (pTrigger->test_type)
- {
- case XSyncPositiveTransition:
- pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
- break;
- case XSyncNegativeTransition:
- pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
- break;
- case XSyncPositiveComparison:
- pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
- break;
- case XSyncNegativeComparison:
- pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
- break;
- }
- }
- if (changes & (XSyncCAValueType | XSyncCAValue))
- {
- if (pTrigger->value_type == XSyncAbsolute)
- pTrigger->test_value = pTrigger->wait_value;
- else /* relative */
- {
- Bool overflow;
- if (pCounter == NULL)
- return BadMatch;
- XSyncValueAdd(&pTrigger->test_value, pCounter->value,
- pTrigger->wait_value, &overflow);
- if (overflow)
- {
- client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
- return BadValue;
- }
- }
- }
- /* we wait until we're sure there are no errors before registering
- * a new counter on a trigger
- */
- if (newcounter)
- {
- if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
- return status;
- }
- else if (IsSystemCounter(pCounter))
- {
- SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
- }
-
- return Success;
- }
- /* AlarmNotify events happen in response to actions taken on an Alarm or
- * the counter used by the alarm. AlarmNotify may be sent to multiple
- * clients. The alarm maintains a list of clients interested in events.
- */
- static void
- SyncSendAlarmNotifyEvents(pAlarm)
- SyncAlarm *pAlarm;
- {
- SyncAlarmClientList *pcl;
- xSyncAlarmNotifyEvent ane;
- SyncTrigger *pTrigger = &pAlarm->trigger;
- UpdateCurrentTime();
- ane.type = SyncEventBase + XSyncAlarmNotify;
- ane.kind = XSyncAlarmNotify;
- ane.sequenceNumber = pAlarm->client->sequence;
- ane.alarm = pAlarm->alarm_id;
- if (pTrigger->pCounter)
- {
- ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
- ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
- }
- else
- { /* XXX what else can we do if there's no counter? */
- ane.counter_value_hi = ane.counter_value_lo = 0;
- }
- ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
- ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
- ane.time = currentTime.milliseconds;
- ane.state = pAlarm->state;
- /* send to owner */
- if (pAlarm->events && !pAlarm->client->clientGone)
- WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
- /* send to other interested clients */
- for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
- {
- if (!pAlarm->client->clientGone)
- {
- ane.sequenceNumber = pcl->client->sequence;
- WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
- }
- }
- }
- /* CounterNotify events only occur in response to an Await. The events
- * go only to the Awaiting client.
- */
- static void
- SyncSendCounterNotifyEvents(client, ppAwait, num_events)
- ClientPtr client;
- SyncAwait **ppAwait;
- int num_events;
- {
- xSyncCounterNotifyEvent *pEvents, *pev;
- int i;
- if (client->clientGone)
- return;
- pev = pEvents = (xSyncCounterNotifyEvent *)
- ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
- if (!pEvents)
- return;
- UpdateCurrentTime();
- for (i = 0; i < num_events; i++, ppAwait++, pev++)
- {
- SyncTrigger *pTrigger = &(*ppAwait)->trigger;
- pev->type = SyncEventBase + XSyncCounterNotify;
- pev->kind = XSyncCounterNotify;
- pev->sequenceNumber = client->sequence;
- pev->counter = pTrigger->pCounter->id;
- pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
- pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
- pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
- pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
- pev->time = currentTime.milliseconds;
- pev->count = num_events - i - 1; /* events remaining */
- pev->destroyed = pTrigger->pCounter->beingDestroyed;
- }
- /* swapping will be taken care of by this */
- WriteEventsToClient(client, num_events, (xEvent *)pEvents);
- DEALLOCATE_LOCAL(pEvents);
- }
- /* This function is called when an alarm's counter is destroyed.
- * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
- */
- void
- SyncAlarmCounterDestroyed(pTrigger)
- SyncTrigger *pTrigger;
- {
- SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
- pAlarm->state = XSyncAlarmInactive;
- SyncSendAlarmNotifyEvents(pAlarm);
- pTrigger->pCounter = NULL;
- }
- /* This function is called when an alarm "goes off."
- * It is plugged into pTrigger->TriggerFired (for alarm triggers).
- */
- static void
- SyncAlarmTriggerFired(pTrigger)
- SyncTrigger *pTrigger;
- {
- SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
- CARD64 new_test_value;
- /* no need to check alarm unless it's active */
- if (pAlarm->state != XSyncAlarmActive)
- return;
- /* " if the counter value is None, or if the delta is 0 and
- * the test-type is PositiveComparison or NegativeComparison,
- * no change is made to value (test-value) and the alarm
- * state is changed to Inactive before the event is generated."
- */
- if (pAlarm->trigger.pCounter == NULL
- || (XSyncValueIsZero(pAlarm->delta)
- && (pAlarm->trigger.test_type == XSyncPositiveComparison
- || pAlarm->trigger.test_type == XSyncNegativeComparison)))
- pAlarm->state = XSyncAlarmInactive;
- new_test_value = pAlarm->trigger.test_value;
- if (pAlarm->state == XSyncAlarmActive)
- {
- Bool overflow;
- CARD64 oldvalue;
- SyncTrigger *paTrigger = &pAlarm->trigger;
- /* "The alarm is updated by repeatedly adding delta to the
- * value of the trigger and re-initializing it until it
- * becomes FALSE."
- */
- oldvalue = paTrigger->test_value;
- /* XXX really should do something smarter here */
- do
- {
- XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
- pAlarm->delta, &overflow);
- } while (!overflow &&
- (*paTrigger->CheckTrigger)(paTrigger,
- paTrigger->pCounter->value));
- new_test_value = paTrigger->test_value;
- paTrigger->test_value = oldvalue;
- /* "If this update would cause value to fall outside the range
- * for an INT64...no change is made to value (test-value) and
- * the alarm state is changed to Inactive before the event is
- * generated."
- */
- if (overflow)
- {
- new_test_value = oldvalue;
- pAlarm->state = XSyncAlarmInactive;
- }
- }
- /* The AlarmNotify event has to have the "new state of the alarm"
- * which we can't be sure of until this point. However, it has
- * to have the "old" trigger test value. That's the reason for
- * all the newvalue/oldvalue shuffling above. After we send the
- * events, give the trigger its new test value.
- */
- SyncSendAlarmNotifyEvents(pAlarm);
- pTrigger->test_value = new_test_value;
- }
- /* This function is called when an Await unblocks, either as a result
- * of the trigger firing OR the counter being destroyed.
- * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
- * (for Await triggers).
- */
- static void
- SyncAwaitTriggerFired(pTrigger)
- SyncTrigger *pTrigger;
- {
- SyncAwait *pAwait = (SyncAwait *)pTrigger;
- int numwaits;
- SyncAwaitUnion *pAwaitUnion;
- SyncAwait **ppAwait;
- int num_events = 0;
- pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
- numwaits = pAwaitUnion->header.num_waitconditions;
- ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
- if (!ppAwait)
- goto bail;
- pAwait = &(pAwaitUnion+1)->await;
- /* "When a client is unblocked, all the CounterNotify events for
- * the Await request are generated contiguously. If count is 0
- * there are no more events to follow for this request. If
- * count is n, there are at least n more events to follow."
- *
- * Thus, it is best to find all the counters for which events
- * need to be sent first, so that an accurate count field can
- * be stored in the events.
- */
- for ( ; numwaits; numwaits--, pAwait++)
- {
- CARD64 diff;
- Bool overflow, diffgreater, diffequal;
- /* "A CounterNotify event with the destroyed flag set to TRUE is
- * always generated if the counter for one of the triggers is
- * destroyed."
- */
- if (pAwait->trigger.pCounter->beingDestroyed)
- {
- ppAwait[num_events++] = pAwait;
- continue;
- }
- /* "The difference between the counter and the test value is
- * calculated by subtracting the test value from the value of
- * the counter."
- */
- XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
- pAwait->trigger.test_value, &overflow);
- /* "If the difference lies outside the range for an INT64, an
- * event is not generated."
- */
- if (overflow)
- continue;
- diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
- diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
- /* "If the test-type is PositiveTransition or
- * PositiveComparison, a CounterNotify event is generated if
- * the difference is at least event-threshold. If the test-type
- * is NegativeTransition or NegativeComparison, a CounterNotify
- * event is generated if the difference is at most
- * event-threshold."
- */
- if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
- pAwait->trigger.test_type == XSyncPositiveTransition)
- && (diffgreater || diffequal))
- ||
- ((pAwait->trigger.test_type == XSyncNegativeComparison ||
- pAwait->trigger.test_type == XSyncNegativeTransition)
- && (!diffgreater) /* less or equal */
- )
- )
- {
- ppAwait[num_events++] = pAwait;
- }
- }
- if (num_events)
- SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
- num_events);
- DEALLOCATE_LOCAL(ppAwait);
- bail:
- /* unblock the client */
- AttendClient(pAwaitUnion->header.client);
- /* delete the await */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- }
- /* This function should always be used to change a counter's value so that
- * any triggers depending on the counter will be checked.
- */
- void
- SyncChangeCounter(pCounter, newval)
- SyncCounter *pCounter;
- CARD64 newval;
- {
- SyncTriggerList *ptl, *pnext;
- CARD64 oldval;
- oldval = pCounter->value;
- pCounter->value = newval;
- /* run through triggers to see if any become true */
- for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
- {
- pnext = ptl->next;
- if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
- (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
- }
- if (IsSystemCounter(pCounter))
- {
- SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
- }
- }
- /* loosely based on dix/events.c/EventSelectForWindow */
- static Bool
- SyncEventSelectForAlarm(pAlarm, client, wantevents)
- SyncAlarm *pAlarm;
- ClientPtr client;
- Bool wantevents;
- {
- SyncAlarmClientList *pClients;
- if (client == pAlarm->client) /* alarm owner */
- {
- pAlarm->events = wantevents;
- return Success;
- }
- /* see if the client is already on the list (has events selected) */
- for (pClients = pAlarm->pEventClients; pClients;
- pClients = pClients->next)
- {
- if (pClients->client == client)
- {
- /* client's presence on the list indicates desire for
- * events. If the client doesn't want events, remove it
- * from the list. If the client does want events, do
- * nothing, since it's already got them.
- */
- if (!wantevents)
- {
- FreeResource(pClients->delete_id, RT_NONE);
- }
- return Success;
- }
- }
- /* if we get here, this client does not currently have
- * events selected on the alarm
- */
- if (!wantevents)
- /* client doesn't want events, and we just discovered that it
- * doesn't have them, so there's nothing to do.
- */
- return Success;
- /* add new client to pAlarm->pEventClients */
- pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
- if (!pClients)
- return BadAlloc;
- /* register it as a resource so it will be cleaned up
- * if the client dies
- */
- pClients->delete_id = FakeClientID(client->index);
- if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
- {
- xfree(pClients);
- return BadAlloc;
- }
- /* link it into list after we know all the allocations succeed */
- pClients->next = pAlarm->pEventClients;
- pAlarm->pEventClients = pClients;
- pClients->client = client;
- return Success;
- }
- /*
- * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
- */
- static int
- SyncChangeAlarmAttributes(client, pAlarm, mask, values)
- ClientPtr client;
- SyncAlarm *pAlarm;
- Mask mask;
- CARD32 *values;
- {
- int status;
- XSyncCounter counter;
- Mask origmask = mask;
- counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
- while (mask)
- {
- int index2 = lowbit(mask);
- mask &= ~index2;
- switch (index2)
- {
- case XSyncCACounter:
- mask &= ~XSyncCACounter;
- /* sanity check in SyncInitTrigger */
- counter = *values++;
- break;
- case XSyncCAValueType:
- mask &= ~XSyncCAValueType;
- /* sanity check in SyncInitTrigger */
- pAlarm->trigger.value_type = *values++;
- break;
- case XSyncCAValue:
- mask &= ~XSyncCAValue;
- XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
- values += 2;
- break;
- case XSyncCATestType:
- mask &= ~XSyncCATestType;
- /* sanity check in SyncInitTrigger */
- pAlarm->trigger.test_type = *values++;
- break;
- case XSyncCADelta:
- mask &= ~XSyncCADelta;
- XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
- values += 2;
- break;
- case XSyncCAEvents:
- mask &= ~XSyncCAEvents;
- if ((*values != xTrue) && (*values != xFalse))
- {
- client->errorValue = *values;
- return BadValue;
- }
- status = SyncEventSelectForAlarm(pAlarm, client,
- (Bool)(*values++));
- if (status != Success)
- return status;
- break;
- default:
- client->errorValue = mask;
- return BadValue;
- }
- }
- /* "If the test-type is PositiveComparison or PositiveTransition
- * and delta is less than zero, or if the test-type is
- * NegativeComparison or NegativeTransition and delta is
- * greater than zero, a Match error is generated."
- */
- if (origmask & (XSyncCADelta|XSyncCATestType))
- {
- CARD64 zero;
- XSyncIntToValue(&zero, 0);
- if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
- (pAlarm->trigger.test_type == XSyncPositiveTransition))
- && XSyncValueLessThan(pAlarm->delta, zero))
- ||
- (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
- (pAlarm->trigger.test_type == XSyncNegativeTransition))
- && XSyncValueGreaterThan(pAlarm->delta, zero))
- )
- {
- return BadMatch;
- }
- }
- /* postpone this until now, when we're sure nothing else can go wrong */
- if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
- origmask & XSyncCAAllTrigger)) != Success)
- return status;
- /* XXX spec does not really say to do this - needs clarification */
- pAlarm->state = XSyncAlarmActive;
- return Success;
- }
- static SyncCounter *
- SyncCreateCounter(client, id, initialvalue)
- ClientPtr client;
- XSyncCounter id;
- CARD64 initialvalue;
- {
- SyncCounter *pCounter;
- if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
- return (SyncCounter *)NULL;
- if (!AddResource(id, RTCounter, (pointer) pCounter))
- {
- xfree((pointer) pCounter);
- return (SyncCounter *)NULL;
- }
- pCounter->client = client;
- pCounter->id = id;
- pCounter->value = initialvalue;
- pCounter->pTriglist = NULL;
- pCounter->beingDestroyed = FALSE;
- pCounter->pSysCounterInfo = NULL;
- return pCounter;
- }
- static int FreeCounter(
- pointer /*env*/,
- XID /*id*/
- );
- /*
- * ***** System Counter utilities
- */
- pointer
- SyncCreateSystemCounter(name, initial, resolution, counterType,
- QueryValue, BracketValues)
- char *name;
- CARD64 initial;
- CARD64 resolution;
- SyncCounterType counterType;
- void (*QueryValue) (
- pointer /* pCounter */,
- CARD64 * /* pValue_return */);
- void (*BracketValues) (
- pointer /* pCounter */,
- CARD64 * /* pbracket_less */,
- CARD64 * /* pbracket_greater */);
- {
- SyncCounter *pCounter;
- SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
- (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
- if (!SysCounterList)
- return (pointer)NULL;
- /* this function may be called before SYNC has been initialized, so we
- * have to make sure RTCounter is created.
- */
- if (RTCounter == 0)
- {
- RTCounter = CreateNewResourceType(FreeCounter);
- if (RTCounter == 0)
- {
- return (pointer)NULL;
- }
- }
- pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
- if (pCounter)
- {
- SysCounterInfo *psci;
- psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
- if (!psci)
- {
- FreeResource(pCounter->id, RT_NONE);
- return (pointer) pCounter;
- }
- pCounter->pSysCounterInfo = psci;
- psci->name = name;
- psci->resolution = resolution;
- psci->counterType = counterType;
- psci->QueryValue = QueryValue;
- psci->BracketValues = BracketValues;
- XSyncMaxValue(&psci->bracket_greater);
- XSyncMinValue(&psci->bracket_less);
- SysCounterList[SyncNumSystemCounters++] = pCounter;
- }
- return (pointer) pCounter;
- }
- void
- SyncDestroySystemCounter(pSysCounter)
- pointer pSysCounter;
- {
- SyncCounter *pCounter = (SyncCounter *)pSysCounter;
- FreeResource(pCounter->id, RT_NONE);
- }
- static void
- SyncComputeBracketValues(pCounter, startOver)
- SyncCounter *pCounter;
- Bool startOver;
- {
- SyncTriggerList *pCur;
- SyncTrigger *pTrigger;
- SysCounterInfo *psci = pCounter->pSysCounterInfo;
- CARD64 *pnewgtval = NULL;
- CARD64 *pnewltval = NULL;
- SyncCounterType ct;
- if (!pCounter)
- return;
- ct = pCounter->pSysCounterInfo->counterType;
- if (ct == XSyncCounterNeverChanges)
- return;
- if (startOver)
- {
- XSyncMaxValue(&psci->bracket_greater);
- XSyncMinValue(&psci->bracket_less);
- }
- for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
- {
- pTrigger = pCur->pTrigger;
-
- if (pTrigger->test_type == XSyncPositiveComparison &&
- ct != XSyncCounterNeverIncreases)
- {
- if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueLessThan(pTrigger->test_value,
- psci->bracket_greater))
- {
- psci->bracket_greater = pTrigger->test_value;
- pnewgtval = &psci->bracket_greater;
- }
- }
- else if (pTrigger->test_type == XSyncNegativeComparison &&
- ct != XSyncCounterNeverDecreases)
- {
- if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueGreaterThan(pTrigger->test_value,
- psci->bracket_less))
- {
- psci->bracket_less = pTrigger->test_value;
- pnewltval = &psci->bracket_less;
- }
- }
- else if ( (pTrigger->test_type == XSyncPositiveTransition &&
- ct != XSyncCounterNeverIncreases)
- ||
- (pTrigger->test_type == XSyncNegativeTransition &&
- ct != XSyncCounterNeverDecreases)
- )
- {
- if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
- {
- if (XSyncValueLessThan(pTrigger->test_value,
- psci->bracket_greater))
- {
- psci->bracket_greater = pTrigger->test_value;
- pnewgtval = &psci->bracket_greater;
- }
- else
- if (XSyncValueGreaterThan(pTrigger->test_value,
- psci->bracket_less))
- {
- psci->bracket_less = pTrigger->test_value;
- pnewltval = &psci->bracket_less;
- }
- }
- }
- } /* end for each trigger */
- if (pnewgtval || pnewltval)
- {
- (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
- }
- }
- /*
- * ***** Resource delete functions
- */
- /* ARGSUSED */
- static int
- FreeAlarm(addr, id)
- pointer addr;
- XID id;
- {
- SyncAlarm *pAlarm = (SyncAlarm *) addr;
- pAlarm->state = XSyncAlarmDestroyed;
- SyncSendAlarmNotifyEvents(pAlarm);
- /* delete event selections */
- while (pAlarm->pEventClients)
- FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
- SyncDeleteTriggerFromCounter(&pAlarm->trigger);
- xfree(pAlarm);
- return Success;
- }
- /*
- * ** Cleanup after the destruction of a Counter
- */
- /* ARGSUSED */
- static int
- FreeCounter(env, id)
- pointer env;
- XID id;
- {
- SyncCounter *pCounter = (SyncCounter *) env;
- SyncTriggerList *ptl, *pnext;
- pCounter->beingDestroyed = TRUE;
- /* tell all the counter's triggers that the counter has been destroyed */
- for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
- {
- (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
- pnext = ptl->next;
- xfree(ptl); /* destroy the trigger list as we go */
- }
- if (IsSystemCounter(pCounter))
- {
- int i, found = 0;
- xfree(pCounter->pSysCounterInfo);
- /* find the counter in the list of system counters and remove it */
- if (SysCounterList)
- {
- for (i = 0; i < SyncNumSystemCounters; i++)
- {
- if (SysCounterList[i] == pCounter)
- {
- found = i;
- break;
- }
- }
- if (found < (SyncNumSystemCounters-1))
- {
- for (i = found; i < SyncNumSystemCounters-1; i++)
- {
- SysCounterList[i] = SysCounterList[i+1];
- }
- }
- }
- SyncNumSystemCounters--;
- }
- xfree(pCounter);
- return Success;
- }
- /*
- * ** Cleanup after Await
- */
- /* ARGSUSED */
- static int
- FreeAwait(addr, id)
- pointer addr;
- XID id;
- {
- SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
- SyncAwait *pAwait;
- int numwaits;
- pAwait = &(pAwaitUnion+1)->await; /* first await on list */
- /* remove triggers from counters */
- for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
- numwaits--, pAwait++)
- {
- /* If the counter is being destroyed, FreeCounter will delete
- * the trigger list itself, so don't do it here.
- */
- SyncCounter *pCounter = pAwait->trigger.pCounter;
- if (pCounter && !pCounter->beingDestroyed)
- SyncDeleteTriggerFromCounter(&pAwait->trigger);
- }
- xfree(pAwaitUnion);
- return Success;
- }
- /* loosely based on dix/events.c/OtherClientGone */
- static int
- FreeAlarmClient(value, id)
- pointer value; /* must conform to DeleteType */
- XID id;
- {
- SyncAlarm *pAlarm = (SyncAlarm *)value;
- SyncAlarmClientList *pCur, *pPrev;
- for (pPrev = NULL, pCur = pAlarm->pEventClients;
- pCur;
- pPrev = pCur, pCur = pCur->next)
- {
- if (pCur->delete_id == id)
- {
- if (pPrev)
- pPrev->next = pCur->next;
- else
- pAlarm->pEventClients = pCur->next;
- xfree(pCur);
- return(Success);
- }
- }
- FatalError("alarm client not on event list");
- /*NOTREACHED*/
- }
- /*
- * ***** Proc functions
- */
- /*
- * ** Initialize the extension
- */
- static int
- ProcSyncInitialize(client)
- ClientPtr client;
- {
- xSyncInitializeReply rep;
- int n;
- REQUEST_SIZE_MATCH(xSyncInitializeReq);
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.majorVersion = SYNC_MAJOR_VERSION;
- rep.minorVersion = SYNC_MINOR_VERSION;
- rep.length = 0;
- if (client->swapped)
- {
- swaps(&rep.sequenceNumber, n);
- }
- WriteToClient(client, sizeof(rep), (char *) &rep);
- return (client->noClientException);
- }
- /*
- * ** Get list of system counters available through the extension
- */
- static int
- ProcSyncListSystemCounters(client)
- ClientPtr client;
- {
- xSyncListSystemCountersReply rep;
- int i, len;
- xSyncSystemCounter *list = NULL, *walklist = NULL;
-
- REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.nCounters = SyncNumSystemCounters;
- for (i = len = 0; i < SyncNumSystemCounters; i++)
- {
- char *name = SysCounterList[i]->pSysCounterInfo->name;
- /* pad to 4 byte boundary */
- len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
- }
- if (len)
- {
- walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
- if (!list)
- return BadAlloc;
- }
- rep.length = len >> 2;
- if (client->swapped)
- {
- register char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.nCounters, n);
- }
- for (i = 0; i < SyncNumSystemCounters; i++)
- {
- int namelen;
- char *pname_in_reply;
- SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
- walklist->counter = SysCounterList[i]->id;
- walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
- walklist->resolution_lo = XSyncValueLow32(psci->resolution);
- namelen = strlen(psci->name);
- walklist->name_length = namelen;
- if (client->swapped)
- {
- register char n;
- swapl(&walklist->counter, n);
- swapl(&walklist->resolution_hi, n);
- swapl(&walklist->resolution_lo, n);
- swaps(&walklist->name_length, n);
- }
- pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
- strncpy(pname_in_reply, psci->name, namelen);
- walklist = (xSyncSystemCounter *) (((char *)walklist) +
- ((sz_xSyncSystemCounter + namelen + 3) & ~3));
- }
- WriteToClient(client, sizeof(rep), (char *) &rep);
- if (len)
- {
- WriteToClient(client, len, (char *) list);
- DEALLOCATE_LOCAL(list);
- }
- return (client->noClientException);
- }
- /*
- * ** Set client Priority
- */
- static int
- ProcSyncSetPriority(client)
- ClientPtr client;
- {
- REQUEST(xSyncSetPriorityReq);
- ClientPtr priorityclient;
- REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
- if (stuff->id == None)
- priorityclient = client;
- else if (!(priorityclient = LookupClient(stuff->id, client)))
- {
- client->errorValue = stuff->id;
- return BadMatch;
- }
- if (priorityclient->priority != stuff->priority)
- {
- priorityclient->priority = stuff->priority;
- /* The following will force the server back into WaitForSomething
- * so that the change in this client's priority is immediately
- * reflected.
- */
- isItTimeToYield = TRUE;
- dispatchException |= DE_PRIORITYCHANGE;
- }
- return Success;
- }
- /*
- * ** Get client Priority
- */
- static int
- ProcSyncGetPriority(client)
- ClientPtr client;
- {
- REQUEST(xSyncGetPriorityReq);
- xSyncGetPriorityReply rep;
- ClientPtr priorityclient;
- REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
- if (stuff->id == None)
- priorityclient = client;
- else if (!(priorityclient = LookupClient(stuff->id, client)))
- {
- client->errorValue = stuff->id;
- return BadMatch;
- }
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.priority = priorityclient->priority;
- if (client->swapped)
- {
- register char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.priority, n);
- }
- WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
- return (client->noClientException);
- }
- /*
- * ** Create a new counter
- */
- static int
- ProcSyncCreateCounter(client)
- ClientPtr client;
- {
- REQUEST(xSyncCreateCounterReq);
- CARD64 initial;
- REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
- LEGAL_NEW_RESOURCE(stuff->cid, client);
- XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
- if (!SyncCreateCounter(client, stuff->cid, initial))
- return BadAlloc;
- return (client->noClientException);
- }
- /*
- * ** Set Counter value
- */
- static int
- ProcSyncSetCounter(client)
- ClientPtr client;
- {
- REQUEST(xSyncSetCounterReq);
- SyncCounter *pCounter;
- CARD64 newvalue;
- REQUEST_SIZE_MATCH(xSyncSetCounterReq);
- pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
- RTCounter, SecurityWriteAccess);
- if (pCounter == NULL)
- {
- client->errorValue = stuff->cid;
- return SyncErrorBase + XSyncBadCounter;
- }
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->cid;
- return BadAccess;
- }
- XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
- SyncChangeCounter(pCounter, newvalue);
- return Success;
- }
- /*
- * ** Change Counter value
- */
- static int
- ProcSyncChangeCounter(client)
- ClientPtr client;
- {
- REQUEST(xSyncChangeCounterReq);
- SyncCounter *pCounter;
- CARD64 newvalue;
- Bool overflow;
- REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
- pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
- RTCounter, SecurityWriteAccess);
- if (pCounter == NULL)
- {
- client->errorValue = stuff->cid;
- return SyncErrorBase + XSyncBadCounter;
- }
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->cid;
- return BadAccess;
- }
- XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
- XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
- if (overflow)
- {
- /* XXX 64 bit value can't fit in 32 bits; do the best we can */
- client->errorValue = stuff->value_hi;
- return BadValue;
- }
- SyncChangeCounter(pCounter, newvalue);
- return Success;
- }
- /*
- * ** Destroy a counter
- */
- static int
- ProcSyncDestroyCounter(client)
- ClientPtr client;
- {
- REQUEST(xSyncDestroyCounterReq);
- SyncCounter *pCounter;
- REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
- pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
- RTCounter, SecurityDestroyAccess);
- if (pCounter == NULL)
- {
- client->errorValue = stuff->counter;
- return SyncErrorBase + XSyncBadCounter;
- }
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->counter;
- return BadAccess;
- }
- FreeResource(pCounter->id, RT_NONE);
- return Success;
- }
- /*
- * ** Await
- */
- static int
- ProcSyncAwait(client)
- ClientPtr client;
- {
- REQUEST(xSyncAwaitReq);
- int len, items;
- int i;
- xSyncWaitCondition *pProtocolWaitConds;
- SyncAwaitUnion *pAwaitUnion;
- SyncAwait *pAwait;
- int status;
- REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
- len = client->req_len << 2;
- len -= sz_xSyncAwaitReq;
- items = len / sz_xSyncWaitCondition;
- if (items * sz_xSyncWaitCondition != len)
- {
- return BadLength;
- }
- if (items == 0)
- {
- client->errorValue = items; /* XXX protocol change */
- return BadValue;
- }
- pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
- /* all the memory for the entire await list is allocated
- * here in one chunk
- */
- pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
- if (!pAwaitUnion)
- return BadAlloc;
- /* first item is the header, remainder are real wait conditions */
- pAwaitUnion->header.delete_id = FakeClientID(client->index);
- if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
- {
- xfree(pAwaitUnion);
- return BadAlloc;
- }
- /* don't need to do any more memory allocation for this request! */
- pAwaitUnion->header.client = client;
- pAwaitUnion->header.num_waitconditions = 0;
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
- {
- if (pProtocolWaitConds->counter == None) /* XXX protocol change */
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on counters
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- client->errorValue = pProtocolWaitConds->counter;
- return SyncErrorBase + XSyncBadCounter;
- }
- /* sanity checks are in SyncInitTrigger */
- pAwait->trigger.pCounter = NULL;
- pAwait->trigger.value_type = pProtocolWaitConds->value_type;
- XSyncIntsToValue(&pAwait->trigger.wait_value,
- pProtocolWaitConds->wait_value_lo,
- pProtocolWaitConds->wait_value_hi);
- pAwait->trigger.test_type = pProtocolWaitConds->test_type;
- status = SyncInitTrigger(client, &pAwait->trigger,
- pProtocolWaitConds->counter, XSyncCAAllTrigger);
- if (status != Success)
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on counters
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- return status;
- }
- /* this is not a mistake -- same function works for both cases */
- pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
- pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
- XSyncIntsToValue(&pAwait->event_threshold,
- pProtocolWaitConds->event_threshold_lo,
- pProtocolWaitConds->event_threshold_hi);
- pAwait->pHeader = &pAwaitUnion->header;
- pAwaitUnion->header.num_waitconditions++;
- }
- IgnoreClient(client);
- /* see if any of the triggers are already true */
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pAwait++)
- {
- /* don't have to worry about NULL counters because the request
- * errors before we get here out if they occur
- */
- if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
- pAwait->trigger.pCounter->value))
- {
- (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
- break; /* once is enough */
- }
- }
- return Success;
- }
- /*
- * ** Query a counter
- */
- static int
- ProcSyncQueryCounter(client)
- ClientPtr client;
- {
- REQUEST(xSyncQueryCounterReq);
- xSyncQueryCounterReply rep;
- SyncCounter *pCounter;
- REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
- pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
- RTCounter, SecurityReadAccess);
- if (pCounter == NULL)
- {
- client->errorValue = stuff->counter;
- return SyncErrorBase + XSyncBadCounter;
- }
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- /* if system counter, ask it what the current value is */
- if (IsSystemCounter(pCounter))
- {
- (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
- &pCounter->value);
- }
- rep.value_hi = XSyncValueHigh32(pCounter->value);
- rep.value_lo = XSyncValueLow32(pCounter->value);
- if (client->swapped)
- {
- register char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.value_hi, n);
- swapl(&rep.value_lo, n);
- }
- WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
- return (client->noClientException);
- }
- /*
- * ** Create Alarm
- */
- static int
- ProcSyncCreateAlarm(client)
- ClientPtr client;
- {
- REQUEST(xSyncCreateAlarmReq);
- SyncAlarm *pAlarm;
- int status;
- unsigned long len, vmask;
- SyncTrigger *pTrigger;
- REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
- LEGAL_NEW_RESOURCE(stuff->id, client);
- vmask = stuff->valueMask;
- len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
- /* the "extra" call to Ones accounts for the presence of 64 bit values */
- if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
- return BadLength;
- if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
- {
- return BadAlloc;
- }
- /* set up defaults */
- pTrigger = &pAlarm->trigger;
- pTrigger->pCounter = NULL;
- pTrigger->value_type = XSyncAbsolute;
- XSyncIntToValue(&pTrigger->wait_value, 0L);
- pTrigger->test_type = XSyncPositiveComparison;
- pTrigger->TriggerFired = SyncAlarmTriggerFired;
- pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
- status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
- if (status != Success)
- {
- xfree(pAlarm);
- return status;
- }
- pAlarm->client = client;
- pAlarm->alarm_id = stuff->id;
- XSyncIntToValue(&pAlarm->delta, 1L);
- pAlarm->events = TRUE;
- pAlarm->state = XSyncAlarmInactive;
- pAlarm->pEventClients = NULL;
- status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
- (CARD32 *)&stuff[1]);
- if (status != Success)
- {
- xfree(pAlarm);
- return status;
- }
- if (!AddResource(stuff->id, RTAlarm, pAlarm))
- {
- xfree(pAlarm);
- return BadAlloc;
- }
- /* see if alarm already triggered. NULL counter will not trigger
- * in CreateAlarm and sets alarm state to Inactive.
- */
- if (!pTrigger->pCounter)
- {
- pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
- }
- else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
- {
- (*pTrigger->TriggerFired)(pTrigger);
- }
- return Success;
- }
- /*
- * ** Change Alarm
- */
- static int
- ProcSyncChangeAlarm(client)
- ClientPtr client;
- {
- REQUEST(xSyncChangeAlarmReq);
- SyncAlarm *pAlarm;
- long vmask;
- int len, status;
- REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
- if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
- RTAlarm, SecurityWriteAccess)))
- {
- client->errorValue = stuff->alarm;
- return SyncErrorBase + XSyncBadAlarm;
- }
- vmask = stuff->valueMask;
- len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
- /* the "extra" call to Ones accounts for the presence of 64 bit values */
- if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
- return BadLength;
- if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
- (CARD32 *)&stuff[1])) != Success)
- return status;
- /* see if alarm already triggered. NULL counter WILL trigger
- * in ChangeAlarm.
- */
- if (!pAlarm->trigger.pCounter ||
- (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
- pAlarm->trigger.pCounter->value))
- {
- (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
- }
- return Success;
- }
- static int
- ProcSyncQueryAlarm(client)
- ClientPtr client;
- {
- REQUEST(xS…
Large files files are truncated, but you can click here to view the full file