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
This commit is contained in:
James Zern 2022-08-11 18:58:40 -07:00
parent cad0d5adb6
commit 782ed48cd3

View File

@ -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 <pthread.h> // 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,