Skip to content

Commit 22cdfea

Browse files
make callonce a header library
1 parent 80c4958 commit 22cdfea

File tree

3 files changed

+26
-43
lines changed

3 files changed

+26
-43
lines changed

libc/src/__support/threads/linux/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,8 @@ add_object_library(
9797
# value other than 0 is dangerous. We know.
9898
)
9999

100-
add_object_library(
100+
add_header_library(
101101
callonce
102-
SRCS
103-
callonce.cpp
104102
HDRS
105103
../callonce.h
106104
callonce.h

libc/src/__support/threads/linux/callonce.cpp

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

libc/src/__support/threads/linux/callonce.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,31 @@ static constexpr FutexWordType FINISH = 0x33;
2626
LIBC_INLINE bool callonce_fastpath(CallOnceFlag *flag) {
2727
return flag->load(cpp::MemoryOrder::RELAXED) == FINISH;
2828
}
29+
30+
[[gnu::noinline]]
31+
LIBC_INLINE int callonce_slowpath(CallOnceFlag *flag, void (*func)(void)) {
32+
auto *futex_word = reinterpret_cast<Futex *>(flag);
33+
34+
FutexWordType not_called = NOT_CALLED;
35+
36+
// The call_once call can return only after the called function |func|
37+
// returns. So, we use futexes to synchronize calls with the same flag value.
38+
if (futex_word->compare_exchange_strong(not_called, START)) {
39+
func();
40+
auto status = futex_word->exchange(FINISH);
41+
if (status == WAITING)
42+
futex_word->notify_all();
43+
return 0;
44+
}
45+
46+
FutexWordType status = START;
47+
if (futex_word->compare_exchange_strong(status, WAITING) ||
48+
status == WAITING) {
49+
futex_word->wait(WAITING);
50+
}
51+
52+
return 0;
53+
}
2954
} // namespace callonce_impl
3055

3156
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)