Skip to content

Commit b8f4f39

Browse files
[libc] avoid cmpxchg on the fastpath of callonce (#91748)
Avoid `cmpxchg` operation if the function has already been called. The destination operand of `cmpxchg` may receive a write cycle without regard to the result of the comparison
1 parent 023cdfc commit b8f4f39

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/__support/threads/callonce.h"
10+
#include "src/__support/macros/optimization.h"
1011
#include "src/__support/threads/linux/futex_utils.h"
1112

1213
namespace LIBC_NAMESPACE {
@@ -21,6 +22,12 @@ int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
2122

2223
FutexWordType not_called = NOT_CALLED;
2324

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+
2431
// The call_once call can return only after the called function |func|
2532
// returns. So, we use futexes to synchronize calls with the same flag value.
2633
if (futex_word->compare_exchange_strong(not_called, START)) {

0 commit comments

Comments
 (0)