[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