Skip to content

Commit 7df151b

Browse files
committed
CDRIVER-4215 use legacy atomic built-ins on gcc (>= 4.1, < 4.9)
1 parent a33c4f9 commit 7df151b

File tree

1 file changed

+73
-5
lines changed

1 file changed

+73
-5
lines changed

src/libbson/src/bson/bson-atomic.h

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,42 +47,68 @@ enum bson_memory_order {
4747
#define MSVC_MEMORDER_SUFFIX(X)
4848
#endif
4949

50+
#if defined(USE_LEGACY_GCC_ATOMICS) || (!defined(__clang__) && \
51+
__GNUC__ == 4 && __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 9)
52+
#define BSON_USE_LEGACY_GCC_ATOMICS
53+
#else
54+
#undef BSON_USE_LEGACY_GCC_ATOMICS
55+
#endif
56+
57+
#ifdef BSON_USE_LEGACY_GCC_ATOMICS
58+
#undef BSON_IF_GNU_LIKE
59+
#define BSON_IF_GNU_LIKE(...)
60+
#define BSON_IF_GNU_LEGACY_ATOMICS(...) __VA_ARGS__
61+
#else
62+
#define BSON_IF_GNU_LEGACY_ATOMICS(...)
63+
#endif
5064

51-
#define DEF_ATOMIC_OP(MSVC_Intrinsic, GNU_Intrinsic, Order, ...) \
65+
#define DEF_ATOMIC_OP(MSVC_Intrinsic, GNU_Intrinsic, GNU_Legacy_Intrinsic, Order, ...) \
5266
do { \
5367
switch (Order) { \
5468
case bson_memory_order_acq_rel: \
5569
BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
5670
BSON_IF_GNU_LIKE ( \
5771
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQ_REL);) \
72+
BSON_IF_GNU_LEGACY_ATOMICS ( \
73+
return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
5874
case bson_memory_order_seq_cst: \
5975
BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
6076
BSON_IF_GNU_LIKE ( \
6177
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_SEQ_CST);) \
78+
BSON_IF_GNU_LEGACY_ATOMICS ( \
79+
return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
6280
case bson_memory_order_acquire: \
6381
BSON_IF_MSVC ( \
6482
return BSON_CONCAT (MSVC_Intrinsic, \
6583
MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
6684
BSON_IF_GNU_LIKE ( \
6785
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQUIRE);) \
86+
BSON_IF_GNU_LEGACY_ATOMICS ( \
87+
return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
6888
case bson_memory_order_consume: \
6989
BSON_IF_MSVC ( \
7090
return BSON_CONCAT (MSVC_Intrinsic, \
7191
MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
7292
BSON_IF_GNU_LIKE ( \
7393
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_CONSUME);) \
94+
BSON_IF_GNU_LEGACY_ATOMICS ( \
95+
return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
7496
case bson_memory_order_release: \
7597
BSON_IF_MSVC ( \
7698
return BSON_CONCAT (MSVC_Intrinsic, \
7799
MSVC_MEMORDER_SUFFIX (_rel)) (__VA_ARGS__);) \
78100
BSON_IF_GNU_LIKE ( \
79101
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELEASE);) \
102+
BSON_IF_GNU_LEGACY_ATOMICS ( \
103+
return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
80104
case bson_memory_order_relaxed: \
81105
BSON_IF_MSVC ( \
82106
return BSON_CONCAT (MSVC_Intrinsic, \
83107
MSVC_MEMORDER_SUFFIX (_nf)) (__VA_ARGS__);) \
84108
BSON_IF_GNU_LIKE ( \
85109
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELAXED);) \
110+
BSON_IF_GNU_LEGACY_ATOMICS ( \
111+
return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
86112
default: \
87113
BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
88114
} \
@@ -102,6 +128,12 @@ enum bson_memory_order {
102128
false, /* Not weak */ \
103129
GNU_MemOrder, \
104130
GNU_MemOrder);) \
131+
BSON_IF_GNU_LEGACY_ATOMICS ( \
132+
__typeof__ (ExpectActualVar) _val; \
133+
_val = __sync_val_compare_and_swap (Ptr, \
134+
ExpectActualVar, \
135+
NewValue); \
136+
ExpectActualVar = _val;) \
105137
} while (0)
106138

107139

@@ -118,6 +150,12 @@ enum bson_memory_order {
118150
true, /* Yes weak */ \
119151
GNU_MemOrder, \
120152
GNU_MemOrder);) \
153+
BSON_IF_GNU_LEGACY_ATOMICS ( \
154+
__typeof__ (ExpectActualVar) _val; \
155+
_val = __sync_val_compare_and_swap (Ptr, \
156+
ExpectActualVar, \
157+
NewValue); \
158+
ExpectActualVar = _val;) \
121159
} while (0)
122160

123161

@@ -127,6 +165,7 @@ enum bson_memory_order {
127165
{ \
128166
DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchangeAdd, VCIntrinSuffix), \
129167
__atomic_fetch_add, \
168+
__sync_fetch_and_add, \
130169
ord, \
131170
a, \
132171
addend); \
@@ -139,7 +178,9 @@ enum bson_memory_order {
139178
BSON_IF_MSVC ( \
140179
return bson_atomic_##NamePart##_fetch_add (a, -subtrahend, ord);) \
141180
BSON_IF_GNU_LIKE ( \
142-
DEF_ATOMIC_OP (~, __atomic_fetch_sub, ord, a, subtrahend);) \
181+
DEF_ATOMIC_OP (~, __atomic_fetch_sub, ~, ord, a, subtrahend);) \
182+
BSON_IF_GNU_LEGACY_ATOMICS ( \
183+
DEF_ATOMIC_OP (~, ~, __sync_fetch_and_sub, ord, a, subtrahend);) \
143184
} \
144185
\
145186
static BSON_INLINE Type bson_atomic_##NamePart##_fetch ( \
@@ -164,13 +205,15 @@ enum bson_memory_order {
164205
default: \
165206
BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
166207
}) \
208+
BSON_IF_GNU_LEGACY_ATOMICS ({ __sync_synchronize (); return *a; }) \
167209
} \
168210
\
169211
static BSON_INLINE Type bson_atomic_##NamePart##_exchange ( \
170212
Type volatile *a, Type value, enum bson_memory_order ord) \
171213
{ \
172214
BSON_IF_MSVC ( \
173215
DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchange, VCIntrinSuffix), \
216+
~, \
174217
~, \
175218
ord, \
176219
a, \
@@ -192,6 +235,8 @@ enum bson_memory_order {
192235
default: \
193236
BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
194237
}) \
238+
BSON_IF_GNU_LEGACY_ATOMICS ( \
239+
return __sync_val_compare_and_swap (a, *a, value);) \
195240
} \
196241
\
197242
static BSON_INLINE Type bson_atomic_##NamePart##_compare_exchange_strong ( \
@@ -285,7 +330,7 @@ enum bson_memory_order {
285330
#define DECL_ATOMIC_STDINT(Name, VCSuffix) \
286331
DECL_ATOMIC_INTEGRAL (Name, Name##_t, VCSuffix)
287332

288-
#ifdef _MSC_VER
333+
#if defined(_MSC_VER) || defined (BSON_USE_LEGACY_GCC_ATOMICS)
289334
/* MSVC expects precise types for their atomic intrinsics. */
290335
DECL_ATOMIC_INTEGRAL (int8, char, 8);
291336
DECL_ATOMIC_INTEGRAL (int16, short, 16)
@@ -388,8 +433,23 @@ bson_atomic_ptr_exchange (void *volatile *ptr,
388433
void *new_value,
389434
enum bson_memory_order ord)
390435
{
391-
DEF_ATOMIC_OP (
392-
_InterlockedExchangePointer, __atomic_exchange_n, ord, ptr, new_value);
436+
/* The older __sync_val_compare_and_swap also takes oldval */
437+
#if defined(BSON_USE_LEGACY_GCC_ATOMICS)
438+
DEF_ATOMIC_OP (_InterlockedExchangePointer,
439+
,
440+
__sync_val_compare_and_swap,
441+
ord,
442+
ptr,
443+
*ptr,
444+
new_value);
445+
#else
446+
DEF_ATOMIC_OP (_InterlockedExchangePointer,
447+
__atomic_exchange_n,
448+
,
449+
ord,
450+
ptr,
451+
new_value);
452+
#endif
393453
}
394454

395455
static BSON_INLINE void *
@@ -500,8 +560,16 @@ bson_atomic_thread_fence ()
500560
{
501561
BSON_IF_MSVC (MemoryBarrier ();)
502562
BSON_IF_GNU_LIKE (__sync_synchronize ();)
563+
BSON_IF_GNU_LEGACY_ATOMICS (__sync_synchronize ();)
503564
}
504565

566+
#ifdef BSON_USE_LEGACY_GCC_ATOMICS
567+
#undef BSON_IF_GNU_LIKE
568+
#define BSON_IF_GNU_LIKE(...) __VA_ARGS__
569+
#endif
570+
#undef BSON_IF_GNU_LEGACY_ATOMICS
571+
#undef BSON_USE_LEGACY_GCC_ATOMICS
572+
505573
BSON_GNUC_DEPRECATED_FOR ("bson_atomic_thread_fence")
506574
BSON_EXPORT (void) bson_memory_barrier (void);
507575

0 commit comments

Comments
 (0)