[VDPAU] [PATCH 4/4] vdpau_wrapper: protect concurrent access to _imp_get_proc_address

Rémi Denis-Courmont remi at remlab.net
Wed Oct 29 05:47:02 PDT 2014


From: Rémi Denis-Courmont <remid at nvidia.com>

The wrapper, as it's currently written, cannot cope with more than one
VdpGetProcAddress implementation. Luckily, this should hardly ever
happen.

This patch protects access to the _imp_get_proc_address variable to
conform to the memory model, and ensures that a single VDPAU
implementation is used - failing safe if not so.
---
 src/vdpau_wrapper.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/src/vdpau_wrapper.c b/src/vdpau_wrapper.c
index 7d4885d..196050b 100644
--- a/src/vdpau_wrapper.c
+++ b/src/vdpau_wrapper.c
@@ -526,6 +526,7 @@ VdpStatus vdp_device_create_x11(
 {
     static pthread_once_t once = PTHREAD_ONCE_INIT;
     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+    VdpGetProcAddress *gpa;
     VdpStatus status = VDP_STATUS_OK;
 
     pthread_once(&once, init_fixes);
@@ -541,17 +542,33 @@ VdpStatus vdp_device_create_x11(
     if (status != VDP_STATUS_OK)
         return status;
 
-    status = _vdp_imp_device_create_x11_proc(
-        display,
-        screen,
-        device,
-        &_imp_get_proc_address
-    );
+    status = _vdp_imp_device_create_x11_proc(display, screen, device, &gpa);
     if (status != VDP_STATUS_OK) {
         return status;
     }
 
     *get_proc_address = vdp_wrapper_get_proc_address;
 
-    return VDP_STATUS_OK;
+    pthread_mutex_lock(&lock);
+    if (_imp_get_proc_address != gpa) {
+        if (_imp_get_proc_address == NULL)
+            _imp_get_proc_address = gpa;
+        else
+        /* Currently the wrapper can only deal with one back-end.
+         * This should never happen, but better safe than sorry. */
+            status = VDP_STATUS_NO_IMPLEMENTATION;
+    }
+    pthread_mutex_unlock(&lock);
+
+    if (status != VDP_STATUS_OK) {
+        void *pv;
+
+        if (gpa(*device, VDP_FUNC_ID_DEVICE_DESTROY, &pv) == VDP_STATUS_OK) {
+            VdpDeviceDestroy *device_destroy = pv;
+
+            device_destroy(*device);
+        }
+    }
+
+    return status;
 }
-- 
1.9.1



More information about the VDPAU mailing list