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
@@ -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,10 +437,12 @@ 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;
+ 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) {
@@ -433,6 +451,8 @@ void SharpYuvInit(VP8CPUInfo cpu_info_func) {
sharpyuv_last_cpuinfo_used = cpu_info_func;
}
+ UNLOCK_ACCESS_AND_RETURN;
+}
int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step, int rgb_stride,
