Skip to content

Commit 6d61d83

Browse files
[libc] inline fast path of callonce (#96226)
Split from #91572 --------- Co-authored-by: Nick Desaulniers (paternity leave) <[email protected]>
1 parent 2fefc04 commit 6d61d83

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

libc/src/__support/threads/callonce.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,32 @@
99
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
1010
#define LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H
1111

12+
#include "src/__support/macros/optimization.h" // LIBC_LIKELY
13+
14+
// Plaform specific routines, provides:
15+
// - OnceFlag definition
16+
// - callonce_impl::callonce_fastpath for fast path check
17+
// - callonce_impl::callonce_slowpath for slow path execution
18+
#ifdef __linux__
19+
#include "src/__support/threads/linux/callonce.h"
20+
#else
21+
#error "callonce is not supported on this platform"
22+
#endif
23+
1224
namespace LIBC_NAMESPACE {
1325

14-
struct CallOnceFlag;
26+
// Common definitions
1527
using CallOnceCallback = void(void);
28+
namespace callonce_impl {
29+
int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *callback);
30+
} // namespace callonce_impl
1631

17-
int callonce(CallOnceFlag *flag, CallOnceCallback *callback);
32+
LIBC_INLINE int callonce(CallOnceFlag *flag, CallOnceCallback *callback) {
33+
if (LIBC_LIKELY(callonce_impl::callonce_fastpath(flag)))
34+
return 0;
1835

36+
return callonce_impl::callonce_slowpath(flag, callback);
37+
}
1938
} // namespace LIBC_NAMESPACE
2039

2140
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_CALLONCE_H

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ add_object_library(
100100
callonce.cpp
101101
HDRS
102102
../callonce.h
103+
callonce.h
103104
DEPENDS
104105
.futex_utils
106+
libc.src.__support.macros.optimization
105107
)
106108

107109
add_object_library(

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

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,16 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/__support/threads/callonce.h"
10-
#include "src/__support/macros/optimization.h"
10+
#include "src/__support/threads/linux/callonce.h"
1111
#include "src/__support/threads/linux/futex_utils.h"
1212

1313
namespace LIBC_NAMESPACE {
14-
15-
static constexpr FutexWordType NOT_CALLED = 0x0;
16-
static constexpr FutexWordType START = 0x11;
17-
static constexpr FutexWordType WAITING = 0x22;
18-
static constexpr FutexWordType FINISH = 0x33;
19-
20-
int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
14+
namespace callonce_impl {
15+
int callonce_slowpath(CallOnceFlag *flag, CallOnceCallback *func) {
2116
auto *futex_word = reinterpret_cast<Futex *>(flag);
2217

2318
FutexWordType not_called = NOT_CALLED;
2419

25-
// Avoid cmpxchg operation if the function has already been called.
26-
// The destination operand of cmpxchg may receive a write cycle without
27-
// regard to the result of the comparison
28-
if (LIBC_LIKELY(futex_word->load(cpp::MemoryOrder::RELAXED) == FINISH))
29-
return 0;
30-
3120
// The call_once call can return only after the called function |func|
3221
// returns. So, we use futexes to synchronize calls with the same flag value.
3322
if (futex_word->compare_exchange_strong(not_called, START)) {
@@ -46,5 +35,5 @@ int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
4635

4736
return 0;
4837
}
49-
38+
} // namespace callonce_impl
5039
} // namespace LIBC_NAMESPACE
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===-- Linux callonce fastpath -------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_CALLONCE_H
9+
#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_CALLONCE_H
10+
11+
#include "src/__support/threads/linux/futex_utils.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
using CallOnceFlag = Futex;
15+
16+
namespace callonce_impl {
17+
static constexpr FutexWordType NOT_CALLED = 0x0;
18+
static constexpr FutexWordType START = 0x11;
19+
static constexpr FutexWordType WAITING = 0x22;
20+
static constexpr FutexWordType FINISH = 0x33;
21+
22+
// Avoid cmpxchg operation if the function has already been called.
23+
// The destination operand of cmpxchg may receive a write cycle without
24+
// regard to the result of the comparison.
25+
LIBC_INLINE bool callonce_fastpath(CallOnceFlag *flag) {
26+
return flag->load(cpp::MemoryOrder::RELAXED) == FINISH;
27+
}
28+
} // namespace callonce_impl
29+
30+
} // namespace LIBC_NAMESPACE
31+
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_CALLONCE_H

0 commit comments

Comments
 (0)