From 805f78addf3ffb36c736df680806cf722b18fea9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 16 Dec 2012 22:04:54 +0000 Subject: [PATCH] sna: Try to reuse pinned batches by inspecting the kernel busy status Signed-off-by: Chris Wilson --- src/sna/kgem.c | 173 ++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 75 deletions(-) diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 15d56426..36eab9bd 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -1830,6 +1830,89 @@ static bool kgem_retire__flushing(struct kgem *kgem) return retired; } + +static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq) +{ + bool retired = false; + + DBG(("%s: request %d complete\n", + __FUNCTION__, rq->bo->handle)); + + while (!list_is_empty(&rq->buffers)) { + struct kgem_bo *bo; + + bo = list_first_entry(&rq->buffers, + struct kgem_bo, + request); + + assert(RQ(bo->rq) == rq); + assert(bo->exec == NULL); + assert(bo->domain == DOMAIN_GPU); + + list_del(&bo->request); + + if (bo->needs_flush) + bo->needs_flush = kgem_busy(kgem, bo->handle); + if (bo->needs_flush) { + DBG(("%s: moving %d to flushing\n", + __FUNCTION__, bo->handle)); + list_add(&bo->request, &kgem->flushing); + bo->rq = &_kgem_static_request; + } else { + bo->domain = DOMAIN_NONE; + bo->rq = NULL; + } + + if (bo->refcnt) + continue; + + if (bo->snoop) { + if (bo->needs_flush) { + list_add(&bo->request, &kgem->flushing); + bo->rq = &_kgem_static_request; + } else { + kgem_bo_move_to_snoop(kgem, bo); + } + continue; + } + + if (!bo->reusable) { + DBG(("%s: closing %d\n", + __FUNCTION__, bo->handle)); + kgem_bo_free(kgem, bo); + continue; + } + + if (!bo->needs_flush) { + if (kgem_bo_set_purgeable(kgem, bo)) { + kgem_bo_move_to_inactive(kgem, bo); + retired = true; + } else { + DBG(("%s: closing %d\n", + __FUNCTION__, bo->handle)); + kgem_bo_free(kgem, bo); + } + } + } + + assert(rq->bo->rq == NULL); + assert(list_is_empty(&rq->bo->request)); + + if (--rq->bo->refcnt == 0) { + if (kgem_bo_set_purgeable(kgem, rq->bo)) { + kgem_bo_move_to_inactive(kgem, rq->bo); + retired = true; + } else { + DBG(("%s: closing %d\n", + __FUNCTION__, rq->bo->handle)); + kgem_bo_free(kgem, rq->bo); + } + } + + __kgem_request_free(rq); + return retired; +} + static bool kgem_retire__requests_ring(struct kgem *kgem, int ring) { bool retired = false; @@ -1843,81 +1926,7 @@ static bool kgem_retire__requests_ring(struct kgem *kgem, int ring) if (kgem_busy(kgem, rq->bo->handle)) break; - DBG(("%s: request %d complete\n", - __FUNCTION__, rq->bo->handle)); - - while (!list_is_empty(&rq->buffers)) { - struct kgem_bo *bo; - - bo = list_first_entry(&rq->buffers, - struct kgem_bo, - request); - - assert(RQ(bo->rq) == rq); - assert(bo->exec == NULL); - assert(bo->domain == DOMAIN_GPU); - - list_del(&bo->request); - - if (bo->needs_flush) - bo->needs_flush = kgem_busy(kgem, bo->handle); - if (bo->needs_flush) { - DBG(("%s: moving %d to flushing\n", - __FUNCTION__, bo->handle)); - list_add(&bo->request, &kgem->flushing); - bo->rq = &_kgem_static_request; - } else { - bo->domain = DOMAIN_NONE; - bo->rq = NULL; - } - - if (bo->refcnt) - continue; - - if (bo->snoop) { - if (bo->needs_flush) { - list_add(&bo->request, &kgem->flushing); - bo->rq = &_kgem_static_request; - } else { - kgem_bo_move_to_snoop(kgem, bo); - } - continue; - } - - if (!bo->reusable) { - DBG(("%s: closing %d\n", - __FUNCTION__, bo->handle)); - kgem_bo_free(kgem, bo); - continue; - } - - if (!bo->needs_flush) { - if (kgem_bo_set_purgeable(kgem, bo)) { - kgem_bo_move_to_inactive(kgem, bo); - retired = true; - } else { - DBG(("%s: closing %d\n", - __FUNCTION__, bo->handle)); - kgem_bo_free(kgem, bo); - } - } - } - - assert(rq->bo->rq == NULL); - assert(list_is_empty(&rq->bo->request)); - - if (--rq->bo->refcnt == 0) { - if (kgem_bo_set_purgeable(kgem, rq->bo)) { - kgem_bo_move_to_inactive(kgem, rq->bo); - retired = true; - } else { - DBG(("%s: closing %d\n", - __FUNCTION__, rq->bo->handle)); - kgem_bo_free(kgem, rq->bo); - } - } - - __kgem_request_free(rq); + retired |= __kgem_retire_rq(kgem, rq); } #if HAS_DEBUG_FULL @@ -2357,9 +2366,16 @@ kgem_create_batch(struct kgem *kgem, int size) struct kgem_bo, list); if (!bo->rq) { +out_4096: list_move_tail(&bo->list, &kgem->pinned_batches[0]); return kgem_bo_reference(bo); } + + if (!kgem_busy(kgem, bo->handle)) { + assert(RQ(bo->rq)->bo == bo); + __kgem_retire_rq(kgem, RQ(bo->rq)); + goto out_4096; + } } if (size <= 16384) { @@ -2367,9 +2383,16 @@ kgem_create_batch(struct kgem *kgem, int size) struct kgem_bo, list); if (!bo->rq) { +out_16384: list_move_tail(&bo->list, &kgem->pinned_batches[1]); return kgem_bo_reference(bo); } + + if (!kgem_busy(kgem, bo->handle)) { + assert(RQ(bo->rq)->bo == bo); + __kgem_retire_rq(kgem, RQ(bo->rq)); + goto out_16384; + } } if (kgem->gen == 020) {