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