@@ -47,42 +47,68 @@ enum bson_memory_order {
47
47
#define MSVC_MEMORDER_SUFFIX (X )
48
48
#endif
49
49
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
50
64
51
- #define DEF_ATOMIC_OP (MSVC_Intrinsic , GNU_Intrinsic , Order , ...) \
65
+ #define DEF_ATOMIC_OP (MSVC_Intrinsic , GNU_Intrinsic , GNU_Legacy_Intrinsic , Order , ...) \
52
66
do { \
53
67
switch (Order) { \
54
68
case bson_memory_order_acq_rel: \
55
69
BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
56
70
BSON_IF_GNU_LIKE ( \
57
71
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQ_REL);) \
72
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
73
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
58
74
case bson_memory_order_seq_cst: \
59
75
BSON_IF_MSVC (return MSVC_Intrinsic (__VA_ARGS__);) \
60
76
BSON_IF_GNU_LIKE ( \
61
77
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_SEQ_CST);) \
78
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
79
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
62
80
case bson_memory_order_acquire: \
63
81
BSON_IF_MSVC ( \
64
82
return BSON_CONCAT (MSVC_Intrinsic, \
65
83
MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
66
84
BSON_IF_GNU_LIKE ( \
67
85
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_ACQUIRE);) \
86
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
87
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
68
88
case bson_memory_order_consume: \
69
89
BSON_IF_MSVC ( \
70
90
return BSON_CONCAT (MSVC_Intrinsic, \
71
91
MSVC_MEMORDER_SUFFIX (_acq)) (__VA_ARGS__);) \
72
92
BSON_IF_GNU_LIKE ( \
73
93
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_CONSUME);) \
94
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
95
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
74
96
case bson_memory_order_release: \
75
97
BSON_IF_MSVC ( \
76
98
return BSON_CONCAT (MSVC_Intrinsic, \
77
99
MSVC_MEMORDER_SUFFIX (_rel)) (__VA_ARGS__);) \
78
100
BSON_IF_GNU_LIKE ( \
79
101
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELEASE);) \
102
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
103
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
80
104
case bson_memory_order_relaxed: \
81
105
BSON_IF_MSVC ( \
82
106
return BSON_CONCAT (MSVC_Intrinsic, \
83
107
MSVC_MEMORDER_SUFFIX (_nf)) (__VA_ARGS__);) \
84
108
BSON_IF_GNU_LIKE ( \
85
109
return GNU_Intrinsic (__VA_ARGS__, __ATOMIC_RELAXED);) \
110
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
111
+ return GNU_Legacy_Intrinsic (__VA_ARGS__);) \
86
112
default: \
87
113
BSON_UNREACHABLE ("Invalid bson_memory_order value"); \
88
114
} \
@@ -102,6 +128,12 @@ enum bson_memory_order {
102
128
false, /* Not weak */ \
103
129
GNU_MemOrder , \
104
130
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 ;) \
105
137
} while (0 )
106
138
107
139
@@ -118,6 +150,12 @@ enum bson_memory_order {
118
150
true, /* Yes weak */ \
119
151
GNU_MemOrder , \
120
152
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 ;) \
121
159
} while (0 )
122
160
123
161
@@ -127,6 +165,7 @@ enum bson_memory_order {
127
165
{ \
128
166
DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchangeAdd, VCIntrinSuffix), \
129
167
__atomic_fetch_add, \
168
+ __sync_fetch_and_add, \
130
169
ord, \
131
170
a, \
132
171
addend); \
@@ -139,7 +178,9 @@ enum bson_memory_order {
139
178
BSON_IF_MSVC ( \
140
179
return bson_atomic_ ##NamePart ##_fetch_add (a, -subtrahend, ord);) \
141
180
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);) \
143
184
} \
144
185
\
145
186
static BSON_INLINE Type bson_atomic_##NamePart##_fetch ( \
@@ -164,13 +205,15 @@ enum bson_memory_order {
164
205
default : \
165
206
BSON_UNREACHABLE ("Invalid bson_memory_order value" ); \
166
207
}) \
208
+ BSON_IF_GNU_LEGACY_ATOMICS ({ __sync_synchronize (); return * a ; }) \
167
209
} \
168
210
\
169
211
static BSON_INLINE Type bson_atomic_ ##NamePart ##_exchange ( \
170
212
Type volatile *a, Type value, enum bson_memory_order ord) \
171
213
{ \
172
214
BSON_IF_MSVC ( \
173
215
DEF_ATOMIC_OP (BSON_CONCAT (_InterlockedExchange, VCIntrinSuffix), \
216
+ ~, \
174
217
~, \
175
218
ord, \
176
219
a, \
@@ -192,6 +235,8 @@ enum bson_memory_order {
192
235
default : \
193
236
BSON_UNREACHABLE ("Invalid bson_memory_order value" ); \
194
237
}) \
238
+ BSON_IF_GNU_LEGACY_ATOMICS ( \
239
+ return __sync_val_compare_and_swap (a , * a , value );) \
195
240
} \
196
241
\
197
242
static BSON_INLINE Type bson_atomic_ ##NamePart ##_compare_exchange_strong ( \
@@ -285,7 +330,7 @@ enum bson_memory_order {
285
330
#define DECL_ATOMIC_STDINT (Name , VCSuffix ) \
286
331
DECL_ATOMIC_INTEGRAL (Name, Name##_t, VCSuffix)
287
332
288
- #ifdef _MSC_VER
333
+ #if defined( _MSC_VER ) || defined ( BSON_USE_LEGACY_GCC_ATOMICS )
289
334
/* MSVC expects precise types for their atomic intrinsics. */
290
335
DECL_ATOMIC_INTEGRAL (int8 , char , 8 );
291
336
DECL_ATOMIC_INTEGRAL (int16 , short , 16 )
@@ -388,8 +433,23 @@ bson_atomic_ptr_exchange (void *volatile *ptr,
388
433
void * new_value ,
389
434
enum bson_memory_order ord )
390
435
{
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
393
453
}
394
454
395
455
static BSON_INLINE void *
@@ -500,8 +560,16 @@ bson_atomic_thread_fence ()
500
560
{
501
561
BSON_IF_MSVC (MemoryBarrier ();)
502
562
BSON_IF_GNU_LIKE (__sync_synchronize ();)
563
+ BSON_IF_GNU_LEGACY_ATOMICS (__sync_synchronize ();)
503
564
}
504
565
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
+
505
573
BSON_GNUC_DEPRECATED_FOR ("bson_atomic_thread_fence" )
506
574
BSON_EXPORT (void ) bson_memory_barrier (void );
507
575
0 commit comments