summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRĂ©mi Denis-Courmont <remid@nvidia.com>2014-10-29 14:47:02 +0200
committerAaron Plattner <aplattner@nvidia.com>2014-11-04 15:51:21 -0800
commit3162456bb876ffe4bd606968071857e87226d76f (patch)
tree04984daecf97dab377f6846dd8796c2131cf9251
parent9899f7b79f4c33b05d27b0409ab17268dc476b06 (diff)
vdpau_wrapper: protect concurrent access to _imp_get_proc_address
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. Reviewed-by: Aaron Plattner <aplattner@nvidia.com> Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
-rw-r--r--src/vdpau_wrapper.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/vdpau_wrapper.c b/src/vdpau_wrapper.c
index 7cbdda5..8efbd39 100644
--- a/src/vdpau_wrapper.c
+++ b/src/vdpau_wrapper.c
@@ -399,6 +399,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);
@@ -414,17 +415,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;
}