summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-12-16 22:04:54 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-12-16 22:13:21 +0000
commit805f78addf3ffb36c736df680806cf722b18fea9 (patch)
treecb9f35b404439580d8488805cd2d83c14b99956d
parentf1aec676810c4a4c180b342d9a83254e08dd55da (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.c147
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) {