Compare commits

...

2 Commits

Author SHA1 Message Date
Wan-Teh Chang
991170bbab Implement WEBP_DSP_INIT with SRWLOCK for Windows
A slim reader/writer (SRW) lock can be initialized statically with the
constant SRWLOCK_INIT. It is the only Windows synchronization object I
can find with this property.

Note: On old Windows versions that don't have SRWLOCK, use the fallback,
thread-unsafe implementation.

Change a NOLINT comment to a NOLINTNEXTLINE comment to prevent
clang-format from aligning the #else and #endif comments in undesired
way.

Bug: 435213378
Change-Id: Iecff615a14a1905aedd2c05ad9444889f711cc17
(cherry picked from commit 54f23b049e)
2025-08-07 14:01:35 -07:00
Wan-Teh Chang
166968b809 Use file static variables in WEBP_DSP_INIT_FUNC()
Function static variables are initialized on the first call to the
function. In C the initialization of function static variables is not
thread-safe. Use file static variables instead in the
WEBP_DSP_INIT_FUNC() macro.

Remove the volatile qualifier for the pthread version of the
func##_last_cpuinfo_used variable because the variable is only accessed
while holding the mutex.

Change-Id: I1237904a49d2467d7ce79fc53f9e7f966aa7a5c1
(cherry picked from commit 313692d51e)
2025-08-07 13:57:10 -07:00

View File

@@ -189,29 +189,64 @@
#endif
#endif
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
#include <pthread.h> // NOLINT
#if defined(WEBP_USE_THREAD)
#if defined(_WIN32)
#include <windows.h>
#define WEBP_DSP_INIT(func) \
do { \
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used; \
static pthread_mutex_t func##_lock = PTHREAD_MUTEX_INITIALIZER; \
if (pthread_mutex_lock(&func##_lock)) break; \
if (func##_last_cpuinfo_used != VP8GetCPUInfo) func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
(void)pthread_mutex_unlock(&func##_lock); \
#if _WIN32_WINNT >= 0x0600
// clang-format off
#define WEBP_DSP_INIT_VARS(func) \
static VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used; \
static SRWLOCK func##_lock = SRWLOCK_INIT
#define WEBP_DSP_INIT(func) \
do { \
AcquireSRWLockExclusive(&func##_lock); \
if (func##_last_cpuinfo_used != VP8GetCPUInfo) func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
ReleaseSRWLockExclusive(&func##_lock); \
} while (0)
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
// clang-format on
#else // _WIN32_WINNT < 0x0600
// clang-format off
#define WEBP_DSP_INIT_VARS(func) \
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used
#define WEBP_DSP_INIT(func) \
do { \
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used; \
if (func##_last_cpuinfo_used == VP8GetCPUInfo) break; \
func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
} while (0)
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
// clang-format on
#endif // _WIN32_WINNT >= 0x0600
#else // !defined(_WIN32)
// NOLINTNEXTLINE
#include <pthread.h>
#define WEBP_DSP_INIT_VARS(func) \
static VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used; \
static pthread_mutex_t func##_lock = PTHREAD_MUTEX_INITIALIZER
#define WEBP_DSP_INIT(func) \
do { \
if (pthread_mutex_lock(&func##_lock)) break; \
if (func##_last_cpuinfo_used != VP8GetCPUInfo) func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
(void)pthread_mutex_unlock(&func##_lock); \
} while (0)
#endif // defined(_WIN32)
#else // !defined(WEBP_USE_THREAD)
#define WEBP_DSP_INIT_VARS(func) \
static volatile VP8CPUInfo func##_last_cpuinfo_used = \
(VP8CPUInfo)&func##_last_cpuinfo_used
#define WEBP_DSP_INIT(func) \
do { \
if (func##_last_cpuinfo_used == VP8GetCPUInfo) break; \
func(); \
func##_last_cpuinfo_used = VP8GetCPUInfo; \
} while (0)
#endif // defined(WEBP_USE_THREAD)
// Defines an Init + helper function that control multiple initialization of
// function pointers / tables.
@@ -221,6 +256,7 @@
}
*/
#define WEBP_DSP_INIT_FUNC(name) \
WEBP_DSP_INIT_VARS(name##_body); \
static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void); \
WEBP_TSAN_IGNORE_FUNCTION void name(void) { WEBP_DSP_INIT(name##_body); } \
static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void)