diff options
author | RĂ©mi Denis-Courmont <remid@nvidia.com> | 2014-10-29 14:47:02 +0200 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2014-11-04 15:51:21 -0800 |
commit | 3162456bb876ffe4bd606968071857e87226d76f (patch) | |
tree | 04984daecf97dab377f6846dd8796c2131cf9251 /src | |
parent | 9899f7b79f4c33b05d27b0409ab17268dc476b06 (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>
Diffstat (limited to 'src')
-rw-r--r-- | src/vdpau_wrapper.c | 31 |
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; } |