Mesa (master): r300g: fix a possible race condition when mapping a buffer

Marek Olšák mareko at kemper.freedesktop.org
Tue Feb 15 03:03:10 UTC 2011


Module: Mesa
Branch: master
Commit: 8decb0a96de0accfc8361890cbcf9db89f8fe8ba
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8decb0a96de0accfc8361890cbcf9db89f8fe8ba

Author: Marek Olšák <maraeo at gmail.com>
Date:   Tue Feb 15 02:34:05 2011 +0100

r300g: fix a possible race condition when mapping a buffer

This is the last one I think.

---

 src/gallium/winsys/radeon/drm/radeon_drm_bo.c |   54 ++++++++++++++----------
 src/gallium/winsys/radeon/drm/radeon_drm_bo.h |    3 +
 2 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index 027e9d3..6de1ff7 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -107,6 +107,7 @@ void radeon_bo_unref(struct radeon_bo *bo)
     /* Close object. */
     args.handle = bo->handle;
     drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
+    pipe_mutex_destroy(bo->map_mutex);
     FREE(bo);
 }
 
@@ -156,6 +157,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
     struct radeon_bo *bo = radeon_bo(_buf);
     struct radeon_drm_cs *cs = flush_ctx;
     struct drm_radeon_gem_mmap args = {};
+    void *ptr;
     /* prevents a call to radeon_bo_wait if (usage & DONTBLOCK) and
      * radeon_is_busy returns FALSE. */
     boolean may_be_busy = TRUE;
@@ -182,30 +184,34 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
         radeon_bo_wait((struct r300_winsys_bo*)bo);
     }
 
-    /* Map buffer if it's not already mapped. */
-    /* XXX We may get a race in bo->ptr. */
-    if (!bo->ptr) {
-        void *ptr;
-
-        args.handle = bo->handle;
-        args.offset = 0;
-        args.size = (uint64_t)bo->size;
-        if (drmCommandWriteRead(bo->rws->fd,
-                                DRM_RADEON_GEM_MMAP,
-                                &args,
-                                sizeof(args))) {
-            fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
-                    bo, bo->handle);
-            return NULL;
-        }
-        ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
-                   bo->rws->fd, args.addr_ptr);
-        if (ptr == MAP_FAILED) {
-            fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
-            return NULL;
-        }
-        bo->ptr = ptr;
+    /* Return the pointer if it's already mapped. */
+    if (bo->ptr)
+        return bo->ptr;
+
+    /* Map the buffer. */
+    pipe_mutex_lock(bo->map_mutex);
+    args.handle = bo->handle;
+    args.offset = 0;
+    args.size = (uint64_t)bo->size;
+    if (drmCommandWriteRead(bo->rws->fd,
+                            DRM_RADEON_GEM_MMAP,
+                            &args,
+                            sizeof(args))) {
+        pipe_mutex_unlock(bo->map_mutex);
+        fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
+                bo, bo->handle);
+        return NULL;
+    }
+
+    ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
+               bo->rws->fd, args.addr_ptr);
+    if (ptr == MAP_FAILED) {
+        pipe_mutex_unlock(bo->map_mutex);
+        fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
+        return NULL;
     }
+    bo->ptr = ptr;
+    pipe_mutex_unlock(bo->map_mutex);
 
     return bo->ptr;
 }
@@ -284,6 +290,7 @@ static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr,
     bo->rws = mgr->rws;
     bo->handle = args.handle;
     bo->size = size;
+    pipe_mutex_init(bo->map_mutex);
 
     radeon_bo_ref(bo);
     return &bo->base;
@@ -514,6 +521,7 @@ static struct r300_winsys_bo *radeon_winsys_bo_from_handle(struct r300_winsys_sc
     bo->base.vtbl = &radeon_bo_vtbl;
     bo->mgr = mgr;
     bo->rws = mgr->rws;
+    pipe_mutex_init(bo->map_mutex);
 
     util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo);
 
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
index cb1afd6..d877512 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
@@ -34,6 +34,7 @@
 
 #include "radeon_winsys.h"
 #include "pipebuffer/pb_bufmgr.h"
+#include "os/os_thread.h"
 
 #define RADEON_PB_USAGE_CACHE       (1 << 28)
 #define RADEON_PB_USAGE_DOMAIN_GTT  (1 << 29)
@@ -47,6 +48,8 @@ struct radeon_bo {
     struct radeon_drm_winsys *rws;
 
     void *ptr;
+    pipe_mutex map_mutex;
+
     uint32_t size;
     uint32_t handle;
     uint32_t name;




More information about the mesa-commit mailing list