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

Reply via email to