From d77bf512bd0c4ff53019e357a2d24f6c4e3fbefc Mon Sep 17 00:00:00 2001 From: James Zern Date: Mon, 16 Apr 2018 20:19:54 -0700 Subject: [PATCH] add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC this internalizes the init checks and provides stronger synchronization with pthreads when available while still allowing VP8GetCPUInfo to be modified (mostly for testing purposes). windows is left as is since a critical section or mutex would cause a leak. Change-Id: Ieb997e014f2805c0ae39c16f13337663521356f4 --- src/dec/vp8_dec.c | 2 +- src/dsp/alpha_processing.c | 9 +-------- src/dsp/cost.c | 9 +-------- src/dsp/dec.c | 9 +-------- src/dsp/dsp.h | 38 ++++++++++++++++++++++++++++++++++++- src/dsp/enc.c | 9 +-------- src/dsp/filters.c | 9 +-------- src/dsp/lossless.c | 9 +-------- src/dsp/lossless_enc.c | 9 +-------- src/dsp/rescaler.c | 7 +------ src/dsp/ssim.c | 9 +-------- src/dsp/upsampling.c | 16 ++-------------- src/dsp/yuv.c | 17 ++--------------- src/enc/near_lossless_enc.c | 2 +- src/enc/picture_csp_enc.c | 4 ++-- 15 files changed, 54 insertions(+), 104 deletions(-) diff --git a/src/dec/vp8_dec.c b/src/dec/vp8_dec.c index 6212efd1..c904b529 100644 --- a/src/dec/vp8_dec.c +++ b/src/dec/vp8_dec.c @@ -491,7 +491,7 @@ static int GetCoeffsAlt(VP8BitReader* const br, return 16; } -WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) { +static WEBP_TSAN_IGNORE_FUNCTION void InitGetCoeffs(void) { if (GetCoeffs == NULL) { if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) { GetCoeffs = GetCoeffsAlt; diff --git a/src/dsp/alpha_processing.c b/src/dsp/alpha_processing.c index 995b4345..819d1391 100644 --- a/src/dsp/alpha_processing.c +++ b/src/dsp/alpha_processing.c @@ -409,12 +409,7 @@ extern void WebPInitAlphaProcessingSSE2(void); extern void WebPInitAlphaProcessingSSE41(void); extern void WebPInitAlphaProcessingNEON(void); -static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = - (VP8CPUInfo)&alpha_processing_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { - if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) { WebPMultARGBRow = WebPMultARGBRow_C; WebPMultRow = WebPMultRow_C; WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C; @@ -474,6 +469,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { assert(WebPPackRGB != NULL); assert(WebPHasAlpha8b != NULL); assert(WebPHasAlpha32b != NULL); - - alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/cost.c b/src/dsp/cost.c index a732389d..634ccc20 100644 --- a/src/dsp/cost.c +++ b/src/dsp/cost.c @@ -378,12 +378,7 @@ extern void VP8EncDspCostInitMIPS32(void); extern void VP8EncDspCostInitMIPSdspR2(void); extern void VP8EncDspCostInitSSE2(void); -static volatile VP8CPUInfo cost_last_cpuinfo_used = - (VP8CPUInfo)&cost_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) { - if (cost_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) { VP8GetResidualCost = GetResidualCost_C; VP8SetResidualCoeffs = SetResidualCoeffs_C; @@ -405,8 +400,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) { } #endif } - - cost_last_cpuinfo_used = VP8GetCPUInfo; } //------------------------------------------------------------------------------ diff --git a/src/dsp/dec.c b/src/dsp/dec.c index 7e824075..1119842d 100644 --- a/src/dsp/dec.c +++ b/src/dsp/dec.c @@ -741,12 +741,7 @@ extern void VP8DspInitMIPS32(void); extern void VP8DspInitMIPSdspR2(void); extern void VP8DspInitMSA(void); -static volatile VP8CPUInfo dec_last_cpuinfo_used = - (VP8CPUInfo)&dec_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { - if (dec_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8DspInit) { VP8InitClipTables(); #if !WEBP_NEON_OMIT_C_CODE @@ -889,6 +884,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { assert(VP8PredChroma8[5] != NULL); assert(VP8PredChroma8[6] != NULL); assert(VP8DitherCombine8x8 != NULL); - - dec_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index 5146949e..4ab77a51 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -141,6 +141,42 @@ extern "C" { #endif #endif +#if defined(WEBP_USE_THREAD) && !defined(_WIN32) +#include // NOLINT + +#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); \ +} while (0) +#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32)) +#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) + +// Defines an Init + helper function that control multiple initialization of +// function pointers / tables. +/* Usage: + WEBP_DSP_INIT_FUNC(InitFunc) { + ...function body + } +*/ +#define WEBP_DSP_INIT_FUNC(name) \ + 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) + #define WEBP_UBSAN_IGNORE_UNDEF #define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW #if defined(__clang__) && defined(__has_attribute) @@ -196,7 +232,7 @@ WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; // avoiding a compiler warning. #define WEBP_DSP_INIT_STUB(func) \ extern void func(void); \ - WEBP_TSAN_IGNORE_FUNCTION void func(void) {} + void func(void) {} //------------------------------------------------------------------------------ // Encoding diff --git a/src/dsp/enc.c b/src/dsp/enc.c index 1c807f1d..fa23b40a 100644 --- a/src/dsp/enc.c +++ b/src/dsp/enc.c @@ -740,12 +740,7 @@ extern void VP8EncDspInitMIPS32(void); extern void VP8EncDspInitMIPSdspR2(void); extern void VP8EncDspInitMSA(void); -static volatile VP8CPUInfo enc_last_cpuinfo_used = - (VP8CPUInfo)&enc_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { - if (enc_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8EncDspInit) { VP8DspInit(); // common inverse transforms InitTables(); @@ -838,6 +833,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { assert(VP8EncQuantizeBlockWHT != NULL); assert(VP8Copy4x4 != NULL); assert(VP8Copy16x8 != NULL); - - enc_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/filters.c b/src/dsp/filters.c index ca5f877d..069a22ea 100644 --- a/src/dsp/filters.c +++ b/src/dsp/filters.c @@ -238,12 +238,7 @@ extern void VP8FiltersInitMSA(void); extern void VP8FiltersInitNEON(void); extern void VP8FiltersInitSSE2(void); -static volatile VP8CPUInfo filters_last_cpuinfo_used = - (VP8CPUInfo)&filters_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { - if (filters_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8FiltersInit) { WebPUnfilters[WEBP_FILTER_NONE] = NULL; #if !WEBP_NEON_OMIT_C_CODE WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C; @@ -289,6 +284,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL); assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL); assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL); - - filters_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/lossless.c b/src/dsp/lossless.c index 83f553d9..f9b3c182 100644 --- a/src/dsp/lossless.c +++ b/src/dsp/lossless.c @@ -577,9 +577,6 @@ extern void VP8LDspInitNEON(void); extern void VP8LDspInitMIPSdspR2(void); extern void VP8LDspInitMSA(void); -static volatile VP8CPUInfo lossless_last_cpuinfo_used = - (VP8CPUInfo)&lossless_last_cpuinfo_used; - #define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ (OUT)[0] = IN##0_C; \ (OUT)[1] = IN##1_C; \ @@ -599,9 +596,7 @@ static volatile VP8CPUInfo lossless_last_cpuinfo_used = (OUT)[15] = IN##0_C; \ } while (0); -WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { - if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8LDspInit) { COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors) COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C) COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) @@ -658,8 +653,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { assert(VP8LConvertBGRAToRGB565 != NULL); assert(VP8LMapColor32b != NULL); assert(VP8LMapColor8b != NULL); - - lossless_last_cpuinfo_used = VP8GetCPUInfo; } #undef COPY_PREDICTOR_ARRAY diff --git a/src/dsp/lossless_enc.c b/src/dsp/lossless_enc.c index 92ca3c05..d608326f 100644 --- a/src/dsp/lossless_enc.c +++ b/src/dsp/lossless_enc.c @@ -863,12 +863,7 @@ extern void VP8LEncDspInitMIPS32(void); extern void VP8LEncDspInitMIPSdspR2(void); extern void VP8LEncDspInitMSA(void); -static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used = - (VP8CPUInfo)&lossless_enc_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { - if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8LEncDspInit) { VP8LDspInit(); #if !WEBP_NEON_OMIT_C_CODE @@ -1011,8 +1006,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { assert(VP8LPredictorsSub_C[13] != NULL); assert(VP8LPredictorsSub_C[14] != NULL); assert(VP8LPredictorsSub_C[15] != NULL); - - lossless_enc_last_cpuinfo_used = VP8GetCPUInfo; } //------------------------------------------------------------------------------ diff --git a/src/dsp/rescaler.c b/src/dsp/rescaler.c index 4b6b7834..f307d350 100644 --- a/src/dsp/rescaler.c +++ b/src/dsp/rescaler.c @@ -204,11 +204,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void); extern void WebPRescalerDspInitMSA(void); extern void WebPRescalerDspInitNEON(void); -static volatile VP8CPUInfo rescaler_last_cpuinfo_used = - (VP8CPUInfo)&rescaler_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { - if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return; +WEBP_DSP_INIT_FUNC(WebPRescalerDspInit) { #if !defined(WEBP_REDUCE_SIZE) #if !WEBP_NEON_OMIT_C_CODE WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C; @@ -253,5 +249,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { assert(WebPRescalerImportRowExpand != NULL); assert(WebPRescalerImportRowShrink != NULL); #endif // WEBP_REDUCE_SIZE - rescaler_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/ssim.c b/src/dsp/ssim.c index dc1b518a..989ce825 100644 --- a/src/dsp/ssim.c +++ b/src/dsp/ssim.c @@ -139,12 +139,7 @@ VP8AccumulateSSEFunc VP8AccumulateSSE; extern void VP8SSIMDspInitSSE2(void); -static volatile VP8CPUInfo ssim_last_cpuinfo_used = - (VP8CPUInfo)&ssim_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) { - if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(VP8SSIMDspInit) { #if !defined(WEBP_REDUCE_SIZE) VP8SSIMGetClipped = SSIMGetClipped_C; VP8SSIMGet = SSIMGet_C; @@ -161,6 +156,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) { } #endif } - - ssim_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/upsampling.c b/src/dsp/upsampling.c index ddfd1925..9b60da5b 100644 --- a/src/dsp/upsampling.c +++ b/src/dsp/upsampling.c @@ -219,12 +219,7 @@ extern void WebPInitYUV444ConvertersMIPSdspR2(void); extern void WebPInitYUV444ConvertersSSE2(void); extern void WebPInitYUV444ConvertersSSE41(void); -static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 = - (VP8CPUInfo)&upsampling_last_cpuinfo_used1; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) { - if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(WebPInitYUV444Converters) { WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C; WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C; WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C; @@ -254,7 +249,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) { } #endif } - upsampling_last_cpuinfo_used1 = VP8GetCPUInfo; } //------------------------------------------------------------------------------ @@ -266,12 +260,7 @@ extern void WebPInitUpsamplersNEON(void); extern void WebPInitUpsamplersMIPSdspR2(void); extern void WebPInitUpsamplersMSA(void); -static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 = - (VP8CPUInfo)&upsampling_last_cpuinfo_used2; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { - if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(WebPInitUpsamplers) { #ifdef FANCY_UPSAMPLING #if !WEBP_NEON_OMIT_C_CODE WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C; @@ -333,7 +322,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { #endif #endif // FANCY_UPSAMPLING - upsampling_last_cpuinfo_used2 = VP8GetCPUInfo; } //------------------------------------------------------------------------------ diff --git a/src/dsp/yuv.c b/src/dsp/yuv.c index 957d1d66..14e67fc2 100644 --- a/src/dsp/yuv.c +++ b/src/dsp/yuv.c @@ -75,12 +75,7 @@ extern void WebPInitSamplersSSE41(void); extern void WebPInitSamplersMIPS32(void); extern void WebPInitSamplersMIPSdspR2(void); -static volatile VP8CPUInfo yuv_last_cpuinfo_used = - (VP8CPUInfo)&yuv_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) { - if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(WebPInitSamplers) { WebPSamplers[MODE_RGB] = YuvToRgbRow; WebPSamplers[MODE_RGBA] = YuvToRgbaRow; WebPSamplers[MODE_BGR] = YuvToBgrRow; @@ -116,7 +111,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) { } #endif // WEBP_USE_MIPS_DSP_R2 } - yuv_last_cpuinfo_used = VP8GetCPUInfo; } //----------------------------------------------------------------------------- @@ -260,18 +254,13 @@ void (*WebPSharpYUVUpdateRGB)(const int16_t* ref, const int16_t* src, void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len, const uint16_t* best_y, uint16_t* out); -static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used = - (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used; - extern void WebPInitConvertARGBToYUVSSE2(void); extern void WebPInitConvertARGBToYUVSSE41(void); extern void WebPInitConvertARGBToYUVNEON(void); extern void WebPInitSharpYUVSSE2(void); extern void WebPInitSharpYUVNEON(void); -WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { - if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - +WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) { WebPConvertARGBToY = ConvertARGBToY_C; WebPConvertARGBToUV = WebPConvertARGBToUV_C; @@ -316,6 +305,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { assert(WebPSharpYUVUpdateY != NULL); assert(WebPSharpYUVUpdateRGB != NULL); assert(WebPSharpYUVFilterRow != NULL); - - rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/enc/near_lossless_enc.c b/src/enc/near_lossless_enc.c index cadd14c6..5517a7e2 100644 --- a/src/enc/near_lossless_enc.c +++ b/src/enc/near_lossless_enc.c @@ -146,6 +146,6 @@ int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, // Define a stub to suppress compiler warnings. extern void VP8LNearLosslessStub(void); -WEBP_TSAN_IGNORE_FUNCTION void VP8LNearLosslessStub(void) {} +void VP8LNearLosslessStub(void) {} #endif // (WEBP_NEAR_LOSSLESS == 1) diff --git a/src/enc/picture_csp_enc.c b/src/enc/picture_csp_enc.c index d6dbae62..02d9df76 100644 --- a/src/enc/picture_csp_enc.c +++ b/src/enc/picture_csp_enc.c @@ -126,7 +126,7 @@ static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { #else -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {} +static void InitGammaTables(void) {} static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { return (int)(base_value << shift); @@ -238,7 +238,7 @@ static WEBP_INLINE uint32_t LinearToGammaS(uint32_t value) { #else -static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesS(void) {} +static void InitGammaTablesS(void) {} static WEBP_INLINE uint32_t GammaToLinearS(int v) { return (v << GAMMA_TO_LINEAR_BITS) / MAX_Y_T; }