Module: Mesa
Branch: staging/22.2
Commit: 3632392123c336e7c6612663413d3960e540518a
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=3632392123c336e7c6612663413d3960e540518a

Author: Karol Herbst <[email protected]>
Date:   Wed Jan 27 11:11:36 2021 +0100

nouveau/mm: make code thread safe

With this helgrind doesn't report any races in this code.

Cc: mesa-stable
Signed-off-by: Karol Herbst <[email protected]>
Reviewed-by: Pierre Moreau <[email protected]>
Reviewed-by: Emma Anholt <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10752>
(cherry picked from commit 35d28251d1328d258da74756ef8eb2cc4ea80eba)

---

 .pick_status.json                        |  2 +-
 src/gallium/drivers/nouveau/nouveau_mm.c | 20 +++++++++++++++-----
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index 8502539c7da..e7c9ff4744c 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -8014,7 +8014,7 @@
         "description": "nouveau/mm: make code thread safe",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": null
     },
diff --git a/src/gallium/drivers/nouveau/nouveau_mm.c 
b/src/gallium/drivers/nouveau/nouveau_mm.c
index 95ebbae3f34..33a13753d10 100644
--- a/src/gallium/drivers/nouveau/nouveau_mm.c
+++ b/src/gallium/drivers/nouveau/nouveau_mm.c
@@ -1,6 +1,7 @@
 
 #include <inttypes.h>
 
+#include "util/simple_mtx.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 #include "util/list.h"
@@ -29,6 +30,7 @@ struct mm_bucket {
    struct list_head used;
    struct list_head full;
    int num_free;
+   simple_mtx_t lock;
 };
 
 struct nouveau_mman {
@@ -124,6 +126,8 @@ mm_slab_new(struct nouveau_mman *cache, struct mm_bucket 
*bucket, int chunk_orde
    int words, ret;
    const uint32_t size = mm_default_slab_size(chunk_order);
 
+   simple_mtx_assert_locked(&bucket->lock);
+
    words = ((size >> chunk_order) + 31) / 32;
    assert(words);
 
@@ -151,7 +155,7 @@ mm_slab_new(struct nouveau_mman *cache, struct mm_bucket 
*bucket, int chunk_orde
    assert(bucket == mm_bucket_by_order(cache, chunk_order));
    list_add(&slab->head, &bucket->free);
 
-   cache->allocated += size;
+   p_atomic_add(&cache->allocated, size);
 
    if (nouveau_mesa_debug)
       debug_printf("MM: new slab, total memory = %"PRIu64" KiB\n",
@@ -182,6 +186,11 @@ nouveau_mm_allocate(struct nouveau_mman *cache,
       return NULL;
    }
 
+   alloc = MALLOC_STRUCT(nouveau_mm_allocation);
+   if (!alloc)
+      return NULL;
+
+   simple_mtx_lock(&bucket->lock);
    if (!list_is_empty(&bucket->used)) {
       slab = list_entry(bucket->used.next, struct mm_slab, head);
    } else {
@@ -196,16 +205,13 @@ nouveau_mm_allocate(struct nouveau_mman *cache,
 
    *offset = mm_slab_alloc(slab) << slab->order;
 
-   alloc = MALLOC_STRUCT(nouveau_mm_allocation);
-   if (!alloc)
-      return NULL;
-
    nouveau_bo_ref(slab->bo, bo);
 
    if (slab->free == 0) {
       list_del(&slab->head);
       list_add(&slab->head, &bucket->full);
    }
+   simple_mtx_unlock(&bucket->lock);
 
    alloc->offset = *offset;
    alloc->priv = (void *)slab;
@@ -219,6 +225,7 @@ nouveau_mm_free(struct nouveau_mm_allocation *alloc)
    struct mm_slab *slab = (struct mm_slab *)alloc->priv;
    struct mm_bucket *bucket = mm_bucket_by_order(slab->cache, slab->order);
 
+   simple_mtx_lock(&bucket->lock);
    mm_slab_free(slab, alloc->offset >> slab->order);
 
    if (slab->free == slab->count) {
@@ -229,6 +236,7 @@ nouveau_mm_free(struct nouveau_mm_allocation *alloc)
       list_del(&slab->head);
       list_addtail(&slab->head, &bucket->used);
    }
+   simple_mtx_unlock(&bucket->lock);
 
    FREE(alloc);
 }
@@ -258,6 +266,7 @@ nouveau_mm_create(struct nouveau_device *dev, uint32_t 
domain,
       list_inithead(&cache->bucket[i].free);
       list_inithead(&cache->bucket[i].used);
       list_inithead(&cache->bucket[i].full);
+      simple_mtx_init(&cache->bucket[i].lock, mtx_plain);
    }
 
    return cache;
@@ -292,6 +301,7 @@ nouveau_mm_destroy(struct nouveau_mman *cache)
       nouveau_mm_free_slabs(&cache->bucket[i].free);
       nouveau_mm_free_slabs(&cache->bucket[i].used);
       nouveau_mm_free_slabs(&cache->bucket[i].full);
+      simple_mtx_destroy(&cache->bucket[i].lock);
    }
 
    FREE(cache);

Reply via email to