From 6e181476c3f0876fab2723ed1652f1ca1e489c27 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 6 Jan 2022 21:46:25 +0100 Subject: [PATCH] etnaviv: drm: make etna_bo_map thread safe This might be called from multiple threads at the same time. To avoid taking a global lock just to guard against the fairly low chance of multiple threads calling this on the same BO at the same time, we allow for the threads to race. All threads will set up a mapping, but only the first thread is able to set the map member of the etna_bo, all other threads just roll back and use the mapping set up by the winning thread. Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Part-of: --- src/etnaviv/drm/etnaviv_bo.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/etnaviv/drm/etnaviv_bo.c b/src/etnaviv/drm/etnaviv_bo.c index b0a3dfa6651..e7988c6df31 100644 --- a/src/etnaviv/drm/etnaviv_bo.c +++ b/src/etnaviv/drm/etnaviv_bo.c @@ -388,6 +388,7 @@ void *etna_bo_map(struct etna_bo *bo) { if (!bo->map) { int ret; + void *map; struct drm_etnaviv_gem_info req = { .handle = bo->handle, }; @@ -397,12 +398,15 @@ void *etna_bo_map(struct etna_bo *bo) if (ret) return NULL; - bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, + map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->dev->fd, req.offset); - if (bo->map == MAP_FAILED) { + if (map == MAP_FAILED) { ERROR_MSG("mmap failed: %s", strerror(errno)); - bo->map = NULL; + return NULL; } + + if (p_atomic_cmpxchg(&bo->map, NULL, map)) + munmap(map, bo->size); } return bo->map;