xf86-video-intel: 4 commits - src/sna/kgem.c src/sna/kgem.h src/sna/sna_accel.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Dec 18 12:19:47 PST 2011


 src/sna/kgem.c      |   84 ++++++++++++++++++++++++++++++++++++----------------
 src/sna/kgem.h      |    1 
 src/sna/sna_accel.c |    5 +--
 3 files changed, 62 insertions(+), 28 deletions(-)

New commits:
commit 8df9653135c6390ed699ba9f8cbf374b2cc84396
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 18 19:53:14 2011 +0000

    sna: clear the request list when reusing a flushing bo
    
    That the rq is NULL when on the flushing list is no longer true, but
    now it points to the static request instead.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 6d7eceb..6ac1342 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1179,6 +1179,7 @@ void _kgem_submit(struct kgem *kgem)
 		kgem_fixup_self_relocs(kgem, rq->bo);
 		kgem_finish_partials(kgem);
 
+		assert(!rq->bo->needs_flush);
 		if (kgem_batch_write(kgem, handle) == 0) {
 			struct drm_i915_gem_execbuffer2 execbuf;
 			int ret, retry = 3;
@@ -1481,7 +1482,7 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
 			continue;
 
 		list_del(&bo->list);
-		if (bo->rq == NULL)
+		if (bo->rq == &_kgem_static_request)
 			list_del(&bo->request);
 		if (bo->map) {
 			assert(!list_is_empty(&bo->vma));
@@ -1495,6 +1496,7 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
 		     __FUNCTION__, bo->handle, bo->size,
 		     use_active ? "active" : "inactive"));
 		assert(use_active || bo->domain != DOMAIN_GPU);
+		assert(!bo->needs_flush || use_active);
 		//assert(use_active || !kgem_busy(kgem, bo->handle));
 		return bo;
 	}
