Skip to content

Commit a0cd4f8

Browse files
CDRIVER-4124 New atomics (#840)
* Additional atomic operations * Closes: CDRIVER-4124 * Update names to reflect C11 names, strong/weak cmpxchg * No 'consume' memorder for atomic exchange * Remove config checks for atomics * Set march=i686 for 32bit builds * CheckAtomics.cmake is gone * Use new atomics in the threadsafe-pool
1 parent 9a0ab6c commit a0cd4f8

File tree

15 files changed

+758
-253
lines changed

15 files changed

+758
-253
lines changed

.evergreen/config.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ functions:
483483
export OBSOLETE_TLS='${obsolete_tls}'
484484
export VALGRIND='${valgrind}'
485485
export ATLAS_SERVERLESS_SRV='${atlas_serverless_srv}'
486-
export ATLAS_SERVERLESS='${atlas_serverless}'
486+
export ATLAS_SERVERLESS='${atlas_serverless}
487487
sh .evergreen/run-auth-tests.sh
488488
run mock server tests:
489489
- command: shell.exec
@@ -26811,11 +26811,11 @@ buildvariants:
2681126811
- .3.4 .nossl
2681226812
- .3.2 .nossl
2681326813
- .3.0 .nossl .nosasl !.auth
26814-
- name: clang60-i386
26815-
display_name: clang 6.0 (i386) (Ubuntu 18.04)
26814+
- name: clang60-i686
26815+
display_name: clang 6.0 (i686) (Ubuntu 18.04)
2681626816
expansions:
2681726817
CC: clang
26818-
MARCH: i386
26818+
MARCH: i686
2681926819
run_on: ubuntu1804-test
2682026820
tasks:
2682126821
- debug-compile-scan-build
@@ -26829,11 +26829,11 @@ buildvariants:
2682926829
- .4.4 .nossl .nosasl
2683026830
- .4.2 .nossl .nosasl
2683126831
- .4.0 .nossl .nosasl
26832-
- name: clang38-i386
26833-
display_name: clang 3.8 (i386) (Ubuntu 16.04)
26832+
- name: clang38-i686
26833+
display_name: clang 3.8 (i686) (Ubuntu 16.04)
2683426834
expansions:
2683526835
CC: clang
26836-
MARCH: i386
26836+
MARCH: i686
2683726837
run_on: ubuntu1604-test
2683826838
tasks:
2683926839
- debug-compile-scan-build
@@ -26966,11 +26966,11 @@ buildvariants:
2696626966
- .latest .openssl !.nosasl .server
2696726967
- .latest .openssl-static !.nosasl .server
2696826968
- .latest .nossl
26969-
- name: gcc75-i386
26970-
display_name: GCC 7.5 (i386) (Ubuntu 18.04)
26969+
- name: gcc75-i686
26970+
display_name: GCC 7.5 (i686) (Ubuntu 18.04)
2697126971
expansions:
2697226972
CC: gcc
26973-
MARCH: i386
26973+
MARCH: i686
2697426974
run_on: ubuntu1804-test
2697526975
tasks:
2697626976
- debug-compile-coverage
@@ -27063,7 +27063,7 @@ buildvariants:
2706327063
- test-aws-openssl-regular-4.4
2706427064
- test-aws-openssl-regular-latest
2706527065
- name: windows-2017-32
27066-
display_name: Windows (i386) (VS 2017)
27066+
display_name: Windows (i686) (VS 2017)
2706727067
expansions:
2706827068
CC: Visual Studio 15 2017
2706927069
run_on: windows-64-vs2017-test
@@ -27121,7 +27121,7 @@ buildvariants:
2712127121
- .3.2 .winssl !.nosasl .server
2712227122
- .3.0 .nossl
2712327123
- name: windows-2015-32
27124-
display_name: Windows (i386) (VS 2015)
27124+
display_name: Windows (i686) (VS 2015)
2712527125
expansions:
2712627126
CC: Visual Studio 14 2015
2712727127
run_on: windows-64-vs2015-compile
@@ -27154,7 +27154,7 @@ buildvariants:
2715427154
- .4.2 .winssl !.nosasl .server !.client-side-encryption
2715527155
- .4.0 .winssl !.nosasl .server
2715627156
- name: windows-2013-32
27157-
display_name: Windows (i386) (VS 2013)
27157+
display_name: Windows (i686) (VS 2013)
2715827158
expansions:
2715927159
CC: Visual Studio 12 2013
2716027160
run_on: windows-64-vs2013-compile

build/evergreen_config_lib/variants.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ def days(n):
152152
'.3.2 .nossl',
153153
'.3.0 .nossl .nosasl !.auth'],
154154
{'CC': 'clang'}),
155-
Variant('clang60-i386',
156-
'clang 6.0 (i386) (Ubuntu 18.04)',
155+
Variant('clang60-i686',
156+
'clang 6.0 (i686) (Ubuntu 18.04)',
157157
'ubuntu1804-test',
158158
['debug-compile-scan-build',
159159
'release-compile',
@@ -166,9 +166,9 @@ def days(n):
166166
'.4.4 .nossl .nosasl',
167167
'.4.2 .nossl .nosasl',
168168
'.4.0 .nossl .nosasl'],
169-
{'CC': 'clang', 'MARCH': 'i386'}),
170-
Variant('clang38-i386',
171-
'clang 3.8 (i386) (Ubuntu 16.04)',
169+
{'CC': 'clang', 'MARCH': 'i686'}),
170+
Variant('clang38-i686',
171+
'clang 3.8 (i686) (Ubuntu 16.04)',
172172
'ubuntu1604-test',
173173
['debug-compile-scan-build',
174174
'release-compile',
@@ -177,7 +177,7 @@ def days(n):
177177
'.debug-compile .stdflags !.c89',
178178
'.debug-compile !.sspi .nossl .nosasl',
179179
'.3.6 .nossl .nosasl'],
180-
{'CC': 'clang', 'MARCH': 'i386'}),
180+
{'CC': 'clang', 'MARCH': 'i686'}),
181181
Variant('clang38ubuntu',
182182
'clang 3.8 (Ubuntu 16.04)',
183183
'ubuntu1604-test',
@@ -287,8 +287,8 @@ def days(n):
287287
'.latest .openssl-static !.nosasl .server',
288288
'.latest .nossl'],
289289
{'CC': 'gcc'}),
290-
Variant('gcc75-i386',
291-
'GCC 7.5 (i386) (Ubuntu 18.04)',
290+
Variant('gcc75-i686',
291+
'GCC 7.5 (i686) (Ubuntu 18.04)',
292292
'ubuntu1804-test',
293293
['debug-compile-coverage',
294294
'release-compile',
@@ -300,7 +300,7 @@ def days(n):
300300
'.4.4 .nossl .nosasl',
301301
'.4.2 .nossl .nosasl',
302302
'.4.0 .nossl .nosasl'],
303-
{'CC': 'gcc', 'MARCH': 'i386'}),
303+
{'CC': 'gcc', 'MARCH': 'i686'}),
304304
Variant('gcc75',
305305
'GCC 7.5 (Ubuntu 18.04)',
306306
'ubuntu1804-test',
@@ -379,7 +379,7 @@ def days(n):
379379
],
380380
{'CC': 'clang'}),
381381
Variant ('windows-2017-32',
382-
'Windows (i386) (VS 2017)',
382+
'Windows (i686) (VS 2017)',
383383
'windows-64-vs2017-test',
384384
['.debug-compile .winssl .nosasl',
385385
'.debug-compile !.sspi .nossl .nosasl',
@@ -433,7 +433,7 @@ def days(n):
433433
'.3.0 .nossl'],
434434
{'CC': 'Visual Studio 14 2015 Win64'}),
435435
Variant('windows-2015-32',
436-
'Windows (i386) (VS 2015)',
436+
'Windows (i686) (VS 2015)',
437437
'windows-64-vs2015-compile',
438438
['.compression !.snappy !.zstd !.latest',
439439
'release-compile',
@@ -463,7 +463,7 @@ def days(n):
463463
'.4.0 .winssl !.nosasl .server'],
464464
{'CC': 'Visual Studio 12 2013 Win64'}),
465465
Variant('windows-2013-32',
466-
'Windows (i386) (VS 2013)',
466+
'Windows (i686) (VS 2013)',
467467
'windows-64-vs2013-compile',
468468
['release-compile',
469469
'debug-compile-nosasl-nossl',

src/libbson/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ else ()
131131
set (BSON_BYTE_ORDER 1234)
132132
endif ()
133133

134-
include (CheckAtomics)
135-
136134
configure_file (
137135
"${PROJECT_SOURCE_DIR}/src/bson/bson-config.h.in"
138136
"${PROJECT_BINARY_DIR}/src/bson/bson-config.h"

src/libbson/build/cmake/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
set (src_libbson_build_cmake_MODULES
22
BSONPackage.cmake
3-
CheckAtomics.cmake
43
)
54

65
set (src_libbson_build_cmake_PKGCONFIG

src/libbson/build/cmake/CheckAtomics.cmake

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/libbson/src/bson/bson-atomic.c

Lines changed: 92 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,79 +17,123 @@
1717

1818
#include "bson-atomic.h"
1919

20+
#ifdef BSON_OS_UNIX
21+
/* For sched_yield() */
22+
#include <sched.h>
23+
#endif
2024

21-
/*
22-
* We should only ever hit these on non-Windows systems, for which we require
23-
* pthread support. Therefore, we will avoid making a threading portability
24-
* for threads here and just use pthreads directly.
25-
*/
25+
int32_t
26+
bson_atomic_int_add (volatile int32_t *p, int32_t n)
27+
{
28+
return n + bson_atomic_int32_fetch_add (p, n, bson_memory_order_seq_cst);
29+
}
2630

31+
int64_t
32+
bson_atomic_int64_add (volatile int64_t *p, int64_t n)
33+
{
34+
return n + bson_atomic_int64_fetch_add (p, n, bson_memory_order_seq_cst);
35+
}
36+
37+
void
38+
bson_thrd_yield (void)
39+
{
40+
BSON_IF_WINDOWS (SwitchToThread ();)
41+
BSON_IF_POSIX (sched_yield ();)
42+
}
2743

28-
#ifdef __BSON_NEED_BARRIER
29-
#include <pthread.h>
30-
static pthread_mutex_t gBarrier = PTHREAD_MUTEX_INITIALIZER;
3144
void
3245
bson_memory_barrier (void)
3346
{
34-
pthread_mutex_lock (&gBarrier);
35-
pthread_mutex_unlock (&gBarrier);
47+
bson_atomic_thread_fence ();
3648
}
37-
#endif
3849

50+
/**
51+
* 32-bit x86 does not support 64-bit atomic integer operations.
52+
* We emulate that here using a spin lock and regular arithmetic operations
53+
*/
54+
static int g64bitAtomicLock = 0;
3955

40-
#ifdef __BSON_NEED_ATOMIC_32
41-
#include <pthread.h>
42-
static pthread_mutex_t gSync32 = PTHREAD_MUTEX_INITIALIZER;
43-
int32_t
44-
bson_atomic_int_add (volatile int32_t *p, int32_t n)
56+
static void
57+
_lock_64bit_atomic ()
4558
{
46-
int ret;
59+
int i;
60+
if (bson_atomic_int_compare_exchange_weak (
61+
&g64bitAtomicLock, 0, 1, bson_memory_order_acquire) == 0) {
62+
/* Successfully took the spinlock */
63+
return;
64+
}
65+
/* Failed. Try taking ten more times, then begin sleeping. */
66+
for (i = 0; i < 10; ++i) {
67+
if (bson_atomic_int_compare_exchange_weak (
68+
&g64bitAtomicLock, 0, 1, bson_memory_order_acquire) == 0) {
69+
/* Succeeded in taking the lock */
70+
return;
71+
}
72+
}
73+
/* Still don't have the lock. Spin and yield */
74+
while (bson_atomic_int_compare_exchange_weak (
75+
&g64bitAtomicLock, 0, 1, bson_memory_order_acquire) != 0) {
76+
bson_thrd_yield ();
77+
}
78+
}
4779

48-
pthread_mutex_lock (&gSync32);
49-
*p += n;
50-
ret = *p;
51-
pthread_mutex_unlock (&gSync32);
80+
static void
81+
_unlock_64bit_atomic ()
82+
{
83+
int64_t rv = bson_atomic_int_exchange (
84+
&g64bitAtomicLock, 0, bson_memory_order_release);
85+
BSON_ASSERT (rv == 1 && "Released atomic lock while not holding it");
86+
}
5287

88+
int64_t
89+
_bson_emul_atomic_int64_fetch_add (volatile int64_t *p,
90+
int64_t n,
91+
enum bson_memory_order _unused)
92+
{
93+
int64_t ret;
94+
_lock_64bit_atomic ();
95+
ret = *p;
96+
*p += n;
97+
_unlock_64bit_atomic ();
5398
return ret;
5499
}
55-
#endif
56-
57100

58-
#ifdef __BSON_NEED_ATOMIC_64
59-
#include <pthread.h>
60-
static pthread_mutex_t gSync64 = PTHREAD_MUTEX_INITIALIZER;
61101
int64_t
62-
bson_atomic_int64_add (volatile int64_t *p, int64_t n)
102+
_bson_emul_atomic_int64_exchange (volatile int64_t *p,
103+
int64_t n,
104+
enum bson_memory_order _unused)
63105
{
64106
int64_t ret;
65-
66-
pthread_mutex_lock (&gSync64);
67-
*p += n;
107+
_lock_64bit_atomic ();
68108
ret = *p;
69-
pthread_mutex_unlock (&gSync64);
70-
109+
*p = n;
110+
_unlock_64bit_atomic ();
71111
return ret;
72112
}
73-
#endif
74-
75113

76-
/*
77-
* The logic in the header is such that __BSON_NEED_ATOMIC_WINDOWS should only
78-
* be defined if neither __BSON_NEED_ATOMIC_32 nor __BSON_NEED_ATOMIC_64 are.
79-
*/
80-
81-
82-
#ifdef __BSON_NEED_ATOMIC_WINDOWS
83-
int32_t
84-
bson_atomic_int_add (volatile int32_t *p, int32_t n)
114+
int64_t
115+
_bson_emul_atomic_int64_compare_exchange_strong (volatile int64_t *p,
116+
int64_t expect_value,
117+
int64_t new_value,
118+
enum bson_memory_order _unused)
85119
{
86-
return InterlockedExchangeAdd (p, n) + n;
120+
int64_t ret;
121+
_lock_64bit_atomic ();
122+
ret = *p;
123+
if (ret == expect_value) {
124+
*p = new_value;
125+
}
126+
_unlock_64bit_atomic ();
127+
return ret;
87128
}
88129

89-
90130
int64_t
91-
bson_atomic_int64_add (volatile int64_t *p, int64_t n)
131+
_bson_emul_atomic_int64_compare_exchange_weak (volatile int64_t *p,
132+
int64_t expect_value,
133+
int64_t new_value,
134+
enum bson_memory_order order)
92135
{
93-
return InterlockedExchangeAdd (p, n) + n;
136+
/* We're emulating. We can't do a weak version. */
137+
return _bson_emul_atomic_int64_compare_exchange_strong (
138+
p, expect_value, new_value, order);
94139
}
95-
#endif

0 commit comments

Comments
 (0)