From b2ff2dfc2a8797260d7b87a5cc6188d891f713ff Mon Sep 17 00:00:00 2001 From: Rohan Garg Date: Fri, 30 Aug 2019 18:00:13 +0200 Subject: [PATCH] panfrost: protect access to shared bo cache and transient pool Both the BO cache and the transient pool are shared across context's. Protect access to these with mutexes. Signed-off-by: Rohan Garg Reviewed-by: Boris Brezillon Reviewed-by: Alyssa Rosenzweig Signed-off-by: Boris Brezillon --- src/gallium/drivers/panfrost/pan_allocate.c | 2 ++ src/gallium/drivers/panfrost/pan_bo_cache.c | 16 +++++++++++----- src/gallium/drivers/panfrost/pan_job.c | 2 ++ src/gallium/drivers/panfrost/pan_screen.c | 4 ++++ src/gallium/drivers/panfrost/pan_screen.h | 4 ++++ 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_allocate.c b/src/gallium/drivers/panfrost/pan_allocate.c index f549c86..fb8b18f 100644 --- a/src/gallium/drivers/panfrost/pan_allocate.c +++ b/src/gallium/drivers/panfrost/pan_allocate.c @@ -74,6 +74,7 @@ panfrost_allocate_transient(struct panfrost_context *ctx, size_t sz) unsigned offset = 0; bool update_offset = false; + pthread_mutex_lock(&screen->transient_lock); bool has_current = batch->transient_indices.size; bool fits_in_current = (batch->transient_offset + sz) < TRANSIENT_SLAB_SIZE; @@ -131,6 +132,7 @@ panfrost_allocate_transient(struct panfrost_context *ctx, size_t sz) if (update_offset) batch->transient_offset = offset + sz; + pthread_mutex_unlock(&screen->transient_lock); return ret; diff --git a/src/gallium/drivers/panfrost/pan_bo_cache.c b/src/gallium/drivers/panfrost/pan_bo_cache.c index 9dd6b69..f2f4943 100644 --- a/src/gallium/drivers/panfrost/pan_bo_cache.c +++ b/src/gallium/drivers/panfrost/pan_bo_cache.c @@ -24,6 +24,7 @@ * Alyssa Rosenzweig */ #include +#include #include "drm-uapi/panfrost_drm.h" #include "pan_screen.h" @@ -84,7 +85,9 @@ panfrost_bo_cache_fetch( struct panfrost_screen *screen, size_t size, uint32_t flags) { + pthread_mutex_lock(&screen->bo_cache_lock); struct list_head *bucket = pan_bucket(screen, size); + struct panfrost_bo *bo = NULL; /* Iterate the bucket looking for something suitable */ list_for_each_entry_safe(struct panfrost_bo, entry, bucket, link) { @@ -106,12 +109,13 @@ panfrost_bo_cache_fetch( continue; } /* Let's go! */ - return entry; + bo = entry; + break; } } + pthread_mutex_unlock(&screen->bo_cache_lock); - /* We didn't find anything */ - return NULL; + return bo; } /* Tries to add a BO to the cache. Returns if it was @@ -122,6 +126,7 @@ panfrost_bo_cache_put( struct panfrost_screen *screen, struct panfrost_bo *bo) { + pthread_mutex_lock(&screen->bo_cache_lock); struct list_head *bucket = pan_bucket(screen, bo->size); struct drm_panfrost_madvise madv; @@ -133,6 +138,7 @@ panfrost_bo_cache_put( /* Add us to the bucket */ list_addtail(&bo->link, bucket); + pthread_mutex_unlock(&screen->bo_cache_lock); return true; } @@ -147,6 +153,7 @@ void panfrost_bo_cache_evict_all( struct panfrost_screen *screen) { + pthread_mutex_lock(&screen->bo_cache_lock); for (unsigned i = 0; i < ARRAY_SIZE(screen->bo_cache); ++i) { struct list_head *bucket = &screen->bo_cache[i]; @@ -155,7 +162,6 @@ panfrost_bo_cache_evict_all( panfrost_drm_release_bo(screen, entry, false); } } - - return; + pthread_mutex_unlock(&screen->bo_cache_lock); } diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index f5bbd04..f7ff57c 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -67,10 +67,12 @@ panfrost_free_job(struct panfrost_context *ctx, struct panfrost_job *job) /* Free up the transient BOs we're sitting on */ struct panfrost_screen *screen = pan_screen(ctx->base.screen); + pthread_mutex_lock(&screen->transient_lock); util_dynarray_foreach(&job->transient_indices, unsigned, index) { /* Mark it free */ BITSET_SET(screen->free_transient, *index); } + pthread_mutex_unlock(&screen->transient_lock); /* Unreference the polygon list */ panfrost_bo_unreference(ctx->base.screen, job->polygon_list); diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index 5c288f5..bd82680 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -542,6 +542,8 @@ panfrost_destroy_screen(struct pipe_screen *pscreen) { struct panfrost_screen *screen = pan_screen(pscreen); panfrost_bo_cache_evict_all(screen); + pthread_mutex_destroy(&screen->bo_cache_lock); + pthread_mutex_destroy(&screen->transient_lock); drmFreeVersion(screen->kernel_version); ralloc_free(screen); } @@ -639,8 +641,10 @@ panfrost_create_screen(int fd, struct renderonly *ro) return NULL; } + pthread_mutex_init(&screen->transient_lock, NULL); util_dynarray_init(&screen->transient_bo, screen); + pthread_mutex_init(&screen->bo_cache_lock, NULL); for (unsigned i = 0; i < ARRAY_SIZE(screen->bo_cache); ++i) list_inithead(&screen->bo_cache[i]); diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h index 0a8da33..d8ea559 100644 --- a/src/gallium/drivers/panfrost/pan_screen.h +++ b/src/gallium/drivers/panfrost/pan_screen.h @@ -104,6 +104,8 @@ struct panfrost_screen { struct renderonly *ro; + pthread_mutex_t transient_lock; + /* Transient memory management is based on borrowing fixed-size slabs * off the screen (loaning them out to the batch). Dynamic array * container of panfrost_bo */ @@ -113,6 +115,8 @@ struct panfrost_screen { /* Set of free transient BOs */ BITSET_DECLARE(free_transient, MAX_TRANSIENT_SLABS); + pthread_mutex_t bo_cache_lock; + /* The BO cache is a set of buckets with power-of-two sizes ranging * from 2^12 (4096, the page size) to 2^(12 + MAX_BO_CACHE_BUCKETS). * Each bucket is a linked list of free panfrost_bo objects. */ -- 2.7.4