winsys/amdgpu: Keep track of retrieved KMS handles using hash tables
authorMichel Dänzer <mdaenzer@redhat.com>
Mon, 30 Sep 2019 16:00:50 +0000 (18:00 +0200)
committerMichel Dänzer <michel@daenzer.net>
Thu, 23 Jan 2020 16:24:00 +0000 (17:24 +0100)
The assumption being that KMS handles are only retrieved for relatively
few BOs, so hash tables should be efficient both in terms of performance
and memory consumption.

We use the address of struct amdgpu_winsys_bo as the key and its
kms_handle field (the KMS handle valid for the DRM file descriptor
passed to amdgpu_device_initialize) as the hash value.

v2:
* Add comment above amdgpu_screen_winsys::kms_handles (Pierre-Eric
  Pelloux-Prayer)
v3:
* Protect kms_handles hash table with amdgpu_winsys::sws_list_lock
  mutex.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3202>

src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c
src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h

index 8bbdb9b2eb0ab9cee259fa45e8bff6c0d591a6b4..5f44b02d3513a0068f2fa3c916aa05b2b7cb368b 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "amdgpu_cs.h"
 
+#include "util/hash_table.h"
 #include "util/os_time.h"
 #include "util/u_hash_table.h"
 #include "state_tracker/drm_driver.h"
@@ -164,6 +165,7 @@ static void amdgpu_bo_remove_fences(struct amdgpu_winsys_bo *bo)
 void amdgpu_bo_destroy(struct pb_buffer *_buf)
 {
    struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
+   struct amdgpu_screen_winsys *sws_iter;
    struct amdgpu_winsys *ws = bo->ws;
 
    assert(bo->bo && "must not be called for slab entries");
@@ -181,6 +183,11 @@ void amdgpu_bo_destroy(struct pb_buffer *_buf)
       simple_mtx_unlock(&ws->global_bo_list_lock);
    }
 
+   simple_mtx_lock(&ws->sws_list_lock);
+   for (sws_iter = ws->sws_list; sws_iter; sws_iter = sws_iter->next)
+      _mesa_hash_table_remove_key(sws_iter->kms_handles, bo);
+   simple_mtx_unlock(&ws->sws_list_lock);
+
    simple_mtx_lock(&ws->bo_export_table_lock);
    util_hash_table_remove(ws->bo_export_table, bo->bo);
    simple_mtx_unlock(&ws->bo_export_table_lock);
@@ -1530,6 +1537,7 @@ static bool amdgpu_bo_get_handle(struct radeon_winsys *rws,
    struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(buffer);
    struct amdgpu_winsys *ws = bo->ws;
    enum amdgpu_bo_handle_type type;
+   struct hash_entry *entry;
    int r;
 
    /* Don't allow exports of slab entries and sparse buffers. */
@@ -1543,6 +1551,14 @@ static bool amdgpu_bo_get_handle(struct radeon_winsys *rws,
       type = amdgpu_bo_handle_type_gem_flink_name;
       break;
    case WINSYS_HANDLE_TYPE_KMS:
+      simple_mtx_lock(&ws->sws_list_lock);
+      entry = _mesa_hash_table_search(sws->kms_handles, bo);
+      simple_mtx_unlock(&ws->sws_list_lock);
+      if (entry) {
+         whandle->handle = (uintptr_t)entry->data;
+         return true;
+      }
+      /* Fall through */
    case WINSYS_HANDLE_TYPE_FD:
       type = amdgpu_bo_handle_type_dma_buf_fd;
       break;
@@ -1562,6 +1578,12 @@ static bool amdgpu_bo_get_handle(struct radeon_winsys *rws,
 
       if (r)
          return false;
+
+      simple_mtx_lock(&ws->sws_list_lock);
+      _mesa_hash_table_insert_pre_hashed(sws->kms_handles,
+                                         bo->u.real.kms_handle, bo,
+                                         (void*)(uintptr_t)whandle->handle);
+      simple_mtx_unlock(&ws->sws_list_lock);
    }
 
    simple_mtx_lock(&ws->bo_export_table_lock);
index dfdd6fb16312b296a75abf06ce387d1c386d5952..7bc5fed02f671885e914167e3d8dfdcd6b687468 100644 (file)
@@ -188,6 +188,7 @@ static void amdgpu_winsys_destroy(struct radeon_winsys *rws)
       simple_mtx_unlock(&ws->sws_list_lock);
    }
 
+   _mesa_hash_table_destroy(sws->kms_handles, NULL);
    close(sws->fd);
    FREE(rws);
 }
@@ -308,6 +309,18 @@ static void amdgpu_pin_threads_to_L3_cache(struct radeon_winsys *rws,
                          util_cpu_caps.cores_per_L3);
 }
 
+static uint32_t kms_handle_hash(const void *key)
+{
+   const struct amdgpu_winsys_bo *bo = key;
+
+   return bo->u.real.kms_handle;
+}
+
+static bool kms_handle_equals(const void *a, const void *b)
+{
+   return a == b;
+}
+
 PUBLIC struct radeon_winsys *
 amdgpu_winsys_create(int fd, const struct pipe_screen_config *config,
                     radeon_screen_create_t screen_create)
@@ -323,6 +336,11 @@ amdgpu_winsys_create(int fd, const struct pipe_screen_config *config,
 
    ws->fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
 
+   ws->kms_handles = _mesa_hash_table_create(NULL, kms_handle_hash,
+                                             kms_handle_equals);
+   if (!ws->kms_handles)
+      goto fail;
+
    /* Look up the winsys from the dev table. */
    simple_mtx_lock(&dev_tab_mutex);
    if (!dev_tab)
@@ -465,6 +483,8 @@ amdgpu_winsys_create(int fd, const struct pipe_screen_config *config,
 fail_alloc:
    FREE(aws);
 fail:
+   if (ws->kms_handles)
+      _mesa_hash_table_destroy(ws->kms_handles, NULL);
    close(ws->fd);
    FREE(ws);
    simple_mtx_unlock(&dev_tab_mutex);
index 43e1df09ad58f46f9e55cc2913624221c08abbcb..147e4b23b9b3f538d44ba3133a5125ce535a7877 100644 (file)
@@ -104,6 +104,11 @@ struct amdgpu_screen_winsys {
    struct amdgpu_winsys *aws;
    int fd;
    struct amdgpu_screen_winsys *next;
+
+   /* Maps a BO to its KMS handle valid for this DRM file descriptor
+    * Protected by amdgpu_winsys::sws_list_lock
+    */
+   struct hash_table *kms_handles;
 };
 
 static inline struct amdgpu_screen_winsys *