@@ -1813,7 +1815,7 @@ search_active: /* Best active match first */
 		s = bo->pitch * tiled_height[bo->tiling];
 		if (s <= bo->size) {
 			list_del(&bo->list);
-			if (bo->rq == NULL)
+			if (bo->rq == &_kgem_static_request)
 				list_del(&bo->request);
 
 			if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
commit b51e3de66292e4b29483324e1dbfeb2495817351
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 18 19:51:17 2011 +0000

    sna: When freeing vma, first see if the kernel evicted any
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index fba0693..6d7eceb 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2089,6 +2089,9 @@ uint32_t kgem_add_reloc(struct kgem *kgem,
 
 static void kgem_trim_vma_cache(struct kgem *kgem)
 {
+	if (kgem->vma_count > MAX_VMA_CACHE && kgem->need_purge)
+		kgem_purge_cache(kgem);
+
 	/* vma are limited on a per-process basis to around 64k.
 	 * This includes all malloc arenas as well as other file
 	 * mappings. In order to be fair and not hog the cache,
commit fed8d145c148bfa8a8a29f4088902377f9a10440
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 18 19:26:38 2011 +0000

    sna: Use a safe iterator whilst searching for inactive linear bo
    
    As we may free a purged bo whilst iterating, we need to keep the next bo
    as a local member.
    
    Include the debugging that led to this find.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index f95b5b2..fba0693 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -46,6 +46,8 @@
 
 static inline void _list_del(struct list *list)
 {
+	assert(list->prev->next == list);
+	assert(list->next->prev == list);
 	__list_del(list->prev, list->next);
 }
 
@@ -821,6 +823,10 @@ bool kgem_retire(struct kgem *kgem)
 	DBG(("%s\n", __FUNCTION__));
 
 	list_for_each_entry_safe(bo, next, &kgem->flushing, request) {
+		assert(bo->refcnt == 0);
+		assert(bo->rq == &_kgem_static_request);
+		assert(bo->exec == NULL);
+
 		if (kgem_busy(kgem, bo->handle))
 			break;
 
@@ -829,7 +835,6 @@ bool kgem_retire(struct kgem *kgem)
 		if (kgem_bo_set_purgeable(kgem, bo)) {
 			bo->needs_flush = false;
 			bo->domain = DOMAIN_NONE;
-			assert(bo->rq == &_kgem_static_request);
 			bo->rq = NULL;
 			list_move(&bo->list, inactive(kgem, bo->size));
 			list_del(&bo->request);
@@ -1449,11 +1454,15 @@ void kgem_cleanup_cache(struct kgem *kgem)
 static struct kgem_bo *
 search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
 {
-	struct kgem_bo *bo;
+	struct kgem_bo *bo, *next;
 	struct list *cache;
 
 	cache = use_active ? active(kgem, size): inactive(kgem, size);
-	list_for_each_entry(bo, cache, list) {
+	list_for_each_entry_safe(bo, next, cache, list) {
+		assert(bo->refcnt == 0);
+		assert(bo->reusable);
+		assert(!!bo->rq == !!use_active);
+
 		if (size > bo->size)
 			continue;
 
@@ -1485,8 +1494,6 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
 		DBG(("  %s: found handle=%d (size=%d) in linear %s cache\n",
 		     __FUNCTION__, bo->handle, bo->size,
 		     use_active ? "active" : "inactive"));
-		assert(bo->refcnt == 0);
-		assert(bo->reusable);
 		assert(use_active || bo->domain != DOMAIN_GPU);
 		//assert(use_active || !kgem_busy(kgem, bo->handle));
 		return bo;
commit 2a98dabcabf25067abcda60f233656e19e83493a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 18 18:48:30 2011 +0000

    sna: Purge all evicted bo
    
    After we find a single bo that has been evicted from our cache, the
    kernel is likely to have evicted many more so check our caches for any
    more bo to reap.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index e05bb6c..f95b5b2 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -700,6 +700,7 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 	struct kgem_bo_binding *b;
 
 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+	assert(bo->refcnt == 0);
 	assert(bo->exec == NULL);
 
 	b = bo->binding.next;
@@ -781,6 +782,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 		list_move(&bo->list, active(kgem, bo->size));
 		bo->rq = &_kgem_static_request;
 	} else {
+		assert(bo->exec == NULL);
 		if (!IS_CPU_MAP(bo->map)) {
 			if (!kgem_bo_set_purgeable(kgem, bo)) {
 				kgem->need_purge |= bo->domain == DOMAIN_GPU;
@@ -1319,6 +1321,26 @@ static void kgem_expire_partial(struct kgem *kgem)
 	}
 }
 
+void kgem_purge_cache(struct kgem *kgem)
+{
+	struct kgem_bo *bo, *next;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) {
+		list_for_each_entry_safe(bo, next, &kgem->inactive[i], list)
+			if (!kgem_bo_is_retained(kgem, bo))
+				kgem_bo_free(kgem, bo);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(kgem->active); i++) {
+		list_for_each_entry_safe(bo, next, &kgem->active[i], list)
+			if (!kgem_bo_is_retained(kgem, bo))
+				kgem_bo_free(kgem, bo);
+	}
+
+	kgem->need_purge = false;
+}
+
 bool kgem_expire_cache(struct kgem *kgem)
 {
 	time_t now, expire;
@@ -1333,6 +1355,9 @@ bool kgem_expire_cache(struct kgem *kgem)
 
 	kgem_expire_partial(kgem);
 
+	if (kgem->need_purge)
+		kgem_purge_cache(kgem);
+
 	time(&now);
 	expire = 0;
 
@@ -1348,15 +1373,13 @@ bool kgem_expire_cache(struct kgem *kgem)
 			bo->delta = now;
 		}
 	}
-	if (!kgem->need_purge) {
-		if (idle) {
-			DBG(("%s: idle\n", __FUNCTION__));
-			kgem->need_expire = false;
-			return false;
-		}
-		if (expire == 0)
-			return true;
+	if (idle) {
+		DBG(("%s: idle\n", __FUNCTION__));
+		kgem->need_expire = false;
+		return false;
 	}
+	if (expire == 0)
+		return true;
 
 	idle = true;
 	for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) {
@@ -1377,10 +1400,9 @@ bool kgem_expire_cache(struct kgem *kgem)
 		}
 	}
 
-	DBG(("%s: purge? %d -- expired %d objects, %d bytes, idle? %d\n",
-	     __FUNCTION__, kgem->need_purge,  count, size, idle));
+	DBG(("%s: expired %d objects, %d bytes, idle? %d\n",
+	     __FUNCTION__, count, size, idle));
 
-	kgem->need_purge = false;
 	kgem->need_expire = !idle;
 	return !idle;
 	(void)count;
@@ -1440,6 +1462,7 @@ search_linear_cache(struct kgem *kgem, unsigned int size, bool use_active)
 
 		if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
 			kgem->need_purge |= bo->domain == DOMAIN_GPU;
+			kgem_bo_free(kgem, bo);
 			continue;
 		}
 
@@ -1817,8 +1840,10 @@ skip_active_search:
 		    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
 			if (tiling != gem_set_tiling(kgem->fd,
 						     bo->handle,
-						     tiling, pitch))
-				goto next_bo;
+						     tiling, pitch)) {
+				kgem_bo_free(kgem, bo);
+				continue;
+			}
 
 			if (bo->map) {
 				munmap(CPU_MAP(bo->map), bo->size);
@@ -1837,7 +1862,8 @@ skip_active_search:
 
 		if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
 			kgem->need_purge |= bo->domain == DOMAIN_GPU;
-			goto next_bo;
+			kgem_bo_free(kgem, bo);
+			continue;
 		}
 
 		if (bo->map)
@@ -1854,10 +1880,6 @@ skip_active_search:
 		assert((flags & CREATE_INACTIVE) == 0 ||
 		       !kgem_busy(kgem, bo->handle));
 		return kgem_bo_reference(bo);
-
-next_bo:
-		kgem_bo_free(kgem, bo);
-		continue;
 	}
 
 	if (flags & CREATE_INACTIVE && !list_is_empty(&kgem->requests)) {
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 35acc1d..97eedb5 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -367,6 +367,7 @@ void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo);
 void kgem_throttle(struct kgem *kgem);
 #define MAX_INACTIVE_TIME 10
 bool kgem_expire_cache(struct kgem *kgem);
+void kgem_purge_cache(struct kgem *kgem);
 void kgem_cleanup_cache(struct kgem *kgem);
 
 #if HAS_EXTRA_DEBUG
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 976066e..aef002f 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -9262,11 +9262,10 @@ void sna_accel_wakeup_handler(struct sna *sna)
 {
 	if (sna->kgem.need_retire)
 		kgem_retire(&sna->kgem);
+	if (sna->kgem.need_purge)
+		kgem_purge_cache(&sna->kgem);
 
 	sna_deferred_free(sna);
-
-	if (sna->kgem.need_purge)
-		kgem_expire_cache(&sna->kgem);
 }
 
 void sna_accel_free(struct sna *sna)


More information about the xorg-commit mailing list