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