Use InterlockedExchange() for changing the dtoa_CS_init variable to ensure
that new value would be immediately visible in all threads.
In dtoa_unlock() wait until the dtoa_CS_init leaves the initializing (1)
state. This can happen when dtoa_CS_init is in uninitialized (0) state and
two threads in parallel calls the dtoa_lock() function followed by
dtoa_unlock() call. Both threads changes the dtoa_CS_init to the
initializing (1) state, and one thread can do it even when the dtoa_CS_init
was already in the initialized (2) state.
---
mingw-w64-crt/gdtoa/misc.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/mingw-w64-crt/gdtoa/misc.c b/mingw-w64-crt/gdtoa/misc.c
index adc955ec0cbf..6716392d33fe 100644
--- a/mingw-w64-crt/gdtoa/misc.c
+++ b/mingw-w64-crt/gdtoa/misc.c
@@ -82,10 +82,10 @@ static void dtoa_lock (unsigned int n)
for (i = 0; i < NLOCKS; i++)
InitializeCriticalSection (&dtoa_CritSec[i]);
atexit (dtoa_lock_cleanup);
- dtoa_CS_init = 2;
+ (void)InterlockedExchange (&dtoa_CS_init, 2);
}
else if (2 == last_CS_init)
- dtoa_CS_init = 2;
+ (void)InterlockedExchange (&dtoa_CS_init, 2);
}
/* Another thread is initializing. Wait. */
while (1 == dtoa_CS_init)
@@ -98,6 +98,8 @@ static void dtoa_lock (unsigned int n)
static void dtoa_unlock (unsigned int n)
{
+ while (1 == dtoa_CS_init)
+ Sleep (1);
if (2 == dtoa_CS_init)
LeaveCriticalSection (&dtoa_CritSec[n]);
}
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public