-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 <jajo...@nvidia.com>
Reviewed-by: Aaron Plattner <aplatt...@nvidia.com>
Reviewed-by: Robert Morell <rmor...@nvidia.com>
Reviewed-by: Adam Jackson <a...@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

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to