This is a followup to '[PATCH] crt: gdtoa: Fix race conditions during initialization of dtoa lock'.
From 3d94cfd3408dd11fce3bc6c2384522517f8b6f2d Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Mon, 14 Sep 2026 11:19:15 +0800 Subject: [PATCH] crt: gdtoa: Eliminate a race condition on `dtoa_CS_init` When a thread saw `dtoa_CS_init == 0`, it was possible that another thread got scheduled and completed initialization, so `dtoa_CS_init` became 2; and then the current thread did `last_CS_init = InterlockedExchange (&dtoa_CS_init, 1)` and saw `last_CS_init == 2` and restored it with `InterlockedExchange (&dtoa_CS_init, 2)`. The value of `dtoa_CS_init` went from 2 to 1 to 2, which was an ABA pattern. The other thread which actually completed initialization should only call `EnterCriticalSection(&dtoa_CritSec[n])` when it saw `dtoa_CS_init == 2`. In the middle of this ABA sequence, the call might get missed. The fix is to update `dtoa_CS_init` to 1 with a CAS from 0 so it will not be updated from anything else. The update to 2 is idempotent. Signed-off-by: LIU Hao <[email protected]> --- mingw-w64-crt/gdtoa/misc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mingw-w64-crt/gdtoa/misc.c b/mingw-w64-crt/gdtoa/misc.c index 6716392d3..74a2ca605 100644 --- a/mingw-w64-crt/gdtoa/misc.c +++ b/mingw-w64-crt/gdtoa/misc.c @@ -76,16 +76,13 @@ static void dtoa_lock (unsigned int n) return; } else if (0 == dtoa_CS_init) { - long last_CS_init = InterlockedExchange (&dtoa_CS_init, 1); - if (0 == last_CS_init) { + if (0 == InterlockedCompareExchange (&dtoa_CS_init, 1, 0)) { int i; for (i = 0; i < NLOCKS; i++) InitializeCriticalSection (&dtoa_CritSec[i]); atexit (dtoa_lock_cleanup); (void)InterlockedExchange (&dtoa_CS_init, 2); } - else if (2 == last_CS_init) - (void)InterlockedExchange (&dtoa_CS_init, 2); } /* Another thread is initializing. Wait. */ while (1 == dtoa_CS_init) @@ -98,8 +95,6 @@ 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.55.0
From 3d94cfd3408dd11fce3bc6c2384522517f8b6f2d Mon Sep 17 00:00:00 2001 From: LIU Hao <[email protected]> Date: Mon, 14 Sep 2026 11:19:15 +0800 Subject: [PATCH] crt: gdtoa: Eliminate a race condition on `dtoa_CS_init` When a thread saw `dtoa_CS_init == 0`, it was possible that another thread got scheduled and completed initialization, so `dtoa_CS_init` became 2; and then the current thread did `last_CS_init = InterlockedExchange (&dtoa_CS_init, 1)` and saw `last_CS_init == 2` and restored it with `InterlockedExchange (&dtoa_CS_init, 2)`. The value of `dtoa_CS_init` went from 2 to 1 to 2, which was an ABA pattern. The other thread which actually completed initialization should only call `EnterCriticalSection(&dtoa_CritSec[n])` when it saw `dtoa_CS_init == 2`. In the middle of this ABA sequence, the call might get missed. The fix is to update `dtoa_CS_init` to 1 with a CAS from 0 so it will not be updated from anything else. The update to 2 is idempotent. Signed-off-by: LIU Hao <[email protected]> --- mingw-w64-crt/gdtoa/misc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mingw-w64-crt/gdtoa/misc.c b/mingw-w64-crt/gdtoa/misc.c index 6716392d3..74a2ca605 100644 --- a/mingw-w64-crt/gdtoa/misc.c +++ b/mingw-w64-crt/gdtoa/misc.c @@ -76,16 +76,13 @@ static void dtoa_lock (unsigned int n) return; } else if (0 == dtoa_CS_init) { - long last_CS_init = InterlockedExchange (&dtoa_CS_init, 1); - if (0 == last_CS_init) { + if (0 == InterlockedCompareExchange (&dtoa_CS_init, 1, 0)) { int i; for (i = 0; i < NLOCKS; i++) InitializeCriticalSection (&dtoa_CritSec[i]); atexit (dtoa_lock_cleanup); (void)InterlockedExchange (&dtoa_CS_init, 2); } - else if (2 == last_CS_init) - (void)InterlockedExchange (&dtoa_CS_init, 2); } /* Another thread is initializing. Wait. */ while (1 == dtoa_CS_init) @@ -98,8 +95,6 @@ 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.55.0
OpenPGP_signature.asc
Description: OpenPGP digital signature
_______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
