Skip to content

Commit 35342db

Browse files
Copilotithewei
andauthored
Fix Windows atomic ops to return pre-operation value (match Linux/C11 semantics) (#812)
* Initial plan * fix: use InterlockedExchangeAdd for Windows atomic ops to return old value Replace InterlockedAdd/InterlockedIncrement/InterlockedDecrement with InterlockedExchangeAdd which returns the value before the operation, matching the behavior of __sync_fetch_and_add (GCC) and atomic_fetch_add (C11). Also fix ATOMIC_SUB macro parenthesization: -(n) instead of -n. Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com> * fix: prefer GCC builtins over Interlocked for MinGW compatibility Reorder #ifdef checks so GCC-based compilers (including MinGW) use __sync_fetch_and_add builtins via a direct __GNUC__ version check, instead of relying on __GNUC_PREREQ which is broken on MinGW. Only pure MSVC now uses InterlockedExchangeAdd for atomic operations. This completely avoids any MinGW compatibility concerns with Windows Interlocked functions. Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
1 parent 85d1265 commit 35342db

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

base/hatomic.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,30 @@ typedef volatile size_t atomic_size_t;
4444

4545
typedef struct atomic_flag { atomic_long _Value; } atomic_flag;
4646

47-
#ifdef _WIN32
47+
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
4848

4949
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
5050
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
51-
// return InterlockedIncrement((LONG*)&p->_Value, 1);
52-
return InterlockedCompareExchange(&p->_Value, 1, 0);
51+
return !__sync_bool_compare_and_swap(&p->_Value, 0, 1);
5352
}
5453

55-
#define ATOMIC_ADD InterlockedAdd
56-
#define ATOMIC_SUB(p, n) InterlockedAdd(p, -n)
57-
#define ATOMIC_INC InterlockedIncrement
58-
#define ATOMIC_DEC InterlockedDecrement
54+
#define ATOMIC_ADD __sync_fetch_and_add
55+
#define ATOMIC_SUB __sync_fetch_and_sub
56+
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
57+
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)
5958

60-
#elif __GNUC_PREREQ(4, 1)
59+
#elif defined(_WIN32)
6160

6261
#define ATOMIC_FLAG_TEST_AND_SET atomic_flag_test_and_set
6362
static inline bool atomic_flag_test_and_set(atomic_flag* p) {
64-
return !__sync_bool_compare_and_swap(&p->_Value, 0, 1);
63+
// return InterlockedIncrement((LONG*)&p->_Value, 1);
64+
return InterlockedCompareExchange(&p->_Value, 1, 0);
6565
}
6666

67-
#define ATOMIC_ADD __sync_fetch_and_add
68-
#define ATOMIC_SUB __sync_fetch_and_sub
69-
#define ATOMIC_INC(p) ATOMIC_ADD(p, 1)
70-
#define ATOMIC_DEC(p) ATOMIC_SUB(p, 1)
67+
#define ATOMIC_ADD InterlockedExchangeAdd
68+
#define ATOMIC_SUB(p, n) InterlockedExchangeAdd(p, -(n))
69+
#define ATOMIC_INC(p) InterlockedExchangeAdd(p, 1)
70+
#define ATOMIC_DEC(p) InterlockedExchangeAdd(p, -1)
7171

7272
#endif
7373

0 commit comments

Comments
 (0)