[PATCH libdrm 6/9] amdgpu: Re-use an existing amdgpu_device when possible
Michel Dänzer
michel at daenzer.net
Mon Jun 24 16:54:03 UTC 2019
From: Michel Dänzer <michel.daenzer at amd.com>
It's possible if amdgpu_device's user_fd references the same file
description as the fd passed to amdgpu_device_initialize.
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
amdgpu/amdgpu_device.c | 76 +++++++++++++++++++++++++++++-----------
amdgpu/amdgpu_internal.h | 3 +-
2 files changed, 58 insertions(+), 21 deletions(-)
diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c
index abf5f942..8d9a85c2 100644
--- a/amdgpu/amdgpu_device.c
+++ b/amdgpu/amdgpu_device.c
@@ -28,6 +28,11 @@
*
*/
+#ifdef __linux__
+#include <linux/kcmp.h>
+#include <sys/syscall.h>
+#endif
+
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
@@ -44,7 +49,7 @@
#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
static pthread_mutex_t dev_mutex = PTHREAD_MUTEX_INITIALIZER;
-static struct amdgpu_core_device *dev_list;
+static amdgpu_device_handle dev_list;
static int fd_compare(int fd1, int fd2)
{
@@ -67,12 +72,6 @@ static int fd_compare(int fd1, int fd2)
static void amdgpu_device_free(struct amdgpu_core_device *dev)
{
- struct amdgpu_core_device **node = &dev_list;
-
- while (*node != dev && (*node)->next)
- node = &(*node)->next;
- *node = (*node)->next;
-
close(dev->fd);
amdgpu_vamgr_deinit(&dev->vamgr_32);
@@ -86,20 +85,35 @@ static void amdgpu_device_free(struct amdgpu_core_device *dev)
free(dev);
}
+static bool same_file_description(int fd1, int fd2)
+{
+#ifdef __linux__
+ pid_t pid = getpid();
+
+ return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2) == 0;
+#endif
+
+ /* NOTE: This is never true at this point, since we always duplicate the
+ * fd passed to amdgpu_device_initialize
+ */
+ return fd1 == fd2;
+}
+
static int amdgpu_device_init(amdgpu_device_handle user_dev)
{
+ struct amdgpu_device *dev_iter;
struct amdgpu_core_device *dev;
drmVersionPtr version;
uint64_t start, max;
int r;
- for (dev = dev_list; dev; dev = dev->next)
- if (fd_compare(dev->fd, user_dev->user_fd) == 0)
+ for (dev_iter = dev_list; dev_iter; dev_iter = dev_iter->next)
+ if (fd_compare(dev_iter->core->fd, user_dev->user_fd) == 0)
break;
- if (dev) {
- atomic_inc(&dev->refcount);
- user_dev->core = dev;
+ if (dev_iter) {
+ atomic_inc(&dev_iter->core->refcount);
+ user_dev->core = dev_iter->core;
return 0;
}
@@ -115,9 +129,6 @@ static int amdgpu_device_init(amdgpu_device_handle user_dev)
dev->fd = user_dev->user_fd;
user_dev->core = dev;
- dev->next = dev_list;
- dev_list = dev;
-
version = drmGetVersion(dev->fd);
if (version->version_major != 3) {
fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is "
@@ -184,6 +195,17 @@ drm_public int amdgpu_device_initialize(int fd,
*device_handle = NULL;
+ pthread_mutex_lock(&dev_mutex);
+
+ for (user_dev = dev_list; user_dev; user_dev = user_dev->next) {
+ if (same_file_description(user_dev->user_fd, fd)) {
+ atomic_inc(&user_dev->refcount);
+ goto out;
+ }
+ }
+
+ pthread_mutex_unlock(&dev_mutex);
+
user_dev = calloc(1, sizeof(struct amdgpu_device));
if (!user_dev) {
fprintf(stderr, "%s: calloc failed\n", __func__);
@@ -211,6 +233,11 @@ drm_public int amdgpu_device_initialize(int fd,
goto cleanup;
}
+ atomic_set(&user_dev->refcount, 1);
+ user_dev->next = dev_list;
+ dev_list = user_dev;
+
+out:
*major_version = user_dev->core->major_version;
*minor_version = user_dev->core->minor_version;
*device_handle = user_dev;
@@ -234,14 +261,23 @@ drm_public int amdgpu_device_deinitialize(amdgpu_device_handle user_dev)
pthread_mutex_lock(&dev_mutex);
- if (user_dev->user_fd != dev->fd)
- close(user_dev->user_fd);
+ if (update_references(&user_dev->refcount, NULL)) {
+ struct amdgpu_device **node = &dev_list;
- if (update_references(&dev->refcount, NULL))
- amdgpu_device_free(dev);
+ while (*node != user_dev && (*node)->next)
+ node = &(*node)->next;
+ *node = (*node)->next;
+
+ if (user_dev->user_fd != dev->fd)
+ close(user_dev->user_fd);
+
+ if (update_references(&dev->refcount, NULL))
+ amdgpu_device_free(dev);
+
+ free(user_dev);
+ }
pthread_mutex_unlock(&dev_mutex);
- free(user_dev);
return 0;
}
diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h
index a08a4ae8..686d50ec 100644
--- a/amdgpu/amdgpu_internal.h
+++ b/amdgpu/amdgpu_internal.h
@@ -70,7 +70,6 @@ struct amdgpu_core_device {
unsigned major_version;
unsigned minor_version;
- struct amdgpu_core_device *next;
char *marketing_name;
/** List of buffer handles. Protected by bo_table_mutex. */
struct handle_table bo_handles;
@@ -91,8 +90,10 @@ struct amdgpu_core_device {
};
struct amdgpu_device {
+ atomic_t refcount;
int user_fd;
struct amdgpu_core_device *core;
+ struct amdgpu_device *next;
};
struct amdgpu_core_bo {
--
2.20.1
More information about the dri-devel
mailing list