@@ -23,12 +23,20 @@ using namespace swift;
23
23
24
24
#ifdef __APPLE__
25
25
26
- // On OS X and iOS, swift_once is implemented using GCD.
26
+ // On macOS and iOS, swift_once is implemented using GCD.
27
+ // The compiler emits an inline check matching the barrier-free inline fast
28
+ // path of dispatch_once(). See SwiftTargetInfo.OnceDonePredicateValue.
27
29
28
30
#include < dispatch/dispatch.h>
29
31
static_assert (std::is_same<swift_once_t , dispatch_once_t >::value,
30
32
" swift_once_t and dispatch_once_t must stay in sync" );
33
+ #else
34
+
35
+ // On non-Darwin platforms we do not assume any barrier-free inline path
36
+ // and SwiftTargetInfo.OnceDonePredicateValue is unset in the compiler.
37
+
31
38
#endif
39
+
32
40
// The compiler generates the swift_once_t values as word-sized zero-initialized
33
41
// variables, so we want to make sure swift_once_t isn't larger than the
34
42
// platform word or the function below might overwrite something it shouldn't.
@@ -44,14 +52,6 @@ void swift::swift_once(swift_once_t *predicate, void (*fn)(void *)) {
44
52
#elif defined(__CYGWIN__)
45
53
_swift_once_f (predicate, nullptr , fn);
46
54
#else
47
- // FIXME: We're relying here on the coincidence that libstdc++ uses pthread's
48
- // pthread_once, and that on glibc pthread_once follows a compatible init
49
- // process (the token is a word that is atomically incremented from 0 to
50
- // 1 to 2 during initialization) to work. We should implement our own version
51
- // that we can rely on to continue to work that way.
52
- // The MSVC port also relies on this, because the std::call_once on MSVC
53
- // follows the compatible init process.
54
- // For more information, see rdar://problem/18499385
55
55
std::call_once (*predicate, [fn]() { fn (nullptr ); });
56
56
#endif
57
57
}
0 commit comments