diff options
author | Kévin Petit <kpet@free.fr> | 2023-08-19 11:15:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-19 11:15:17 +0100 |
commit | 0702f2ecee4b250818a7fe289508ef9c54c1b48e (patch) | |
tree | 6278f0c4127ae1ad75326972a27a96221ad9d352 | |
parent | df53e02a12453340f418c8544291e7b3c08e3aa5 (diff) | |
download | OpenCL-CTS-0702f2ecee4b250818a7fe289508ef9c54c1b48e.tar.gz |
Make genrand_int32 thread safe (#1797)
The initialisation code is clearly meant to be run once but the volatile
flag did not guarantee that at all:
- Volatile does not mean atomic and loading the flag vs. other writes
was not safe.
- Multiple threads could have loaded 0 and performed the initialisation
resulting in write collisions.
Rely on std::call_once to provide the guarantee.
This issue was flagged by TSAN.
Signed-off-by: Kévin Petit <kpet@free.fr>
-rw-r--r-- | test_common/harness/mt19937.cpp | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/test_common/harness/mt19937.cpp b/test_common/harness/mt19937.cpp index f5665deb..2d503eb5 100644 --- a/test_common/harness/mt19937.cpp +++ b/test_common/harness/mt19937.cpp @@ -51,6 +51,7 @@ #include "harness/alloc.h" #ifdef __SSE2__ +#include <mutex> #include <emmintrin.h> #endif @@ -107,7 +108,7 @@ cl_uint genrand_int32(MTdata d) /* mag01[x] = x * MATRIX_A for x=0,1 */ static const cl_uint mag01[2] = { 0x0UL, MATRIX_A }; #ifdef __SSE2__ - static volatile int init = 0; + static std::once_flag init_flag; static union { __m128i v; cl_uint s[4]; @@ -123,8 +124,7 @@ cl_uint genrand_int32(MTdata d) int kk; #ifdef __SSE2__ - if (0 == init) - { + auto init_fn = []() { upper_mask.s[0] = upper_mask.s[1] = upper_mask.s[2] = upper_mask.s[3] = UPPER_MASK; lower_mask.s[0] = lower_mask.s[1] = lower_mask.s[2] = @@ -134,8 +134,8 @@ cl_uint genrand_int32(MTdata d) MATRIX_A; c0.s[0] = c0.s[1] = c0.s[2] = c0.s[3] = (cl_uint)0x9d2c5680UL; c1.s[0] = c1.s[1] = c1.s[2] = c1.s[3] = (cl_uint)0xefc60000UL; - init = 1; - } + }; + std::call_once(init_flag, init_fn); #endif kk = 0; |