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