-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