From 782ed48cd314b3b09232ea2bf3b54df99f155046 Mon Sep 17 00:00:00 2001 From: James Zern Date: Thu, 11 Aug 2022 18:58:40 -0700 Subject: [PATCH] sharpyuv,SharpYuvInit: add mutex protection when available this is similar to WEBP_DSP_INIT and avoids the potential for a race in initializing the function pointers and gamma table Change-Id: I15af7d1a3e92c42eaa735751ca33eba0d1e83283 --- sharpyuv/sharpyuv.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/sharpyuv/sharpyuv.c b/sharpyuv/sharpyuv.c index 3fc8496c..5ff02225 100644 --- a/sharpyuv/sharpyuv.c +++ b/sharpyuv/sharpyuv.c @@ -414,6 +414,22 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, } #undef SAFE_ALLOC +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include // NOLINT + +#define LOCK_ACCESS \ + static pthread_mutex_t sharpyuv_lock = PTHREAD_MUTEX_INITIALIZER; \ + if (pthread_mutex_lock(&sharpyuv_lock)) return +#define UNLOCK_ACCESS_AND_RETURN \ + do { \ + (void)pthread_mutex_unlock(&sharpyuv_lock); \ + return; \ + } while (0) +#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32)) +#define LOCK_ACCESS do {} while (0) +#define UNLOCK_ACCESS_AND_RETURN return +#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32) + // Hidden exported init function. // By default SharpYuvConvert calls it with NULL. If needed, users can declare // it as extern and call it with a VP8CPUInfo function. @@ -421,17 +437,21 @@ SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func); void SharpYuvInit(VP8CPUInfo cpu_info_func) { static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used = (VP8CPUInfo)&sharpyuv_last_cpuinfo_used; - const int initialized = + LOCK_ACCESS; + { + const int initialized = (sharpyuv_last_cpuinfo_used != (VP8CPUInfo)&sharpyuv_last_cpuinfo_used); - if (cpu_info_func == NULL && initialized) return; - if (sharpyuv_last_cpuinfo_used == cpu_info_func) return; + if (cpu_info_func == NULL && initialized) UNLOCK_ACCESS_AND_RETURN; + if (sharpyuv_last_cpuinfo_used == cpu_info_func) UNLOCK_ACCESS_AND_RETURN; - SharpYuvInitDsp(cpu_info_func); - if (!initialized) { - SharpYuvInitGammaTables(); + SharpYuvInitDsp(cpu_info_func); + if (!initialized) { + SharpYuvInitGammaTables(); + } + + sharpyuv_last_cpuinfo_used = cpu_info_func; } - - sharpyuv_last_cpuinfo_used = cpu_info_func; + UNLOCK_ACCESS_AND_RETURN; } int SharpYuvConvert(const void* r_ptr, const void* g_ptr,