2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 1991, 1993, 1998 The Open Group
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
|
|
other dealings in this Software without prior written authorization
|
|
|
|
from The Open Group.
|
|
|
|
|
|
|
|
Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
|
|
|
|
and Olivetti Research Limited, Cambridge, England.
|
|
|
|
|
|
|
|
All Rights Reserved
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
|
|
documentation for any purpose and without fee is hereby granted,
|
|
|
|
provided that the above copyright notice appear in all copies and that
|
|
|
|
both that copyright notice and this permission notice appear in
|
2008-12-10 20:18:59 +01:00
|
|
|
supporting documentation, and that the names of Digital or Olivetti
|
2003-11-14 16:54:54 +01:00
|
|
|
not be used in advertising or publicity pertaining to distribution of the
|
|
|
|
software without specific, written prior permission. Digital and Olivetti
|
|
|
|
make no representations about the suitability of this software
|
|
|
|
for any purpose. It is provided "as is" without express or implied warranty.
|
|
|
|
|
|
|
|
DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
|
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
|
|
|
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2005-07-03 09:02:09 +02:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
2006-02-10 23:00:30 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
2005-04-20 14:25:48 +02:00
|
|
|
#include <X11/X.h>
|
|
|
|
#include <X11/Xproto.h>
|
|
|
|
#include <X11/Xmd.h>
|
2010-06-29 01:10:13 +02:00
|
|
|
#include "scrnintstr.h"
|
2005-07-03 10:53:54 +02:00
|
|
|
#include "os.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
#include "extnsionst.h"
|
|
|
|
#include "dixstruct.h"
|
2010-06-26 02:59:14 +02:00
|
|
|
#include "pixmapstr.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
#include "resource.h"
|
|
|
|
#include "opaque.h"
|
2009-07-15 08:51:05 +02:00
|
|
|
#include <X11/extensions/syncproto.h>
|
2008-12-10 19:32:04 +01:00
|
|
|
#include "syncsrv.h"
|
2010-06-26 02:59:14 +02:00
|
|
|
#include "syncsdk.h"
|
2010-12-06 22:36:14 +01:00
|
|
|
#include "protocol-versions.h"
|
2012-03-12 07:36:31 +01:00
|
|
|
#include "inputstr.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2003-11-14 17:49:22 +01:00
|
|
|
#include <stdio.h>
|
2008-07-17 17:59:24 +02:00
|
|
|
#if !defined(WIN32)
|
2003-11-14 17:49:22 +01:00
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
|
2012-07-10 03:02:56 +02:00
|
|
|
#include "extinit.h"
|
2003-11-25 20:29:01 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
* Local Global Variables
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
static int SyncEventBase;
|
|
|
|
static int SyncErrorBase;
|
|
|
|
static RESTYPE RTCounter = 0;
|
|
|
|
static RESTYPE RTAwait;
|
|
|
|
static RESTYPE RTAlarm;
|
|
|
|
static RESTYPE RTAlarmClient;
|
|
|
|
static RESTYPE RTFence;
|
2012-03-15 01:22:18 +01:00
|
|
|
static struct xorg_list SysCounterList;
|
2010-12-20 20:05:57 +01:00
|
|
|
static int SyncNumInvalidCounterWarnings = 0;
|
2012-03-21 20:55:09 +01:00
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
#define MAX_INVALID_COUNTER_WARNINGS 5
|
|
|
|
|
|
|
|
static const char *WARN_INVALID_COUNTER_COMPARE =
|
2012-03-21 20:55:09 +01:00
|
|
|
"Warning: Non-counter XSync object using Counter-only\n"
|
|
|
|
" comparison. Result will never be true.\n";
|
2010-12-20 20:05:57 +01:00
|
|
|
|
|
|
|
static const char *WARN_INVALID_COUNTER_ALARM =
|
2012-03-21 20:55:09 +01:00
|
|
|
"Warning: Non-counter XSync object used in alarm. This is\n"
|
|
|
|
" the result of a programming error in the X server.\n";
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
#define IsSystemCounter(pCounter) \
|
2010-06-28 23:51:54 +02:00
|
|
|
(pCounter && (pCounter->sync.client == NULL))
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* these are all the alarm attributes that pertain to the alarm's trigger */
|
|
|
|
#define XSyncCAAllTrigger \
|
|
|
|
(XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
|
|
|
|
|
2010-05-10 23:00:49 +02:00
|
|
|
static void SyncComputeBracketValues(SyncCounter *);
|
2003-11-14 17:49:22 +01:00
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static void SyncInitServerTime(void);
|
2003-11-14 17:49:22 +01:00
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static void SyncInitIdleTime(void);
|
2003-11-14 17:49:22 +01:00
|
|
|
|
2012-03-13 00:28:15 +01:00
|
|
|
static inline void*
|
|
|
|
SysCounterGetPrivate(SyncCounter *counter)
|
|
|
|
{
|
|
|
|
BUG_WARN(!IsSystemCounter(counter));
|
|
|
|
|
|
|
|
return counter->pSysCounterInfo ? counter->pSysCounterInfo->private : NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning)
|
2010-12-20 20:05:57 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pSync && (SYNC_COUNTER != pSync->type)) {
|
|
|
|
if (SyncNumInvalidCounterWarnings++ < MAX_INVALID_COUNTER_WARNINGS) {
|
|
|
|
ErrorF("%s", warning);
|
|
|
|
ErrorF(" Counter type: %d\n", pSync->type);
|
|
|
|
}
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2010-12-20 20:05:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-11-14 17:49:22 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/* Each counter maintains a simple linked list of triggers that are
|
|
|
|
* interested in the counter. The two functions below are used to
|
|
|
|
* delete and add triggers on this list.
|
|
|
|
*/
|
2013-04-10 04:59:39 +02:00
|
|
|
void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-04-03 04:13:47 +02:00
|
|
|
SyncTriggerList *pCur;
|
2006-05-12 23:53:28 +02:00
|
|
|
SyncTriggerList *pPrev;
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-06-28 23:59:01 +02:00
|
|
|
/* pSync needs to be stored in pTrigger before calling here. */
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-06-28 23:59:01 +02:00
|
|
|
if (!pTrigger->pSync)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-05-12 23:53:28 +02:00
|
|
|
pPrev = NULL;
|
2010-06-28 23:59:01 +02:00
|
|
|
pCur = pTrigger->pSync->pTriglist;
|
2006-05-12 23:53:28 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
while (pCur) {
|
|
|
|
if (pCur->pTrigger == pTrigger) {
|
|
|
|
if (pPrev)
|
|
|
|
pPrev->next = pCur->next;
|
|
|
|
else
|
|
|
|
pTrigger->pSync->pTriglist = pCur->next;
|
|
|
|
|
|
|
|
free(pCur);
|
|
|
|
break;
|
|
|
|
}
|
2008-12-10 20:18:59 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pPrev = pCur;
|
|
|
|
pCur = pCur->next;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2008-12-10 20:18:59 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (SYNC_COUNTER == pTrigger->pSync->type) {
|
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (IsSystemCounter(pCounter))
|
|
|
|
SyncComputeBracketValues(pCounter);
|
2010-06-28 23:59:01 +02:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else if (SYNC_FENCE == pTrigger->pSync->type) {
|
|
|
|
SyncFence *pFence = (SyncFence *) pTrigger->pSync;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pFence->funcs.DeleteTrigger(pTrigger);
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2013-04-10 04:59:39 +02:00
|
|
|
int
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
SyncTriggerList *pCur;
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-06-28 23:59:01 +02:00
|
|
|
if (!pTrigger->pSync)
|
2012-03-21 20:55:09 +01:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* don't do anything if it's already there */
|
2012-03-21 20:55:09 +01:00
|
|
|
for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next) {
|
|
|
|
if (pCur->pTrigger == pTrigger)
|
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2010-05-05 20:44:06 +02:00
|
|
|
if (!(pCur = malloc(sizeof(SyncTriggerList))))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pCur->pTrigger = pTrigger;
|
2010-06-28 23:59:01 +02:00
|
|
|
pCur->next = pTrigger->pSync->pTriglist;
|
|
|
|
pTrigger->pSync->pTriglist = pCur;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (SYNC_COUNTER == pTrigger->pSync->type) {
|
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
|
|
|
|
|
|
|
if (IsSystemCounter(pCounter))
|
|
|
|
SyncComputeBracketValues(pCounter);
|
|
|
|
}
|
|
|
|
else if (SYNC_FENCE == pTrigger->pSync->type) {
|
|
|
|
SyncFence *pFence = (SyncFence *) pTrigger->pSync;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pFence->funcs.AddTrigger(pTrigger);
|
2010-06-28 23:59:01 +02:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2010-12-06 22:10:42 +01:00
|
|
|
/* Below are five possible functions that can be plugged into
|
|
|
|
* pTrigger->CheckTrigger for counter sync objects, corresponding to
|
|
|
|
* the four possible test-types, and the one possible function that
|
|
|
|
* can be plugged into pTrigger->CheckTrigger for fence sync objects.
|
|
|
|
* These functions are called after the sync object's state changes
|
|
|
|
* but are also passed the old state so they can inspect both the old
|
|
|
|
* and new values. (PositiveTransition and NegativeTransition need to
|
|
|
|
* see both pieces of information.) These functions return the truth
|
|
|
|
* value of the trigger.
|
2003-11-14 16:54:54 +01:00
|
|
|
*
|
2010-12-06 22:10:42 +01:00
|
|
|
* All of them include the condition pTrigger->pSync == NULL.
|
|
|
|
* This is because the spec says that a trigger with a sync value
|
2003-11-14 16:54:54 +01:00
|
|
|
* of None is always TRUE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCheckTriggerPositiveComparison(SyncTrigger * pTrigger, CARD64 oldval)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
/* Non-counter sync objects should never get here because they
|
|
|
|
* never trigger this comparison. */
|
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
|
|
|
return (pCounter == NULL ||
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCheckTriggerNegativeComparison(SyncTrigger * pTrigger, CARD64 oldval)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
/* Non-counter sync objects should never get here because they
|
|
|
|
* never trigger this comparison. */
|
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
|
|
|
return (pCounter == NULL ||
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCheckTriggerPositiveTransition(SyncTrigger * pTrigger, CARD64 oldval)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
/* Non-counter sync objects should never get here because they
|
|
|
|
* never trigger this comparison. */
|
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
|
|
|
return (pCounter == NULL ||
|
2012-03-21 20:55:09 +01:00
|
|
|
(XSyncValueLessThan(oldval, pTrigger->test_value) &&
|
|
|
|
XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCheckTriggerNegativeTransition(SyncTrigger * pTrigger, CARD64 oldval)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
/* Non-counter sync objects should never get here because they
|
|
|
|
* never trigger this comparison. */
|
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
|
2012-03-21 20:55:09 +01:00
|
|
|
return FALSE;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
|
|
|
return (pCounter == NULL ||
|
2012-03-21 20:55:09 +01:00
|
|
|
(XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
|
|
|
|
XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 22:10:42 +01:00
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCheckTriggerFence(SyncTrigger * pTrigger, CARD64 unused)
|
2010-12-06 22:10:42 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncFence *pFence = (SyncFence *) pTrigger->pSync;
|
|
|
|
|
|
|
|
(void) unused;
|
2010-12-06 22:10:42 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
return (pFence == NULL || pFence->funcs.CheckTriggered(pFence));
|
2010-12-06 22:10:42 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
|
|
|
|
RESTYPE resType, Mask changes)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncObject *pSync = pTrigger->pSync;
|
|
|
|
SyncCounter *pCounter = NULL;
|
2012-03-21 20:55:09 +01:00
|
|
|
int rc;
|
|
|
|
Bool newSyncObject = FALSE;
|
|
|
|
|
|
|
|
if (changes & XSyncCACounter) {
|
|
|
|
if (syncObject == None)
|
|
|
|
pSync = NULL;
|
2013-12-15 10:05:51 +01:00
|
|
|
else if (Success != (rc = dixLookupResourceByType((void **) &pSync,
|
2012-03-21 20:55:09 +01:00
|
|
|
syncObject, resType,
|
|
|
|
client,
|
|
|
|
DixReadAccess))) {
|
|
|
|
client->errorValue = syncObject;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
if (pSync != pTrigger->pSync) { /* new counter for trigger */
|
|
|
|
SyncDeleteTriggerFromSyncObject(pTrigger);
|
|
|
|
pTrigger->pSync = pSync;
|
|
|
|
newSyncObject = TRUE;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if system counter, ask it what the current value is */
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pSync && SYNC_COUNTER == pSync->type) {
|
|
|
|
pCounter = (SyncCounter *) pSync;
|
|
|
|
|
|
|
|
if (IsSystemCounter(pCounter)) {
|
2013-12-15 10:05:51 +01:00
|
|
|
(*pCounter->pSysCounterInfo->QueryValue) ((void *) pCounter,
|
2012-03-21 20:55:09 +01:00
|
|
|
&pCounter->value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changes & XSyncCAValueType) {
|
|
|
|
if (pTrigger->value_type != XSyncRelative &&
|
|
|
|
pTrigger->value_type != XSyncAbsolute) {
|
|
|
|
client->errorValue = pTrigger->value_type;
|
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changes & XSyncCATestType) {
|
|
|
|
|
|
|
|
if (pSync && SYNC_FENCE == pSync->type) {
|
|
|
|
pTrigger->CheckTrigger = SyncCheckTriggerFence;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* select appropriate CheckTrigger function */
|
|
|
|
|
|
|
|
switch (pTrigger->test_type) {
|
|
|
|
case XSyncPositiveTransition:
|
|
|
|
pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
|
|
|
|
break;
|
|
|
|
case XSyncNegativeTransition:
|
|
|
|
pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
|
|
|
|
break;
|
|
|
|
case XSyncPositiveComparison:
|
|
|
|
pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
|
|
|
|
break;
|
|
|
|
case XSyncNegativeComparison:
|
|
|
|
pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
client->errorValue = pTrigger->test_type;
|
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changes & (XSyncCAValueType | XSyncCAValue)) {
|
|
|
|
if (pTrigger->value_type == XSyncAbsolute)
|
|
|
|
pTrigger->test_value = pTrigger->wait_value;
|
|
|
|
else { /* relative */
|
|
|
|
|
|
|
|
Bool overflow;
|
|
|
|
|
|
|
|
if (pCounter == NULL)
|
|
|
|
return BadMatch;
|
|
|
|
|
|
|
|
XSyncValueAdd(&pTrigger->test_value, pCounter->value,
|
|
|
|
pTrigger->wait_value, &overflow);
|
|
|
|
if (overflow) {
|
|
|
|
client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
|
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* we wait until we're sure there are no errors before registering
|
|
|
|
* a new counter on a trigger
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
if (newSyncObject) {
|
|
|
|
if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
|
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else if (pCounter && IsSystemCounter(pCounter)) {
|
|
|
|
SyncComputeBracketValues(pCounter);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2008-12-10 20:18:59 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* AlarmNotify events happen in response to actions taken on an Alarm or
|
2008-12-10 20:18:59 +01:00
|
|
|
* the counter used by the alarm. AlarmNotify may be sent to multiple
|
2003-11-14 16:54:54 +01:00
|
|
|
* clients. The alarm maintains a list of clients interested in events.
|
|
|
|
*/
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncSendAlarmNotifyEvents(SyncAlarm * pAlarm)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
SyncAlarmClientList *pcl;
|
|
|
|
xSyncAlarmNotifyEvent ane;
|
|
|
|
SyncTrigger *pTrigger = &pAlarm->trigger;
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
UpdateCurrentTime();
|
|
|
|
|
2012-07-10 04:12:44 +02:00
|
|
|
ane = (xSyncAlarmNotifyEvent) {
|
|
|
|
.type = SyncEventBase + XSyncAlarmNotify,
|
|
|
|
.kind = XSyncAlarmNotify,
|
|
|
|
.alarm = pAlarm->alarm_id,
|
|
|
|
.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value),
|
|
|
|
.alarm_value_lo = XSyncValueLow32(pTrigger->test_value),
|
|
|
|
.time = currentTime.milliseconds,
|
|
|
|
.state = pAlarm->state
|
|
|
|
};
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type) {
|
|
|
|
ane.counter_value_hi = XSyncValueHigh32(pCounter->value);
|
|
|
|
ane.counter_value_lo = XSyncValueLow32(pCounter->value);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-07-10 04:12:42 +02:00
|
|
|
else {
|
|
|
|
/* XXX what else can we do if there's no counter? */
|
2012-03-21 20:55:09 +01:00
|
|
|
ane.counter_value_hi = ane.counter_value_lo = 0;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* send to owner */
|
2010-05-15 21:31:34 +02:00
|
|
|
if (pAlarm->events)
|
2012-03-21 20:55:09 +01:00
|
|
|
WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* send to other interested clients */
|
|
|
|
for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
|
2012-03-21 20:55:09 +01:00
|
|
|
WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
/* CounterNotify events only occur in response to an Await. The events
|
2003-11-14 16:54:54 +01:00
|
|
|
* go only to the Awaiting client.
|
|
|
|
*/
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait ** ppAwait,
|
|
|
|
int num_events)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
xSyncCounterNotifyEvent *pEvents, *pev;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (client->clientGone)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2012-07-10 04:12:42 +02:00
|
|
|
pev = pEvents = calloc(num_events, sizeof(xSyncCounterNotifyEvent));
|
2008-12-10 20:18:59 +01:00
|
|
|
if (!pEvents)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
UpdateCurrentTime();
|
2012-03-21 20:55:09 +01:00
|
|
|
for (i = 0; i < num_events; i++, ppAwait++, pev++) {
|
|
|
|
SyncTrigger *pTrigger = &(*ppAwait)->trigger;
|
|
|
|
|
|
|
|
pev->type = SyncEventBase + XSyncCounterNotify;
|
|
|
|
pev->kind = XSyncCounterNotify;
|
|
|
|
pev->counter = pTrigger->pSync->id;
|
|
|
|
pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
|
|
|
|
pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
|
|
|
|
if (SYNC_COUNTER == pTrigger->pSync->type) {
|
|
|
|
SyncCounter *pCounter = (SyncCounter *) pTrigger->pSync;
|
|
|
|
|
|
|
|
pev->counter_value_lo = XSyncValueLow32(pCounter->value);
|
|
|
|
pev->counter_value_hi = XSyncValueHigh32(pCounter->value);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pev->counter_value_lo = 0;
|
|
|
|
pev->counter_value_hi = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pev->time = currentTime.milliseconds;
|
|
|
|
pev->count = num_events - i - 1; /* events remaining */
|
|
|
|
pev->destroyed = pTrigger->pSync->beingDestroyed;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
/* swapping will be taken care of by this */
|
2012-03-21 20:55:09 +01:00
|
|
|
WriteEventsToClient(client, num_events, (xEvent *) pEvents);
|
2010-05-05 20:44:06 +02:00
|
|
|
free(pEvents);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called when an alarm's counter is destroyed.
|
|
|
|
* It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
|
|
|
|
*/
|
2009-01-11 08:16:55 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarmCounterDestroyed(SyncTrigger * pTrigger)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm = (SyncAlarm *) pTrigger;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pAlarm->state = XSyncAlarmInactive;
|
|
|
|
SyncSendAlarmNotifyEvents(pAlarm);
|
2010-06-28 23:59:01 +02:00
|
|
|
pTrigger->pSync = NULL;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
/* This function is called when an alarm "goes off."
|
2003-11-14 16:54:54 +01:00
|
|
|
* It is plugged into pTrigger->TriggerFired (for alarm triggers).
|
|
|
|
*/
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarmTriggerFired(SyncTrigger * pTrigger)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm = (SyncAlarm *) pTrigger;
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter;
|
2003-11-14 16:54:54 +01:00
|
|
|
CARD64 new_test_value;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/* no need to check alarm unless it's active */
|
|
|
|
if (pAlarm->state != XSyncAlarmActive)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* " if the counter value is None, or if the delta is 0 and
|
|
|
|
* the test-type is PositiveComparison or NegativeComparison,
|
|
|
|
* no change is made to value (test-value) and the alarm
|
|
|
|
* state is changed to Inactive before the event is generated."
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pCounter == NULL || (XSyncValueIsZero(pAlarm->delta)
|
|
|
|
&& (pAlarm->trigger.test_type ==
|
|
|
|
XSyncPositiveComparison ||
|
|
|
|
pAlarm->trigger.test_type ==
|
|
|
|
XSyncNegativeComparison)))
|
|
|
|
pAlarm->state = XSyncAlarmInactive;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
new_test_value = pAlarm->trigger.test_value;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pAlarm->state == XSyncAlarmActive) {
|
|
|
|
Bool overflow;
|
|
|
|
CARD64 oldvalue;
|
|
|
|
SyncTrigger *paTrigger = &pAlarm->trigger;
|
|
|
|
SyncCounter *paCounter;
|
|
|
|
|
|
|
|
if (!SyncCheckWarnIsCounter(paTrigger->pSync,
|
|
|
|
WARN_INVALID_COUNTER_ALARM))
|
|
|
|
return;
|
|
|
|
|
|
|
|
paCounter = (SyncCounter *) pTrigger->pSync;
|
|
|
|
|
|
|
|
/* "The alarm is updated by repeatedly adding delta to the
|
|
|
|
* value of the trigger and re-initializing it until it
|
|
|
|
* becomes FALSE."
|
|
|
|
*/
|
|
|
|
oldvalue = paTrigger->test_value;
|
|
|
|
|
|
|
|
/* XXX really should do something smarter here */
|
|
|
|
|
|
|
|
do {
|
|
|
|
XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
|
|
|
|
pAlarm->delta, &overflow);
|
|
|
|
} while (!overflow &&
|
|
|
|
(*paTrigger->CheckTrigger) (paTrigger, paCounter->value));
|
|
|
|
|
|
|
|
new_test_value = paTrigger->test_value;
|
|
|
|
paTrigger->test_value = oldvalue;
|
|
|
|
|
|
|
|
/* "If this update would cause value to fall outside the range
|
|
|
|
* for an INT64...no change is made to value (test-value) and
|
|
|
|
* the alarm state is changed to Inactive before the event is
|
|
|
|
* generated."
|
|
|
|
*/
|
|
|
|
if (overflow) {
|
|
|
|
new_test_value = oldvalue;
|
|
|
|
pAlarm->state = XSyncAlarmInactive;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
/* The AlarmNotify event has to have the "new state of the alarm"
|
|
|
|
* which we can't be sure of until this point. However, it has
|
|
|
|
* to have the "old" trigger test value. That's the reason for
|
|
|
|
* all the newvalue/oldvalue shuffling above. After we send the
|
|
|
|
* events, give the trigger its new test value.
|
|
|
|
*/
|
|
|
|
SyncSendAlarmNotifyEvents(pAlarm);
|
|
|
|
pTrigger->test_value = new_test_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called when an Await unblocks, either as a result
|
|
|
|
* of the trigger firing OR the counter being destroyed.
|
|
|
|
* It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
|
|
|
|
* (for Await triggers).
|
|
|
|
*/
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAwaitTriggerFired(SyncTrigger * pTrigger)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAwait *pAwait = (SyncAwait *) pTrigger;
|
2003-11-14 16:54:54 +01:00
|
|
|
int numwaits;
|
|
|
|
SyncAwaitUnion *pAwaitUnion;
|
|
|
|
SyncAwait **ppAwait;
|
|
|
|
int num_events = 0;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pAwaitUnion = (SyncAwaitUnion *) pAwait->pHeader;
|
2003-11-14 16:54:54 +01:00
|
|
|
numwaits = pAwaitUnion->header.num_waitconditions;
|
2010-05-05 20:44:06 +02:00
|
|
|
ppAwait = malloc(numwaits * sizeof(SyncAwait *));
|
2003-11-14 16:54:54 +01:00
|
|
|
if (!ppAwait)
|
2012-03-21 20:55:09 +01:00
|
|
|
goto bail;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pAwait = &(pAwaitUnion + 1)->await;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* "When a client is unblocked, all the CounterNotify events for
|
|
|
|
* the Await request are generated contiguously. If count is 0
|
|
|
|
* there are no more events to follow for this request. If
|
|
|
|
* count is n, there are at least n more events to follow."
|
|
|
|
*
|
|
|
|
* Thus, it is best to find all the counters for which events
|
|
|
|
* need to be sent first, so that an accurate count field can
|
|
|
|
* be stored in the events.
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
for (; numwaits; numwaits--, pAwait++) {
|
|
|
|
CARD64 diff;
|
|
|
|
Bool overflow, diffgreater, diffequal;
|
|
|
|
|
|
|
|
/* "A CounterNotify event with the destroyed flag set to TRUE is
|
|
|
|
* always generated if the counter for one of the triggers is
|
|
|
|
* destroyed."
|
|
|
|
*/
|
|
|
|
if (pAwait->trigger.pSync->beingDestroyed) {
|
|
|
|
ppAwait[num_events++] = pAwait;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SYNC_COUNTER == pAwait->trigger.pSync->type) {
|
|
|
|
SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
|
|
|
|
|
|
|
|
/* "The difference between the counter and the test value is
|
|
|
|
* calculated by subtracting the test value from the value of
|
|
|
|
* the counter."
|
|
|
|
*/
|
|
|
|
XSyncValueSubtract(&diff, pCounter->value,
|
|
|
|
pAwait->trigger.test_value, &overflow);
|
|
|
|
|
|
|
|
/* "If the difference lies outside the range for an INT64, an
|
|
|
|
* event is not generated."
|
|
|
|
*/
|
|
|
|
if (overflow)
|
|
|
|
continue;
|
|
|
|
diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
|
|
|
|
diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
|
|
|
|
|
|
|
|
/* "If the test-type is PositiveTransition or
|
|
|
|
* PositiveComparison, a CounterNotify event is generated if
|
|
|
|
* the difference is at least event-threshold. If the test-type
|
|
|
|
* is NegativeTransition or NegativeComparison, a CounterNotify
|
|
|
|
* event is generated if the difference is at most
|
|
|
|
* event-threshold."
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (((pAwait->trigger.test_type == XSyncPositiveComparison ||
|
|
|
|
pAwait->trigger.test_type == XSyncPositiveTransition)
|
|
|
|
&& (diffgreater || diffequal))
|
|
|
|
||
|
|
|
|
((pAwait->trigger.test_type == XSyncNegativeComparison ||
|
|
|
|
pAwait->trigger.test_type == XSyncNegativeTransition)
|
|
|
|
&& (!diffgreater) /* less or equal */
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
ppAwait[num_events++] = pAwait;
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
if (num_events)
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
|
|
|
|
num_events);
|
2010-05-05 20:44:06 +02:00
|
|
|
free(ppAwait);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
bail:
|
2003-11-14 16:54:54 +01:00
|
|
|
/* unblock the client */
|
|
|
|
AttendClient(pAwaitUnion->header.client);
|
|
|
|
/* delete the await */
|
|
|
|
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
|
|
|
|
}
|
|
|
|
|
2013-10-17 04:02:27 +02:00
|
|
|
static CARD64
|
|
|
|
SyncUpdateCounter(SyncCounter *pCounter, CARD64 newval)
|
|
|
|
{
|
|
|
|
CARD64 oldval = pCounter->value;
|
|
|
|
pCounter->value = newval;
|
|
|
|
return oldval;
|
|
|
|
}
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/* This function should always be used to change a counter's value so that
|
|
|
|
* any triggers depending on the counter will be checked.
|
|
|
|
*/
|
|
|
|
void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncChangeCounter(SyncCounter * pCounter, CARD64 newval)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncTriggerList *ptl, *pnext;
|
2003-11-14 16:54:54 +01:00
|
|
|
CARD64 oldval;
|
|
|
|
|
2013-10-17 04:02:27 +02:00
|
|
|
oldval = SyncUpdateCounter(pCounter, newval);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* run through triggers to see if any become true */
|
2012-03-21 20:55:09 +01:00
|
|
|
for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
|
|
|
|
pnext = ptl->next;
|
|
|
|
if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval))
|
|
|
|
(*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (IsSystemCounter(pCounter)) {
|
|
|
|
SyncComputeBracketValues(pCounter);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* loosely based on dix/events.c/EventSelectForWindow */
|
|
|
|
static Bool
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncEventSelectForAlarm(SyncAlarm * pAlarm, ClientPtr client, Bool wantevents)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
SyncAlarmClientList *pClients;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client == pAlarm->client) { /* alarm owner */
|
|
|
|
pAlarm->events = wantevents;
|
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* see if the client is already on the list (has events selected) */
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
for (pClients = pAlarm->pEventClients; pClients; pClients = pClients->next) {
|
|
|
|
if (pClients->client == client) {
|
|
|
|
/* client's presence on the list indicates desire for
|
|
|
|
* events. If the client doesn't want events, remove it
|
|
|
|
* from the list. If the client does want events, do
|
|
|
|
* nothing, since it's already got them.
|
|
|
|
*/
|
|
|
|
if (!wantevents) {
|
|
|
|
FreeResource(pClients->delete_id, RT_NONE);
|
|
|
|
}
|
|
|
|
return Success;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if we get here, this client does not currently have
|
|
|
|
* events selected on the alarm
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!wantevents)
|
2012-03-21 20:55:09 +01:00
|
|
|
/* client doesn't want events, and we just discovered that it
|
|
|
|
* doesn't have them, so there's nothing to do.
|
|
|
|
*/
|
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* add new client to pAlarm->pEventClients */
|
|
|
|
|
2010-05-05 20:44:06 +02:00
|
|
|
pClients = malloc(sizeof(SyncAlarmClientList));
|
2003-11-14 16:54:54 +01:00
|
|
|
if (!pClients)
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
/* register it as a resource so it will be cleaned up
|
2003-11-14 16:54:54 +01:00
|
|
|
* if the client dies
|
|
|
|
*/
|
|
|
|
|
|
|
|
pClients->delete_id = FakeClientID(client->index);
|
|
|
|
|
|
|
|
/* link it into list after we know all the allocations succeed */
|
|
|
|
pClients->next = pAlarm->pEventClients;
|
|
|
|
pAlarm->pEventClients = pClients;
|
|
|
|
pClients->client = client;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
|
|
|
if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask,
|
|
|
|
CARD32 *values)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
XSyncCounter counter;
|
|
|
|
Mask origmask = mask;
|
|
|
|
|
|
|
|
counter = pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None;
|
|
|
|
|
|
|
|
while (mask) {
|
|
|
|
int index2 = lowbit(mask);
|
|
|
|
|
|
|
|
mask &= ~index2;
|
|
|
|
switch (index2) {
|
|
|
|
case XSyncCACounter:
|
|
|
|
mask &= ~XSyncCACounter;
|
|
|
|
/* sanity check in SyncInitTrigger */
|
|
|
|
counter = *values++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XSyncCAValueType:
|
|
|
|
mask &= ~XSyncCAValueType;
|
|
|
|
/* sanity check in SyncInitTrigger */
|
|
|
|
pAlarm->trigger.value_type = *values++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XSyncCAValue:
|
|
|
|
mask &= ~XSyncCAValue;
|
|
|
|
XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
|
|
|
|
values += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XSyncCATestType:
|
|
|
|
mask &= ~XSyncCATestType;
|
|
|
|
/* sanity check in SyncInitTrigger */
|
|
|
|
pAlarm->trigger.test_type = *values++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XSyncCADelta:
|
|
|
|
mask &= ~XSyncCADelta;
|
|
|
|
XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
|
|
|
|
values += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XSyncCAEvents:
|
|
|
|
mask &= ~XSyncCAEvents;
|
|
|
|
if ((*values != xTrue) && (*values != xFalse)) {
|
|
|
|
client->errorValue = *values;
|
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
status = SyncEventSelectForAlarm(pAlarm, client,
|
|
|
|
(Bool) (*values++));
|
|
|
|
if (status != Success)
|
|
|
|
return status;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
client->errorValue = mask;
|
|
|
|
return BadValue;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* "If the test-type is PositiveComparison or PositiveTransition
|
|
|
|
* and delta is less than zero, or if the test-type is
|
|
|
|
* NegativeComparison or NegativeTransition and delta is
|
|
|
|
* greater than zero, a Match error is generated."
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
if (origmask & (XSyncCADelta | XSyncCATestType)) {
|
|
|
|
CARD64 zero;
|
|
|
|
|
|
|
|
XSyncIntToValue(&zero, 0);
|
|
|
|
if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
|
|
|
|
(pAlarm->trigger.test_type == XSyncPositiveTransition))
|
|
|
|
&& XSyncValueLessThan(pAlarm->delta, zero))
|
|
|
|
||
|
|
|
|
(((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
|
|
|
|
(pAlarm->trigger.test_type == XSyncNegativeTransition))
|
|
|
|
&& XSyncValueGreaterThan(pAlarm->delta, zero))
|
|
|
|
) {
|
|
|
|
return BadMatch;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* postpone this until now, when we're sure nothing else can go wrong */
|
2010-06-28 23:59:01 +02:00
|
|
|
if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter,
|
2012-03-21 20:55:09 +01:00
|
|
|
origmask & XSyncCAAllTrigger)) != Success)
|
|
|
|
return status;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* XXX spec does not really say to do this - needs clarification */
|
|
|
|
pAlarm->state = XSyncAlarmActive;
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2010-06-28 23:51:54 +02:00
|
|
|
static SyncObject *
|
|
|
|
SyncCreate(ClientPtr client, XID id, unsigned char type)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2010-06-28 23:51:54 +02:00
|
|
|
SyncObject *pSync;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-06-28 23:51:54 +02:00
|
|
|
switch (type) {
|
|
|
|
case SYNC_COUNTER:
|
2012-03-21 20:55:09 +01:00
|
|
|
pSync = malloc(sizeof(SyncCounter));
|
|
|
|
break;
|
2010-06-26 02:59:14 +02:00
|
|
|
case SYNC_FENCE:
|
2012-03-21 20:55:09 +01:00
|
|
|
pSync = (SyncObject *) dixAllocateObjectWithPrivates(SyncFence,
|
|
|
|
PRIVATE_SYNC_FENCE);
|
|
|
|
break;
|
2010-06-28 23:51:54 +02:00
|
|
|
default:
|
2012-03-21 20:55:09 +01:00
|
|
|
return NULL;
|
2010-06-28 23:51:54 +02:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-06-26 02:59:14 +02:00
|
|
|
if (!pSync)
|
2012-03-21 20:55:09 +01:00
|
|
|
return NULL;
|
2010-06-28 23:51:54 +02:00
|
|
|
|
|
|
|
pSync->client = client;
|
|
|
|
pSync->id = id;
|
|
|
|
pSync->pTriglist = NULL;
|
|
|
|
pSync->beingDestroyed = FALSE;
|
|
|
|
pSync->type = type;
|
|
|
|
|
|
|
|
return pSync;
|
|
|
|
}
|
|
|
|
|
2013-04-10 04:59:39 +02:00
|
|
|
int
|
|
|
|
SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
|
|
|
|
{
|
2013-11-03 18:56:02 +01:00
|
|
|
#if HAVE_XSHMFENCE
|
2013-04-10 04:59:39 +02:00
|
|
|
SyncFence *pFence;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE);
|
|
|
|
if (!pFence)
|
|
|
|
return BadAlloc;
|
|
|
|
|
|
|
|
status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered);
|
|
|
|
if (status != Success) {
|
2013-11-19 07:33:27 +01:00
|
|
|
dixFreeObjectWithPrivates(pFence, PRIVATE_SYNC_FENCE);
|
2013-04-10 04:59:39 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
if (!AddResource(id, RTFence, (void *) pFence))
|
2013-04-10 04:59:39 +02:00
|
|
|
return BadAlloc;
|
|
|
|
|
|
|
|
return Success;
|
2013-11-03 18:56:02 +01:00
|
|
|
#else
|
|
|
|
return BadImplementation;
|
|
|
|
#endif
|
2013-04-10 04:59:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
|
|
|
|
{
|
2013-11-03 18:56:02 +01:00
|
|
|
#if HAVE_XSHMFENCE
|
2013-04-10 04:59:39 +02:00
|
|
|
return miSyncFDFromFence(pDraw, pFence);
|
2013-11-03 18:56:02 +01:00
|
|
|
#else
|
|
|
|
return BadImplementation;
|
|
|
|
#endif
|
2013-04-10 04:59:39 +02:00
|
|
|
}
|
|
|
|
|
2010-06-28 23:51:54 +02:00
|
|
|
static SyncCounter *
|
|
|
|
SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
|
|
|
|
{
|
|
|
|
SyncCounter *pCounter;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!(pCounter = (SyncCounter *) SyncCreate(client, id, SYNC_COUNTER)))
|
|
|
|
return NULL;
|
2010-06-28 23:51:54 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
pCounter->value = initialvalue;
|
|
|
|
pCounter->pSysCounterInfo = NULL;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
if (!AddResource(id, RTCounter, (void *) pCounter))
|
2012-03-21 20:55:09 +01:00
|
|
|
return NULL;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
return pCounter;
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int FreeCounter(void *, XID);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ***** System Counter utilities
|
|
|
|
*/
|
|
|
|
|
2012-03-12 07:03:50 +01:00
|
|
|
SyncCounter*
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCreateSystemCounter(const char *name,
|
|
|
|
CARD64 initial,
|
|
|
|
CARD64 resolution,
|
|
|
|
SyncCounterType counterType,
|
2012-03-12 05:07:44 +01:00
|
|
|
SyncSystemCounterQueryValue QueryValue,
|
|
|
|
SyncSystemCounterBracketValues BracketValues
|
2012-03-21 20:55:09 +01:00
|
|
|
)
|
|
|
|
{
|
|
|
|
SyncCounter *pCounter;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* this function may be called before SYNC has been initialized, so we
|
|
|
|
* have to make sure RTCounter is created.
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
if (RTCounter == 0) {
|
|
|
|
RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
|
|
|
|
if (RTCounter == 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-07-10 10:10:21 +02:00
|
|
|
xorg_list_init(&SysCounterList);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2009-01-22 08:11:16 +01:00
|
|
|
pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pCounter) {
|
|
|
|
SysCounterInfo *psci;
|
|
|
|
|
|
|
|
psci = malloc(sizeof(SysCounterInfo));
|
|
|
|
if (!psci) {
|
|
|
|
FreeResource(pCounter->sync.id, RT_NONE);
|
|
|
|
return pCounter;
|
|
|
|
}
|
|
|
|
pCounter->pSysCounterInfo = psci;
|
2012-03-15 01:22:18 +01:00
|
|
|
psci->pCounter = pCounter;
|
2012-03-13 01:21:23 +01:00
|
|
|
psci->name = strdup(name);
|
2012-03-21 20:55:09 +01:00
|
|
|
psci->resolution = resolution;
|
|
|
|
psci->counterType = counterType;
|
|
|
|
psci->QueryValue = QueryValue;
|
|
|
|
psci->BracketValues = BracketValues;
|
2012-03-13 00:28:15 +01:00
|
|
|
psci->private = NULL;
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncMaxValue(&psci->bracket_greater);
|
|
|
|
XSyncMinValue(&psci->bracket_less);
|
2012-03-15 01:22:18 +01:00
|
|
|
xorg_list_add(&psci->entry, &SysCounterList);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2008-12-10 17:47:35 +01:00
|
|
|
return pCounter;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-12-15 10:05:51 +01:00
|
|
|
SyncDestroySystemCounter(void *pSysCounter)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCounter *pCounter = (SyncCounter *) pSysCounter;
|
|
|
|
|
2010-06-28 23:51:54 +02:00
|
|
|
FreeResource(pCounter->sync.id, RT_NONE);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncComputeBracketValues(SyncCounter * pCounter)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
SyncTriggerList *pCur;
|
|
|
|
SyncTrigger *pTrigger;
|
2006-04-03 03:28:11 +02:00
|
|
|
SysCounterInfo *psci;
|
2003-11-14 16:54:54 +01:00
|
|
|
CARD64 *pnewgtval = NULL;
|
|
|
|
CARD64 *pnewltval = NULL;
|
|
|
|
SyncCounterType ct;
|
|
|
|
|
|
|
|
if (!pCounter)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-04-03 03:28:11 +02:00
|
|
|
psci = pCounter->pSysCounterInfo;
|
2003-11-14 16:54:54 +01:00
|
|
|
ct = pCounter->pSysCounterInfo->counterType;
|
|
|
|
if (ct == XSyncCounterNeverChanges)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-05-10 23:00:49 +02:00
|
|
|
XSyncMaxValue(&psci->bracket_greater);
|
|
|
|
XSyncMinValue(&psci->bracket_less);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
for (pCur = pCounter->sync.pTriglist; pCur; pCur = pCur->next) {
|
|
|
|
pTrigger = pCur->pTrigger;
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
if (pTrigger->test_type == XSyncPositiveComparison &&
|
2012-03-21 20:55:09 +01:00
|
|
|
ct != XSyncCounterNeverIncreases) {
|
|
|
|
if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueLessThan(pTrigger->test_value,
|
|
|
|
psci->bracket_greater)) {
|
|
|
|
psci->bracket_greater = pTrigger->test_value;
|
|
|
|
pnewgtval = &psci->bracket_greater;
|
|
|
|
}
|
sync: always set the brackets (#59644)
The current code sets bracket_greater to the first trigger after the current
value, and bracket_less to the last trigger before the current value.
For example, the idle timer with three negative and three positive transitions
would set this:
nt1 nt2 nt3
|--------|------|--|------- idle --|---|--|-----> t
pt1 pt2 pt3
bracket_less == nt2
bracket_greater == pt2
This is an optimization so we can skip code paths in the block/wakeup handlers
if the current value doesn't meet any of the trigger requirements. Those
handlers largely do a
if (bracket_less is less than current value &&
bracket_greater is greater than current value)
return, nothing to do
However, unless the bracket values are updated at the correct time, the
following may happen:
nt
|--------------|---------- idle ------|--------> t
pt
In this case, neither bracket is set, we're past the pos transition and not
yet at the neg transition. idle may now go past nt, but the brackets are not
updated. If idle is then reset to 0, no alarm is triggered for nt. Likewise,
idle may now go past pt and no alarm is triggered.
Changing an alarm or triggering an alarm will re-calculate the brackets, so
this bug is somewhat random. If any other client triggers an alarm when the
brackets are wrongly NULL, the recalculation will set them this bug may not
appear.
This patch changes the behavior, so that the brackets are always the nearest
positive or negative transitions to the current counter value. In the example
above, nt will trigger a wakeup and a re-calculation of the brackets, so that
going past it in the negative direction will then cause the proper alarm
triggers.
Or, in Keith's words:
Timer currently past a positive trigger
No bracket values, because no trigger in range
Timer moves backwards before the positive trigger
Brackets not reset, even though there is now a trigger in range
Timer moves forward past the positive trigger
Trigger doesn't fire because brackets not set
Setting the LT bracket in this case will cause everything to get
re-evaluated when the sync value moves backwards before the trigger
value.
X.Org Bug 59644 <http://bugs.freedesktop.org/show_bug.cgi?id=59644>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
2013-10-16 08:31:15 +02:00
|
|
|
else if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) {
|
|
|
|
psci->bracket_less = pTrigger->test_value;
|
|
|
|
pnewltval = &psci->bracket_less;
|
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else if (pTrigger->test_type == XSyncNegativeComparison &&
|
|
|
|
ct != XSyncCounterNeverDecreases) {
|
|
|
|
if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueGreaterThan(pTrigger->test_value,
|
|
|
|
psci->bracket_less)) {
|
|
|
|
psci->bracket_less = pTrigger->test_value;
|
|
|
|
pnewltval = &psci->bracket_less;
|
|
|
|
}
|
sync: always set the brackets (#59644)
The current code sets bracket_greater to the first trigger after the current
value, and bracket_less to the last trigger before the current value.
For example, the idle timer with three negative and three positive transitions
would set this:
nt1 nt2 nt3
|--------|------|--|------- idle --|---|--|-----> t
pt1 pt2 pt3
bracket_less == nt2
bracket_greater == pt2
This is an optimization so we can skip code paths in the block/wakeup handlers
if the current value doesn't meet any of the trigger requirements. Those
handlers largely do a
if (bracket_less is less than current value &&
bracket_greater is greater than current value)
return, nothing to do
However, unless the bracket values are updated at the correct time, the
following may happen:
nt
|--------------|---------- idle ------|--------> t
pt
In this case, neither bracket is set, we're past the pos transition and not
yet at the neg transition. idle may now go past nt, but the brackets are not
updated. If idle is then reset to 0, no alarm is triggered for nt. Likewise,
idle may now go past pt and no alarm is triggered.
Changing an alarm or triggering an alarm will re-calculate the brackets, so
this bug is somewhat random. If any other client triggers an alarm when the
brackets are wrongly NULL, the recalculation will set them this bug may not
appear.
This patch changes the behavior, so that the brackets are always the nearest
positive or negative transitions to the current counter value. In the example
above, nt will trigger a wakeup and a re-calculation of the brackets, so that
going past it in the negative direction will then cause the proper alarm
triggers.
Or, in Keith's words:
Timer currently past a positive trigger
No bracket values, because no trigger in range
Timer moves backwards before the positive trigger
Brackets not reset, even though there is now a trigger in range
Timer moves forward past the positive trigger
Trigger doesn't fire because brackets not set
Setting the LT bracket in this case will cause everything to get
re-evaluated when the sync value moves backwards before the trigger
value.
X.Org Bug 59644 <http://bugs.freedesktop.org/show_bug.cgi?id=59644>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
2013-10-16 08:31:15 +02:00
|
|
|
else if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) {
|
|
|
|
psci->bracket_greater = pTrigger->test_value;
|
|
|
|
pnewgtval = &psci->bracket_greater;
|
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else if (pTrigger->test_type == XSyncNegativeTransition &&
|
|
|
|
ct != XSyncCounterNeverIncreases) {
|
2013-10-15 02:11:20 +02:00
|
|
|
if (XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) {
|
|
|
|
/*
|
|
|
|
* If the value is exactly equal to our threshold, we want one
|
|
|
|
* more event in the negative direction to ensure we pick up
|
|
|
|
* when the value is less than this threshold.
|
|
|
|
*/
|
|
|
|
psci->bracket_less = pTrigger->test_value;
|
|
|
|
pnewltval = &psci->bracket_less;
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
sync: always set the brackets (#59644)
The current code sets bracket_greater to the first trigger after the current
value, and bracket_less to the last trigger before the current value.
For example, the idle timer with three negative and three positive transitions
would set this:
nt1 nt2 nt3
|--------|------|--|------- idle --|---|--|-----> t
pt1 pt2 pt3
bracket_less == nt2
bracket_greater == pt2
This is an optimization so we can skip code paths in the block/wakeup handlers
if the current value doesn't meet any of the trigger requirements. Those
handlers largely do a
if (bracket_less is less than current value &&
bracket_greater is greater than current value)
return, nothing to do
However, unless the bracket values are updated at the correct time, the
following may happen:
nt
|--------------|---------- idle ------|--------> t
pt
In this case, neither bracket is set, we're past the pos transition and not
yet at the neg transition. idle may now go past nt, but the brackets are not
updated. If idle is then reset to 0, no alarm is triggered for nt. Likewise,
idle may now go past pt and no alarm is triggered.
Changing an alarm or triggering an alarm will re-calculate the brackets, so
this bug is somewhat random. If any other client triggers an alarm when the
brackets are wrongly NULL, the recalculation will set them this bug may not
appear.
This patch changes the behavior, so that the brackets are always the nearest
positive or negative transitions to the current counter value. In the example
above, nt will trigger a wakeup and a re-calculation of the brackets, so that
going past it in the negative direction will then cause the proper alarm
triggers.
Or, in Keith's words:
Timer currently past a positive trigger
No bracket values, because no trigger in range
Timer moves backwards before the positive trigger
Brackets not reset, even though there is now a trigger in range
Timer moves forward past the positive trigger
Trigger doesn't fire because brackets not set
Setting the LT bracket in this case will cause everything to get
re-evaluated when the sync value moves backwards before the trigger
value.
X.Org Bug 59644 <http://bugs.freedesktop.org/show_bug.cgi?id=59644>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
2013-10-16 08:31:15 +02:00
|
|
|
else if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) {
|
|
|
|
psci->bracket_greater = pTrigger->test_value;
|
|
|
|
pnewgtval = &psci->bracket_greater;
|
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
2009-08-13 08:37:00 +02:00
|
|
|
else if (pTrigger->test_type == XSyncPositiveTransition &&
|
2012-03-21 20:55:09 +01:00
|
|
|
ct != XSyncCounterNeverDecreases) {
|
2013-10-15 02:11:20 +02:00
|
|
|
if (XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) {
|
|
|
|
/*
|
|
|
|
* If the value is exactly equal to our threshold, we
|
|
|
|
* want one more event in the positive direction to
|
|
|
|
* ensure we pick up when the value *exceeds* this
|
|
|
|
* threshold.
|
|
|
|
*/
|
|
|
|
psci->bracket_greater = pTrigger->test_value;
|
|
|
|
pnewgtval = &psci->bracket_greater;
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
sync: always set the brackets (#59644)
The current code sets bracket_greater to the first trigger after the current
value, and bracket_less to the last trigger before the current value.
For example, the idle timer with three negative and three positive transitions
would set this:
nt1 nt2 nt3
|--------|------|--|------- idle --|---|--|-----> t
pt1 pt2 pt3
bracket_less == nt2
bracket_greater == pt2
This is an optimization so we can skip code paths in the block/wakeup handlers
if the current value doesn't meet any of the trigger requirements. Those
handlers largely do a
if (bracket_less is less than current value &&
bracket_greater is greater than current value)
return, nothing to do
However, unless the bracket values are updated at the correct time, the
following may happen:
nt
|--------------|---------- idle ------|--------> t
pt
In this case, neither bracket is set, we're past the pos transition and not
yet at the neg transition. idle may now go past nt, but the brackets are not
updated. If idle is then reset to 0, no alarm is triggered for nt. Likewise,
idle may now go past pt and no alarm is triggered.
Changing an alarm or triggering an alarm will re-calculate the brackets, so
this bug is somewhat random. If any other client triggers an alarm when the
brackets are wrongly NULL, the recalculation will set them this bug may not
appear.
This patch changes the behavior, so that the brackets are always the nearest
positive or negative transitions to the current counter value. In the example
above, nt will trigger a wakeup and a re-calculation of the brackets, so that
going past it in the negative direction will then cause the proper alarm
triggers.
Or, in Keith's words:
Timer currently past a positive trigger
No bracket values, because no trigger in range
Timer moves backwards before the positive trigger
Brackets not reset, even though there is now a trigger in range
Timer moves forward past the positive trigger
Trigger doesn't fire because brackets not set
Setting the LT bracket in this case will cause everything to get
re-evaluated when the sync value moves backwards before the trigger
value.
X.Org Bug 59644 <http://bugs.freedesktop.org/show_bug.cgi?id=59644>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
2013-10-16 08:31:15 +02:00
|
|
|
else if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
|
|
|
|
XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) {
|
|
|
|
psci->bracket_less = pTrigger->test_value;
|
|
|
|
pnewltval = &psci->bracket_less;
|
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
} /* end for each trigger */
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
(*psci->BracketValues) ((void *) pCounter, pnewltval, pnewgtval);
|
2013-10-16 05:01:01 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ***** Resource delete functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
static int
|
2008-12-10 20:18:59 +01:00
|
|
|
FreeAlarm(void *addr, XID id)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm = (SyncAlarm *) addr;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pAlarm->state = XSyncAlarmDestroyed;
|
|
|
|
|
|
|
|
SyncSendAlarmNotifyEvents(pAlarm);
|
|
|
|
|
|
|
|
/* delete event selections */
|
|
|
|
|
|
|
|
while (pAlarm->pEventClients)
|
2012-03-21 20:55:09 +01:00
|
|
|
FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-05-05 20:44:06 +02:00
|
|
|
free(pAlarm);
|
2003-11-14 16:54:54 +01:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Cleanup after the destruction of a Counter
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
|
|
static int
|
2008-12-10 20:18:59 +01:00
|
|
|
FreeCounter(void *env, XID id)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCounter *pCounter = (SyncCounter *) env;
|
2003-11-14 16:54:54 +01:00
|
|
|
SyncTriggerList *ptl, *pnext;
|
|
|
|
|
2010-06-28 23:51:54 +02:00
|
|
|
pCounter->sync.beingDestroyed = TRUE;
|
2003-11-14 16:54:54 +01:00
|
|
|
/* tell all the counter's triggers that the counter has been destroyed */
|
2012-03-21 20:55:09 +01:00
|
|
|
for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
|
|
|
|
(*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
|
|
|
|
pnext = ptl->next;
|
|
|
|
free(ptl); /* destroy the trigger list as we go */
|
|
|
|
}
|
|
|
|
if (IsSystemCounter(pCounter)) {
|
2012-03-15 01:22:18 +01:00
|
|
|
xorg_list_del(&pCounter->pSysCounterInfo->entry);
|
2012-03-13 01:21:23 +01:00
|
|
|
free(pCounter->pSysCounterInfo->name);
|
2012-03-13 00:28:15 +01:00
|
|
|
free(pCounter->pSysCounterInfo->private);
|
2012-03-21 20:55:09 +01:00
|
|
|
free(pCounter->pSysCounterInfo);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-05-05 20:44:06 +02:00
|
|
|
free(pCounter);
|
2003-11-14 16:54:54 +01:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Cleanup after Await
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
|
|
static int
|
2008-12-10 20:18:59 +01:00
|
|
|
FreeAwait(void *addr, XID id)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
|
|
|
|
SyncAwait *pAwait;
|
|
|
|
int numwaits;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pAwait = &(pAwaitUnion + 1)->await; /* first await on list */
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* remove triggers from counters */
|
|
|
|
|
|
|
|
for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
|
2012-03-21 20:55:09 +01:00
|
|
|
numwaits--, pAwait++) {
|
|
|
|
/* If the counter is being destroyed, FreeCounter will delete
|
|
|
|
* the trigger list itself, so don't do it here.
|
|
|
|
*/
|
|
|
|
SyncObject *pSync = pAwait->trigger.pSync;
|
|
|
|
|
|
|
|
if (pSync && !pSync->beingDestroyed)
|
|
|
|
SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-05-05 20:44:06 +02:00
|
|
|
free(pAwaitUnion);
|
2003-11-14 16:54:54 +01:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* loosely based on dix/events.c/OtherClientGone */
|
|
|
|
static int
|
2008-12-10 20:18:59 +01:00
|
|
|
FreeAlarmClient(void *value, XID id)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm = (SyncAlarm *) value;
|
2003-11-14 16:54:54 +01:00
|
|
|
SyncAlarmClientList *pCur, *pPrev;
|
|
|
|
|
|
|
|
for (pPrev = NULL, pCur = pAlarm->pEventClients;
|
2012-03-21 20:55:09 +01:00
|
|
|
pCur; pPrev = pCur, pCur = pCur->next) {
|
|
|
|
if (pCur->delete_id == id) {
|
|
|
|
if (pPrev)
|
|
|
|
pPrev->next = pCur->next;
|
|
|
|
else
|
|
|
|
pAlarm->pEventClients = pCur->next;
|
|
|
|
free(pCur);
|
|
|
|
return Success;
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
FatalError("alarm client not on event list");
|
2012-03-21 20:55:09 +01:00
|
|
|
/*NOTREACHED*/}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ***** Proc functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Initialize the extension
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncInitialize(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-07-10 04:12:43 +02:00
|
|
|
xSyncInitializeReply rep = {
|
|
|
|
.type = X_Reply,
|
|
|
|
.sequenceNumber = client->sequence,
|
|
|
|
.length = 0,
|
|
|
|
.majorVersion = SERVER_SYNC_MAJOR_VERSION,
|
|
|
|
.minorVersion = SERVER_SYNC_MINOR_VERSION,
|
|
|
|
};
|
2012-03-21 20:55:09 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncInitializeReq);
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swaps(&rep.sequenceNumber);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, sizeof(rep), &rep);
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Get list of system counters available through the extension
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncListSystemCounters(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-07-10 04:12:43 +02:00
|
|
|
xSyncListSystemCountersReply rep = {
|
|
|
|
.type = X_Reply,
|
|
|
|
.sequenceNumber = client->sequence,
|
|
|
|
.nCounters = 0,
|
|
|
|
};
|
2012-03-15 01:22:18 +01:00
|
|
|
SysCounterInfo *psci;
|
|
|
|
int len = 0;
|
2003-11-14 17:49:22 +01:00
|
|
|
xSyncSystemCounter *list = NULL, *walklist = NULL;
|
2008-12-10 20:18:59 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
|
|
|
|
|
2012-03-15 01:22:18 +01:00
|
|
|
xorg_list_for_each_entry(psci, &SysCounterList, entry) {
|
2012-03-21 20:55:09 +01:00
|
|
|
/* pad to 4 byte boundary */
|
2012-03-15 01:22:18 +01:00
|
|
|
len += pad_to_int32(sz_xSyncSystemCounter + strlen(psci->name));
|
|
|
|
++rep.nCounters;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (len) {
|
|
|
|
walklist = list = malloc(len);
|
|
|
|
if (!list)
|
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2009-07-06 04:20:21 +02:00
|
|
|
rep.length = bytes_to_int32(len);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swaps(&rep.sequenceNumber);
|
|
|
|
swapl(&rep.length);
|
|
|
|
swapl(&rep.nCounters);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-03-15 01:22:18 +01:00
|
|
|
xorg_list_for_each_entry(psci, &SysCounterList, entry) {
|
2012-03-21 20:55:09 +01:00
|
|
|
int namelen;
|
|
|
|
char *pname_in_reply;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-15 01:22:18 +01:00
|
|
|
walklist->counter = psci->pCounter->sync.id;
|
2012-03-21 20:55:09 +01:00
|
|
|
walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
|
|
|
|
walklist->resolution_lo = XSyncValueLow32(psci->resolution);
|
|
|
|
namelen = strlen(psci->name);
|
|
|
|
walklist->name_length = namelen;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swapl(&walklist->counter);
|
|
|
|
swapl(&walklist->resolution_hi);
|
|
|
|
swapl(&walklist->resolution_lo);
|
|
|
|
swaps(&walklist->name_length);
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pname_in_reply = ((char *) walklist) + sz_xSyncSystemCounter;
|
|
|
|
strncpy(pname_in_reply, psci->name, namelen);
|
|
|
|
walklist = (xSyncSystemCounter *) (((char *) walklist) +
|
|
|
|
pad_to_int32(sz_xSyncSystemCounter +
|
|
|
|
namelen));
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, sizeof(rep), &rep);
|
2012-03-21 20:55:09 +01:00
|
|
|
if (len) {
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, len, list);
|
2012-03-21 20:55:09 +01:00
|
|
|
free(list);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Set client Priority
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncSetPriority(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncSetPriorityReq);
|
|
|
|
ClientPtr priorityclient;
|
2006-12-15 23:26:58 +01:00
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
|
|
|
|
|
|
|
|
if (stuff->id == None)
|
2012-03-21 20:55:09 +01:00
|
|
|
priorityclient = client;
|
2006-12-15 23:26:58 +01:00
|
|
|
else {
|
2012-03-21 20:55:09 +01:00
|
|
|
rc = dixLookupClient(&priorityclient, stuff->id, client,
|
|
|
|
DixSetAttrAccess);
|
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (priorityclient->priority != stuff->priority) {
|
|
|
|
priorityclient->priority = stuff->priority;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
/* The following will force the server back into WaitForSomething
|
|
|
|
* so that the change in this client's priority is immediately
|
|
|
|
* reflected.
|
|
|
|
*/
|
|
|
|
isItTimeToYield = TRUE;
|
|
|
|
dispatchException |= DE_PRIORITYCHANGE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Get client Priority
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncGetPriority(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncGetPriorityReq);
|
|
|
|
xSyncGetPriorityReply rep;
|
|
|
|
ClientPtr priorityclient;
|
2006-12-15 23:26:58 +01:00
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
|
|
|
|
|
|
|
|
if (stuff->id == None)
|
2012-03-21 20:55:09 +01:00
|
|
|
priorityclient = client;
|
2006-12-15 23:26:58 +01:00
|
|
|
else {
|
2012-03-21 20:55:09 +01:00
|
|
|
rc = dixLookupClient(&priorityclient, stuff->id, client,
|
|
|
|
DixGetAttrAccess);
|
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-07-10 04:12:43 +02:00
|
|
|
rep = (xSyncGetPriorityReply) {
|
|
|
|
.type = X_Reply,
|
|
|
|
.sequenceNumber = client->sequence,
|
|
|
|
.length = 0,
|
|
|
|
.priority = priorityclient->priority
|
|
|
|
};
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swaps(&rep.sequenceNumber);
|
|
|
|
swapl(&rep.priority);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, sizeof(xSyncGetPriorityReply), &rep);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Create a new counter
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncCreateCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncCreateCounterReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
CARD64 initial;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
|
|
|
|
|
|
|
|
LEGAL_NEW_RESOURCE(stuff->cid, client);
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncIntsToValue(&initial, stuff->initial_value_lo,
|
|
|
|
stuff->initial_value_hi);
|
2003-11-14 16:54:54 +01:00
|
|
|
if (!SyncCreateCounter(client, stuff->cid, initial))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Set Counter value
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncSetCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncSetCounterReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
CARD64 newvalue;
|
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2003-11-25 20:29:01 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncSetCounterReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pCounter, stuff->cid, RTCounter,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixWriteAccess);
|
2009-04-29 07:04:37 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (IsSystemCounter(pCounter)) {
|
|
|
|
client->errorValue = stuff->cid;
|
|
|
|
return BadAccess;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
|
|
|
|
SyncChangeCounter(pCounter, newvalue);
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Change Counter value
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncChangeCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncChangeCounterReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCounter *pCounter;
|
|
|
|
CARD64 newvalue;
|
|
|
|
Bool overflow;
|
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pCounter, stuff->cid, RTCounter,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixWriteAccess);
|
2009-04-29 07:04:37 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (IsSystemCounter(pCounter)) {
|
|
|
|
client->errorValue = stuff->cid;
|
|
|
|
return BadAccess;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
|
|
|
|
XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
|
2012-03-21 20:55:09 +01:00
|
|
|
if (overflow) {
|
|
|
|
/* XXX 64 bit value can't fit in 32 bits; do the best we can */
|
|
|
|
client->errorValue = stuff->value_hi;
|
|
|
|
return BadValue;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
SyncChangeCounter(pCounter, newvalue);
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Destroy a counter
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncDestroyCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncDestroyCounterReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCounter *pCounter;
|
2009-04-29 07:04:37 +02:00
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pCounter, stuff->counter,
|
2012-03-21 20:55:09 +01:00
|
|
|
RTCounter, client, DixDestroyAccess);
|
2009-04-29 07:04:37 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2009-04-29 07:04:37 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (IsSystemCounter(pCounter)) {
|
|
|
|
client->errorValue = stuff->counter;
|
|
|
|
return BadAccess;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2010-06-28 23:51:54 +02:00
|
|
|
FreeResource(pCounter->sync.id, RT_NONE);
|
2003-11-14 16:54:54 +01:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
static SyncAwaitUnion *
|
2010-12-06 19:11:45 +01:00
|
|
|
SyncAwaitPrologue(ClientPtr client, int items)
|
|
|
|
{
|
|
|
|
SyncAwaitUnion *pAwaitUnion;
|
|
|
|
|
|
|
|
/* all the memory for the entire await list is allocated
|
|
|
|
* here in one chunk
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
pAwaitUnion = malloc((items + 1) * sizeof(SyncAwaitUnion));
|
2010-12-06 19:11:45 +01:00
|
|
|
if (!pAwaitUnion)
|
2012-03-21 20:55:09 +01:00
|
|
|
return NULL;
|
2010-12-06 19:11:45 +01:00
|
|
|
|
|
|
|
/* first item is the header, remainder are real wait conditions */
|
|
|
|
|
|
|
|
pAwaitUnion->header.delete_id = FakeClientID(client->index);
|
|
|
|
pAwaitUnion->header.client = client;
|
|
|
|
pAwaitUnion->header.num_waitconditions = 0;
|
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
|
2012-03-21 20:55:09 +01:00
|
|
|
return NULL;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2010-12-06 19:11:45 +01:00
|
|
|
return pAwaitUnion;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion * pAwaitUnion)
|
2010-12-06 19:11:45 +01:00
|
|
|
{
|
|
|
|
SyncAwait *pAwait;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
IgnoreClient(client);
|
|
|
|
|
|
|
|
/* see if any of the triggers are already true */
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pAwait = &(pAwaitUnion + 1)->await; /* skip over header */
|
|
|
|
for (i = 0; i < items; i++, pAwait++) {
|
|
|
|
CARD64 value;
|
|
|
|
|
|
|
|
/* don't have to worry about NULL counters because the request
|
|
|
|
* errors before we get here out if they occur
|
|
|
|
*/
|
|
|
|
switch (pAwait->trigger.pSync->type) {
|
|
|
|
case SYNC_COUNTER:
|
|
|
|
value = ((SyncCounter *) pAwait->trigger.pSync)->value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
XSyncIntToValue(&value, 0);
|
|
|
|
}
|
2010-12-06 19:11:45 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((*pAwait->trigger.CheckTrigger) (&pAwait->trigger, value)) {
|
|
|
|
(*pAwait->trigger.TriggerFired) (&pAwait->trigger);
|
|
|
|
break; /* once is enough */
|
|
|
|
}
|
2010-12-06 19:11:45 +01:00
|
|
|
}
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Await
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncAwait(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncAwaitReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
int len, items;
|
|
|
|
int i;
|
2003-11-14 16:54:54 +01:00
|
|
|
xSyncWaitCondition *pProtocolWaitConds;
|
|
|
|
SyncAwaitUnion *pAwaitUnion;
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAwait *pAwait;
|
|
|
|
int status;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
|
|
|
|
|
|
|
|
len = client->req_len << 2;
|
|
|
|
len -= sz_xSyncAwaitReq;
|
|
|
|
items = len / sz_xSyncWaitCondition;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (items * sz_xSyncWaitCondition != len) {
|
|
|
|
return BadLength;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
if (items == 0) {
|
|
|
|
client->errorValue = items; /* XXX protocol change */
|
|
|
|
return BadValue;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 19:11:45 +01:00
|
|
|
if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* don't need to do any more memory allocation for this request! */
|
|
|
|
|
2012-03-15 16:18:29 +01:00
|
|
|
pProtocolWaitConds = (xSyncWaitCondition *) &stuff[1];
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pAwait = &(pAwaitUnion + 1)->await; /* skip over header */
|
|
|
|
for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) {
|
|
|
|
if (pProtocolWaitConds->counter == None) { /* XXX protocol change */
|
|
|
|
/* this should take care of removing any triggers created by
|
|
|
|
* this request that have already been registered on sync objects
|
|
|
|
*/
|
|
|
|
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
|
|
|
|
client->errorValue = pProtocolWaitConds->counter;
|
|
|
|
return SyncErrorBase + XSyncBadCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sanity checks are in SyncInitTrigger */
|
|
|
|
pAwait->trigger.pSync = NULL;
|
|
|
|
pAwait->trigger.value_type = pProtocolWaitConds->value_type;
|
|
|
|
XSyncIntsToValue(&pAwait->trigger.wait_value,
|
|
|
|
pProtocolWaitConds->wait_value_lo,
|
|
|
|
pProtocolWaitConds->wait_value_hi);
|
|
|
|
pAwait->trigger.test_type = pProtocolWaitConds->test_type;
|
|
|
|
|
|
|
|
status = SyncInitTrigger(client, &pAwait->trigger,
|
|
|
|
pProtocolWaitConds->counter, RTCounter,
|
|
|
|
XSyncCAAllTrigger);
|
|
|
|
if (status != Success) {
|
|
|
|
/* this should take care of removing any triggers created by
|
|
|
|
* this request that have already been registered on sync objects
|
|
|
|
*/
|
|
|
|
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
/* this is not a mistake -- same function works for both cases */
|
|
|
|
pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
|
|
|
|
pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
|
|
|
|
XSyncIntsToValue(&pAwait->event_threshold,
|
|
|
|
pProtocolWaitConds->event_threshold_lo,
|
|
|
|
pProtocolWaitConds->event_threshold_hi);
|
|
|
|
pAwait->pHeader = &pAwaitUnion->header;
|
|
|
|
pAwaitUnion->header.num_waitconditions++;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 19:11:45 +01:00
|
|
|
SyncAwaitEpilogue(client, items, pAwaitUnion);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Query a counter
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncQueryCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncQueryCounterReq);
|
|
|
|
xSyncQueryCounterReply rep;
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncCounter *pCounter;
|
2009-04-29 07:04:37 +02:00
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pCounter, stuff->counter,
|
2012-03-21 20:55:09 +01:00
|
|
|
RTCounter, client, DixReadAccess);
|
2009-04-29 07:04:37 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* if system counter, ask it what the current value is */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (IsSystemCounter(pCounter)) {
|
2013-12-15 10:05:51 +01:00
|
|
|
(*pCounter->pSysCounterInfo->QueryValue) ((void *) pCounter,
|
2012-03-21 20:55:09 +01:00
|
|
|
&pCounter->value);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-07-10 04:12:43 +02:00
|
|
|
rep = (xSyncQueryCounterReply) {
|
|
|
|
.type = X_Reply,
|
|
|
|
.sequenceNumber = client->sequence,
|
|
|
|
.length = 0,
|
|
|
|
.value_hi = XSyncValueHigh32(pCounter->value),
|
|
|
|
.value_lo = XSyncValueLow32(pCounter->value)
|
|
|
|
};
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swaps(&rep.sequenceNumber);
|
|
|
|
swapl(&rep.length);
|
|
|
|
swapl(&rep.value_hi);
|
|
|
|
swapl(&rep.value_lo);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, sizeof(xSyncQueryCounterReply), &rep);
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Create Alarm
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncCreateAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncCreateAlarmReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm;
|
|
|
|
int status;
|
|
|
|
unsigned long len, vmask;
|
|
|
|
SyncTrigger *pTrigger;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
|
|
|
|
|
|
|
|
LEGAL_NEW_RESOURCE(stuff->id, client);
|
|
|
|
|
|
|
|
vmask = stuff->valueMask;
|
2009-07-06 04:20:21 +02:00
|
|
|
len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
|
2003-11-14 16:54:54 +01:00
|
|
|
/* the "extra" call to Ones accounts for the presence of 64 bit values */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta))))
|
|
|
|
return BadLength;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!(pAlarm = malloc(sizeof(SyncAlarm)))) {
|
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set up defaults */
|
|
|
|
|
|
|
|
pTrigger = &pAlarm->trigger;
|
2010-06-28 23:59:01 +02:00
|
|
|
pTrigger->pSync = NULL;
|
2003-11-14 16:54:54 +01:00
|
|
|
pTrigger->value_type = XSyncAbsolute;
|
|
|
|
XSyncIntToValue(&pTrigger->wait_value, 0L);
|
|
|
|
pTrigger->test_type = XSyncPositiveComparison;
|
|
|
|
pTrigger->TriggerFired = SyncAlarmTriggerFired;
|
|
|
|
pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
|
2010-06-28 23:59:01 +02:00
|
|
|
status = SyncInitTrigger(client, pTrigger, None, RTCounter,
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncCAAllTrigger);
|
|
|
|
if (status != Success) {
|
|
|
|
free(pAlarm);
|
|
|
|
return status;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pAlarm->client = client;
|
|
|
|
pAlarm->alarm_id = stuff->id;
|
|
|
|
XSyncIntToValue(&pAlarm->delta, 1L);
|
|
|
|
pAlarm->events = TRUE;
|
|
|
|
pAlarm->state = XSyncAlarmInactive;
|
|
|
|
pAlarm->pEventClients = NULL;
|
|
|
|
status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
|
2012-03-21 20:55:09 +01:00
|
|
|
(CARD32 *) &stuff[1]);
|
|
|
|
if (status != Success) {
|
|
|
|
free(pAlarm);
|
|
|
|
return status;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!AddResource(stuff->id, RTAlarm, pAlarm))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/* see if alarm already triggered. NULL counter will not trigger
|
|
|
|
* in CreateAlarm and sets alarm state to Inactive.
|
|
|
|
*/
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!pTrigger->pSync) {
|
|
|
|
pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
SyncCounter *pCounter;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!SyncCheckWarnIsCounter(pTrigger->pSync,
|
|
|
|
WARN_INVALID_COUNTER_ALARM)) {
|
|
|
|
FreeResource(stuff->id, RT_NONE);
|
|
|
|
return BadAlloc;
|
|
|
|
}
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pCounter = (SyncCounter *) pTrigger->pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if ((*pTrigger->CheckTrigger) (pTrigger, pCounter->value))
|
|
|
|
(*pTrigger->TriggerFired) (pTrigger);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Change Alarm
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncChangeAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncChangeAlarmReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm;
|
2010-06-28 23:59:01 +02:00
|
|
|
SyncCounter *pCounter = NULL;
|
2012-03-21 20:55:09 +01:00
|
|
|
long vmask;
|
|
|
|
int len, status;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
status = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixWriteAccess);
|
2009-04-29 07:04:37 +02:00
|
|
|
if (status != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return status;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
vmask = stuff->valueMask;
|
2009-07-06 04:20:21 +02:00
|
|
|
len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
|
2003-11-14 16:54:54 +01:00
|
|
|
/* the "extra" call to Ones accounts for the presence of 64 bit values */
|
2012-03-21 20:55:09 +01:00
|
|
|
if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta))))
|
|
|
|
return BadLength;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
|
2012-03-21 20:55:09 +01:00
|
|
|
(CARD32 *) &stuff[1])) != Success)
|
|
|
|
return status;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-12-20 20:05:57 +01:00
|
|
|
if (SyncCheckWarnIsCounter(pAlarm->trigger.pSync,
|
2012-03-21 20:55:09 +01:00
|
|
|
WARN_INVALID_COUNTER_ALARM))
|
|
|
|
pCounter = (SyncCounter *) pAlarm->trigger.pSync;
|
2010-06-28 23:59:01 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/* see if alarm already triggered. NULL counter WILL trigger
|
|
|
|
* in ChangeAlarm.
|
|
|
|
*/
|
|
|
|
|
2010-06-28 23:59:01 +02:00
|
|
|
if (!pCounter ||
|
2012-03-21 20:55:09 +01:00
|
|
|
(*pAlarm->trigger.CheckTrigger) (&pAlarm->trigger, pCounter->value)) {
|
|
|
|
(*pAlarm->trigger.TriggerFired) (&pAlarm->trigger);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncQueryAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncQueryAlarmReq);
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncAlarm *pAlarm;
|
2003-11-14 16:54:54 +01:00
|
|
|
xSyncQueryAlarmReply rep;
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncTrigger *pTrigger;
|
2009-04-29 07:04:37 +02:00
|
|
|
int rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixReadAccess);
|
2009-04-29 07:04:37 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
pTrigger = &pAlarm->trigger;
|
2012-07-10 04:12:43 +02:00
|
|
|
rep = (xSyncQueryAlarmReply) {
|
|
|
|
.type = X_Reply,
|
|
|
|
.sequenceNumber = client->sequence,
|
|
|
|
.length =
|
|
|
|
bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)),
|
|
|
|
.counter = (pTrigger->pSync) ? pTrigger->pSync->id : None,
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-07-10 04:12:42 +02:00
|
|
|
#if 0 /* XXX unclear what to do, depends on whether relative value-types
|
|
|
|
* are "consumed" immediately and are considered absolute from then
|
|
|
|
* on.
|
|
|
|
*/
|
2012-07-10 04:12:43 +02:00
|
|
|
.value_type = pTrigger->value_type,
|
|
|
|
.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value),
|
|
|
|
.wait_value_lo = XSyncValueLow32(pTrigger->wait_value),
|
2003-11-14 16:54:54 +01:00
|
|
|
#else
|
2012-07-10 04:12:43 +02:00
|
|
|
.value_type = XSyncAbsolute,
|
|
|
|
.wait_value_hi = XSyncValueHigh32(pTrigger->test_value),
|
|
|
|
.wait_value_lo = XSyncValueLow32(pTrigger->test_value),
|
2003-11-14 16:54:54 +01:00
|
|
|
#endif
|
|
|
|
|
2012-07-10 04:12:43 +02:00
|
|
|
.test_type = pTrigger->test_type,
|
|
|
|
.delta_hi = XSyncValueHigh32(pAlarm->delta),
|
|
|
|
.delta_lo = XSyncValueLow32(pAlarm->delta),
|
|
|
|
.events = pAlarm->events,
|
|
|
|
.state = pAlarm->state
|
|
|
|
};
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swaps(&rep.sequenceNumber);
|
|
|
|
swapl(&rep.length);
|
|
|
|
swapl(&rep.counter);
|
|
|
|
swapl(&rep.wait_value_hi);
|
|
|
|
swapl(&rep.wait_value_lo);
|
|
|
|
swapl(&rep.test_type);
|
|
|
|
swapl(&rep.delta_hi);
|
|
|
|
swapl(&rep.delta_lo);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, sizeof(xSyncQueryAlarmReply), &rep);
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncDestroyAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2009-04-29 07:04:37 +02:00
|
|
|
SyncAlarm *pAlarm;
|
|
|
|
int rc;
|
2012-03-21 20:55:09 +01:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
REQUEST(xSyncDestroyAlarmReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pAlarm, stuff->alarm, RTAlarm,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixDestroyAccess);
|
2009-08-13 02:50:26 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
FreeResource(stuff->alarm, RT_NONE);
|
2010-05-11 05:22:05 +02:00
|
|
|
return Success;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2010-06-26 02:59:14 +02:00
|
|
|
static int
|
|
|
|
ProcSyncCreateFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncCreateFenceReq);
|
|
|
|
DrawablePtr pDraw;
|
|
|
|
SyncFence *pFence;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
|
|
|
|
|
|
|
|
rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
|
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
LEGAL_NEW_RESOURCE(stuff->fid, client);
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!(pFence = (SyncFence *) SyncCreate(client, stuff->fid, SYNC_FENCE)))
|
|
|
|
return BadAlloc;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
if (!AddResource(stuff->fid, RTFence, (void *) pFence))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2010-12-20 20:05:57 +01:00
|
|
|
|
2010-06-26 02:59:14 +02:00
|
|
|
return client->noClientException;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
FreeFence(void *obj, XID id)
|
|
|
|
{
|
|
|
|
SyncFence *pFence = (SyncFence *) obj;
|
|
|
|
|
|
|
|
miSyncDestroyFence(pFence);
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
int
|
|
|
|
SyncVerifyFence(SyncFence ** ppSyncFence, XID fid, ClientPtr client, Mask mode)
|
2010-06-26 02:59:14 +02:00
|
|
|
{
|
2013-12-15 10:05:51 +01:00
|
|
|
int rc = dixLookupResourceByType((void **) ppSyncFence, fid, RTFence,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, mode);
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
client->errorValue = fid;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSyncTriggerFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncTriggerFenceReq);
|
|
|
|
SyncFence *pFence;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixWriteAccess);
|
2010-06-26 02:59:14 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
miSyncTriggerFence(pFence);
|
|
|
|
|
|
|
|
return client->noClientException;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSyncResetFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncResetFenceReq);
|
|
|
|
SyncFence *pFence;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncResetFenceReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixWriteAccess);
|
2010-06-26 02:59:14 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
if (pFence->funcs.CheckTriggered(pFence) != TRUE)
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadMatch;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
pFence->funcs.Reset(pFence);
|
|
|
|
|
|
|
|
return client->noClientException;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSyncDestroyFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncDestroyFenceReq);
|
|
|
|
SyncFence *pFence;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pFence, stuff->fid, RTFence,
|
2012-03-21 20:55:09 +01:00
|
|
|
client, DixDestroyAccess);
|
2010-06-26 02:59:14 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
FreeResource(stuff->fid, RT_NONE);
|
|
|
|
return client->noClientException;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSyncQueryFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncQueryFenceReq);
|
|
|
|
xSyncQueryFenceReply rep;
|
|
|
|
SyncFence *pFence;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
rc = dixLookupResourceByType((void **) &pFence, stuff->fid,
|
2012-03-21 20:55:09 +01:00
|
|
|
RTFence, client, DixReadAccess);
|
2010-06-26 02:59:14 +02:00
|
|
|
if (rc != Success)
|
2012-03-21 20:55:09 +01:00
|
|
|
return rc;
|
2010-06-26 02:59:14 +02:00
|
|
|
|
2012-07-10 04:12:43 +02:00
|
|
|
rep = (xSyncQueryFenceReply) {
|
|
|
|
.type = X_Reply,
|
|
|
|
.sequenceNumber = client->sequence,
|
|
|
|
.length = 0,
|
2010-06-26 02:59:14 +02:00
|
|
|
|
2012-07-10 04:12:43 +02:00
|
|
|
.triggered = pFence->funcs.CheckTriggered(pFence)
|
|
|
|
};
|
2010-06-26 02:59:14 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (client->swapped) {
|
|
|
|
swaps(&rep.sequenceNumber);
|
|
|
|
swapl(&rep.length);
|
2010-06-26 02:59:14 +02:00
|
|
|
}
|
|
|
|
|
2012-05-13 09:03:35 +02:00
|
|
|
WriteToClient(client, sizeof(xSyncQueryFenceReply), &rep);
|
2010-06-26 02:59:14 +02:00
|
|
|
return client->noClientException;
|
|
|
|
}
|
|
|
|
|
2010-12-06 22:10:42 +01:00
|
|
|
static int
|
|
|
|
ProcSyncAwaitFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncAwaitFenceReq);
|
|
|
|
SyncAwaitUnion *pAwaitUnion;
|
|
|
|
SyncAwait *pAwait;
|
2012-03-21 20:55:09 +01:00
|
|
|
|
2010-12-06 22:10:42 +01:00
|
|
|
/* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
|
|
|
|
* CARD32 in protocol definitions */
|
|
|
|
CARD32 *pProtocolFences;
|
|
|
|
int status;
|
|
|
|
int len;
|
|
|
|
int items;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
|
|
|
|
|
|
|
|
len = client->req_len << 2;
|
|
|
|
len -= sz_xSyncAwaitFenceReq;
|
|
|
|
items = len / sizeof(CARD32);
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (items * sizeof(CARD32) != len) {
|
|
|
|
return BadLength;
|
2010-12-06 22:10:42 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
if (items == 0) {
|
|
|
|
client->errorValue = items;
|
|
|
|
return BadValue;
|
2010-12-06 22:10:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
|
2012-03-21 20:55:09 +01:00
|
|
|
return BadAlloc;
|
2010-12-06 22:10:42 +01:00
|
|
|
|
|
|
|
/* don't need to do any more memory allocation for this request! */
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
pProtocolFences = (CARD32 *) &stuff[1];
|
|
|
|
|
|
|
|
pAwait = &(pAwaitUnion + 1)->await; /* skip over header */
|
|
|
|
for (i = 0; i < items; i++, pProtocolFences++, pAwait++) {
|
|
|
|
if (*pProtocolFences == None) {
|
|
|
|
/* this should take care of removing any triggers created by
|
|
|
|
* this request that have already been registered on sync objects
|
|
|
|
*/
|
|
|
|
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
|
|
|
|
client->errorValue = *pProtocolFences;
|
|
|
|
return SyncErrorBase + XSyncBadFence;
|
|
|
|
}
|
|
|
|
|
|
|
|
pAwait->trigger.pSync = NULL;
|
|
|
|
/* Provide acceptable values for these unused fields to
|
|
|
|
* satisfy SyncInitTrigger's validation logic
|
|
|
|
*/
|
|
|
|
pAwait->trigger.value_type = XSyncAbsolute;
|
|
|
|
XSyncIntToValue(&pAwait->trigger.wait_value, 0);
|
|
|
|
pAwait->trigger.test_type = 0;
|
|
|
|
|
|
|
|
status = SyncInitTrigger(client, &pAwait->trigger,
|
|
|
|
*pProtocolFences, RTFence, XSyncCAAllTrigger);
|
|
|
|
if (status != Success) {
|
|
|
|
/* this should take care of removing any triggers created by
|
|
|
|
* this request that have already been registered on sync objects
|
|
|
|
*/
|
|
|
|
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
/* this is not a mistake -- same function works for both cases */
|
|
|
|
pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
|
|
|
|
pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
|
|
|
|
/* event_threshold is unused for fence syncs */
|
|
|
|
XSyncIntToValue(&pAwait->event_threshold, 0);
|
|
|
|
pAwait->pHeader = &pAwaitUnion->header;
|
|
|
|
pAwaitUnion->header.num_waitconditions++;
|
2010-12-06 22:10:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SyncAwaitEpilogue(client, items, pAwaitUnion);
|
|
|
|
|
|
|
|
return client->noClientException;
|
|
|
|
}
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
* ** Given an extension request, call the appropriate request procedure
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
ProcSyncDispatch(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xReq);
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
switch (stuff->data) {
|
|
|
|
case X_SyncInitialize:
|
|
|
|
return ProcSyncInitialize(client);
|
|
|
|
case X_SyncListSystemCounters:
|
|
|
|
return ProcSyncListSystemCounters(client);
|
|
|
|
case X_SyncCreateCounter:
|
|
|
|
return ProcSyncCreateCounter(client);
|
|
|
|
case X_SyncSetCounter:
|
|
|
|
return ProcSyncSetCounter(client);
|
|
|
|
case X_SyncChangeCounter:
|
|
|
|
return ProcSyncChangeCounter(client);
|
|
|
|
case X_SyncQueryCounter:
|
|
|
|
return ProcSyncQueryCounter(client);
|
|
|
|
case X_SyncDestroyCounter:
|
|
|
|
return ProcSyncDestroyCounter(client);
|
|
|
|
case X_SyncAwait:
|
|
|
|
return ProcSyncAwait(client);
|
|
|
|
case X_SyncCreateAlarm:
|
|
|
|
return ProcSyncCreateAlarm(client);
|
|
|
|
case X_SyncChangeAlarm:
|
|
|
|
return ProcSyncChangeAlarm(client);
|
|
|
|
case X_SyncQueryAlarm:
|
|
|
|
return ProcSyncQueryAlarm(client);
|
|
|
|
case X_SyncDestroyAlarm:
|
|
|
|
return ProcSyncDestroyAlarm(client);
|
|
|
|
case X_SyncSetPriority:
|
|
|
|
return ProcSyncSetPriority(client);
|
|
|
|
case X_SyncGetPriority:
|
|
|
|
return ProcSyncGetPriority(client);
|
|
|
|
case X_SyncCreateFence:
|
|
|
|
return ProcSyncCreateFence(client);
|
|
|
|
case X_SyncTriggerFence:
|
|
|
|
return ProcSyncTriggerFence(client);
|
|
|
|
case X_SyncResetFence:
|
|
|
|
return ProcSyncResetFence(client);
|
|
|
|
case X_SyncDestroyFence:
|
|
|
|
return ProcSyncDestroyFence(client);
|
|
|
|
case X_SyncQueryFence:
|
|
|
|
return ProcSyncQueryFence(client);
|
|
|
|
case X_SyncAwaitFence:
|
|
|
|
return ProcSyncAwaitFence(client);
|
|
|
|
default:
|
|
|
|
return BadRequest;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Boring Swapping stuff ...
|
|
|
|
*/
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncInitialize(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncInitializeReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncInitializeReq);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncInitialize(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncListSystemCounters(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncListSystemCountersReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncListSystemCounters(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncCreateCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncCreateCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->cid);
|
|
|
|
swapl(&stuff->initial_value_lo);
|
|
|
|
swapl(&stuff->initial_value_hi);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncCreateCounter(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncSetCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncSetCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncSetCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->cid);
|
|
|
|
swapl(&stuff->value_lo);
|
|
|
|
swapl(&stuff->value_hi);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncSetCounter(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncChangeCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncChangeCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->cid);
|
|
|
|
swapl(&stuff->value_lo);
|
|
|
|
swapl(&stuff->value_hi);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncChangeCounter(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncQueryCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncQueryCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->counter);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncQueryCounter(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncDestroyCounter(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncDestroyCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->counter);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncDestroyCounter(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncAwait(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncAwaitReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2003-11-14 16:54:54 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
|
|
|
|
SwapRestL(stuff);
|
|
|
|
|
|
|
|
return ProcSyncAwait(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncCreateAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncCreateAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2003-11-14 16:54:54 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->id);
|
|
|
|
swapl(&stuff->valueMask);
|
2003-11-14 16:54:54 +01:00
|
|
|
SwapRestL(stuff);
|
|
|
|
|
|
|
|
return ProcSyncCreateAlarm(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncChangeAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncChangeAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2003-11-14 16:54:54 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->alarm);
|
|
|
|
swapl(&stuff->valueMask);
|
2003-11-14 16:54:54 +01:00
|
|
|
SwapRestL(stuff);
|
|
|
|
return ProcSyncChangeAlarm(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncQueryAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncQueryAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->alarm);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncQueryAlarm(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncDestroyAlarm(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncDestroyAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->alarm);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncDestroyAlarm(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncSetPriority(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncSetPriorityReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->id);
|
|
|
|
swapl(&stuff->priority);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncSetPriority(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncGetPriority(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xSyncGetPriorityReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->id);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
return ProcSyncGetPriority(client);
|
|
|
|
}
|
|
|
|
|
2010-06-26 02:59:14 +02:00
|
|
|
static int
|
|
|
|
SProcSyncCreateFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncCreateFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->fid);
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
return ProcSyncCreateFence(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSyncTriggerFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncTriggerFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->fid);
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
return ProcSyncTriggerFence(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSyncResetFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncResetFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncResetFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->fid);
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
return ProcSyncResetFence(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSyncDestroyFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncDestroyFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->fid);
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
return ProcSyncDestroyFence(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSyncQueryFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncQueryFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2012-03-21 20:55:09 +01:00
|
|
|
REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swapl(&stuff->fid);
|
2010-06-26 02:59:14 +02:00
|
|
|
|
|
|
|
return ProcSyncQueryFence(client);
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-12-06 22:10:42 +01:00
|
|
|
static int
|
|
|
|
SProcSyncAwaitFence(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xSyncAwaitFenceReq);
|
2011-08-04 21:35:41 +02:00
|
|
|
swaps(&stuff->length);
|
2010-12-06 22:10:42 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
|
|
|
|
SwapRestL(stuff);
|
|
|
|
|
|
|
|
return ProcSyncAwaitFence(client);
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static int
|
|
|
|
SProcSyncDispatch(ClientPtr client)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
REQUEST(xReq);
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
switch (stuff->data) {
|
|
|
|
case X_SyncInitialize:
|
|
|
|
return SProcSyncInitialize(client);
|
|
|
|
case X_SyncListSystemCounters:
|
|
|
|
return SProcSyncListSystemCounters(client);
|
|
|
|
case X_SyncCreateCounter:
|
|
|
|
return SProcSyncCreateCounter(client);
|
|
|
|
case X_SyncSetCounter:
|
|
|
|
return SProcSyncSetCounter(client);
|
|
|
|
case X_SyncChangeCounter:
|
|
|
|
return SProcSyncChangeCounter(client);
|
|
|
|
case X_SyncQueryCounter:
|
|
|
|
return SProcSyncQueryCounter(client);
|
|
|
|
case X_SyncDestroyCounter:
|
|
|
|
return SProcSyncDestroyCounter(client);
|
|
|
|
case X_SyncAwait:
|
|
|
|
return SProcSyncAwait(client);
|
|
|
|
case X_SyncCreateAlarm:
|
|
|
|
return SProcSyncCreateAlarm(client);
|
|
|
|
case X_SyncChangeAlarm:
|
|
|
|
return SProcSyncChangeAlarm(client);
|
|
|
|
case X_SyncQueryAlarm:
|
|
|
|
return SProcSyncQueryAlarm(client);
|
|
|
|
case X_SyncDestroyAlarm:
|
|
|
|
return SProcSyncDestroyAlarm(client);
|
|
|
|
case X_SyncSetPriority:
|
|
|
|
return SProcSyncSetPriority(client);
|
|
|
|
case X_SyncGetPriority:
|
|
|
|
return SProcSyncGetPriority(client);
|
|
|
|
case X_SyncCreateFence:
|
|
|
|
return SProcSyncCreateFence(client);
|
|
|
|
case X_SyncTriggerFence:
|
|
|
|
return SProcSyncTriggerFence(client);
|
|
|
|
case X_SyncResetFence:
|
|
|
|
return SProcSyncResetFence(client);
|
|
|
|
case X_SyncDestroyFence:
|
|
|
|
return SProcSyncDestroyFence(client);
|
|
|
|
case X_SyncQueryFence:
|
|
|
|
return SProcSyncQueryFence(client);
|
|
|
|
case X_SyncAwaitFence:
|
|
|
|
return SProcSyncAwaitFence(client);
|
|
|
|
default:
|
|
|
|
return BadRequest;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Event Swapping
|
|
|
|
*/
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SCounterNotifyEvent(xSyncCounterNotifyEvent * from,
|
|
|
|
xSyncCounterNotifyEvent * to)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
to->type = from->type;
|
|
|
|
to->kind = from->kind;
|
|
|
|
cpswaps(from->sequenceNumber, to->sequenceNumber);
|
|
|
|
cpswapl(from->counter, to->counter);
|
|
|
|
cpswapl(from->wait_value_lo, to->wait_value_lo);
|
|
|
|
cpswapl(from->wait_value_hi, to->wait_value_hi);
|
|
|
|
cpswapl(from->counter_value_lo, to->counter_value_lo);
|
|
|
|
cpswapl(from->counter_value_hi, to->counter_value_hi);
|
|
|
|
cpswapl(from->time, to->time);
|
|
|
|
cpswaps(from->count, to->count);
|
|
|
|
to->destroyed = from->destroyed;
|
|
|
|
}
|
|
|
|
|
2008-12-10 20:18:59 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SAlarmNotifyEvent(xSyncAlarmNotifyEvent * from, xSyncAlarmNotifyEvent * to)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
to->type = from->type;
|
|
|
|
to->kind = from->kind;
|
|
|
|
cpswaps(from->sequenceNumber, to->sequenceNumber);
|
|
|
|
cpswapl(from->alarm, to->alarm);
|
|
|
|
cpswapl(from->counter_value_lo, to->counter_value_lo);
|
|
|
|
cpswapl(from->counter_value_hi, to->counter_value_hi);
|
|
|
|
cpswapl(from->alarm_value_lo, to->alarm_value_lo);
|
|
|
|
cpswapl(from->alarm_value_hi, to->alarm_value_hi);
|
|
|
|
cpswapl(from->time, to->time);
|
|
|
|
to->state = from->state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Close everything down. ** This is fairly simple for now.
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
2008-12-10 20:18:59 +01:00
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
SyncResetProc(ExtensionEntry * extEntry)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
RTCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ** Initialise the extension.
|
|
|
|
*/
|
2008-12-10 20:18:59 +01:00
|
|
|
void
|
|
|
|
SyncExtensionInit(void)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
ExtensionEntry *extEntry;
|
2012-03-21 20:55:09 +01:00
|
|
|
int s;
|
2010-06-29 01:10:13 +02:00
|
|
|
|
|
|
|
for (s = 0; s < screenInfo.numScreens; s++)
|
2012-03-21 20:55:09 +01:00
|
|
|
miSyncSetup(screenInfo.screens[s]);
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (RTCounter == 0) {
|
|
|
|
RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
|
2012-07-10 10:10:21 +02:00
|
|
|
xorg_list_init(&SysCounterList);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2009-12-03 02:43:01 +01:00
|
|
|
RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
|
|
|
|
RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
|
2010-06-26 02:59:14 +02:00
|
|
|
RTFence = CreateNewResourceType(FreeFence, "SyncFence");
|
2009-12-11 09:46:22 +01:00
|
|
|
if (RTAwait)
|
2012-03-21 20:55:09 +01:00
|
|
|
RTAwait |= RC_NEVERRETAIN;
|
2009-12-03 02:43:01 +01:00
|
|
|
RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
|
2009-12-11 09:46:22 +01:00
|
|
|
if (RTAlarmClient)
|
2012-03-21 20:55:09 +01:00
|
|
|
RTAlarmClient |= RC_NEVERRETAIN;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
|
2012-03-21 20:55:09 +01:00
|
|
|
RTAlarmClient == 0 ||
|
|
|
|
(extEntry = AddExtension(SYNC_NAME,
|
|
|
|
XSyncNumberEvents, XSyncNumberErrors,
|
|
|
|
ProcSyncDispatch, SProcSyncDispatch,
|
|
|
|
SyncResetProc, StandardMinorOpcode)) == NULL) {
|
|
|
|
ErrorF("Sync Extension %d.%d failed to Initialise\n",
|
|
|
|
SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
|
|
|
|
return;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SyncEventBase = extEntry->eventBase;
|
|
|
|
SyncErrorBase = extEntry->errorBase;
|
2012-03-21 20:55:09 +01:00
|
|
|
EventSwapVector[SyncEventBase + XSyncCounterNotify] =
|
|
|
|
(EventSwapPtr) SCounterNotifyEvent;
|
|
|
|
EventSwapVector[SyncEventBase + XSyncAlarmNotify] =
|
|
|
|
(EventSwapPtr) SAlarmNotifyEvent;
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2010-04-25 08:56:36 +02:00
|
|
|
SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
|
|
|
|
SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
|
2010-06-26 02:59:14 +02:00
|
|
|
SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
|
2010-04-25 08:56:36 +02:00
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
* Although SERVERTIME is implemented by the OS layer, we initialise it
|
|
|
|
* here because doing it in OsInit() is too early. The resource database
|
|
|
|
* is not initialised when OsInit() is called. This is just about OK
|
|
|
|
* because there is always a servertime counter.
|
|
|
|
*/
|
|
|
|
SyncInitServerTime();
|
2007-05-18 20:06:14 +02:00
|
|
|
SyncInitIdleTime();
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Sync Extension %d.%d\n",
|
2012-03-21 20:55:09 +01:00
|
|
|
SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
|
2003-11-14 16:54:54 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ***** SERVERTIME implementation - should go in its own file in OS directory?
|
|
|
|
*/
|
|
|
|
|
2013-12-15 10:05:51 +01:00
|
|
|
static void *ServertimeCounter;
|
2003-11-14 16:54:54 +01:00
|
|
|
static XSyncValue Now;
|
|
|
|
static XSyncValue *pnext_time;
|
|
|
|
|
|
|
|
#define GetTime()\
|
|
|
|
{\
|
|
|
|
unsigned long millis = GetTimeInMillis();\
|
|
|
|
unsigned long maxis = XSyncValueHigh32(Now);\
|
|
|
|
if (millis < XSyncValueLow32(Now)) maxis++;\
|
|
|
|
XSyncIntsToValue(&Now, millis, maxis);\
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*** Server Block Handler
|
2010-03-30 18:10:36 +02:00
|
|
|
*** code inspired by multibuffer extension (now deprecated)
|
2003-11-14 16:54:54 +01:00
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
/*ARGSUSED*/ static void
|
2008-12-10 20:18:59 +01:00
|
|
|
ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
XSyncValue delay;
|
|
|
|
unsigned long timeout;
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pnext_time) {
|
2003-11-14 16:54:54 +01:00
|
|
|
GetTime();
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (XSyncValueGreaterOrEqual(Now, *pnext_time)) {
|
2003-11-14 16:54:54 +01:00
|
|
|
timeout = 0;
|
2008-12-10 20:18:59 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else {
|
|
|
|
Bool overflow;
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
|
2012-03-21 20:55:09 +01:00
|
|
|
(void) overflow;
|
2003-11-14 16:54:54 +01:00
|
|
|
timeout = XSyncValueLow32(delay);
|
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
AdjustWaitForDelay(wt, timeout); /* os/utils.c */
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*** Wakeup Handler
|
|
|
|
*/
|
2012-03-21 20:55:09 +01:00
|
|
|
/*ARGSUSED*/ static void
|
2008-12-10 20:18:59 +01:00
|
|
|
ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (pnext_time) {
|
2003-11-14 16:54:54 +01:00
|
|
|
GetTime();
|
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (XSyncValueGreaterOrEqual(Now, *pnext_time)) {
|
2003-11-14 16:54:54 +01:00
|
|
|
SyncChangeCounter(ServertimeCounter, Now);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
ServertimeQueryValue(void *pCounter, CARD64 * pValue_return)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
GetTime();
|
|
|
|
*pValue_return = Now;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-03-21 20:55:09 +01:00
|
|
|
ServertimeBracketValues(void *pCounter, CARD64 * pbracket_less,
|
|
|
|
CARD64 * pbracket_greater)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2012-03-21 20:55:09 +01:00
|
|
|
if (!pnext_time && pbracket_greater) {
|
|
|
|
RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
|
|
|
|
ServertimeWakeupHandler, NULL);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else if (pnext_time && !pbracket_greater) {
|
|
|
|
RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
|
|
|
|
ServertimeWakeupHandler, NULL);
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
pnext_time = pbracket_greater;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-04-09 23:33:15 +02:00
|
|
|
SyncInitServerTime(void)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
|
|
|
CARD64 resolution;
|
|
|
|
|
|
|
|
XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
|
|
|
|
XSyncIntToValue(&resolution, 4);
|
|
|
|
ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncCounterNeverDecreases,
|
|
|
|
ServertimeQueryValue,
|
|
|
|
ServertimeBracketValues);
|
2003-11-14 16:54:54 +01:00
|
|
|
pnext_time = NULL;
|
|
|
|
}
|
2007-05-18 20:06:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* IDLETIME implementation
|
|
|
|
*/
|
|
|
|
|
2012-03-13 00:31:09 +01:00
|
|
|
typedef struct {
|
|
|
|
XSyncValue *value_less;
|
|
|
|
XSyncValue *value_greater;
|
2012-03-12 07:36:31 +01:00
|
|
|
int deviceid;
|
2012-03-13 00:31:09 +01:00
|
|
|
} IdleCounterPriv;
|
2007-05-18 20:06:14 +02:00
|
|
|
|
|
|
|
static void
|
2013-12-15 10:05:51 +01:00
|
|
|
IdleTimeQueryValue(void *pCounter, CARD64 * pValue_return)
|
2007-05-18 20:06:14 +02:00
|
|
|
{
|
2012-03-12 07:36:31 +01:00
|
|
|
int deviceid;
|
|
|
|
CARD32 idle;
|
2012-03-21 20:55:09 +01:00
|
|
|
|
2012-03-12 07:36:31 +01:00
|
|
|
if (pCounter) {
|
|
|
|
SyncCounter *counter = pCounter;
|
|
|
|
IdleCounterPriv *priv = SysCounterGetPrivate(counter);
|
|
|
|
deviceid = priv->deviceid;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
deviceid = XIAllDevices;
|
2013-10-16 01:36:01 +02:00
|
|
|
idle = GetTimeInMillis() - LastEventTime(deviceid).milliseconds;
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncIntsToValue(pValue_return, idle, 0);
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-12-15 10:05:51 +01:00
|
|
|
IdleTimeBlockHandler(void *pCounter, struct timeval **wt, void *LastSelectMask)
|
2007-05-18 20:06:14 +02:00
|
|
|
{
|
2012-03-13 00:31:09 +01:00
|
|
|
SyncCounter *counter = pCounter;
|
|
|
|
IdleCounterPriv *priv = SysCounterGetPrivate(counter);
|
|
|
|
XSyncValue *less = priv->value_less,
|
|
|
|
*greater = priv->value_greater;
|
2008-12-10 22:13:20 +01:00
|
|
|
XSyncValue idle, old_idle;
|
2012-03-12 06:27:56 +01:00
|
|
|
SyncTriggerList *list = counter->sync.pTriglist;
|
2008-12-10 22:13:20 +01:00
|
|
|
SyncTrigger *trig;
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2012-03-12 06:31:39 +01:00
|
|
|
if (!less && !greater)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2012-03-12 06:27:56 +01:00
|
|
|
old_idle = counter->value;
|
2013-10-16 01:21:47 +02:00
|
|
|
IdleTimeQueryValue(counter, &idle);
|
2012-03-12 06:27:56 +01:00
|
|
|
counter->value = idle; /* push, so CheckTrigger works */
|
2012-03-21 20:55:09 +01:00
|
|
|
|
2013-10-30 06:40:58 +01:00
|
|
|
/**
|
|
|
|
* There's an indefinite amount of time between ProcessInputEvents()
|
|
|
|
* where the idle time is reset and the time we actually get here. idle
|
|
|
|
* may be past the lower bracket if we dawdled with the events, so
|
|
|
|
* check for whether we did reset and bomb out of select immediately.
|
|
|
|
*/
|
|
|
|
if (less && XSyncValueGreaterThan(idle, *less) &&
|
|
|
|
LastEventTimeWasReset(priv->deviceid)) {
|
|
|
|
AdjustWaitForDelay(wt, 0);
|
|
|
|
} else if (less && XSyncValueLessOrEqual(idle, *less)) {
|
2012-03-21 20:55:09 +01:00
|
|
|
/*
|
|
|
|
* We've been idle for less than the threshold value, and someone
|
|
|
|
* wants to know about that, but now we need to know whether they
|
|
|
|
* want level or edge trigger. Check the trigger list against the
|
|
|
|
* current idle time, and if any succeed, bomb out of select()
|
|
|
|
* immediately so we can reschedule.
|
|
|
|
*/
|
|
|
|
|
2012-03-12 06:27:56 +01:00
|
|
|
for (list = counter->sync.pTriglist; list; list = list->next) {
|
2012-03-21 20:55:09 +01:00
|
|
|
trig = list->pTrigger;
|
|
|
|
if (trig->CheckTrigger(trig, old_idle)) {
|
|
|
|
AdjustWaitForDelay(wt, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* We've been called exactly on the idle time, but we have a
|
|
|
|
* NegativeTransition trigger which requires a transition from an
|
|
|
|
* idle time greater than this. Schedule a wakeup for the next
|
|
|
|
* millisecond so we won't miss a transition.
|
|
|
|
*/
|
2012-03-12 06:31:39 +01:00
|
|
|
if (XSyncValueEqual(idle, *less))
|
2012-03-21 20:55:09 +01:00
|
|
|
AdjustWaitForDelay(wt, 1);
|
|
|
|
}
|
2012-03-12 06:31:39 +01:00
|
|
|
else if (greater) {
|
2012-03-21 20:55:09 +01:00
|
|
|
/*
|
|
|
|
* There's a threshold in the positive direction. If we've been
|
|
|
|
* idle less than it, schedule a wakeup for sometime in the future.
|
|
|
|
* If we've been idle more than it, and someone wants to know about
|
|
|
|
* that level-triggered, schedule an immediate wakeup.
|
|
|
|
*/
|
|
|
|
|
2012-03-12 06:31:39 +01:00
|
|
|
if (XSyncValueLessThan(idle, *greater)) {
|
2012-03-21 20:55:09 +01:00
|
|
|
XSyncValue value;
|
|
|
|
Bool overflow;
|
|
|
|
|
2012-03-12 06:31:39 +01:00
|
|
|
XSyncValueSubtract(&value, *greater, idle, &overflow);
|
2013-12-15 14:31:10 +01:00
|
|
|
AdjustWaitForDelay(wt, XSyncValueLow32(value));
|
2012-03-21 20:55:09 +01:00
|
|
|
}
|
|
|
|
else {
|
2012-03-12 06:27:56 +01:00
|
|
|
for (list = counter->sync.pTriglist; list;
|
2012-03-21 20:55:09 +01:00
|
|
|
list = list->next) {
|
|
|
|
trig = list->pTrigger;
|
|
|
|
if (trig->CheckTrigger(trig, old_idle)) {
|
2013-12-15 14:31:10 +01:00
|
|
|
AdjustWaitForDelay(wt, 0);
|
2012-03-21 20:55:09 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-12 06:27:56 +01:00
|
|
|
counter->value = old_idle; /* pop */
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
|
|
|
|
2013-10-16 02:08:46 +02:00
|
|
|
static void
|
|
|
|
IdleTimeCheckBrackets(SyncCounter *counter, XSyncValue idle, XSyncValue *less, XSyncValue *greater)
|
|
|
|
{
|
|
|
|
if ((greater && XSyncValueGreaterOrEqual(idle, *greater)) ||
|
|
|
|
(less && XSyncValueLessOrEqual(idle, *less))) {
|
|
|
|
SyncChangeCounter(counter, idle);
|
|
|
|
}
|
2013-10-17 04:02:27 +02:00
|
|
|
else
|
|
|
|
SyncUpdateCounter(counter, idle);
|
2013-10-16 02:08:46 +02:00
|
|
|
}
|
|
|
|
|
2007-05-18 20:06:14 +02:00
|
|
|
static void
|
2013-12-15 10:05:51 +01:00
|
|
|
IdleTimeWakeupHandler(void *pCounter, int rc, void *LastSelectMask)
|
2007-05-18 20:06:14 +02:00
|
|
|
{
|
2012-03-13 00:31:09 +01:00
|
|
|
SyncCounter *counter = pCounter;
|
|
|
|
IdleCounterPriv *priv = SysCounterGetPrivate(counter);
|
|
|
|
XSyncValue *less = priv->value_less,
|
|
|
|
*greater = priv->value_greater;
|
2007-05-18 20:06:14 +02:00
|
|
|
XSyncValue idle;
|
|
|
|
|
2012-03-12 06:31:39 +01:00
|
|
|
if (!less && !greater)
|
2012-03-21 20:55:09 +01:00
|
|
|
return;
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2012-03-12 07:36:31 +01:00
|
|
|
IdleTimeQueryValue(pCounter, &idle);
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2013-10-16 02:08:46 +02:00
|
|
|
/*
|
|
|
|
There is no guarantee for the WakeupHandler to be called within a specific
|
|
|
|
timeframe. Idletime may go to 0, but by the time we get here, it may be
|
|
|
|
non-zero and alarms for a pos. transition on 0 won't get triggered.
|
|
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=70476
|
|
|
|
*/
|
|
|
|
if (LastEventTimeWasReset(priv->deviceid)) {
|
|
|
|
LastEventTimeToggleResetFlag(priv->deviceid, FALSE);
|
|
|
|
if (!XSyncValueIsZero(idle)) {
|
|
|
|
XSyncValue zero;
|
|
|
|
XSyncIntsToValue(&zero, 0, 0);
|
|
|
|
IdleTimeCheckBrackets(counter, zero, less, greater);
|
|
|
|
less = priv->value_less;
|
|
|
|
greater = priv->value_greater;
|
|
|
|
}
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
2013-10-16 02:08:46 +02:00
|
|
|
|
|
|
|
IdleTimeCheckBrackets(counter, idle, less, greater);
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-12-15 10:05:51 +01:00
|
|
|
IdleTimeBracketValues(void *pCounter, CARD64 * pbracket_less,
|
2012-03-21 20:55:09 +01:00
|
|
|
CARD64 * pbracket_greater)
|
2007-05-18 20:06:14 +02:00
|
|
|
{
|
2012-03-13 00:31:09 +01:00
|
|
|
SyncCounter *counter = pCounter;
|
|
|
|
IdleCounterPriv *priv = SysCounterGetPrivate(counter);
|
|
|
|
XSyncValue *less = priv->value_less,
|
|
|
|
*greater = priv->value_greater;
|
2012-03-12 06:31:39 +01:00
|
|
|
Bool registered = (less || greater);
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
if (registered && !pbracket_less && !pbracket_greater) {
|
|
|
|
RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
|
2012-03-13 00:29:39 +01:00
|
|
|
IdleTimeWakeupHandler, pCounter);
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
2012-03-21 20:55:09 +01:00
|
|
|
else if (!registered && (pbracket_less || pbracket_greater)) {
|
2013-10-16 02:08:46 +02:00
|
|
|
/* Reset flag must be zero so we don't force a idle timer reset on
|
|
|
|
the first wakeup */
|
|
|
|
LastEventTimeToggleResetAll(FALSE);
|
2012-03-21 20:55:09 +01:00
|
|
|
RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
|
2012-03-13 00:29:39 +01:00
|
|
|
IdleTimeWakeupHandler, pCounter);
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
|
|
|
|
2012-03-13 00:31:09 +01:00
|
|
|
priv->value_greater = pbracket_greater;
|
|
|
|
priv->value_less = pbracket_less;
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|
|
|
|
|
2012-03-12 07:36:31 +01:00
|
|
|
static SyncCounter*
|
|
|
|
init_system_idle_counter(const char *name, int deviceid)
|
2007-05-18 20:06:14 +02:00
|
|
|
{
|
|
|
|
CARD64 resolution;
|
|
|
|
XSyncValue idle;
|
2012-03-13 00:31:09 +01:00
|
|
|
SyncCounter *idle_time_counter;
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2012-03-21 20:55:09 +01:00
|
|
|
IdleTimeQueryValue(NULL, &idle);
|
|
|
|
XSyncIntToValue(&resolution, 4);
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2012-03-12 07:36:31 +01:00
|
|
|
idle_time_counter = SyncCreateSystemCounter(name, idle, resolution,
|
2012-03-13 00:31:09 +01:00
|
|
|
XSyncCounterUnrestricted,
|
|
|
|
IdleTimeQueryValue,
|
|
|
|
IdleTimeBracketValues);
|
2007-05-18 20:06:14 +02:00
|
|
|
|
2013-01-27 19:06:42 +01:00
|
|
|
if (idle_time_counter != NULL) {
|
|
|
|
IdleCounterPriv *priv = malloc(sizeof(IdleCounterPriv));
|
2012-03-13 00:31:09 +01:00
|
|
|
|
2013-01-27 19:06:42 +01:00
|
|
|
priv->value_less = priv->value_greater = NULL;
|
|
|
|
priv->deviceid = deviceid;
|
|
|
|
|
|
|
|
idle_time_counter->pSysCounterInfo->private = priv;
|
|
|
|
}
|
2012-03-12 07:36:31 +01:00
|
|
|
|
|
|
|
return idle_time_counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SyncInitIdleTime(void)
|
|
|
|
{
|
|
|
|
init_system_idle_counter("IDLETIME", XIAllDevices);
|
|
|
|
}
|
|
|
|
|
|
|
|
SyncCounter*
|
|
|
|
SyncInitDeviceIdleTime(DeviceIntPtr dev)
|
|
|
|
{
|
|
|
|
char timer_name[64];
|
|
|
|
sprintf(timer_name, "DEVICEIDLETIME %d", dev->id);
|
|
|
|
|
|
|
|
return init_system_idle_counter(timer_name, dev->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SyncRemoveDeviceIdleTime(SyncCounter *counter)
|
|
|
|
{
|
|
|
|
/* FreeAllResources() frees all system counters before the devices are
|
|
|
|
shut down, check if there are any left before freeing the device's
|
|
|
|
counter */
|
2013-01-27 19:06:42 +01:00
|
|
|
if (counter && !xorg_list_is_empty(&SysCounterList))
|
2012-03-12 07:36:31 +01:00
|
|
|
xorg_list_del(&counter->pSysCounterInfo->entry);
|
2007-05-18 20:06:14 +02:00
|
|
|
}
|