aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xext
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-12-23 07:51:31 +0000
committermarha <marha@users.sourceforge.net>2010-12-23 07:51:31 +0000
commit71e1361d0fd4c2d1c6c31f9a28d474fceee7e12e (patch)
tree4e5cebc3ac6d1c0f5dd765697a7c2ad7be796136 /xorg-server/Xext
parent374f6889ce26ba0a914d07f4946cd113263a6e18 (diff)
parent8fd06c45853cb2300105db84e4b722f0e2dad8d2 (diff)
downloadvcxsrv-71e1361d0fd4c2d1c6c31f9a28d474fceee7e12e.tar.gz
vcxsrv-71e1361d0fd4c2d1c6c31f9a28d474fceee7e12e.tar.bz2
vcxsrv-71e1361d0fd4c2d1c6c31f9a28d474fceee7e12e.zip
svn merge ^/branches/released .
Diffstat (limited to 'xorg-server/Xext')
-rw-r--r--xorg-server/Xext/sync.c5768
-rw-r--r--xorg-server/Xext/xf86bigfont.c1502
2 files changed, 3650 insertions, 3620 deletions
diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c
index d1948d3ed..5af055a7d 100644
--- a/xorg-server/Xext/sync.c
+++ b/xorg-server/Xext/sync.c
@@ -1,2869 +1,2899 @@
-/*
-
-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.
-
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xmd.h>
-#include "scrnintstr.h"
-#include "os.h"
-#include "extnsionst.h"
-#include "dixstruct.h"
-#include "pixmapstr.h"
-#include "resource.h"
-#include "opaque.h"
-#include <X11/extensions/syncproto.h>
-#include "syncsrv.h"
-#include "syncsdk.h"
-#include "protocol-versions.h"
-
-#include <stdio.h>
-#if !defined(WIN32)
-#include <sys/time.h>
-#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 RESTYPE RTFence;
-static int SyncNumSystemCounters = 0;
-static SyncCounter **SysCounterList = NULL;
-
-#define IsSystemCounter(pCounter) \
- (pCounter && (pCounter->sync.client == NULL))
-
-/* these are all the alarm attributes that pertain to the alarm's trigger */
-#define XSyncCAAllTrigger \
- (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
-
-static void SyncComputeBracketValues(SyncCounter *);
-
-static void SyncInitServerTime(void);
-
-static void SyncInitIdleTime(void);
-
-
-/* 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
-SyncDeleteTriggerFromSyncObject(SyncTrigger *pTrigger)
-{
- SyncTriggerList *pCur;
- SyncTriggerList *pPrev;
- SyncCounter *pCounter;
-
- /* pSync needs to be stored in pTrigger before calling here. */
-
- if (!pTrigger->pSync)
- return;
-
- pPrev = NULL;
- pCur = pTrigger->pSync->pTriglist;
-
- while (pCur)
- {
- if (pCur->pTrigger == pTrigger)
- {
- if (pPrev)
- pPrev->next = pCur->next;
- else
- pTrigger->pSync->pTriglist = pCur->next;
-
- free(pCur);
- break;
- }
-
- pPrev = pCur;
- pCur = pCur->next;
- }
-
- if (SYNC_COUNTER == pTrigger->pSync->type)
- {
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- if (IsSystemCounter(pCounter))
- SyncComputeBracketValues(pCounter);
- } else if (SYNC_FENCE == pTrigger->pSync->type) {
- SyncFence* pFence = (SyncFence*) pTrigger->pSync;
- pFence->funcs.DeleteTrigger(pTrigger);
- }
-}
-
-
-static int
-SyncAddTriggerToSyncObject(SyncTrigger *pTrigger)
-{
- SyncTriggerList *pCur;
- SyncCounter *pCounter;
-
- if (!pTrigger->pSync)
- return Success;
-
- /* don't do anything if it's already there */
- for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next)
- {
- if (pCur->pTrigger == pTrigger)
- return Success;
- }
-
- if (!(pCur = malloc(sizeof(SyncTriggerList))))
- return BadAlloc;
-
- pCur->pTrigger = pTrigger;
- pCur->next = pTrigger->pSync->pTriglist;
- pTrigger->pSync->pTriglist = pCur;
-
- if (SYNC_COUNTER == pTrigger->pSync->type)
- {
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- if (IsSystemCounter(pCounter))
- SyncComputeBracketValues(pCounter);
- } else if (SYNC_FENCE == pTrigger->pSync->type) {
- SyncFence* pFence = (SyncFence*) pTrigger->pSync;
- pFence->funcs.AddTrigger(pTrigger);
- }
-
- return Success;
-}
-
-
-/* Below are five possible functions that can be plugged into
- * pTrigger->CheckTrigger for counter sync objects, corresponding to
- * the four possible test-types, and the one possible function that
- * can be plugged into pTrigger->CheckTrigger for fence sync objects.
- * These functions are called after the sync object's state changes
- * but are also passed the old state 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->pSync == NULL.
- * This is because the spec says that a trigger with a sync value
- * of None is always TRUE.
- */
-
-static Bool
-SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value));
-}
-
-static Bool
-SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value));
-}
-
-static Bool
-SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- (XSyncValueLessThan(oldval, pTrigger->test_value) &&
- XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)));
-}
-
-static Bool
-SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
- XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)));
-}
-
-static Bool
-SyncCheckTriggerFence(SyncTrigger *pTrigger, CARD64 unused)
-{
- SyncFence* pFence = (SyncFence*) pTrigger->pSync;
- (void)unused;
-
- return (pFence == NULL ||
- pFence->funcs.CheckTriggered(pFence));
-}
-
-static int
-SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
- RESTYPE resType, Mask changes)
-{
- SyncObject *pSync = pTrigger->pSync;
- SyncCounter *pCounter = NULL;
- int rc;
- Bool newSyncObject = FALSE;
-
- if (changes & XSyncCACounter)
- {
- if (syncObject == None)
- pSync = NULL;
- else if (Success != (rc = dixLookupResourceByType ((pointer *)&pSync,
- syncObject, resType, client, DixReadAccess)))
- {
- client->errorValue = syncObject;
- return rc;
- }
- if (pSync != pTrigger->pSync)
- { /* new counter for trigger */
- SyncDeleteTriggerFromSyncObject(pTrigger);
- pTrigger->pSync = pSync;
- newSyncObject = TRUE;
- }
- }
-
- /* if system counter, ask it what the current value is */
-
- if (pSync && SYNC_COUNTER == pSync->type)
- {
- pCounter = (SyncCounter *)pSync;
-
- 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 (pSync && SYNC_FENCE == pSync->type)
- {
- pTrigger->CheckTrigger = SyncCheckTriggerFence;
- }
- else
- {
- 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 (newSyncObject)
- {
- if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
- return rc;
- }
- else if (pCounter && IsSystemCounter(pCounter))
- {
- SyncComputeBracketValues(pCounter);
- }
-
- 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(SyncAlarm *pAlarm)
-{
- SyncAlarmClientList *pcl;
- xSyncAlarmNotifyEvent ane;
- SyncTrigger *pTrigger = &pAlarm->trigger;
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
-
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- UpdateCurrentTime();
-
- ane.type = SyncEventBase + XSyncAlarmNotify;
- ane.kind = XSyncAlarmNotify;
- ane.alarm = pAlarm->alarm_id;
- if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type)
- {
- ane.counter_value_hi = XSyncValueHigh32(pCounter->value);
- ane.counter_value_lo = XSyncValueLow32(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)
- WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
-
- /* send to other interested clients */
- for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
- 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(ClientPtr client, SyncAwait **ppAwait,
- int num_events)
-{
- xSyncCounterNotifyEvent *pEvents, *pev;
- int i;
-
- if (client->clientGone)
- return;
- pev = pEvents = malloc(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->counter = pTrigger->pSync->id;
- pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
- pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
- if (SYNC_COUNTER == pTrigger->pSync->type)
- {
- SyncCounter *pCounter = (SyncCounter *)pTrigger->pSync;
-
- pev->counter_value_lo = XSyncValueLow32(pCounter->value);
- pev->counter_value_hi = XSyncValueHigh32(pCounter->value);
- }
- else
- {
- pev->counter_value_lo = 0;
- pev->counter_value_hi = 0;
- }
-
- pev->time = currentTime.milliseconds;
- pev->count = num_events - i - 1; /* events remaining */
- pev->destroyed = pTrigger->pSync->beingDestroyed;
- }
- /* swapping will be taken care of by this */
- WriteEventsToClient(client, num_events, (xEvent *)pEvents);
- free(pEvents);
-}
-
-
-/* This function is called when an alarm's counter is destroyed.
- * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
- */
-static void
-SyncAlarmCounterDestroyed(SyncTrigger *pTrigger)
-{
- SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
-
- pAlarm->state = XSyncAlarmInactive;
- SyncSendAlarmNotifyEvents(pAlarm);
- pTrigger->pSync = NULL;
-}
-
-
-/* This function is called when an alarm "goes off."
- * It is plugged into pTrigger->TriggerFired (for alarm triggers).
- */
-static void
-SyncAlarmTriggerFired(SyncTrigger *pTrigger)
-{
- SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
- SyncCounter *pCounter;
- CARD64 new_test_value;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- /* 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 (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;
- SyncCounter *paCounter;
-
- assert(!paTrigger->pSync || (SYNC_COUNTER == paTrigger->pSync->type));
- paCounter = (SyncCounter *)pTrigger->pSync;
-
- /* "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,
- paCounter->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(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 = malloc(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.pSync->beingDestroyed)
- {
- ppAwait[num_events++] = pAwait;
- continue;
- }
-
- if (SYNC_COUNTER == pAwait->trigger.pSync->type)
- {
- SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
-
- /* "The difference between the counter and the test value is
- * calculated by subtracting the test value from the value of
- * the counter."
- */
- XSyncValueSubtract(&diff, 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);
- free(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(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->sync.pTriglist; ptl; ptl = pnext)
- {
- pnext = ptl->next;
- if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
- (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
- }
-
- if (IsSystemCounter(pCounter))
- {
- SyncComputeBracketValues(pCounter);
- }
-}
-
-
-/* loosely based on dix/events.c/EventSelectForWindow */
-static Bool
-SyncEventSelectForAlarm(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 = malloc(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))
- {
- free(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(ClientPtr client, SyncAlarm *pAlarm, Mask mask,
- CARD32 *values)
-{
- int status;
- XSyncCounter counter;
- Mask origmask = mask;
-
- counter =
- pAlarm->trigger.pSync ? pAlarm->trigger.pSync->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, RTCounter,
- origmask & XSyncCAAllTrigger)) != Success)
- return status;
-
- /* XXX spec does not really say to do this - needs clarification */
- pAlarm->state = XSyncAlarmActive;
- return Success;
-}
-
-static SyncObject *
-SyncCreate(ClientPtr client, XID id, unsigned char type)
-{
- SyncObject *pSync;
- RESTYPE resType;
-
- switch (type) {
- case SYNC_COUNTER:
- resType = RTCounter;
- pSync = malloc(sizeof(SyncCounter));
- break;
- case SYNC_FENCE:
- resType = RTFence;
- pSync = dixAllocateObjectWithPrivates(SyncFence,
- PRIVATE_SYNC_FENCE);
- break;
- default:
- return NULL;
- }
-
- if (!pSync)
- return NULL;
-
- if (!AddResource(id, resType, (pointer) pSync))
- {
- switch (type) {
- case SYNC_FENCE:
- dixFreeObjectWithPrivates((SyncFence *)pSync, PRIVATE_SYNC_FENCE);
- break;
- default:
- free(pSync);
- }
-
- return NULL;
- }
-
- pSync->client = client;
- pSync->id = id;
- pSync->pTriglist = NULL;
- pSync->beingDestroyed = FALSE;
- pSync->type = type;
-
- return pSync;
-}
-
-
-static SyncCounter *
-SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
-{
- SyncCounter *pCounter;
-
- if (!(pCounter = (SyncCounter *)SyncCreate(client,
- id,
- SYNC_COUNTER)))
- return NULL;
-
- pCounter->value = initialvalue;
- pCounter->pSysCounterInfo = NULL;
- return pCounter;
-}
-
-static int FreeCounter(void *, XID);
-
-/*
- * ***** System Counter utilities
- */
-
-pointer
-SyncCreateSystemCounter(
- 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 = realloc(SysCounterList,
- (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
- if (!SysCounterList)
- return 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, "SyncCounter");
- if (RTCounter == 0)
- {
- return NULL;
- }
- }
-
- pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
-
- if (pCounter)
- {
- SysCounterInfo *psci;
-
- psci = malloc(sizeof(SysCounterInfo));
- if (!psci)
- {
- FreeResource(pCounter->sync.id, RT_NONE);
- return 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 pCounter;
-}
-
-void
-SyncDestroySystemCounter(pointer pSysCounter)
-{
- SyncCounter *pCounter = (SyncCounter *)pSysCounter;
- FreeResource(pCounter->sync.id, RT_NONE);
-}
-
-static void
-SyncComputeBracketValues(SyncCounter *pCounter)
-{
- SyncTriggerList *pCur;
- SyncTrigger *pTrigger;
- SysCounterInfo *psci;
- CARD64 *pnewgtval = NULL;
- CARD64 *pnewltval = NULL;
- SyncCounterType ct;
-
- if (!pCounter)
- return;
-
- psci = pCounter->pSysCounterInfo;
- ct = pCounter->pSysCounterInfo->counterType;
- if (ct == XSyncCounterNeverChanges)
- return;
-
- XSyncMaxValue(&psci->bracket_greater);
- XSyncMinValue(&psci->bracket_less);
-
- for (pCur = pCounter->sync.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 == XSyncNegativeTransition &&
- ct != XSyncCounterNeverIncreases)
- {
- 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 != XSyncCounterNeverDecreases)
- {
- if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater))
- {
- psci->bracket_greater = pTrigger->test_value;
- pnewgtval = &psci->bracket_greater;
- }
- }
- } /* end for each trigger */
-
- if (pnewgtval || pnewltval)
- {
- (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
- }
-}
-
-/*
- * ***** Resource delete functions
- */
-
-/* ARGSUSED */
-static int
-FreeAlarm(void *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);
-
- SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
-
- free(pAlarm);
- return Success;
-}
-
-
-/*
- * ** Cleanup after the destruction of a Counter
- */
-/* ARGSUSED */
-static int
-FreeCounter(void *env, XID id)
-{
- SyncCounter *pCounter = (SyncCounter *) env;
- SyncTriggerList *ptl, *pnext;
-
- pCounter->sync.beingDestroyed = TRUE;
- /* tell all the counter's triggers that the counter has been destroyed */
- for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
- {
- (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
- pnext = ptl->next;
- free(ptl); /* destroy the trigger list as we go */
- }
- if (IsSystemCounter(pCounter))
- {
- int i, found = 0;
-
- free(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--;
- }
- free(pCounter);
- return Success;
-}
-
-/*
- * ** Cleanup after Await
- */
-/* ARGSUSED */
-static int
-FreeAwait(void *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.
- */
- SyncObject *pSync = pAwait->trigger.pSync;
- if (pSync && !pSync->beingDestroyed)
- SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
- }
- free(pAwaitUnion);
- return Success;
-}
-
-#ifdef _MSC_VER
-#pragma warning(disable:4715) /* Not all control paths return a value */
-#endif
-
-/* loosely based on dix/events.c/OtherClientGone */
-static int
-FreeAlarmClient(void *value, 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;
- free(pCur);
- return Success;
- }
- }
- FatalError("alarm client not on event list");
- /*NOTREACHED*/
-}
-
-
-/*
- * ***** Proc functions
- */
-
-
-/*
- * ** Initialize the extension
- */
-static int
-ProcSyncInitialize(ClientPtr client)
-{
- xSyncInitializeReply rep;
- int n;
-
- REQUEST_SIZE_MATCH(xSyncInitializeReq);
-
- memset(&rep, 0, sizeof(xSyncInitializeReply));
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.majorVersion = SERVER_SYNC_MAJOR_VERSION;
- rep.minorVersion = SERVER_SYNC_MINOR_VERSION;
- rep.length = 0;
-
- if (client->swapped)
- {
- swaps(&rep.sequenceNumber, n);
- }
- WriteToClient(client, sizeof(rep), (char *) &rep);
- return Success;
-}
-
-/*
- * ** Get list of system counters available through the extension
- */
-static int
-ProcSyncListSystemCounters(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 += pad_to_int32(sz_xSyncSystemCounter + strlen(name));
- }
-
- if (len)
- {
- walklist = list = malloc(len);
- if (!list)
- return BadAlloc;
- }
-
- rep.length = bytes_to_int32(len);
-
- if (client->swapped)
- {
- 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]->sync.id;
- walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
- walklist->resolution_lo = XSyncValueLow32(psci->resolution);
- namelen = strlen(psci->name);
- walklist->name_length = namelen;
-
- if (client->swapped)
- {
- 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) +
- pad_to_int32(sz_xSyncSystemCounter + namelen));
- }
-
- WriteToClient(client, sizeof(rep), (char *) &rep);
- if (len)
- {
- WriteToClient(client, len, (char *) list);
- free(list);
- }
-
- return Success;
-}
-
-/*
- * ** Set client Priority
- */
-static int
-ProcSyncSetPriority(ClientPtr client)
-{
- REQUEST(xSyncSetPriorityReq);
- ClientPtr priorityclient;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
-
- if (stuff->id == None)
- priorityclient = client;
- else {
- rc = dixLookupClient(&priorityclient, stuff->id, client,
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- 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(ClientPtr client)
-{
- REQUEST(xSyncGetPriorityReq);
- xSyncGetPriorityReply rep;
- ClientPtr priorityclient;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
-
- if (stuff->id == None)
- priorityclient = client;
- else {
- rc = dixLookupClient(&priorityclient, stuff->id, client,
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.priority = priorityclient->priority;
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.priority, n);
- }
-
- WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
-
- return Success;
-}
-
-/*
- * ** Create a new counter
- */
-static int
-ProcSyncCreateCounter(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 Success;
-}
-
-/*
- * ** Set Counter value
- */
-static int
-ProcSyncSetCounter(ClientPtr client)
-{
- REQUEST(xSyncSetCounterReq);
- SyncCounter *pCounter;
- CARD64 newvalue;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncSetCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- 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(ClientPtr client)
-{
- REQUEST(xSyncChangeCounterReq);
- SyncCounter *pCounter;
- CARD64 newvalue;
- Bool overflow;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- 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(ClientPtr client)
-{
- REQUEST(xSyncDestroyCounterReq);
- SyncCounter *pCounter;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter,
- client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->counter;
- return BadAccess;
- }
- FreeResource(pCounter->sync.id, RT_NONE);
- return Success;
-}
-
-static SyncAwaitUnion*
-SyncAwaitPrologue(ClientPtr client, int items)
-{
- SyncAwaitUnion *pAwaitUnion;
-
- /* all the memory for the entire await list is allocated
- * here in one chunk
- */
- pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
- if (!pAwaitUnion)
- return NULL;
-
- /* 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))
- {
- free(pAwaitUnion);
- return NULL;
- }
-
- pAwaitUnion->header.client = client;
- pAwaitUnion->header.num_waitconditions = 0;
-
- return pAwaitUnion;
-}
-
-static void
-SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion)
-{
- SyncAwait *pAwait;
- int i;
-
- 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++)
- {
- CARD64 value;
-
- /* don't have to worry about NULL counters because the request
- * errors before we get here out if they occur
- */
- switch (pAwait->trigger.pSync->type) {
- case SYNC_COUNTER:
- value = ((SyncCounter *)pAwait->trigger.pSync)->value;
- break;
- default:
- XSyncIntToValue(&value, 0);
- }
-
- if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
- {
- (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
- break; /* once is enough */
- }
- }
-}
-
-/*
- * ** Await
- */
-static int
-ProcSyncAwait(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;
- }
-
- if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
- return BadAlloc;
-
- /* don't need to do any more memory allocation for this request! */
-
- pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
-
- 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 sync objects
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- client->errorValue = pProtocolWaitConds->counter;
- return SyncErrorBase + XSyncBadCounter;
- }
-
- /* sanity checks are in SyncInitTrigger */
- pAwait->trigger.pSync = 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, RTCounter,
- XSyncCAAllTrigger);
- if (status != Success)
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- 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++;
- }
-
- SyncAwaitEpilogue(client, items, pAwaitUnion);
-
- return Success;
-}
-
-
-/*
- * ** Query a counter
- */
-static int
-ProcSyncQueryCounter(ClientPtr client)
-{
- REQUEST(xSyncQueryCounterReq);
- xSyncQueryCounterReply rep;
- SyncCounter *pCounter;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter,
- RTCounter, client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- 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)
- {
- 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 Success;
-}
-
-
-/*
- * ** Create Alarm
- */
-static int
-ProcSyncCreateAlarm(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 - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
- /* 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 = malloc(sizeof(SyncAlarm))))
- {
- return BadAlloc;
- }
-
- /* set up defaults */
-
- pTrigger = &pAlarm->trigger;
- pTrigger->pSync = 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, RTCounter,
- XSyncCAAllTrigger);
- if (status != Success)
- {
- free(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)
- {
- free(pAlarm);
- return status;
- }
-
- if (!AddResource(stuff->id, RTAlarm, pAlarm))
- {
- free(pAlarm);
- return BadAlloc;
- }
-
- /* see if alarm already triggered. NULL counter will not trigger
- * in CreateAlarm and sets alarm state to Inactive.
- */
-
- if (!pTrigger->pSync)
- {
- pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
- }
- else
- {
- SyncCounter *pCounter;
-
- assert(SYNC_COUNTER == pTrigger->pSync->type);
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- if ((*pTrigger->CheckTrigger)(pTrigger, pCounter->value))
- (*pTrigger->TriggerFired)(pTrigger);
- }
-
- return Success;
-}
-
-/*
- * ** Change Alarm
- */
-static int
-ProcSyncChangeAlarm(ClientPtr client)
-{
- REQUEST(xSyncChangeAlarmReq);
- SyncAlarm *pAlarm;
- SyncCounter *pCounter = NULL;
- long vmask;
- int len, status;
-
- REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
-
- status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
- client, DixWriteAccess);
- if (status != Success)
- return status;
-
- vmask = stuff->valueMask;
- len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
- /* 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;
-
- if (pAlarm->trigger.pSync)
- {
- assert(SYNC_COUNTER == pAlarm->trigger.pSync->type);
- pCounter = (SyncCounter *)pAlarm->trigger.pSync;
- }
-
- /* see if alarm already triggered. NULL counter WILL trigger
- * in ChangeAlarm.
- */
-
- if (!pCounter ||
- (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, pCounter->value))
- {
- (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
- }
- return Success;
-}
-
-static int
-ProcSyncQueryAlarm(ClientPtr client)
-{
- REQUEST(xSyncQueryAlarmReq);
- SyncAlarm *pAlarm;
- xSyncQueryAlarmReply rep;
- SyncTrigger *pTrigger;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
-
- rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
- client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply));
- rep.sequenceNumber = client->sequence;
-
- pTrigger = &pAlarm->trigger;
- rep.counter = (pTrigger->pSync) ? pTrigger->pSync->id : None;
-
-#if 0 /* XXX unclear what to do, depends on whether relative value-types
- * are "consumed" immediately and are considered absolute from then
- * on.
- */
- rep.value_type = pTrigger->value_type;
- rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
- rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
-#else
- rep.value_type = XSyncAbsolute;
- rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
- rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
-#endif
-
- rep.test_type = pTrigger->test_type;
- rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
- rep.delta_lo = XSyncValueLow32(pAlarm->delta);
- rep.events = pAlarm->events;
- rep.state = pAlarm->state;
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.counter, n);
- swapl(&rep.wait_value_hi, n);
- swapl(&rep.wait_value_lo, n);
- swapl(&rep.test_type, n);
- swapl(&rep.delta_hi, n);
- swapl(&rep.delta_lo, n);
- }
-
- WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
- return Success;
-}
-
-static int
-ProcSyncDestroyAlarm(ClientPtr client)
-{
- SyncAlarm *pAlarm;
- int rc;
- REQUEST(xSyncDestroyAlarmReq);
-
- REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
-
- rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
- client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- FreeResource(stuff->alarm, RT_NONE);
- return Success;
-}
-
-static int
-ProcSyncCreateFence(ClientPtr client)
-{
- REQUEST(xSyncCreateFenceReq);
- DrawablePtr pDraw;
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
-
- rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- LEGAL_NEW_RESOURCE(stuff->fid, client);
-
- if (!(pFence = (SyncFence *)SyncCreate(client,
- stuff->fid,
- SYNC_FENCE)))
- return BadAlloc;
-
- miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
-
- return client->noClientException;
-}
-
-static int
-FreeFence(void *obj, XID id)
-{
- SyncFence *pFence = (SyncFence *) obj;
-
- miSyncDestroyFence(pFence);
-
- return Success;
-}
-
-int SyncVerifyFence(SyncFence **ppSyncFence, XID fid,
- ClientPtr client, Mask mode)
-{
- int rc = dixLookupResourceByType((pointer *)ppSyncFence, fid, RTFence,
- client, mode);
-
- if (rc != Success)
- client->errorValue = fid;
-
- return rc;
-}
-
-static int
-ProcSyncTriggerFence(ClientPtr client)
-{
- REQUEST(xSyncTriggerFenceReq);
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- miSyncTriggerFence(pFence);
-
- return client->noClientException;
-}
-
-static int
-ProcSyncResetFence(ClientPtr client)
-{
- REQUEST(xSyncResetFenceReq);
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncResetFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- if (pFence->funcs.CheckTriggered(pFence) != TRUE)
- return BadMatch;
-
- pFence->funcs.Reset(pFence);
-
- return client->noClientException;
-}
-
-static int
-ProcSyncDestroyFence(ClientPtr client)
-{
- REQUEST(xSyncDestroyFenceReq);
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
- client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- FreeResource(stuff->fid, RT_NONE);
- return client->noClientException;
-}
-
-static int
-ProcSyncQueryFence(ClientPtr client)
-{
- REQUEST(xSyncQueryFenceReq);
- xSyncQueryFenceReply rep;
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid,
- RTFence, client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- rep.triggered = pFence->funcs.CheckTriggered(pFence);
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- }
-
- WriteToClient(client, sizeof(xSyncQueryFenceReply), (char *) &rep);
- return client->noClientException;
-}
-
-static int
-ProcSyncAwaitFence(ClientPtr client)
-{
- REQUEST(xSyncAwaitFenceReq);
- SyncAwaitUnion *pAwaitUnion;
- SyncAwait *pAwait;
- /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
- * CARD32 in protocol definitions */
- CARD32 *pProtocolFences;
- int status;
- int len;
- int items;
- int i;
-
- REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
-
- len = client->req_len << 2;
- len -= sz_xSyncAwaitFenceReq;
- items = len / sizeof(CARD32);
-
- if (items * sizeof(CARD32) != len)
- {
- return BadLength;
- }
- if (items == 0)
- {
- client->errorValue = items; /* XXX protocol change */
- return BadValue;
- }
-
- if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
- return BadAlloc;
-
- /* don't need to do any more memory allocation for this request! */
-
- pProtocolFences = (CARD32 *) & stuff[1];
-
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pProtocolFences++, pAwait++)
- {
- if (*pProtocolFences == None) /* XXX protocol change */
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- client->errorValue = *pProtocolFences;
- return SyncErrorBase + XSyncBadCounter;
- }
-
- pAwait->trigger.pSync = NULL;
- /* Provide acceptable values for these unused fields to
- * satisfy SyncInitTrigger's validation logic
- */
- pAwait->trigger.value_type = XSyncAbsolute;
- XSyncIntToValue(&pAwait->trigger.wait_value, 0);
- pAwait->trigger.test_type = 0;
-
- status = SyncInitTrigger(client, &pAwait->trigger,
- *pProtocolFences, RTFence,
- XSyncCAAllTrigger);
- if (status != Success)
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- 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;
- /* event_threshold is unused for fence syncs */
- XSyncIntToValue(&pAwait->event_threshold, 0);
- pAwait->pHeader = &pAwaitUnion->header;
- pAwaitUnion->header.num_waitconditions++;
- }
-
- SyncAwaitEpilogue(client, items, pAwaitUnion);
-
- return client->noClientException;
-}
-
-/*
- * ** Given an extension request, call the appropriate request procedure
- */
-static int
-ProcSyncDispatch(ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data)
- {
- case X_SyncInitialize:
- return ProcSyncInitialize(client);
- case X_SyncListSystemCounters:
- return ProcSyncListSystemCounters(client);
- case X_SyncCreateCounter:
- return ProcSyncCreateCounter(client);
- case X_SyncSetCounter:
- return ProcSyncSetCounter(client);
- case X_SyncChangeCounter:
- return ProcSyncChangeCounter(client);
- case X_SyncQueryCounter:
- return ProcSyncQueryCounter(client);
- case X_SyncDestroyCounter:
- return ProcSyncDestroyCounter(client);
- case X_SyncAwait:
- return ProcSyncAwait(client);
- case X_SyncCreateAlarm:
- return ProcSyncCreateAlarm(client);
- case X_SyncChangeAlarm:
- return ProcSyncChangeAlarm(client);
- case X_SyncQueryAlarm:
- return ProcSyncQueryAlarm(client);
- case X_SyncDestroyAlarm:
- return ProcSyncDestroyAlarm(client);
- case X_SyncSetPriority:
- return ProcSyncSetPriority(client);
- case X_SyncGetPriority:
- return ProcSyncGetPriority(client);
- case X_SyncCreateFence:
- return ProcSyncCreateFence(client);
- case X_SyncTriggerFence:
- return ProcSyncTriggerFence(client);
- case X_SyncResetFence:
- return ProcSyncResetFence(client);
- case X_SyncDestroyFence:
- return ProcSyncDestroyFence(client);
- case X_SyncQueryFence:
- return ProcSyncQueryFence(client);
- case X_SyncAwaitFence:
- return ProcSyncAwaitFence(client);
- default:
- return BadRequest;
- }
-}
-
-/*
- * Boring Swapping stuff ...
- */
-
-static int
-SProcSyncInitialize(ClientPtr client)
-{
- REQUEST(xSyncInitializeReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncInitializeReq);
-
- return ProcSyncInitialize(client);
-}
-
-static int
-SProcSyncListSystemCounters(ClientPtr client)
-{
- REQUEST(xSyncListSystemCountersReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
-
- return ProcSyncListSystemCounters(client);
-}
-
-static int
-SProcSyncCreateCounter(ClientPtr client)
-{
- REQUEST(xSyncCreateCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->initial_value_lo, n);
- swapl(&stuff->initial_value_hi, n);
-
- return ProcSyncCreateCounter(client);
-}
-
-static int
-SProcSyncSetCounter(ClientPtr client)
-{
- REQUEST(xSyncSetCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncSetCounterReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->value_lo, n);
- swapl(&stuff->value_hi, n);
-
- return ProcSyncSetCounter(client);
-}
-
-static int
-SProcSyncChangeCounter(ClientPtr client)
-{
- REQUEST(xSyncChangeCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->value_lo, n);
- swapl(&stuff->value_hi, n);
-
- return ProcSyncChangeCounter(client);
-}
-
-static int
-SProcSyncQueryCounter(ClientPtr client)
-{
- REQUEST(xSyncQueryCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
- swapl(&stuff->counter, n);
-
- return ProcSyncQueryCounter(client);
-}
-
-static int
-SProcSyncDestroyCounter(ClientPtr client)
-{
- REQUEST(xSyncDestroyCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
- swapl(&stuff->counter, n);
-
- return ProcSyncDestroyCounter(client);
-}
-
-static int
-SProcSyncAwait(ClientPtr client)
-{
- REQUEST(xSyncAwaitReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
- SwapRestL(stuff);
-
- return ProcSyncAwait(client);
-}
-
-static int
-SProcSyncCreateAlarm(ClientPtr client)
-{
- REQUEST(xSyncCreateAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
- swapl(&stuff->id, n);
- swapl(&stuff->valueMask, n);
- SwapRestL(stuff);
-
- return ProcSyncCreateAlarm(client);
-}
-
-static int
-SProcSyncChangeAlarm(ClientPtr client)
-{
- REQUEST(xSyncChangeAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
- swapl(&stuff->alarm, n);
- swapl(&stuff->valueMask, n);
- SwapRestL(stuff);
- return ProcSyncChangeAlarm(client);
-}
-
-static int
-SProcSyncQueryAlarm(ClientPtr client)
-{
- REQUEST(xSyncQueryAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
- swapl(&stuff->alarm, n);
-
- return ProcSyncQueryAlarm(client);
-}
-
-static int
-SProcSyncDestroyAlarm(ClientPtr client)
-{
- REQUEST(xSyncDestroyAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
- swapl(&stuff->alarm, n);
-
- return ProcSyncDestroyAlarm(client);
-}
-
-static int
-SProcSyncSetPriority(ClientPtr client)
-{
- REQUEST(xSyncSetPriorityReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
- swapl(&stuff->id, n);
- swapl(&stuff->priority, n);
-
- return ProcSyncSetPriority(client);
-}
-
-static int
-SProcSyncGetPriority(ClientPtr client)
-{
- REQUEST(xSyncGetPriorityReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
- swapl(&stuff->id, n);
-
- return ProcSyncGetPriority(client);
-}
-
-static int
-SProcSyncCreateFence(ClientPtr client)
-{
- REQUEST(xSyncCreateFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncCreateFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncCreateFence(client);
-}
-
-static int
-SProcSyncTriggerFence(ClientPtr client)
-{
- REQUEST(xSyncTriggerFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncTriggerFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncTriggerFence(client);
-}
-
-static int
-SProcSyncResetFence(ClientPtr client)
-{
- REQUEST(xSyncResetFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncResetFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncResetFence(client);
-}
-
-static int
-SProcSyncDestroyFence(ClientPtr client)
-{
- REQUEST(xSyncDestroyFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncDestroyFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncDestroyFence(client);
-}
-
-static int
-SProcSyncQueryFence(ClientPtr client)
-{
- REQUEST(xSyncQueryFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncQueryFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncQueryFence(client);
-}
-
-static int
-SProcSyncAwaitFence(ClientPtr client)
-{
- REQUEST(xSyncAwaitFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
- SwapRestL(stuff);
-
- return ProcSyncAwaitFence(client);
-}
-
-static int
-SProcSyncDispatch(ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data)
- {
- case X_SyncInitialize:
- return SProcSyncInitialize(client);
- case X_SyncListSystemCounters:
- return SProcSyncListSystemCounters(client);
- case X_SyncCreateCounter:
- return SProcSyncCreateCounter(client);
- case X_SyncSetCounter:
- return SProcSyncSetCounter(client);
- case X_SyncChangeCounter:
- return SProcSyncChangeCounter(client);
- case X_SyncQueryCounter:
- return SProcSyncQueryCounter(client);
- case X_SyncDestroyCounter:
- return SProcSyncDestroyCounter(client);
- case X_SyncAwait:
- return SProcSyncAwait(client);
- case X_SyncCreateAlarm:
- return SProcSyncCreateAlarm(client);
- case X_SyncChangeAlarm:
- return SProcSyncChangeAlarm(client);
- case X_SyncQueryAlarm:
- return SProcSyncQueryAlarm(client);
- case X_SyncDestroyAlarm:
- return SProcSyncDestroyAlarm(client);
- case X_SyncSetPriority:
- return SProcSyncSetPriority(client);
- case X_SyncGetPriority:
- return SProcSyncGetPriority(client);
- case X_SyncCreateFence:
- return SProcSyncCreateFence(client);
- case X_SyncTriggerFence:
- return SProcSyncTriggerFence(client);
- case X_SyncResetFence:
- return SProcSyncResetFence(client);
- case X_SyncDestroyFence:
- return SProcSyncDestroyFence(client);
- case X_SyncQueryFence:
- return SProcSyncQueryFence(client);
- case X_SyncAwaitFence:
- return SProcSyncAwaitFence(client);
- default:
- return BadRequest;
- }
-}
-
-/*
- * Event Swapping
- */
-
-static void
-SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to)
-{
- to->type = from->type;
- to->kind = from->kind;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->counter, to->counter);
- cpswapl(from->wait_value_lo, to->wait_value_lo);
- cpswapl(from->wait_value_hi, to->wait_value_hi);
- cpswapl(from->counter_value_lo, to->counter_value_lo);
- cpswapl(from->counter_value_hi, to->counter_value_hi);
- cpswapl(from->time, to->time);
- cpswaps(from->count, to->count);
- to->destroyed = from->destroyed;
-}
-
-
-static void
-SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to)
-{
- to->type = from->type;
- to->kind = from->kind;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->alarm, to->alarm);
- cpswapl(from->counter_value_lo, to->counter_value_lo);
- cpswapl(from->counter_value_hi, to->counter_value_hi);
- cpswapl(from->alarm_value_lo, to->alarm_value_lo);
- cpswapl(from->alarm_value_hi, to->alarm_value_hi);
- cpswapl(from->time, to->time);
- to->state = from->state;
-}
-
-/*
- * ** Close everything down. ** This is fairly simple for now.
- */
-/* ARGSUSED */
-static void
-SyncResetProc(ExtensionEntry *extEntry)
-{
- free(SysCounterList);
- SysCounterList = NULL;
- RTCounter = 0;
-}
-
-/*
- * ** Initialise the extension.
- */
-void
-SyncExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- int s;
-
- for (s = 0; s < screenInfo.numScreens; s++)
- miSyncSetup(screenInfo.screens[s]);
-
- if (RTCounter == 0)
- {
- RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
- }
- RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
- RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
- RTFence = CreateNewResourceType(FreeFence, "SyncFence");
- if (RTAwait)
- RTAwait |= RC_NEVERRETAIN;
- RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
- if (RTAlarmClient)
- RTAlarmClient |= RC_NEVERRETAIN;
-
- if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
- RTAlarmClient == 0 ||
- (extEntry = AddExtension(SYNC_NAME,
- XSyncNumberEvents, XSyncNumberErrors,
- ProcSyncDispatch, SProcSyncDispatch,
- SyncResetProc,
- StandardMinorOpcode)) == NULL)
- {
- ErrorF("Sync Extension %d.%d failed to Initialise\n",
- SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
- return;
- }
-
- SyncEventBase = extEntry->eventBase;
- SyncErrorBase = extEntry->errorBase;
- EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
- EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
-
- SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
- SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
- SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
-
- /*
- * Although SERVERTIME is implemented by the OS layer, we initialise it
- * here because doing it in OsInit() is too early. The resource database
- * is not initialised when OsInit() is called. This is just about OK
- * because there is always a servertime counter.
- */
- SyncInitServerTime();
- SyncInitIdleTime();
-
-#ifdef DEBUG
- fprintf(stderr, "Sync Extension %d.%d\n",
- SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
-#endif
-}
-
-
-/*
- * ***** SERVERTIME implementation - should go in its own file in OS directory?
- */
-
-
-
-static pointer ServertimeCounter;
-static XSyncValue Now;
-static XSyncValue *pnext_time;
-
-#define GetTime()\
-{\
- unsigned long millis = GetTimeInMillis();\
- unsigned long maxis = XSyncValueHigh32(Now);\
- if (millis < XSyncValueLow32(Now)) maxis++;\
- XSyncIntsToValue(&Now, millis, maxis);\
-}
-
-/*
-*** Server Block Handler
-*** code inspired by multibuffer extension (now deprecated)
- */
-/*ARGSUSED*/
-static void
-ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask)
-{
- XSyncValue delay;
- unsigned long timeout;
-
- if (pnext_time)
- {
- GetTime();
-
- if (XSyncValueGreaterOrEqual(Now, *pnext_time))
- {
- timeout = 0;
- }
- else
- {
- Bool overflow;
- XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
- (void)overflow;
- timeout = XSyncValueLow32(delay);
- }
- AdjustWaitForDelay(wt, timeout); /* os/utils.c */
- }
-}
-
-/*
-*** Wakeup Handler
- */
-/*ARGSUSED*/
-static void
-ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask)
-{
- if (pnext_time)
- {
- GetTime();
-
- if (XSyncValueGreaterOrEqual(Now, *pnext_time))
- {
- SyncChangeCounter(ServertimeCounter, Now);
- }
- }
-}
-
-static void
-ServertimeQueryValue(void *pCounter, CARD64 *pValue_return)
-{
- GetTime();
- *pValue_return = Now;
-}
-
-static void
-ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less,
- CARD64 *pbracket_greater)
-{
- if (!pnext_time && pbracket_greater)
- {
- RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
- ServertimeWakeupHandler,
- NULL);
- }
- else if (pnext_time && !pbracket_greater)
- {
- RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
- ServertimeWakeupHandler,
- NULL);
- }
- pnext_time = pbracket_greater;
-}
-
-static void
-SyncInitServerTime(void)
-{
- CARD64 resolution;
-
- XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
- XSyncIntToValue(&resolution, 4);
- ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
- XSyncCounterNeverDecreases,
- ServertimeQueryValue, ServertimeBracketValues);
- pnext_time = NULL;
-}
-
-
-
-/*
- * IDLETIME implementation
- */
-
-static SyncCounter *IdleTimeCounter;
-static XSyncValue *pIdleTimeValueLess;
-static XSyncValue *pIdleTimeValueGreater;
-
-static void
-IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
-{
- CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
- XSyncIntsToValue (pValue_return, idle, 0);
-}
-
-static void
-IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
-{
- XSyncValue idle, old_idle;
- SyncTriggerList *list = IdleTimeCounter->sync.pTriglist;
- SyncTrigger *trig;
-
- if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
- return;
-
- old_idle = IdleTimeCounter->value;
- IdleTimeQueryValue (NULL, &idle);
- IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
-
- if (pIdleTimeValueLess &&
- XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
- {
- /*
- * We've been idle for less than the threshold value, and someone
- * wants to know about that, but now we need to know whether they
- * want level or edge trigger. Check the trigger list against the
- * current idle time, and if any succeed, bomb out of select()
- * immediately so we can reschedule.
- */
-
- for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
- trig = list->pTrigger;
- if (trig->CheckTrigger(trig, old_idle)) {
- AdjustWaitForDelay(wt, 0);
- break;
- }
- }
- }
- else if (pIdleTimeValueGreater)
- {
- /*
- * There's a threshold in the positive direction. If we've been
- * idle less than it, schedule a wakeup for sometime in the future.
- * If we've been idle more than it, and someone wants to know about
- * that level-triggered, schedule an immediate wakeup.
- */
- unsigned long timeout = -1;
-
- if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
- XSyncValue value;
- Bool overflow;
-
- XSyncValueSubtract (&value, *pIdleTimeValueGreater,
- idle, &overflow);
- timeout = min(timeout, XSyncValueLow32 (value));
- } else {
- for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
- trig = list->pTrigger;
- if (trig->CheckTrigger(trig, old_idle)) {
- timeout = min(timeout, 0);
- break;
- }
- }
- }
-
- AdjustWaitForDelay (wt, timeout);
- }
-
- IdleTimeCounter->value = old_idle; /* pop */
-}
-
-static void
-IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask)
-{
- XSyncValue idle;
-
- if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
- return;
-
- IdleTimeQueryValue (NULL, &idle);
-
- if ((pIdleTimeValueGreater &&
- XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) ||
- (pIdleTimeValueLess &&
- XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)))
- {
- SyncChangeCounter (IdleTimeCounter, idle);
- }
-}
-
-static void
-IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less,
- CARD64 *pbracket_greater)
-{
- Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater);
-
- if (registered && !pbracket_less && !pbracket_greater)
- {
- RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
- IdleTimeWakeupHandler,
- NULL);
- }
- else if (!registered && (pbracket_less || pbracket_greater))
- {
- RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
- IdleTimeWakeupHandler,
- NULL);
- }
-
- pIdleTimeValueGreater = pbracket_greater;
- pIdleTimeValueLess = pbracket_less;
-}
-
-static void
-SyncInitIdleTime (void)
-{
- CARD64 resolution;
- XSyncValue idle;
-
- IdleTimeQueryValue (NULL, &idle);
- XSyncIntToValue (&resolution, 4);
-
- IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution,
- XSyncCounterUnrestricted,
- IdleTimeQueryValue,
- IdleTimeBracketValues);
-
- pIdleTimeValueLess = pIdleTimeValueGreater = NULL;
-}
+/*
+
+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.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xmd.h>
+#include "scrnintstr.h"
+#include "os.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "pixmapstr.h"
+#include "resource.h"
+#include "opaque.h"
+#include <X11/extensions/syncproto.h>
+#include "syncsrv.h"
+#include "syncsdk.h"
+#include "protocol-versions.h"
+
+#include <stdio.h>
+#if !defined(WIN32)
+#include <sys/time.h>
+#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 RESTYPE RTFence;
+static int SyncNumSystemCounters = 0;
+static SyncCounter **SysCounterList = NULL;
+
+#define IsSystemCounter(pCounter) \
+ (pCounter && (pCounter->sync.client == NULL))
+
+/* these are all the alarm attributes that pertain to the alarm's trigger */
+#define XSyncCAAllTrigger \
+ (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
+
+static void SyncComputeBracketValues(SyncCounter *);
+
+static void SyncInitServerTime(void);
+
+static void SyncInitIdleTime(void);
+
+
+/* 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
+SyncDeleteTriggerFromSyncObject(SyncTrigger *pTrigger)
+{
+ SyncTriggerList *pCur;
+ SyncTriggerList *pPrev;
+ SyncCounter *pCounter;
+
+ /* pSync needs to be stored in pTrigger before calling here. */
+
+ if (!pTrigger->pSync)
+ return;
+
+ pPrev = NULL;
+ pCur = pTrigger->pSync->pTriglist;
+
+ while (pCur)
+ {
+ if (pCur->pTrigger == pTrigger)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pTrigger->pSync->pTriglist = pCur->next;
+
+ free(pCur);
+ break;
+ }
+
+ pPrev = pCur;
+ pCur = pCur->next;
+ }
+
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if (IsSystemCounter(pCounter))
+ SyncComputeBracketValues(pCounter);
+ } else if (SYNC_FENCE == pTrigger->pSync->type) {
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ pFence->funcs.DeleteTrigger(pTrigger);
+ }
+}
+
+
+static int
+SyncAddTriggerToSyncObject(SyncTrigger *pTrigger)
+{
+ SyncTriggerList *pCur;
+ SyncCounter *pCounter;
+
+ if (!pTrigger->pSync)
+ return Success;
+
+ /* don't do anything if it's already there */
+ for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next)
+ {
+ if (pCur->pTrigger == pTrigger)
+ return Success;
+ }
+
+ if (!(pCur = malloc(sizeof(SyncTriggerList))))
+ return BadAlloc;
+
+ pCur->pTrigger = pTrigger;
+ pCur->next = pTrigger->pSync->pTriglist;
+ pTrigger->pSync->pTriglist = pCur;
+
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if (IsSystemCounter(pCounter))
+ SyncComputeBracketValues(pCounter);
+ } else if (SYNC_FENCE == pTrigger->pSync->type) {
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ pFence->funcs.AddTrigger(pTrigger);
+ }
+
+ return Success;
+}
+
+
+/* Below are five possible functions that can be plugged into
+ * pTrigger->CheckTrigger for counter sync objects, corresponding to
+ * the four possible test-types, and the one possible function that
+ * can be plugged into pTrigger->CheckTrigger for fence sync objects.
+ * These functions are called after the sync object's state changes
+ * but are also passed the old state 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->pSync == NULL.
+ * This is because the spec says that a trigger with a sync value
+ * of None is always TRUE.
+ */
+
+static Bool
+SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ (XSyncValueLessThan(oldval, pTrigger->test_value) &&
+ XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
+ XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerFence(SyncTrigger *pTrigger, CARD64 unused)
+{
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ (void)unused;
+
+ return (pFence == NULL ||
+ pFence->funcs.CheckTriggered(pFence));
+}
+
+static int
+SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
+ RESTYPE resType, Mask changes)
+{
+ SyncObject *pSync = pTrigger->pSync;
+ SyncCounter *pCounter = NULL;
+ int rc;
+ Bool newSyncObject = FALSE;
+
+ if (changes & XSyncCACounter)
+ {
+ if (syncObject == None)
+ pSync = NULL;
+ else if (Success != (rc = dixLookupResourceByType ((pointer *)&pSync,
+ syncObject, resType, client, DixReadAccess)))
+ {
+ client->errorValue = syncObject;
+ return rc;
+ }
+ if (pSync != pTrigger->pSync)
+ { /* new counter for trigger */
+ SyncDeleteTriggerFromSyncObject(pTrigger);
+ pTrigger->pSync = pSync;
+ newSyncObject = TRUE;
+ }
+ }
+
+ /* if system counter, ask it what the current value is */
+
+ if (pSync && SYNC_COUNTER == pSync->type)
+ {
+ pCounter = (SyncCounter *)pSync;
+
+ 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 (pSync && SYNC_FENCE == pSync->type)
+ {
+ pTrigger->CheckTrigger = SyncCheckTriggerFence;
+ }
+ else
+ {
+ 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 (newSyncObject)
+ {
+ if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
+ return rc;
+ }
+ else if (pCounter && IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter);
+ }
+
+ 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(SyncAlarm *pAlarm)
+{
+ SyncAlarmClientList *pcl;
+ xSyncAlarmNotifyEvent ane;
+ SyncTrigger *pTrigger = &pAlarm->trigger;
+ SyncCounter *pCounter;
+
+ assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ UpdateCurrentTime();
+
+ ane.type = SyncEventBase + XSyncAlarmNotify;
+ ane.kind = XSyncAlarmNotify;
+ ane.alarm = pAlarm->alarm_id;
+ if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ ane.counter_value_hi = XSyncValueHigh32(pCounter->value);
+ ane.counter_value_lo = XSyncValueLow32(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)
+ WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
+
+ /* send to other interested clients */
+ for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
+ 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(ClientPtr client, SyncAwait **ppAwait,
+ int num_events)
+{
+ xSyncCounterNotifyEvent *pEvents, *pev;
+ int i;
+
+ if (client->clientGone)
+ return;
+ pev = pEvents = malloc(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->counter = pTrigger->pSync->id;
+ pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+ pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ SyncCounter *pCounter = (SyncCounter *)pTrigger->pSync;
+
+ pev->counter_value_lo = XSyncValueLow32(pCounter->value);
+ pev->counter_value_hi = XSyncValueHigh32(pCounter->value);
+ }
+ else
+ {
+ pev->counter_value_lo = 0;
+ pev->counter_value_hi = 0;
+ }
+
+ pev->time = currentTime.milliseconds;
+ pev->count = num_events - i - 1; /* events remaining */
+ pev->destroyed = pTrigger->pSync->beingDestroyed;
+ }
+ /* swapping will be taken care of by this */
+ WriteEventsToClient(client, num_events, (xEvent *)pEvents);
+ free(pEvents);
+}
+
+
+/* This function is called when an alarm's counter is destroyed.
+ * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
+ */
+static void
+SyncAlarmCounterDestroyed(SyncTrigger *pTrigger)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+
+ pAlarm->state = XSyncAlarmInactive;
+ SyncSendAlarmNotifyEvents(pAlarm);
+ pTrigger->pSync = NULL;
+}
+
+
+/* This function is called when an alarm "goes off."
+ * It is plugged into pTrigger->TriggerFired (for alarm triggers).
+ */
+static void
+SyncAlarmTriggerFired(SyncTrigger *pTrigger)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+ SyncCounter *pCounter;
+ CARD64 new_test_value;
+
+ assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ /* 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 (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;
+ SyncCounter *paCounter;
+
+ assert(!paTrigger->pSync || (SYNC_COUNTER == paTrigger->pSync->type));
+ paCounter = (SyncCounter *)pTrigger->pSync;
+
+ /* "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,
+ paCounter->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(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 = malloc(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.pSync->beingDestroyed)
+ {
+ ppAwait[num_events++] = pAwait;
+ continue;
+ }
+
+ if (SYNC_COUNTER == pAwait->trigger.pSync->type)
+ {
+ SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
+
+ /* "The difference between the counter and the test value is
+ * calculated by subtracting the test value from the value of
+ * the counter."
+ */
+ XSyncValueSubtract(&diff, 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);
+ free(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(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->sync.pTriglist; ptl; ptl = pnext)
+ {
+ pnext = ptl->next;
+ if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
+ (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
+ }
+
+ if (IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter);
+ }
+}
+
+
+/* loosely based on dix/events.c/EventSelectForWindow */
+static Bool
+SyncEventSelectForAlarm(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 = malloc(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))
+ {
+ free(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(ClientPtr client, SyncAlarm *pAlarm, Mask mask,
+ CARD32 *values)
+{
+ int status;
+ XSyncCounter counter;
+ Mask origmask = mask;
+
+ counter =
+ pAlarm->trigger.pSync ? pAlarm->trigger.pSync->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, RTCounter,
+ origmask & XSyncCAAllTrigger)) != Success)
+ return status;
+
+ /* XXX spec does not really say to do this - needs clarification */
+ pAlarm->state = XSyncAlarmActive;
+ return Success;
+}
+
+static SyncObject *
+SyncCreate(ClientPtr client, XID id, unsigned char type)
+{
+ SyncObject *pSync;
+ RESTYPE resType;
+
+ switch (type) {
+ case SYNC_COUNTER:
+ resType = RTCounter;
+ pSync = malloc(sizeof(SyncCounter));
+ break;
+ case SYNC_FENCE:
+ resType = RTFence;
+ pSync = dixAllocateObjectWithPrivates(SyncFence,
+ PRIVATE_SYNC_FENCE);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (!pSync)
+ return NULL;
+
+ if (!AddResource(id, resType, (pointer) pSync))
+ {
+ switch (type) {
+ case SYNC_FENCE:
+ dixFreeObjectWithPrivates((SyncFence *)pSync, PRIVATE_SYNC_FENCE);
+ break;
+ default:
+ free(pSync);
+ }
+
+ return NULL;
+ }
+
+ pSync->client = client;
+ pSync->id = id;
+ pSync->pTriglist = NULL;
+ pSync->beingDestroyed = FALSE;
+ pSync->type = type;
+
+ return pSync;
+}
+
+
+static SyncCounter *
+SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
+{
+ SyncCounter *pCounter;
+
+ if (!(pCounter = (SyncCounter *)SyncCreate(client,
+ id,
+ SYNC_COUNTER)))
+ return NULL;
+
+ pCounter->value = initialvalue;
+ pCounter->pSysCounterInfo = NULL;
+ return pCounter;
+}
+
+static int FreeCounter(void *, XID);
+
+/*
+ * ***** System Counter utilities
+ */
+
+pointer
+SyncCreateSystemCounter(
+ 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 = realloc(SysCounterList,
+ (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
+ if (!SysCounterList)
+ return 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, "SyncCounter");
+ if (RTCounter == 0)
+ {
+ return NULL;
+ }
+ }
+
+ pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
+
+ if (pCounter)
+ {
+ SysCounterInfo *psci;
+
+ psci = malloc(sizeof(SysCounterInfo));
+ if (!psci)
+ {
+ FreeResource(pCounter->sync.id, RT_NONE);
+ return 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 pCounter;
+}
+
+void
+SyncDestroySystemCounter(pointer pSysCounter)
+{
+ SyncCounter *pCounter = (SyncCounter *)pSysCounter;
+ FreeResource(pCounter->sync.id, RT_NONE);
+}
+
+static void
+SyncComputeBracketValues(SyncCounter *pCounter)
+{
+ SyncTriggerList *pCur;
+ SyncTrigger *pTrigger;
+ SysCounterInfo *psci;
+ CARD64 *pnewgtval = NULL;
+ CARD64 *pnewltval = NULL;
+ SyncCounterType ct;
+
+ if (!pCounter)
+ return;
+
+ psci = pCounter->pSysCounterInfo;
+ ct = pCounter->pSysCounterInfo->counterType;
+ if (ct == XSyncCounterNeverChanges)
+ return;
+
+ XSyncMaxValue(&psci->bracket_greater);
+ XSyncMinValue(&psci->bracket_less);
+
+ for (pCur = pCounter->sync.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 == XSyncNegativeTransition &&
+ ct != XSyncCounterNeverIncreases)
+ {
+ 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 (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
+ XSyncValueLessThan(pTrigger->test_value,
+ psci->bracket_greater))
+ {
+ /*
+ * The value is exactly equal to our threshold. We want one
+ * more event in the positive direction to ensure we pick up
+ * when the value *exceeds* this threshold.
+ */
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ }
+ }
+ else if (pTrigger->test_type == XSyncPositiveTransition &&
+ ct != XSyncCounterNeverDecreases)
+ {
+ 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 (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
+ XSyncValueGreaterThan(pTrigger->test_value,
+ psci->bracket_less))
+ {
+ /*
+ * The value is exactly equal to our threshold. We want one
+ * more event in the negative direction to ensure we pick up
+ * when the value is less than this threshold.
+ */
+ 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(void *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);
+
+ SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
+
+ free(pAlarm);
+ return Success;
+}
+
+
+/*
+ * ** Cleanup after the destruction of a Counter
+ */
+/* ARGSUSED */
+static int
+FreeCounter(void *env, XID id)
+{
+ SyncCounter *pCounter = (SyncCounter *) env;
+ SyncTriggerList *ptl, *pnext;
+
+ pCounter->sync.beingDestroyed = TRUE;
+ /* tell all the counter's triggers that the counter has been destroyed */
+ for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
+ {
+ (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
+ pnext = ptl->next;
+ free(ptl); /* destroy the trigger list as we go */
+ }
+ if (IsSystemCounter(pCounter))
+ {
+ int i, found = 0;
+
+ free(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--;
+ }
+ free(pCounter);
+ return Success;
+}
+
+/*
+ * ** Cleanup after Await
+ */
+/* ARGSUSED */
+static int
+FreeAwait(void *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.
+ */
+ SyncObject *pSync = pAwait->trigger.pSync;
+ if (pSync && !pSync->beingDestroyed)
+ SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
+ }
+ free(pAwaitUnion);
+ return Success;
+}
+
+#ifdef _MSC_VER
+#pragma warning(disable:4715) /* Not all control paths return a value */
+#endif
+
+/* loosely based on dix/events.c/OtherClientGone */
+static int
+FreeAlarmClient(void *value, 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;
+ free(pCur);
+ return Success;
+ }
+ }
+ FatalError("alarm client not on event list");
+ /*NOTREACHED*/
+}
+
+
+/*
+ * ***** Proc functions
+ */
+
+
+/*
+ * ** Initialize the extension
+ */
+static int
+ProcSyncInitialize(ClientPtr client)
+{
+ xSyncInitializeReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH(xSyncInitializeReq);
+
+ memset(&rep, 0, sizeof(xSyncInitializeReply));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_SYNC_MAJOR_VERSION;
+ rep.minorVersion = SERVER_SYNC_MINOR_VERSION;
+ rep.length = 0;
+
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ }
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ return Success;
+}
+
+/*
+ * ** Get list of system counters available through the extension
+ */
+static int
+ProcSyncListSystemCounters(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 += pad_to_int32(sz_xSyncSystemCounter + strlen(name));
+ }
+
+ if (len)
+ {
+ walklist = list = malloc(len);
+ if (!list)
+ return BadAlloc;
+ }
+
+ rep.length = bytes_to_int32(len);
+
+ if (client->swapped)
+ {
+ 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]->sync.id;
+ walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
+ walklist->resolution_lo = XSyncValueLow32(psci->resolution);
+ namelen = strlen(psci->name);
+ walklist->name_length = namelen;
+
+ if (client->swapped)
+ {
+ 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) +
+ pad_to_int32(sz_xSyncSystemCounter + namelen));
+ }
+
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ if (len)
+ {
+ WriteToClient(client, len, (char *) list);
+ free(list);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Set client Priority
+ */
+static int
+ProcSyncSetPriority(ClientPtr client)
+{
+ REQUEST(xSyncSetPriorityReq);
+ ClientPtr priorityclient;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else {
+ rc = dixLookupClient(&priorityclient, stuff->id, client,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncGetPriorityReq);
+ xSyncGetPriorityReply rep;
+ ClientPtr priorityclient;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else {
+ rc = dixLookupClient(&priorityclient, stuff->id, client,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.priority = priorityclient->priority;
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.priority, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
+
+ return Success;
+}
+
+/*
+ * ** Create a new counter
+ */
+static int
+ProcSyncCreateCounter(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 Success;
+}
+
+/*
+ * ** Set Counter value
+ */
+static int
+ProcSyncSetCounter(ClientPtr client)
+{
+ REQUEST(xSyncSetCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncSetCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncChangeCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ Bool overflow;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncDestroyCounterReq);
+ SyncCounter *pCounter;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->counter;
+ return BadAccess;
+ }
+ FreeResource(pCounter->sync.id, RT_NONE);
+ return Success;
+}
+
+static SyncAwaitUnion*
+SyncAwaitPrologue(ClientPtr client, int items)
+{
+ SyncAwaitUnion *pAwaitUnion;
+
+ /* all the memory for the entire await list is allocated
+ * here in one chunk
+ */
+ pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
+ if (!pAwaitUnion)
+ return NULL;
+
+ /* 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))
+ {
+ free(pAwaitUnion);
+ return NULL;
+ }
+
+ pAwaitUnion->header.client = client;
+ pAwaitUnion->header.num_waitconditions = 0;
+
+ return pAwaitUnion;
+}
+
+static void
+SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion)
+{
+ SyncAwait *pAwait;
+ int i;
+
+ 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++)
+ {
+ CARD64 value;
+
+ /* don't have to worry about NULL counters because the request
+ * errors before we get here out if they occur
+ */
+ switch (pAwait->trigger.pSync->type) {
+ case SYNC_COUNTER:
+ value = ((SyncCounter *)pAwait->trigger.pSync)->value;
+ break;
+ default:
+ XSyncIntToValue(&value, 0);
+ }
+
+ if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
+ {
+ (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
+ break; /* once is enough */
+ }
+ }
+}
+
+/*
+ * ** Await
+ */
+static int
+ProcSyncAwait(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;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
+
+ 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 sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = pProtocolWaitConds->counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ /* sanity checks are in SyncInitTrigger */
+ pAwait->trigger.pSync = 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, RTCounter,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ 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++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return Success;
+}
+
+
+/*
+ * ** Query a counter
+ */
+static int
+ProcSyncQueryCounter(ClientPtr client)
+{
+ REQUEST(xSyncQueryCounterReq);
+ xSyncQueryCounterReply rep;
+ SyncCounter *pCounter;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter,
+ RTCounter, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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)
+ {
+ 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 Success;
+}
+
+
+/*
+ * ** Create Alarm
+ */
+static int
+ProcSyncCreateAlarm(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 - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
+ /* 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 = malloc(sizeof(SyncAlarm))))
+ {
+ return BadAlloc;
+ }
+
+ /* set up defaults */
+
+ pTrigger = &pAlarm->trigger;
+ pTrigger->pSync = 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, RTCounter,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ free(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)
+ {
+ free(pAlarm);
+ return status;
+ }
+
+ if (!AddResource(stuff->id, RTAlarm, pAlarm))
+ {
+ free(pAlarm);
+ return BadAlloc;
+ }
+
+ /* see if alarm already triggered. NULL counter will not trigger
+ * in CreateAlarm and sets alarm state to Inactive.
+ */
+
+ if (!pTrigger->pSync)
+ {
+ pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
+ }
+ else
+ {
+ SyncCounter *pCounter;
+
+ assert(SYNC_COUNTER == pTrigger->pSync->type);
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if ((*pTrigger->CheckTrigger)(pTrigger, pCounter->value))
+ (*pTrigger->TriggerFired)(pTrigger);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Change Alarm
+ */
+static int
+ProcSyncChangeAlarm(ClientPtr client)
+{
+ REQUEST(xSyncChangeAlarmReq);
+ SyncAlarm *pAlarm;
+ SyncCounter *pCounter = NULL;
+ long vmask;
+ int len, status;
+
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+
+ status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixWriteAccess);
+ if (status != Success)
+ return status;
+
+ vmask = stuff->valueMask;
+ len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
+ /* 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;
+
+ if (pAlarm->trigger.pSync)
+ {
+ assert(SYNC_COUNTER == pAlarm->trigger.pSync->type);
+ pCounter = (SyncCounter *)pAlarm->trigger.pSync;
+ }
+
+ /* see if alarm already triggered. NULL counter WILL trigger
+ * in ChangeAlarm.
+ */
+
+ if (!pCounter ||
+ (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, pCounter->value))
+ {
+ (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
+ }
+ return Success;
+}
+
+static int
+ProcSyncQueryAlarm(ClientPtr client)
+{
+ REQUEST(xSyncQueryAlarmReq);
+ SyncAlarm *pAlarm;
+ xSyncQueryAlarmReply rep;
+ SyncTrigger *pTrigger;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply));
+ rep.sequenceNumber = client->sequence;
+
+ pTrigger = &pAlarm->trigger;
+ rep.counter = (pTrigger->pSync) ? pTrigger->pSync->id : None;
+
+#if 0 /* XXX unclear what to do, depends on whether relative value-types
+ * are "consumed" immediately and are considered absolute from then
+ * on.
+ */
+ rep.value_type = pTrigger->value_type;
+ rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
+ rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
+#else
+ rep.value_type = XSyncAbsolute;
+ rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+#endif
+
+ rep.test_type = pTrigger->test_type;
+ rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
+ rep.delta_lo = XSyncValueLow32(pAlarm->delta);
+ rep.events = pAlarm->events;
+ rep.state = pAlarm->state;
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.counter, n);
+ swapl(&rep.wait_value_hi, n);
+ swapl(&rep.wait_value_lo, n);
+ swapl(&rep.test_type, n);
+ swapl(&rep.delta_hi, n);
+ swapl(&rep.delta_lo, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
+ return Success;
+}
+
+static int
+ProcSyncDestroyAlarm(ClientPtr client)
+{
+ SyncAlarm *pAlarm;
+ int rc;
+ REQUEST(xSyncDestroyAlarmReq);
+
+ REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->alarm, RT_NONE);
+ return Success;
+}
+
+static int
+ProcSyncCreateFence(ClientPtr client)
+{
+ REQUEST(xSyncCreateFenceReq);
+ DrawablePtr pDraw;
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
+
+ rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ LEGAL_NEW_RESOURCE(stuff->fid, client);
+
+ if (!(pFence = (SyncFence *)SyncCreate(client,
+ stuff->fid,
+ SYNC_FENCE)))
+ return BadAlloc;
+
+ miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
+
+ return client->noClientException;
+}
+
+static int
+FreeFence(void *obj, XID id)
+{
+ SyncFence *pFence = (SyncFence *) obj;
+
+ miSyncDestroyFence(pFence);
+
+ return Success;
+}
+
+int SyncVerifyFence(SyncFence **ppSyncFence, XID fid,
+ ClientPtr client, Mask mode)
+{
+ int rc = dixLookupResourceByType((pointer *)ppSyncFence, fid, RTFence,
+ client, mode);
+
+ if (rc != Success)
+ client->errorValue = fid;
+
+ return rc;
+}
+
+static int
+ProcSyncTriggerFence(ClientPtr client)
+{
+ REQUEST(xSyncTriggerFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ miSyncTriggerFence(pFence);
+
+ return client->noClientException;
+}
+
+static int
+ProcSyncResetFence(ClientPtr client)
+{
+ REQUEST(xSyncResetFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncResetFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (pFence->funcs.CheckTriggered(pFence) != TRUE)
+ return BadMatch;
+
+ pFence->funcs.Reset(pFence);
+
+ return client->noClientException;
+}
+
+static int
+ProcSyncDestroyFence(ClientPtr client)
+{
+ REQUEST(xSyncDestroyFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->fid, RT_NONE);
+ return client->noClientException;
+}
+
+static int
+ProcSyncQueryFence(ClientPtr client)
+{
+ REQUEST(xSyncQueryFenceReq);
+ xSyncQueryFenceReply rep;
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid,
+ RTFence, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ rep.triggered = pFence->funcs.CheckTriggered(pFence);
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncQueryFenceReply), (char *) &rep);
+ return client->noClientException;
+}
+
+static int
+ProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait *pAwait;
+ /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
+ * CARD32 in protocol definitions */
+ CARD32 *pProtocolFences;
+ int status;
+ int len;
+ int items;
+ int i;
+
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+
+ len = client->req_len << 2;
+ len -= sz_xSyncAwaitFenceReq;
+ items = len / sizeof(CARD32);
+
+ if (items * sizeof(CARD32) != len)
+ {
+ return BadLength;
+ }
+ if (items == 0)
+ {
+ client->errorValue = items; /* XXX protocol change */
+ return BadValue;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolFences = (CARD32 *) & stuff[1];
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pProtocolFences++, pAwait++)
+ {
+ if (*pProtocolFences == None) /* XXX protocol change */
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = *pProtocolFences;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ pAwait->trigger.pSync = NULL;
+ /* Provide acceptable values for these unused fields to
+ * satisfy SyncInitTrigger's validation logic
+ */
+ pAwait->trigger.value_type = XSyncAbsolute;
+ XSyncIntToValue(&pAwait->trigger.wait_value, 0);
+ pAwait->trigger.test_type = 0;
+
+ status = SyncInitTrigger(client, &pAwait->trigger,
+ *pProtocolFences, RTFence,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ 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;
+ /* event_threshold is unused for fence syncs */
+ XSyncIntToValue(&pAwait->event_threshold, 0);
+ pAwait->pHeader = &pAwaitUnion->header;
+ pAwaitUnion->header.num_waitconditions++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return client->noClientException;
+}
+
+/*
+ * ** Given an extension request, call the appropriate request procedure
+ */
+static int
+ProcSyncDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SyncInitialize:
+ return ProcSyncInitialize(client);
+ case X_SyncListSystemCounters:
+ return ProcSyncListSystemCounters(client);
+ case X_SyncCreateCounter:
+ return ProcSyncCreateCounter(client);
+ case X_SyncSetCounter:
+ return ProcSyncSetCounter(client);
+ case X_SyncChangeCounter:
+ return ProcSyncChangeCounter(client);
+ case X_SyncQueryCounter:
+ return ProcSyncQueryCounter(client);
+ case X_SyncDestroyCounter:
+ return ProcSyncDestroyCounter(client);
+ case X_SyncAwait:
+ return ProcSyncAwait(client);
+ case X_SyncCreateAlarm:
+ return ProcSyncCreateAlarm(client);
+ case X_SyncChangeAlarm:
+ return ProcSyncChangeAlarm(client);
+ case X_SyncQueryAlarm:
+ return ProcSyncQueryAlarm(client);
+ case X_SyncDestroyAlarm:
+ return ProcSyncDestroyAlarm(client);
+ case X_SyncSetPriority:
+ return ProcSyncSetPriority(client);
+ case X_SyncGetPriority:
+ return ProcSyncGetPriority(client);
+ case X_SyncCreateFence:
+ return ProcSyncCreateFence(client);
+ case X_SyncTriggerFence:
+ return ProcSyncTriggerFence(client);
+ case X_SyncResetFence:
+ return ProcSyncResetFence(client);
+ case X_SyncDestroyFence:
+ return ProcSyncDestroyFence(client);
+ case X_SyncQueryFence:
+ return ProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return ProcSyncAwaitFence(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Boring Swapping stuff ...
+ */
+
+static int
+SProcSyncInitialize(ClientPtr client)
+{
+ REQUEST(xSyncInitializeReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncInitializeReq);
+
+ return ProcSyncInitialize(client);
+}
+
+static int
+SProcSyncListSystemCounters(ClientPtr client)
+{
+ REQUEST(xSyncListSystemCountersReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
+
+ return ProcSyncListSystemCounters(client);
+}
+
+static int
+SProcSyncCreateCounter(ClientPtr client)
+{
+ REQUEST(xSyncCreateCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->initial_value_lo, n);
+ swapl(&stuff->initial_value_hi, n);
+
+ return ProcSyncCreateCounter(client);
+}
+
+static int
+SProcSyncSetCounter(ClientPtr client)
+{
+ REQUEST(xSyncSetCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->value_lo, n);
+ swapl(&stuff->value_hi, n);
+
+ return ProcSyncSetCounter(client);
+}
+
+static int
+SProcSyncChangeCounter(ClientPtr client)
+{
+ REQUEST(xSyncChangeCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->value_lo, n);
+ swapl(&stuff->value_hi, n);
+
+ return ProcSyncChangeCounter(client);
+}
+
+static int
+SProcSyncQueryCounter(ClientPtr client)
+{
+ REQUEST(xSyncQueryCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncQueryCounter(client);
+}
+
+static int
+SProcSyncDestroyCounter(ClientPtr client)
+{
+ REQUEST(xSyncDestroyCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncDestroyCounter(client);
+}
+
+static int
+SProcSyncAwait(ClientPtr client)
+{
+ REQUEST(xSyncAwaitReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwait(client);
+}
+
+static int
+SProcSyncCreateAlarm(ClientPtr client)
+{
+ REQUEST(xSyncCreateAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+
+ return ProcSyncCreateAlarm(client);
+}
+
+static int
+SProcSyncChangeAlarm(ClientPtr client)
+{
+ REQUEST(xSyncChangeAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+ swapl(&stuff->alarm, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+ return ProcSyncChangeAlarm(client);
+}
+
+static int
+SProcSyncQueryAlarm(ClientPtr client)
+{
+ REQUEST(xSyncQueryAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncQueryAlarm(client);
+}
+
+static int
+SProcSyncDestroyAlarm(ClientPtr client)
+{
+ REQUEST(xSyncDestroyAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncDestroyAlarm(client);
+}
+
+static int
+SProcSyncSetPriority(ClientPtr client)
+{
+ REQUEST(xSyncSetPriorityReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->priority, n);
+
+ return ProcSyncSetPriority(client);
+}
+
+static int
+SProcSyncGetPriority(ClientPtr client)
+{
+ REQUEST(xSyncGetPriorityReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
+ swapl(&stuff->id, n);
+
+ return ProcSyncGetPriority(client);
+}
+
+static int
+SProcSyncCreateFence(ClientPtr client)
+{
+ REQUEST(xSyncCreateFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncCreateFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncCreateFence(client);
+}
+
+static int
+SProcSyncTriggerFence(ClientPtr client)
+{
+ REQUEST(xSyncTriggerFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncTriggerFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncTriggerFence(client);
+}
+
+static int
+SProcSyncResetFence(ClientPtr client)
+{
+ REQUEST(xSyncResetFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncResetFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncResetFence(client);
+}
+
+static int
+SProcSyncDestroyFence(ClientPtr client)
+{
+ REQUEST(xSyncDestroyFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncDestroyFence(client);
+}
+
+static int
+SProcSyncQueryFence(ClientPtr client)
+{
+ REQUEST(xSyncQueryFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncQueryFence(client);
+}
+
+static int
+SProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwaitFence(client);
+}
+
+static int
+SProcSyncDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SyncInitialize:
+ return SProcSyncInitialize(client);
+ case X_SyncListSystemCounters:
+ return SProcSyncListSystemCounters(client);
+ case X_SyncCreateCounter:
+ return SProcSyncCreateCounter(client);
+ case X_SyncSetCounter:
+ return SProcSyncSetCounter(client);
+ case X_SyncChangeCounter:
+ return SProcSyncChangeCounter(client);
+ case X_SyncQueryCounter:
+ return SProcSyncQueryCounter(client);
+ case X_SyncDestroyCounter:
+ return SProcSyncDestroyCounter(client);
+ case X_SyncAwait:
+ return SProcSyncAwait(client);
+ case X_SyncCreateAlarm:
+ return SProcSyncCreateAlarm(client);
+ case X_SyncChangeAlarm:
+ return SProcSyncChangeAlarm(client);
+ case X_SyncQueryAlarm:
+ return SProcSyncQueryAlarm(client);
+ case X_SyncDestroyAlarm:
+ return SProcSyncDestroyAlarm(client);
+ case X_SyncSetPriority:
+ return SProcSyncSetPriority(client);
+ case X_SyncGetPriority:
+ return SProcSyncGetPriority(client);
+ case X_SyncCreateFence:
+ return SProcSyncCreateFence(client);
+ case X_SyncTriggerFence:
+ return SProcSyncTriggerFence(client);
+ case X_SyncResetFence:
+ return SProcSyncResetFence(client);
+ case X_SyncDestroyFence:
+ return SProcSyncDestroyFence(client);
+ case X_SyncQueryFence:
+ return SProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return SProcSyncAwaitFence(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Event Swapping
+ */
+
+static void
+SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to)
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->counter, to->counter);
+ cpswapl(from->wait_value_lo, to->wait_value_lo);
+ cpswapl(from->wait_value_hi, to->wait_value_hi);
+ cpswapl(from->counter_value_lo, to->counter_value_lo);
+ cpswapl(from->counter_value_hi, to->counter_value_hi);
+ cpswapl(from->time, to->time);
+ cpswaps(from->count, to->count);
+ to->destroyed = from->destroyed;
+}
+
+
+static void
+SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to)
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->alarm, to->alarm);
+ cpswapl(from->counter_value_lo, to->counter_value_lo);
+ cpswapl(from->counter_value_hi, to->counter_value_hi);
+ cpswapl(from->alarm_value_lo, to->alarm_value_lo);
+ cpswapl(from->alarm_value_hi, to->alarm_value_hi);
+ cpswapl(from->time, to->time);
+ to->state = from->state;
+}
+
+/*
+ * ** Close everything down. ** This is fairly simple for now.
+ */
+/* ARGSUSED */
+static void
+SyncResetProc(ExtensionEntry *extEntry)
+{
+ free(SysCounterList);
+ SysCounterList = NULL;
+ RTCounter = 0;
+}
+
+/*
+ * ** Initialise the extension.
+ */
+void
+SyncExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ miSyncSetup(screenInfo.screens[s]);
+
+ if (RTCounter == 0)
+ {
+ RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
+ }
+ RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
+ RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
+ RTFence = CreateNewResourceType(FreeFence, "SyncFence");
+ if (RTAwait)
+ RTAwait |= RC_NEVERRETAIN;
+ RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
+ if (RTAlarmClient)
+ RTAlarmClient |= RC_NEVERRETAIN;
+
+ if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
+ RTAlarmClient == 0 ||
+ (extEntry = AddExtension(SYNC_NAME,
+ XSyncNumberEvents, XSyncNumberErrors,
+ ProcSyncDispatch, SProcSyncDispatch,
+ SyncResetProc,
+ StandardMinorOpcode)) == NULL)
+ {
+ ErrorF("Sync Extension %d.%d failed to Initialise\n",
+ SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
+ return;
+ }
+
+ SyncEventBase = extEntry->eventBase;
+ SyncErrorBase = extEntry->errorBase;
+ EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
+ EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
+
+ SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
+ SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
+ SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
+
+ /*
+ * Although SERVERTIME is implemented by the OS layer, we initialise it
+ * here because doing it in OsInit() is too early. The resource database
+ * is not initialised when OsInit() is called. This is just about OK
+ * because there is always a servertime counter.
+ */
+ SyncInitServerTime();
+ SyncInitIdleTime();
+
+#ifdef DEBUG
+ fprintf(stderr, "Sync Extension %d.%d\n",
+ SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
+#endif
+}
+
+
+/*
+ * ***** SERVERTIME implementation - should go in its own file in OS directory?
+ */
+
+
+
+static pointer ServertimeCounter;
+static XSyncValue Now;
+static XSyncValue *pnext_time;
+
+#define GetTime()\
+{\
+ unsigned long millis = GetTimeInMillis();\
+ unsigned long maxis = XSyncValueHigh32(Now);\
+ if (millis < XSyncValueLow32(Now)) maxis++;\
+ XSyncIntsToValue(&Now, millis, maxis);\
+}
+
+/*
+*** Server Block Handler
+*** code inspired by multibuffer extension (now deprecated)
+ */
+/*ARGSUSED*/
+static void
+ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask)
+{
+ XSyncValue delay;
+ unsigned long timeout;
+
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ timeout = 0;
+ }
+ else
+ {
+ Bool overflow;
+ XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
+ (void)overflow;
+ timeout = XSyncValueLow32(delay);
+ }
+ AdjustWaitForDelay(wt, timeout); /* os/utils.c */
+ }
+}
+
+/*
+*** Wakeup Handler
+ */
+/*ARGSUSED*/
+static void
+ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask)
+{
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ SyncChangeCounter(ServertimeCounter, Now);
+ }
+ }
+}
+
+static void
+ServertimeQueryValue(void *pCounter, CARD64 *pValue_return)
+{
+ GetTime();
+ *pValue_return = Now;
+}
+
+static void
+ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less,
+ CARD64 *pbracket_greater)
+{
+ if (!pnext_time && pbracket_greater)
+ {
+ RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
+ ServertimeWakeupHandler,
+ NULL);
+ }
+ else if (pnext_time && !pbracket_greater)
+ {
+ RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
+ ServertimeWakeupHandler,
+ NULL);
+ }
+ pnext_time = pbracket_greater;
+}
+
+static void
+SyncInitServerTime(void)
+{
+ CARD64 resolution;
+
+ XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
+ XSyncIntToValue(&resolution, 4);
+ ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
+ XSyncCounterNeverDecreases,
+ ServertimeQueryValue, ServertimeBracketValues);
+ pnext_time = NULL;
+}
+
+
+
+/*
+ * IDLETIME implementation
+ */
+
+static SyncCounter *IdleTimeCounter;
+static XSyncValue *pIdleTimeValueLess;
+static XSyncValue *pIdleTimeValueGreater;
+
+static void
+IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
+{
+ CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
+ XSyncIntsToValue (pValue_return, idle, 0);
+}
+
+static void
+IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
+{
+ XSyncValue idle, old_idle;
+ SyncTriggerList *list = IdleTimeCounter->sync.pTriglist;
+ SyncTrigger *trig;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ old_idle = IdleTimeCounter->value;
+ IdleTimeQueryValue (NULL, &idle);
+ IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
+
+ if (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
+ {
+ /*
+ * We've been idle for less than the threshold value, and someone
+ * wants to know about that, but now we need to know whether they
+ * want level or edge trigger. Check the trigger list against the
+ * current idle time, and if any succeed, bomb out of select()
+ * immediately so we can reschedule.
+ */
+
+ for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
+ trig = list->pTrigger;
+ if (trig->CheckTrigger(trig, old_idle)) {
+ AdjustWaitForDelay(wt, 0);
+ break;
+ }
+ }
+ /*
+ * We've been called exactly on the idle time, but we have a
+ * NegativeTransition trigger which requires a transition from an
+ * idle time greater than this. Schedule a wakeup for the next
+ * millisecond so we won't miss a transition.
+ */
+ if (XSyncValueEqual (idle, *pIdleTimeValueLess))
+ AdjustWaitForDelay(wt, 1);
+ }
+ else if (pIdleTimeValueGreater)
+ {
+ /*
+ * There's a threshold in the positive direction. If we've been
+ * idle less than it, schedule a wakeup for sometime in the future.
+ * If we've been idle more than it, and someone wants to know about
+ * that level-triggered, schedule an immediate wakeup.
+ */
+ unsigned long timeout = -1;
+
+ if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
+ XSyncValue value;
+ Bool overflow;
+
+ XSyncValueSubtract (&value, *pIdleTimeValueGreater,
+ idle, &overflow);
+ timeout = min(timeout, XSyncValueLow32 (value));
+ } else {
+ for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
+ trig = list->pTrigger;
+ if (trig->CheckTrigger(trig, old_idle)) {
+ timeout = min(timeout, 0);
+ break;
+ }
+ }
+ }
+
+ AdjustWaitForDelay (wt, timeout);
+ }
+
+ IdleTimeCounter->value = old_idle; /* pop */
+}
+
+static void
+IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask)
+{
+ XSyncValue idle;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ IdleTimeQueryValue (NULL, &idle);
+
+ if ((pIdleTimeValueGreater &&
+ XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) ||
+ (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)))
+ {
+ SyncChangeCounter (IdleTimeCounter, idle);
+ }
+}
+
+static void
+IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less,
+ CARD64 *pbracket_greater)
+{
+ Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater);
+
+ if (registered && !pbracket_less && !pbracket_greater)
+ {
+ RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
+ IdleTimeWakeupHandler,
+ NULL);
+ }
+ else if (!registered && (pbracket_less || pbracket_greater))
+ {
+ RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
+ IdleTimeWakeupHandler,
+ NULL);
+ }
+
+ pIdleTimeValueGreater = pbracket_greater;
+ pIdleTimeValueLess = pbracket_less;
+}
+
+static void
+SyncInitIdleTime (void)
+{
+ CARD64 resolution;
+ XSyncValue idle;
+
+ IdleTimeQueryValue (NULL, &idle);
+ XSyncIntToValue (&resolution, 4);
+
+ IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution,
+ XSyncCounterUnrestricted,
+ IdleTimeQueryValue,
+ IdleTimeBracketValues);
+
+ pIdleTimeValueLess = pIdleTimeValueGreater = NULL;
+}
diff --git a/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c
index 356a6152b..da3528783 100644
--- a/xorg-server/Xext/xf86bigfont.c
+++ b/xorg-server/Xext/xf86bigfont.c
@@ -1,751 +1,751 @@
-/*
- * BIGFONT extension for sharing font metrics between clients (if possible)
- * and for transmitting font metrics to clients in a compressed form.
- *
- * Copyright (c) 1999-2000 Bruno Haible
- * Copyright (c) 1999-2000 The XFree86 Project, Inc.
- */
-
-/* THIS IS NOT AN X CONSORTIUM STANDARD */
-
-/*
- * Big fonts suffer from the following: All clients that have opened a
- * font can access the complete glyph metrics array (the XFontStruct member
- * `per_char') directly, without going through a macro. Moreover these
- * glyph metrics are ink metrics, i.e. are not redundant even for a
- * fixed-width font. For a Unicode font, the size of this array is 768 KB.
- *
- * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
- * metrics data is piped through the socket when the font is opened.
- *
- * This extension addresses these two problems for local clients, by using
- * shared memory. It also addresses the second problem for non-local clients,
- * by compressing the data before transmit by a factor of nearly 6.
- *
- * If you use this extension, your OS ought to nicely support shared memory.
- * This means: Shared memory should be swappable to the swap, and the limits
- * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
- * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
- * on segments that have already been marked "removed", because it permits
- * these segments to be cleaned up by the OS if the X server is killed with
- * signal SIGKILL.
- *
- * This extension is transparently exploited by Xlib (functions XQueryFont,
- * XLoadQueryFont).
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAS_SHM
-#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
-/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
-/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
- Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
- PAGE_SIZE. It is defined in <asm/page.h>. */
-#include <asm/page.h>
-#endif
-#ifdef SVR4
-#include <sys/sysmacros.h>
-#endif
-#if defined(__CYGWIN__) || defined(__SCO__)
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#endif
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "gcstruct.h"
-#include "dixfontstr.h"
-#include "extnsionst.h"
-#include "protocol-versions.h"
-
-#include <X11/extensions/xf86bigfproto.h>
-#include "xf86bigfontsrv.h"
-
-static void XF86BigfontResetProc(
- ExtensionEntry * /* extEntry */
- );
-
-
-#ifdef HAS_SHM
-
-/* A random signature, transmitted to the clients so they can verify that the
- shared memory segment they are attaching to was really established by the
- X server they are talking to. */
-static CARD32 signature;
-
-/* Index for additional information stored in a FontRec's devPrivates array. */
-static int FontShmdescIndex;
-
-static unsigned int pagesize;
-
-static Bool badSysCall = FALSE;
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
-
-#include <sys/signal.h>
-
-static void
-SigSysHandler(
- int signo)
-{
- badSysCall = TRUE;
-}
-
-static Bool
-CheckForShmSyscall(void)
-{
- void (*oldHandler)(int);
- int shmid = -1;
-
- /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
- oldHandler = signal(SIGSYS, SigSysHandler);
-
- badSysCall = FALSE;
- shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
- if (shmid != -1)
- {
- /* Successful allocation - clean up */
- shmctl(shmid, IPC_RMID, NULL);
- }
- else
- {
- /* Allocation failed */
- badSysCall = TRUE;
- }
- signal(SIGSYS, oldHandler);
- return !badSysCall;
-}
-
-#define MUST_CHECK_FOR_SHM_SYSCALL
-
-#endif
-
-#endif
-
-void
-XFree86BigfontExtensionInit(void)
-{
- if (AddExtension(XF86BIGFONTNAME,
- XF86BigfontNumberEvents,
- XF86BigfontNumberErrors,
- ProcXF86BigfontDispatch,
- SProcXF86BigfontDispatch,
- XF86BigfontResetProc,
- StandardMinorOpcode)) {
-#ifdef HAS_SHM
-#ifdef MUST_CHECK_FOR_SHM_SYSCALL
- /*
- * Note: Local-clients will not be optimized without shared memory
- * support. Remote-client optimization does not depend on shared
- * memory support. Thus, the extension is still registered even
- * when shared memory support is not functional.
- */
- if (!CheckForShmSyscall()) {
- ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
- return;
- }
-#endif
-
- srand((unsigned int) time(NULL));
- signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
- + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
- /* fprintf(stderr, "signature = 0x%08X\n", signature); */
-
- FontShmdescIndex = AllocateFontPrivateIndex();
-
-#if !defined(CSRG_BASED) && !defined(__CYGWIN__)
- pagesize = SHMLBA;
-#else
-# ifdef _SC_PAGESIZE
- pagesize = sysconf(_SC_PAGESIZE);
-# else
- pagesize = getpagesize();
-# endif
-#endif
-#endif
- }
-}
-
-
-/* ========== Management of shared memory segments ========== */
-
-#ifdef HAS_SHM
-
-#ifdef __linux__
-/* On Linux, shared memory marked as "removed" can still be attached.
- Nice feature, because the kernel will automatically free the associated
- storage when the server and all clients are gone. */
-#define EARLY_REMOVE
-#endif
-
-typedef struct _ShmDesc {
- struct _ShmDesc *next;
- struct _ShmDesc **prev;
- int shmid;
- char *attach_addr;
-} ShmDescRec, *ShmDescPtr;
-
-static ShmDescPtr ShmList = (ShmDescPtr) NULL;
-
-static ShmDescPtr
-shmalloc(
- unsigned int size)
-{
- ShmDescPtr pDesc;
- int shmid;
- char *addr;
-
-#ifdef MUST_CHECK_FOR_SHM_SYSCALL
- if (pagesize == 0)
- return (ShmDescPtr) NULL;
-#endif
-
- /* On some older Linux systems, the number of shared memory segments
- system-wide is 127. In Linux 2.4, it is 4095.
- Therefore there is a tradeoff to be made between allocating a
- shared memory segment on one hand, and allocating memory and piping
- the glyph metrics on the other hand. If the glyph metrics size is
- small, we prefer the traditional way. */
- if (size < 3500)
- return (ShmDescPtr) NULL;
-
- pDesc = malloc(sizeof(ShmDescRec));
- if (!pDesc)
- return (ShmDescPtr) NULL;
-
- size = (size + pagesize-1) & -pagesize;
- shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
- if (shmid == -1) {
- ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
- size, strerror(errno));
- free(pDesc);
- return (ShmDescPtr) NULL;
- }
-
- if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
- ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
- size, strerror(errno));
- shmctl(shmid, IPC_RMID, (void *) 0);
- free(pDesc);
- return (ShmDescPtr) NULL;
- }
-
-#ifdef EARLY_REMOVE
- shmctl(shmid, IPC_RMID, (void *) 0);
-#endif
-
- pDesc->shmid = shmid;
- pDesc->attach_addr = addr;
- if (ShmList) ShmList->prev = &pDesc->next;
- pDesc->next = ShmList;
- pDesc->prev = &ShmList;
- ShmList = pDesc;
-
- return pDesc;
-}
-
-static void
-shmdealloc(
- ShmDescPtr pDesc)
-{
-#ifndef EARLY_REMOVE
- shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
-#endif
- shmdt(pDesc->attach_addr);
-
- if (pDesc->next) pDesc->next->prev = pDesc->prev;
- *pDesc->prev = pDesc->next;
- free(pDesc);
-}
-
-#endif
-
-/* Called when a font is closed. */
-void
-XF86BigfontFreeFontShm(
- FontPtr pFont)
-{
-#ifdef HAS_SHM
- ShmDescPtr pDesc;
-
- /* If during shutdown of the server, XF86BigfontCleanup() has already
- * called shmdealloc() for all segments, we don't need to do it here.
- */
- if (!ShmList)
- return;
-
- pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
- if (pDesc)
- shmdealloc(pDesc);
-#endif
-}
-
-/* Called upon fatal signal. */
-void
-XF86BigfontCleanup(void)
-{
-#ifdef HAS_SHM
- while (ShmList)
- shmdealloc(ShmList);
-#endif
-}
-
-/* Called when a server generation dies. */
-static void
-XF86BigfontResetProc(
- ExtensionEntry* extEntry)
-{
- /* This function is normally called from CloseDownExtensions(), called
- * from main(). It will be followed by a call to FreeAllResources(),
- * which will call XF86BigfontFreeFontShm() for each font. Thus it
- * appears that we do not need to do anything in this function. --
- * But I prefer to write robust code, and not keep shared memory lying
- * around when it's not needed any more. (Someone might close down the
- * extension without calling FreeAllResources()...)
- */
- XF86BigfontCleanup();
-}
-
-
-/* ========== Handling of extension specific requests ========== */
-
-static int
-ProcXF86BigfontQueryVersion(
- ClientPtr client)
-{
- xXF86BigfontQueryVersionReply reply;
-
- REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
- reply.type = X_Reply;
- reply.length = 0;
- reply.sequenceNumber = client->sequence;
- reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION;
- reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION;
- reply.uid = geteuid();
- reply.gid = getegid();
-#ifdef HAS_SHM
- reply.signature = signature;
-#else
- reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
-#endif
- reply.capabilities =
-#ifdef HAS_SHM
- (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
-#else
- 0
-#endif
- ; /* may add more bits here in future versions */
- if (client->swapped) {
- char tmp;
- swaps(&reply.sequenceNumber, tmp);
- swapl(&reply.length, tmp);
- swaps(&reply.majorVersion, tmp);
- swaps(&reply.minorVersion, tmp);
- swapl(&reply.uid, tmp);
- swapl(&reply.gid, tmp);
- swapl(&reply.signature, tmp);
- }
- WriteToClient(client,
- sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
- return Success;
-}
-
-static void
-swapCharInfo(
- xCharInfo *pCI)
-{
- char tmp;
-
- swaps(&pCI->leftSideBearing, tmp);
- swaps(&pCI->rightSideBearing, tmp);
- swaps(&pCI->characterWidth, tmp);
- swaps(&pCI->ascent, tmp);
- swaps(&pCI->descent, tmp);
- swaps(&pCI->attributes, tmp);
-}
-
-/* static CARD32 hashCI (xCharInfo *p); */
-#define hashCI(p) \
- (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
- (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
- (p->characterWidth << 16) + \
- (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
-
-static int
-ProcXF86BigfontQueryFont(
- ClientPtr client)
-{
- FontPtr pFont;
- REQUEST(xXF86BigfontQueryFontReq);
- CARD32 stuff_flags;
- xCharInfo* pmax;
- xCharInfo* pmin;
- int nCharInfos;
- int shmid;
-#ifdef HAS_SHM
- ShmDescPtr pDesc = NULL;
-#else
-#define pDesc 0
-#endif
- xCharInfo* pCI;
- CARD16* pIndex2UniqIndex;
- CARD16* pUniqIndex2Index;
- CARD32 nUniqCharInfos;
-
-#if 0
- REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
-#else
- switch (client->req_len) {
- case 2: /* client with version 1.0 libX11 */
- stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
- break;
- case 3: /* client with version 1.1 libX11 */
- stuff_flags = stuff->flags;
- break;
- default:
- return BadLength;
- }
-#endif
- if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) != Success)
- return BadFont; /* procotol spec says only error is BadFont */
-
- pmax = FONTINKMAX(pFont);
- pmin = FONTINKMIN(pFont);
- nCharInfos =
- (pmax->rightSideBearing == pmin->rightSideBearing
- && pmax->leftSideBearing == pmin->leftSideBearing
- && pmax->descent == pmin->descent
- && pmax->ascent == pmin->ascent
- && pmax->characterWidth == pmin->characterWidth)
- ? 0 : N2dChars(pFont);
- shmid = -1;
- pCI = NULL;
- pIndex2UniqIndex = NULL;
- pUniqIndex2Index = NULL;
- nUniqCharInfos = 0;
-
- if (nCharInfos > 0) {
-#ifdef HAS_SHM
- if (!badSysCall)
- pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
- if (pDesc) {
- pCI = (xCharInfo *) pDesc->attach_addr;
- if (stuff_flags & XF86Bigfont_FLAGS_Shm)
- shmid = pDesc->shmid;
- } else {
- if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
- pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
- + sizeof(CARD32));
- if (pDesc) {
- pCI = (xCharInfo *) pDesc->attach_addr;
- shmid = pDesc->shmid;
- } else {
-#endif
- pCI = malloc(nCharInfos * sizeof(xCharInfo));
- if (!pCI)
- return BadAlloc;
-#ifdef HAS_SHM
- }
-#endif
- /* Fill nCharInfos starting at pCI. */
- {
- xCharInfo* prCI = pCI;
- int ninfos = 0;
- int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
- int row;
- for (row = pFont->info.firstRow;
- row <= pFont->info.lastRow && ninfos < nCharInfos;
- row++) {
- unsigned char chars[512];
- xCharInfo* tmpCharInfos[256];
- unsigned long count;
- int col;
- unsigned long i;
- i = 0;
- for (col = pFont->info.firstCol;
- col <= pFont->info.lastCol;
- col++) {
- chars[i++] = row;
- chars[i++] = col;
- }
- (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
- &count, tmpCharInfos);
- for (i = 0; i < count && ninfos < nCharInfos; i++) {
- *prCI++ = *tmpCharInfos[i];
- ninfos++;
- }
- }
- }
-#ifdef HAS_SHM
- if (pDesc && !badSysCall) {
- *(CARD32 *)(pCI + nCharInfos) = signature;
- if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
- shmdealloc(pDesc);
- return BadAlloc;
- }
- }
- }
-#endif
- if (shmid == -1) {
- /* Cannot use shared memory, so remove-duplicates the xCharInfos
- using a temporary hash table. */
- /* Note that CARD16 is suitable as index type, because
- nCharInfos <= 0x10000. */
- CARD32 hashModulus;
- CARD16* pHash2UniqIndex;
- CARD16* pUniqIndex2NextUniqIndex;
- CARD32 NextIndex;
- CARD32 NextUniqIndex;
- CARD16* tmp;
- CARD32 i, j;
-
- hashModulus = 67;
- if (hashModulus > nCharInfos+1)
- hashModulus = nCharInfos+1;
-
- tmp = malloc((4*nCharInfos+1) * sizeof(CARD16));
- if (!tmp) {
- if (!pDesc) free(pCI);
- return BadAlloc;
- }
- pIndex2UniqIndex = tmp;
- /* nCharInfos elements */
- pUniqIndex2Index = tmp + nCharInfos;
- /* max. nCharInfos elements */
- pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
- /* max. nCharInfos elements */
- pHash2UniqIndex = tmp + 3*nCharInfos;
- /* hashModulus (<= nCharInfos+1) elements */
-
- /* Note that we can use 0xffff as end-of-list indicator, because
- even if nCharInfos = 0x10000, 0xffff can not occur as valid
- entry before the last element has been inserted. And once the
- last element has been inserted, we don't need the hash table
- any more. */
- for (j = 0; j < hashModulus; j++)
- pHash2UniqIndex[j] = (CARD16)(-1);
-
- NextUniqIndex = 0;
- for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
- xCharInfo* p = &pCI[NextIndex];
- CARD32 hashCode = hashCI(p) % hashModulus;
- for (i = pHash2UniqIndex[hashCode];
- i != (CARD16)(-1);
- i = pUniqIndex2NextUniqIndex[i]) {
- j = pUniqIndex2Index[i];
- if (pCI[j].leftSideBearing == p->leftSideBearing
- && pCI[j].rightSideBearing == p->rightSideBearing
- && pCI[j].characterWidth == p->characterWidth
- && pCI[j].ascent == p->ascent
- && pCI[j].descent == p->descent
- && pCI[j].attributes == p->attributes)
- break;
- }
- if (i != (CARD16)(-1)) {
- /* Found *p at Index j, UniqIndex i */
- pIndex2UniqIndex[NextIndex] = i;
- } else {
- /* Allocate a new entry in the Uniq table */
- if (hashModulus <= 2*NextUniqIndex
- && hashModulus < nCharInfos+1) {
- /* Time to increate hash table size */
- hashModulus = 2*hashModulus+1;
- if (hashModulus > nCharInfos+1)
- hashModulus = nCharInfos+1;
- for (j = 0; j < hashModulus; j++)
- pHash2UniqIndex[j] = (CARD16)(-1);
- for (i = 0; i < NextUniqIndex; i++)
- pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
- for (i = 0; i < NextUniqIndex; i++) {
- j = pUniqIndex2Index[i];
- p = &pCI[j];
- hashCode = hashCI(p) % hashModulus;
- pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
- pHash2UniqIndex[hashCode] = i;
- }
- p = &pCI[NextIndex];
- hashCode = hashCI(p) % hashModulus;
- }
- i = NextUniqIndex++;
- pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
- pHash2UniqIndex[hashCode] = i;
- pUniqIndex2Index[i] = NextIndex;
- pIndex2UniqIndex[NextIndex] = i;
- }
- }
- nUniqCharInfos = NextUniqIndex;
- /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
- }
- }
-
- {
- int nfontprops = pFont->info.nprops;
- int rlength =
- sizeof(xXF86BigfontQueryFontReply)
- + nfontprops * sizeof(xFontProp)
- + (nCharInfos > 0 && shmid == -1
- ? nUniqCharInfos * sizeof(xCharInfo)
- + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
- : 0);
- xXF86BigfontQueryFontReply* reply = malloc(rlength);
- char* p;
- if (!reply) {
- if (nCharInfos > 0) {
- if (shmid == -1) free(pIndex2UniqIndex);
- if (!pDesc) free(pCI);
- }
- return BadAlloc;
- }
- reply->type = X_Reply;
- reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
- reply->sequenceNumber = client->sequence;
- reply->minBounds = pFont->info.ink_minbounds;
- reply->maxBounds = pFont->info.ink_maxbounds;
- reply->minCharOrByte2 = pFont->info.firstCol;
- reply->maxCharOrByte2 = pFont->info.lastCol;
- reply->defaultChar = pFont->info.defaultCh;
- reply->nFontProps = pFont->info.nprops;
- reply->drawDirection = pFont->info.drawDirection;
- reply->minByte1 = pFont->info.firstRow;
- reply->maxByte1 = pFont->info.lastRow;
- reply->allCharsExist = pFont->info.allExist;
- reply->fontAscent = pFont->info.fontAscent;
- reply->fontDescent = pFont->info.fontDescent;
- reply->nCharInfos = nCharInfos;
- reply->nUniqCharInfos = nUniqCharInfos;
- reply->shmid = shmid;
- reply->shmsegoffset = 0;
- if (client->swapped) {
- char tmp;
- swaps(&reply->sequenceNumber, tmp);
- swapl(&reply->length, tmp);
- swapCharInfo(&reply->minBounds);
- swapCharInfo(&reply->maxBounds);
- swaps(&reply->minCharOrByte2, tmp);
- swaps(&reply->maxCharOrByte2, tmp);
- swaps(&reply->defaultChar, tmp);
- swaps(&reply->nFontProps, tmp);
- swaps(&reply->fontAscent, tmp);
- swaps(&reply->fontDescent, tmp);
- swapl(&reply->nCharInfos, tmp);
- swapl(&reply->nUniqCharInfos, tmp);
- swapl(&reply->shmid, tmp);
- swapl(&reply->shmsegoffset, tmp);
- }
- p = (char*) &reply[1];
- {
- FontPropPtr pFP;
- xFontProp* prFP;
- int i;
- for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
- i < nfontprops;
- i++, pFP++, prFP++) {
- prFP->name = pFP->name;
- prFP->value = pFP->value;
- if (client->swapped) {
- char tmp;
- swapl(&prFP->name, tmp);
- swapl(&prFP->value, tmp);
- }
- }
- p = (char*) prFP;
- }
- if (nCharInfos > 0 && shmid == -1) {
- xCharInfo* pci;
- CARD16* ps;
- int i, j;
- pci = (xCharInfo*) p;
- for (i = 0; i < nUniqCharInfos; i++, pci++) {
- *pci = pCI[pUniqIndex2Index[i]];
- if (client->swapped)
- swapCharInfo(pci);
- }
- ps = (CARD16*) pci;
- for (j = 0; j < nCharInfos; j++, ps++) {
- *ps = pIndex2UniqIndex[j];
- if (client->swapped) {
- char tmp;
- swaps(ps, tmp);
- }
- }
- }
- WriteToClient(client, rlength, (char *)reply);
- free(reply);
- if (nCharInfos > 0) {
- if (shmid == -1) free(pIndex2UniqIndex);
- if (!pDesc) free(pCI);
- }
- return Success;
- }
-}
-
-static int
-ProcXF86BigfontDispatch(
- ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data) {
- case X_XF86BigfontQueryVersion:
- return ProcXF86BigfontQueryVersion(client);
- case X_XF86BigfontQueryFont:
- return ProcXF86BigfontQueryFont(client);
- default:
- return BadRequest;
- }
-}
-
-static int
-SProcXF86BigfontQueryVersion(
- ClientPtr client)
-{
- REQUEST(xXF86BigfontQueryVersionReq);
- char tmp;
-
- swaps(&stuff->length, tmp);
- return ProcXF86BigfontQueryVersion(client);
-}
-
-static int
-SProcXF86BigfontQueryFont(
- ClientPtr client)
-{
- REQUEST(xXF86BigfontQueryFontReq);
- char tmp;
-
- swaps(&stuff->length, tmp);
- REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
- swapl(&stuff->id, tmp);
- return ProcXF86BigfontQueryFont(client);
-}
-
-static int
-SProcXF86BigfontDispatch(
- ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data) {
- case X_XF86BigfontQueryVersion:
- return SProcXF86BigfontQueryVersion(client);
- case X_XF86BigfontQueryFont:
- return SProcXF86BigfontQueryFont(client);
- default:
- return BadRequest;
- }
-}
+/*
+ * BIGFONT extension for sharing font metrics between clients (if possible)
+ * and for transmitting font metrics to clients in a compressed form.
+ *
+ * Copyright (c) 1999-2000 Bruno Haible
+ * Copyright (c) 1999-2000 The XFree86 Project, Inc.
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+/*
+ * Big fonts suffer from the following: All clients that have opened a
+ * font can access the complete glyph metrics array (the XFontStruct member
+ * `per_char') directly, without going through a macro. Moreover these
+ * glyph metrics are ink metrics, i.e. are not redundant even for a
+ * fixed-width font. For a Unicode font, the size of this array is 768 KB.
+ *
+ * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
+ * metrics data is piped through the socket when the font is opened.
+ *
+ * This extension addresses these two problems for local clients, by using
+ * shared memory. It also addresses the second problem for non-local clients,
+ * by compressing the data before transmit by a factor of nearly 6.
+ *
+ * If you use this extension, your OS ought to nicely support shared memory.
+ * This means: Shared memory should be swappable to the swap, and the limits
+ * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
+ * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
+ * on segments that have already been marked "removed", because it permits
+ * these segments to be cleaned up by the OS if the X server is killed with
+ * signal SIGKILL.
+ *
+ * This extension is transparently exploited by Xlib (functions XQueryFont,
+ * XLoadQueryFont).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#ifdef HAS_SHM
+#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
+/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
+/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
+ Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
+ PAGE_SIZE. It is defined in <asm/page.h>. */
+#include <asm/page.h>
+#endif
+#ifdef SVR4
+#include <sys/sysmacros.h>
+#endif
+#if defined(__CYGWIN__)
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "dixfontstr.h"
+#include "extnsionst.h"
+#include "protocol-versions.h"
+
+#include <X11/extensions/xf86bigfproto.h>
+#include "xf86bigfontsrv.h"
+
+static void XF86BigfontResetProc(
+ ExtensionEntry * /* extEntry */
+ );
+
+
+#ifdef HAS_SHM
+
+/* A random signature, transmitted to the clients so they can verify that the
+ shared memory segment they are attaching to was really established by the
+ X server they are talking to. */
+static CARD32 signature;
+
+/* Index for additional information stored in a FontRec's devPrivates array. */
+static int FontShmdescIndex;
+
+static unsigned int pagesize;
+
+static Bool badSysCall = FALSE;
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
+
+#include <sys/signal.h>
+
+static void
+SigSysHandler(
+ int signo)
+{
+ badSysCall = TRUE;
+}
+
+static Bool
+CheckForShmSyscall(void)
+{
+ void (*oldHandler)(int);
+ int shmid = -1;
+
+ /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
+ oldHandler = signal(SIGSYS, SigSysHandler);
+
+ badSysCall = FALSE;
+ shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
+ if (shmid != -1)
+ {
+ /* Successful allocation - clean up */
+ shmctl(shmid, IPC_RMID, NULL);
+ }
+ else
+ {
+ /* Allocation failed */
+ badSysCall = TRUE;
+ }
+ signal(SIGSYS, oldHandler);
+ return !badSysCall;
+}
+
+#define MUST_CHECK_FOR_SHM_SYSCALL
+
+#endif
+
+#endif
+
+void
+XFree86BigfontExtensionInit(void)
+{
+ if (AddExtension(XF86BIGFONTNAME,
+ XF86BigfontNumberEvents,
+ XF86BigfontNumberErrors,
+ ProcXF86BigfontDispatch,
+ SProcXF86BigfontDispatch,
+ XF86BigfontResetProc,
+ StandardMinorOpcode)) {
+#ifdef HAS_SHM
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+ /*
+ * Note: Local-clients will not be optimized without shared memory
+ * support. Remote-client optimization does not depend on shared
+ * memory support. Thus, the extension is still registered even
+ * when shared memory support is not functional.
+ */
+ if (!CheckForShmSyscall()) {
+ ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
+ return;
+ }
+#endif
+
+ srand((unsigned int) time(NULL));
+ signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
+ + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
+ /* fprintf(stderr, "signature = 0x%08X\n", signature); */
+
+ FontShmdescIndex = AllocateFontPrivateIndex();
+
+#if !defined(CSRG_BASED) && !defined(__CYGWIN__)
+ pagesize = SHMLBA;
+#else
+# ifdef _SC_PAGESIZE
+ pagesize = sysconf(_SC_PAGESIZE);
+# else
+ pagesize = getpagesize();
+# endif
+#endif
+#endif
+ }
+}
+
+
+/* ========== Management of shared memory segments ========== */
+
+#ifdef HAS_SHM
+
+#ifdef __linux__
+/* On Linux, shared memory marked as "removed" can still be attached.
+ Nice feature, because the kernel will automatically free the associated
+ storage when the server and all clients are gone. */
+#define EARLY_REMOVE
+#endif
+
+typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ struct _ShmDesc **prev;
+ int shmid;
+ char *attach_addr;
+} ShmDescRec, *ShmDescPtr;
+
+static ShmDescPtr ShmList = (ShmDescPtr) NULL;
+
+static ShmDescPtr
+shmalloc(
+ unsigned int size)
+{
+ ShmDescPtr pDesc;
+ int shmid;
+ char *addr;
+
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+ if (pagesize == 0)
+ return (ShmDescPtr) NULL;
+#endif
+
+ /* On some older Linux systems, the number of shared memory segments
+ system-wide is 127. In Linux 2.4, it is 4095.
+ Therefore there is a tradeoff to be made between allocating a
+ shared memory segment on one hand, and allocating memory and piping
+ the glyph metrics on the other hand. If the glyph metrics size is
+ small, we prefer the traditional way. */
+ if (size < 3500)
+ return (ShmDescPtr) NULL;
+
+ pDesc = malloc(sizeof(ShmDescRec));
+ if (!pDesc)
+ return (ShmDescPtr) NULL;
+
+ size = (size + pagesize-1) & -pagesize;
+ shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ if (shmid == -1) {
+ ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
+ size, strerror(errno));
+ free(pDesc);
+ return (ShmDescPtr) NULL;
+ }
+
+ if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
+ ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
+ size, strerror(errno));
+ shmctl(shmid, IPC_RMID, (void *) 0);
+ free(pDesc);
+ return (ShmDescPtr) NULL;
+ }
+
+#ifdef EARLY_REMOVE
+ shmctl(shmid, IPC_RMID, (void *) 0);
+#endif
+
+ pDesc->shmid = shmid;
+ pDesc->attach_addr = addr;
+ if (ShmList) ShmList->prev = &pDesc->next;
+ pDesc->next = ShmList;
+ pDesc->prev = &ShmList;
+ ShmList = pDesc;
+
+ return pDesc;
+}
+
+static void
+shmdealloc(
+ ShmDescPtr pDesc)
+{
+#ifndef EARLY_REMOVE
+ shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
+#endif
+ shmdt(pDesc->attach_addr);
+
+ if (pDesc->next) pDesc->next->prev = pDesc->prev;
+ *pDesc->prev = pDesc->next;
+ free(pDesc);
+}
+
+#endif
+
+/* Called when a font is closed. */
+void
+XF86BigfontFreeFontShm(
+ FontPtr pFont)
+{
+#ifdef HAS_SHM
+ ShmDescPtr pDesc;
+
+ /* If during shutdown of the server, XF86BigfontCleanup() has already
+ * called shmdealloc() for all segments, we don't need to do it here.
+ */
+ if (!ShmList)
+ return;
+
+ pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
+ if (pDesc)
+ shmdealloc(pDesc);
+#endif
+}
+
+/* Called upon fatal signal. */
+void
+XF86BigfontCleanup(void)
+{
+#ifdef HAS_SHM
+ while (ShmList)
+ shmdealloc(ShmList);
+#endif
+}
+
+/* Called when a server generation dies. */
+static void
+XF86BigfontResetProc(
+ ExtensionEntry* extEntry)
+{
+ /* This function is normally called from CloseDownExtensions(), called
+ * from main(). It will be followed by a call to FreeAllResources(),
+ * which will call XF86BigfontFreeFontShm() for each font. Thus it
+ * appears that we do not need to do anything in this function. --
+ * But I prefer to write robust code, and not keep shared memory lying
+ * around when it's not needed any more. (Someone might close down the
+ * extension without calling FreeAllResources()...)
+ */
+ XF86BigfontCleanup();
+}
+
+
+/* ========== Handling of extension specific requests ========== */
+
+static int
+ProcXF86BigfontQueryVersion(
+ ClientPtr client)
+{
+ xXF86BigfontQueryVersionReply reply;
+
+ REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = client->sequence;
+ reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION;
+ reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION;
+ reply.uid = geteuid();
+ reply.gid = getegid();
+#ifdef HAS_SHM
+ reply.signature = signature;
+#else
+ reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
+#endif
+ reply.capabilities =
+#ifdef HAS_SHM
+ (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
+#else
+ 0
+#endif
+ ; /* may add more bits here in future versions */
+ if (client->swapped) {
+ char tmp;
+ swaps(&reply.sequenceNumber, tmp);
+ swapl(&reply.length, tmp);
+ swaps(&reply.majorVersion, tmp);
+ swaps(&reply.minorVersion, tmp);
+ swapl(&reply.uid, tmp);
+ swapl(&reply.gid, tmp);
+ swapl(&reply.signature, tmp);
+ }
+ WriteToClient(client,
+ sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
+ return Success;
+}
+
+static void
+swapCharInfo(
+ xCharInfo *pCI)
+{
+ char tmp;
+
+ swaps(&pCI->leftSideBearing, tmp);
+ swaps(&pCI->rightSideBearing, tmp);
+ swaps(&pCI->characterWidth, tmp);
+ swaps(&pCI->ascent, tmp);
+ swaps(&pCI->descent, tmp);
+ swaps(&pCI->attributes, tmp);
+}
+
+/* static CARD32 hashCI (xCharInfo *p); */
+#define hashCI(p) \
+ (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
+ (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
+ (p->characterWidth << 16) + \
+ (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
+
+static int
+ProcXF86BigfontQueryFont(
+ ClientPtr client)
+{
+ FontPtr pFont;
+ REQUEST(xXF86BigfontQueryFontReq);
+ CARD32 stuff_flags;
+ xCharInfo* pmax;
+ xCharInfo* pmin;
+ int nCharInfos;
+ int shmid;
+#ifdef HAS_SHM
+ ShmDescPtr pDesc = NULL;
+#else
+#define pDesc 0
+#endif
+ xCharInfo* pCI;
+ CARD16* pIndex2UniqIndex;
+ CARD16* pUniqIndex2Index;
+ CARD32 nUniqCharInfos;
+
+#if 0
+ REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
+#else
+ switch (client->req_len) {
+ case 2: /* client with version 1.0 libX11 */
+ stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
+ break;
+ case 3: /* client with version 1.1 libX11 */
+ stuff_flags = stuff->flags;
+ break;
+ default:
+ return BadLength;
+ }
+#endif
+ if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) != Success)
+ return BadFont; /* procotol spec says only error is BadFont */
+
+ pmax = FONTINKMAX(pFont);
+ pmin = FONTINKMIN(pFont);
+ nCharInfos =
+ (pmax->rightSideBearing == pmin->rightSideBearing
+ && pmax->leftSideBearing == pmin->leftSideBearing
+ && pmax->descent == pmin->descent
+ && pmax->ascent == pmin->ascent
+ && pmax->characterWidth == pmin->characterWidth)
+ ? 0 : N2dChars(pFont);
+ shmid = -1;
+ pCI = NULL;
+ pIndex2UniqIndex = NULL;
+ pUniqIndex2Index = NULL;
+ nUniqCharInfos = 0;
+
+ if (nCharInfos > 0) {
+#ifdef HAS_SHM
+ if (!badSysCall)
+ pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
+ if (pDesc) {
+ pCI = (xCharInfo *) pDesc->attach_addr;
+ if (stuff_flags & XF86Bigfont_FLAGS_Shm)
+ shmid = pDesc->shmid;
+ } else {
+ if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
+ pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
+ + sizeof(CARD32));
+ if (pDesc) {
+ pCI = (xCharInfo *) pDesc->attach_addr;
+ shmid = pDesc->shmid;
+ } else {
+#endif
+ pCI = malloc(nCharInfos * sizeof(xCharInfo));
+ if (!pCI)
+ return BadAlloc;
+#ifdef HAS_SHM
+ }
+#endif
+ /* Fill nCharInfos starting at pCI. */
+ {
+ xCharInfo* prCI = pCI;
+ int ninfos = 0;
+ int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
+ int row;
+ for (row = pFont->info.firstRow;
+ row <= pFont->info.lastRow && ninfos < nCharInfos;
+ row++) {
+ unsigned char chars[512];
+ xCharInfo* tmpCharInfos[256];
+ unsigned long count;
+ int col;
+ unsigned long i;
+ i = 0;
+ for (col = pFont->info.firstCol;
+ col <= pFont->info.lastCol;
+ col++) {
+ chars[i++] = row;
+ chars[i++] = col;
+ }
+ (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
+ &count, tmpCharInfos);
+ for (i = 0; i < count && ninfos < nCharInfos; i++) {
+ *prCI++ = *tmpCharInfos[i];
+ ninfos++;
+ }
+ }
+ }
+#ifdef HAS_SHM
+ if (pDesc && !badSysCall) {
+ *(CARD32 *)(pCI + nCharInfos) = signature;
+ if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
+ shmdealloc(pDesc);
+ return BadAlloc;
+ }
+ }
+ }
+#endif
+ if (shmid == -1) {
+ /* Cannot use shared memory, so remove-duplicates the xCharInfos
+ using a temporary hash table. */
+ /* Note that CARD16 is suitable as index type, because
+ nCharInfos <= 0x10000. */
+ CARD32 hashModulus;
+ CARD16* pHash2UniqIndex;
+ CARD16* pUniqIndex2NextUniqIndex;
+ CARD32 NextIndex;
+ CARD32 NextUniqIndex;
+ CARD16* tmp;
+ CARD32 i, j;
+
+ hashModulus = 67;
+ if (hashModulus > nCharInfos+1)
+ hashModulus = nCharInfos+1;
+
+ tmp = malloc((4*nCharInfos+1) * sizeof(CARD16));
+ if (!tmp) {
+ if (!pDesc) free(pCI);
+ return BadAlloc;
+ }
+ pIndex2UniqIndex = tmp;
+ /* nCharInfos elements */
+ pUniqIndex2Index = tmp + nCharInfos;
+ /* max. nCharInfos elements */
+ pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
+ /* max. nCharInfos elements */
+ pHash2UniqIndex = tmp + 3*nCharInfos;
+ /* hashModulus (<= nCharInfos+1) elements */
+
+ /* Note that we can use 0xffff as end-of-list indicator, because
+ even if nCharInfos = 0x10000, 0xffff can not occur as valid
+ entry before the last element has been inserted. And once the
+ last element has been inserted, we don't need the hash table
+ any more. */
+ for (j = 0; j < hashModulus; j++)
+ pHash2UniqIndex[j] = (CARD16)(-1);
+
+ NextUniqIndex = 0;
+ for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
+ xCharInfo* p = &pCI[NextIndex];
+ CARD32 hashCode = hashCI(p) % hashModulus;
+ for (i = pHash2UniqIndex[hashCode];
+ i != (CARD16)(-1);
+ i = pUniqIndex2NextUniqIndex[i]) {
+ j = pUniqIndex2Index[i];
+ if (pCI[j].leftSideBearing == p->leftSideBearing
+ && pCI[j].rightSideBearing == p->rightSideBearing
+ && pCI[j].characterWidth == p->characterWidth
+ && pCI[j].ascent == p->ascent
+ && pCI[j].descent == p->descent
+ && pCI[j].attributes == p->attributes)
+ break;
+ }
+ if (i != (CARD16)(-1)) {
+ /* Found *p at Index j, UniqIndex i */
+ pIndex2UniqIndex[NextIndex] = i;
+ } else {
+ /* Allocate a new entry in the Uniq table */
+ if (hashModulus <= 2*NextUniqIndex
+ && hashModulus < nCharInfos+1) {
+ /* Time to increate hash table size */
+ hashModulus = 2*hashModulus+1;
+ if (hashModulus > nCharInfos+1)
+ hashModulus = nCharInfos+1;
+ for (j = 0; j < hashModulus; j++)
+ pHash2UniqIndex[j] = (CARD16)(-1);
+ for (i = 0; i < NextUniqIndex; i++)
+ pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
+ for (i = 0; i < NextUniqIndex; i++) {
+ j = pUniqIndex2Index[i];
+ p = &pCI[j];
+ hashCode = hashCI(p) % hashModulus;
+ pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
+ pHash2UniqIndex[hashCode] = i;
+ }
+ p = &pCI[NextIndex];
+ hashCode = hashCI(p) % hashModulus;
+ }
+ i = NextUniqIndex++;
+ pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
+ pHash2UniqIndex[hashCode] = i;
+ pUniqIndex2Index[i] = NextIndex;
+ pIndex2UniqIndex[NextIndex] = i;
+ }
+ }
+ nUniqCharInfos = NextUniqIndex;
+ /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
+ }
+ }
+
+ {
+ int nfontprops = pFont->info.nprops;
+ int rlength =
+ sizeof(xXF86BigfontQueryFontReply)
+ + nfontprops * sizeof(xFontProp)
+ + (nCharInfos > 0 && shmid == -1
+ ? nUniqCharInfos * sizeof(xCharInfo)
+ + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
+ : 0);
+ xXF86BigfontQueryFontReply* reply = malloc(rlength);
+ char* p;
+ if (!reply) {
+ if (nCharInfos > 0) {
+ if (shmid == -1) free(pIndex2UniqIndex);
+ if (!pDesc) free(pCI);
+ }
+ return BadAlloc;
+ }
+ reply->type = X_Reply;
+ reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
+ reply->sequenceNumber = client->sequence;
+ reply->minBounds = pFont->info.ink_minbounds;
+ reply->maxBounds = pFont->info.ink_maxbounds;
+ reply->minCharOrByte2 = pFont->info.firstCol;
+ reply->maxCharOrByte2 = pFont->info.lastCol;
+ reply->defaultChar = pFont->info.defaultCh;
+ reply->nFontProps = pFont->info.nprops;
+ reply->drawDirection = pFont->info.drawDirection;
+ reply->minByte1 = pFont->info.firstRow;
+ reply->maxByte1 = pFont->info.lastRow;
+ reply->allCharsExist = pFont->info.allExist;
+ reply->fontAscent = pFont->info.fontAscent;
+ reply->fontDescent = pFont->info.fontDescent;
+ reply->nCharInfos = nCharInfos;
+ reply->nUniqCharInfos = nUniqCharInfos;
+ reply->shmid = shmid;
+ reply->shmsegoffset = 0;
+ if (client->swapped) {
+ char tmp;
+ swaps(&reply->sequenceNumber, tmp);
+ swapl(&reply->length, tmp);
+ swapCharInfo(&reply->minBounds);
+ swapCharInfo(&reply->maxBounds);
+ swaps(&reply->minCharOrByte2, tmp);
+ swaps(&reply->maxCharOrByte2, tmp);
+ swaps(&reply->defaultChar, tmp);
+ swaps(&reply->nFontProps, tmp);
+ swaps(&reply->fontAscent, tmp);
+ swaps(&reply->fontDescent, tmp);
+ swapl(&reply->nCharInfos, tmp);
+ swapl(&reply->nUniqCharInfos, tmp);
+ swapl(&reply->shmid, tmp);
+ swapl(&reply->shmsegoffset, tmp);
+ }
+ p = (char*) &reply[1];
+ {
+ FontPropPtr pFP;
+ xFontProp* prFP;
+ int i;
+ for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
+ i < nfontprops;
+ i++, pFP++, prFP++) {
+ prFP->name = pFP->name;
+ prFP->value = pFP->value;
+ if (client->swapped) {
+ char tmp;
+ swapl(&prFP->name, tmp);
+ swapl(&prFP->value, tmp);
+ }
+ }
+ p = (char*) prFP;
+ }
+ if (nCharInfos > 0 && shmid == -1) {
+ xCharInfo* pci;
+ CARD16* ps;
+ int i, j;
+ pci = (xCharInfo*) p;
+ for (i = 0; i < nUniqCharInfos; i++, pci++) {
+ *pci = pCI[pUniqIndex2Index[i]];
+ if (client->swapped)
+ swapCharInfo(pci);
+ }
+ ps = (CARD16*) pci;
+ for (j = 0; j < nCharInfos; j++, ps++) {
+ *ps = pIndex2UniqIndex[j];
+ if (client->swapped) {
+ char tmp;
+ swaps(ps, tmp);
+ }
+ }
+ }
+ WriteToClient(client, rlength, (char *)reply);
+ free(reply);
+ if (nCharInfos > 0) {
+ if (shmid == -1) free(pIndex2UniqIndex);
+ if (!pDesc) free(pCI);
+ }
+ return Success;
+ }
+}
+
+static int
+ProcXF86BigfontDispatch(
+ ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_XF86BigfontQueryVersion:
+ return ProcXF86BigfontQueryVersion(client);
+ case X_XF86BigfontQueryFont:
+ return ProcXF86BigfontQueryFont(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcXF86BigfontQueryVersion(
+ ClientPtr client)
+{
+ REQUEST(xXF86BigfontQueryVersionReq);
+ char tmp;
+
+ swaps(&stuff->length, tmp);
+ return ProcXF86BigfontQueryVersion(client);
+}
+
+static int
+SProcXF86BigfontQueryFont(
+ ClientPtr client)
+{
+ REQUEST(xXF86BigfontQueryFontReq);
+ char tmp;
+
+ swaps(&stuff->length, tmp);
+ REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
+ swapl(&stuff->id, tmp);
+ return ProcXF86BigfontQueryFont(client);
+}
+
+static int
+SProcXF86BigfontDispatch(
+ ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_XF86BigfontQueryVersion:
+ return SProcXF86BigfontQueryVersion(client);
+ case X_XF86BigfontQueryFont:
+ return SProcXF86BigfontQueryFont(client);
+ default:
+ return BadRequest;
+ }
+}