[PATCH xserver (v3) 07/10] Add XSyncAwaitFence() handler
James Jones
jajones at nvidia.com
Sun Dec 5 19:25:32 PST 2010
-Add the actual ProcSyncAwaitFence() dispatch func
-Factor out some more common code from ProcSyncAwait()
into SyncAwaitPrologue() and SyncAwaitEpilogue(). Call
these from both Await functions.
-Check and handle triggers when triggering or freeing
a fence sync object.
-Fix a few bugs in the previous refactoring changes.
Signed-off-by: James Jones <jajones at nvidia.com>
Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
Reviewed-by: Robert Morell <rmorell at nvidia.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
---
Xext/sync.c | 300 +++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 219 insertions(+), 81 deletions(-)
diff --git a/Xext/sync.c b/Xext/sync.c
index 77ad461..aee2ca1 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -265,7 +265,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
SyncObject *pSync = pTrigger->pSync;
SyncCounter *pCounter = NULL;
int rc;
- Bool newcounter = FALSE;
+ Bool newSyncObject = FALSE;
if (changes & XSyncCACounter)
{
@@ -281,7 +281,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
{ /* new counter for trigger */
SyncDeleteTriggerFromSyncObject(pTrigger);
pTrigger->pSync = pSync;
- newcounter = TRUE;
+ newSyncObject = TRUE;
}
}
@@ -310,30 +310,37 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
if (changes & XSyncCATestType)
{
- if (pTrigger->test_type != XSyncPositiveTransition &&
- pTrigger->test_type != XSyncNegativeTransition &&
- pTrigger->test_type != XSyncPositiveComparison &&
- pTrigger->test_type != XSyncNegativeComparison)
+ if (SYNC_FENCE == pSync->type)
{
- client->errorValue = pTrigger->test_type;
- return BadValue;
+ pTrigger->CheckTrigger = SyncCheckTriggerFence;
}
- /* select appropriate CheckTrigger function */
-
- switch (pTrigger->test_type)
+ else
{
- case XSyncPositiveTransition:
- pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
- break;
- case XSyncNegativeTransition:
- pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
- break;
- case XSyncPositiveComparison:
- pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
- break;
- case XSyncNegativeComparison:
- pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
- break;
+ if (pTrigger->test_type != XSyncPositiveTransition &&
+ pTrigger->test_type != XSyncNegativeTransition &&
+ pTrigger->test_type != XSyncPositiveComparison &&
+ pTrigger->test_type != XSyncNegativeComparison)
+ {
+ client->errorValue = pTrigger->test_type;
+ return BadValue;
+ }
+ /* select appropriate CheckTrigger function */
+
+ switch (pTrigger->test_type)
+ {
+ case XSyncPositiveTransition:
+ pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
+ break;
+ case XSyncNegativeTransition:
+ pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
+ break;
+ case XSyncPositiveComparison:
+ pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
+ break;
+ case XSyncNegativeComparison:
+ pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
+ break;
+ }
}
}
@@ -360,7 +367,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
/* we wait until we're sure there are no errors before registering
* a new counter on a trigger
*/
- if (newcounter)
+ if (newSyncObject)
{
if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
return rc;
@@ -607,14 +614,7 @@ SyncAwaitTriggerFired(SyncTrigger *pTrigger)
continue;
}
- if (SYNC_FENCE == pAwait->trigger.pSync->type)
- {
- SyncFence *pFence = (SyncFence *) pAwait->trigger.pSync;
-
- if (pFence->triggered)
- ppAwait[num_events++] = pAwait;
- }
- else if (SYNC_COUNTER == pAwait->trigger.pSync->type)
+ if (SYNC_COUNTER == pAwait->trigger.pSync->type)
{
SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
@@ -654,10 +654,6 @@ SyncAwaitTriggerFired(SyncTrigger *pTrigger)
ppAwait[num_events++] = pAwait;
}
}
- else
- {
- FatalError("Invalid sync object type");
- }
}
if (num_events)
SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
@@ -1491,6 +1487,66 @@ ProcSyncDestroyCounter(ClientPtr client)
return Success;
}
+static SyncAwaitUnion*
+SyncAwaitPrologue(ClientPtr client, int items)
+{
+ SyncAwaitUnion *pAwaitUnion;
+
+ /* all the memory for the entire await list is allocated
+ * here in one chunk
+ */
+ pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
+ if (!pAwaitUnion)
+ return NULL;
+
+ /* first item is the header, remainder are real wait conditions */
+
+ pAwaitUnion->header.delete_id = FakeClientID(client->index);
+ if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
+ {
+ free(pAwaitUnion);
+ return NULL;
+ }
+
+ pAwaitUnion->header.client = client;
+ pAwaitUnion->header.num_waitconditions = 0;
+
+ return pAwaitUnion;
+}
+
+static void
+SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion)
+{
+ SyncAwait *pAwait;
+ int i;
+
+ IgnoreClient(client);
+
+ /* see if any of the triggers are already true */
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pAwait++)
+ {
+ CARD64 value;
+
+ /* don't have to worry about NULL counters because the request
+ * errors before we get here out if they occur
+ */
+ switch (pAwait->trigger.pSync->type) {
+ case SYNC_COUNTER:
+ value = ((SyncCounter *)pAwait->trigger.pSync)->value;
+ break;
+ default:
+ XSyncIntToValue(&value, 0);
+ }
+
+ if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
+ {
+ (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
+ break; /* once is enough */
+ }
+ }
+}
/*
* ** Await
@@ -1522,28 +1578,12 @@ ProcSyncAwait(ClientPtr client)
return BadValue;
}
- pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
-
- /* all the memory for the entire await list is allocated
- * here in one chunk
- */
- pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
- if (!pAwaitUnion)
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
return BadAlloc;
- /* first item is the header, remainder are real wait conditions */
-
- pAwaitUnion->header.delete_id = FakeClientID(client->index);
- if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
- {
- free(pAwaitUnion);
- return BadAlloc;
- }
-
/* don't need to do any more memory allocation for this request! */
- pAwaitUnion->header.client = client;
- pAwaitUnion->header.num_waitconditions = 0;
+ pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
pAwait = &(pAwaitUnion+1)->await; /* skip over header */
for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
@@ -1551,7 +1591,7 @@ ProcSyncAwait(ClientPtr client)
if (pProtocolWaitConds->counter == None) /* XXX protocol change */
{
/* this should take care of removing any triggers created by
- * this request that have already been registered on counters
+ * this request that have already been registered on sync objects
*/
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
client->errorValue = pProtocolWaitConds->counter;
@@ -1572,7 +1612,7 @@ ProcSyncAwait(ClientPtr client)
if (status != Success)
{
/* this should take care of removing any triggers created by
- * this request that have already been registered on counters
+ * this request that have already been registered on sync objects
*/
FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
return status;
@@ -1587,32 +1627,8 @@ ProcSyncAwait(ClientPtr client)
pAwaitUnion->header.num_waitconditions++;
}
- IgnoreClient(client);
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
- /* see if any of the triggers are already true */
-
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pAwait++)
- {
- CARD64 value;
-
- /* don't have to worry about NULL counters because the request
- * errors before we get here out if they occur
- */
- switch (pAwait->trigger.pSync->type) {
- case SYNC_COUNTER:
- value = ((SyncCounter *)pAwait->trigger.pSync)->value;
- break;
- default:
- XSyncIntToValue(&value, 0);
- }
-
- if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
- {
- (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
- break; /* once is enough */
- }
- }
return Success;
}
@@ -1903,6 +1919,16 @@ static int
FreeFence(void *obj, XID id)
{
SyncFence *pFence = (SyncFence *) obj;
+ SyncTriggerList *ptl, *pNext;
+
+ pFence->sync.beingDestroyed = TRUE;
+ /* tell all the counter's triggers that the counter has been destroyed */
+ for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext)
+ {
+ (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
+ pNext = ptl->next;
+ free(ptl); /* destroy the trigger list as we go */
+ }
free(pFence);
@@ -1914,6 +1940,8 @@ ProcSyncTriggerFence(ClientPtr client)
{
REQUEST(xSyncTriggerFenceReq);
SyncFence *pFence;
+ SyncTriggerList *ptl, *pNext;
+ CARD64 unused;
int rc;
REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
@@ -1925,6 +1953,16 @@ ProcSyncTriggerFence(ClientPtr client)
pFence->triggered = TRUE;
+ XSyncIntToValue(&unused, 0L);
+
+ /* run through triggers to see if any fired */
+ for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext)
+ {
+ pNext = ptl->next;
+ if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, unused))
+ (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
+ }
+
return client->noClientException;
}
@@ -2000,6 +2038,89 @@ ProcSyncQueryFence(ClientPtr client)
return client->noClientException;
}
+static int
+ProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait *pAwait;
+ /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
+ * CARD32 in protocol definitions */
+ CARD32 *pProtocolFences;
+ int status;
+ int len;
+ int items;
+ int i;
+
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+
+ len = client->req_len << 2;
+ len -= sz_xSyncAwaitFenceReq;
+ items = len / sizeof(CARD32);
+
+ if (items * sizeof(CARD32) != len)
+ {
+ return BadLength;
+ }
+ if (items == 0)
+ {
+ client->errorValue = items; /* XXX protocol change */
+ return BadValue;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolFences = (CARD32 *) & stuff[1];
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pProtocolFences++, pAwait++)
+ {
+ if (*pProtocolFences == None) /* XXX protocol change */
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = *pProtocolFences;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ pAwait->trigger.pSync = NULL;
+ /* Provide acceptable values for these unused fields to
+ * satisfy SyncInitTrigger's validation logic
+ */
+ pAwait->trigger.value_type = XSyncAbsolute;
+ XSyncIntToValue(&pAwait->trigger.wait_value, 0);
+ pAwait->trigger.test_type = 0;
+
+ status = SyncInitTrigger(client, &pAwait->trigger,
+ *pProtocolFences, RTFence,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ return status;
+ }
+ /* this is not a mistake -- same function works for both cases */
+ pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
+ pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
+ /* event_threshold is unused for fence syncs */
+ XSyncIntToValue(&pAwait->event_threshold, 0);
+ pAwait->pHeader = &pAwaitUnion->header;
+ pAwaitUnion->header.num_waitconditions++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return client->noClientException;
+}
+
/*
* ** Given an extension request, call the appropriate request procedure
*/
@@ -2048,6 +2169,8 @@ ProcSyncDispatch(ClientPtr client)
return ProcSyncDestroyFence(client);
case X_SyncQueryFence:
return ProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return ProcSyncAwaitFence(client);
default:
return BadRequest;
}
@@ -2313,6 +2436,19 @@ SProcSyncQueryFence(ClientPtr client)
}
static int
+SProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwaitFence(client);
+}
+
+static int
SProcSyncDispatch(ClientPtr client)
{
REQUEST(xReq);
@@ -2357,6 +2493,8 @@ SProcSyncDispatch(ClientPtr client)
return SProcSyncDestroyFence(client);
case X_SyncQueryFence:
return SProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return SProcSyncAwaitFence(client);
default:
return BadRequest;
}
--
1.7.1
More information about the xorg-devel
mailing list