diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-12-16 22:04:54 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-12-16 22:13:21 +0000 |
commit | 805f78addf3ffb36c736df680806cf722b18fea9 (patch) | |
tree | cb9f35b404439580d8488805cd2d83c14b99956d | |
parent | f1aec676810c4a4c180b342d9a83254e08dd55da (diff) |
sna: Try to reuse pinned batches by inspecting the kernel busy status
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/kgem.c | 147 |
1 files changed, 85 insertions, 62 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,94 +1830,103 @@ static bool kgem_retire__flushing(struct kgem *kgem) return retired; } -static bool kgem_retire__requests_ring(struct kgem *kgem, int ring) + +static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq) { bool retired = false; - while (!list_is_empty(&kgem->requests[ring])) { - struct kgem_request *rq; + DBG(("%s: request %d complete\n", + __FUNCTION__, rq->bo->handle)); - rq = list_first_entry(&kgem->requests[ring], - struct kgem_request, - list); - if (kgem_busy(kgem, rq->bo->handle)) - break; + while (!list_is_empty(&rq->buffers)) { + struct kgem_bo *bo; - DBG(("%s: request %d complete\n", - __FUNCTION__, rq->bo->handle)); + bo = list_first_entry(&rq->buffers, + struct kgem_bo, + request); - while (!list_is_empty(&rq->buffers)) { - struct kgem_bo *bo; + assert(RQ(bo->rq) == rq); + assert(bo->exec == NULL); + assert(bo->domain == DOMAIN_GPU); - bo = list_first_entry(&rq->buffers, - struct kgem_bo, - request); + list_del(&bo->request); - assert(RQ(bo->rq) == rq); - assert(bo->exec == NULL); - assert(bo->domain == DOMAIN_GPU); + 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; + } - list_del(&bo->request); + if (bo->refcnt) + continue; - if (bo->needs_flush) - bo->needs_flush = kgem_busy(kgem, bo->handle); + if (bo->snoop) { 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; + kgem_bo_move_to_snoop(kgem, bo); } + continue; + } - 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->reusable) { + 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); - 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)); + 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); - } + 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; - __kgem_request_free(rq); + while (!list_is_empty(&kgem->requests[ring])) { + struct kgem_request *rq; + + rq = list_first_entry(&kgem->requests[ring], + struct kgem_request, + list); + if (kgem_busy(kgem, rq->bo->handle)) + break; + + 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) { |