Skip to content

Commit e2623e8

Browse files
committed
[libc] Add Darwin mutex support via os_sync primitives
This patch implements the generic mutex and raw_mutex interfaces on macOS. A new Futex class is provided that relies on os_sync_wait and os_sync_wake to emulate futex‑like wait and wake semantics. The OS‑specific part is moved into futex_utils, which now contains the Darwin implementation.
1 parent 6780c7f commit e2623e8

File tree

8 files changed

+127
-29
lines changed

8 files changed

+127
-29
lines changed

libc/src/__support/threads/CMakeLists.txt

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,36 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2323
add_subdirectory(${LIBC_TARGET_OS})
2424
endif()
2525

26-
if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex)
26+
if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.futex_utils)
2727
add_header_library(
2828
mutex
2929
HDRS
30-
mutex.h
30+
mutex.h
31+
DEPENDS
32+
.unix_mutex
33+
)
34+
add_header_library(
35+
unix_mutex
36+
HDRS
37+
unix_mutex.h
38+
DEPENDS
39+
.raw_mutex
40+
)
41+
42+
add_header_library(
43+
raw_mutex
44+
HDRS
45+
raw_mutex.h
3146
DEPENDS
32-
.${LIBC_TARGET_OS}.mutex
47+
.${LIBC_TARGET_OS}.futex_utils
48+
libc.src.__support.threads.sleep
49+
libc.src.__support.time.abs_timeout
50+
libc.src.__support.time.monotonicity
51+
libc.src.__support.CPP.optional
52+
libc.hdr.types.pid_t
53+
COMPILE_OPTIONS
54+
-DLIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT=${LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT}
55+
${monotonicity_flags}
3356
)
3457

3558
add_object_library(

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ if(NOT TARGET libc.src.__support.OSUtil.osutil)
33
endif()
44

55
add_header_library(
6-
mutex
6+
futex_utils
77
HDRS
8-
mutex.h
8+
futex_utils.h
99
DEPENDS
10+
libc.include.sys_syscall
11+
libc.src.__support.OSUtil.osutil
12+
libc.src.__support.CPP.atomic
13+
libc.src.__support.CPP.limits
14+
libc.src.__support.CPP.optional
1015
libc.src.__support.threads.mutex_common
1116
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===--- Futex utils for Darwin -----------------------------------*- C++
2+
//-*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H
11+
#define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H
12+
13+
#include "src/__support/CPP/atomic.h"
14+
#include "src/__support/CPP/optional.h"
15+
#include "src/__support/time/abs_timeout.h"
16+
#include "src/__support/time/clock_conversion.h"
17+
18+
#include <os/os_sync_wait_on_address.h>
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
22+
using FutexWordType = uint32_t;
23+
24+
struct Futex : public cpp::Atomic<FutexWordType> {
25+
using cpp::Atomic<FutexWordType>::Atomic;
26+
using Timeout = internal::AbsTimeout;
27+
28+
// The Darwin futex API does not return a value on timeout, so we have to
29+
// check for it manually. This means we can't use the return value to
30+
// distinguish between a timeout and a successful wake-up.
31+
int wait(FutexWordType val, cpp::optional<Timeout> timeout, bool) {
32+
if (timeout) {
33+
struct timespec now;
34+
clock_gettime(timeout->is_realtime() ? CLOCK_REALTIME : CLOCK_MONOTONIC,
35+
&now);
36+
const timespec &target_ts = timeout->get_timespec();
37+
38+
if (now.tv_sec > target_ts.tv_sec ||
39+
(now.tv_sec == target_ts.tv_sec && now.tv_nsec >= target_ts.tv_nsec))
40+
return ETIMEDOUT;
41+
}
42+
43+
os_sync_wait_on_address(reinterpret_cast<void *>(this),
44+
static_cast<uint64_t>(val), sizeof(FutexWordType),
45+
OS_SYNC_WAIT_ON_ADDRESS_NONE);
46+
return 0;
47+
}
48+
49+
void notify_one(bool) {
50+
os_sync_wake_by_address_any(reinterpret_cast<void *>(this),
51+
sizeof(FutexWordType),
52+
OS_SYNC_WAKE_BY_ADDRESS_NONE);
53+
}
54+
55+
void notify_all(bool) {
56+
// os_sync_wake_by_address_all is not available, so we use notify_one.
57+
// This is not ideal, but it's the best we can do with the available API.
58+
os_sync_wake_by_address_any(reinterpret_cast<void *>(this),
59+
sizeof(FutexWordType),
60+
OS_SYNC_WAKE_BY_ADDRESS_NONE);
61+
}
62+
};
63+
64+
} // namespace LIBC_NAMESPACE_DECL
65+
66+
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_FUTEX_UTILS_H

libc/src/__support/threads/darwin/mutex.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
//===--- Implementation of a Darwin mutex class ------------------*- C++
2-
//-*-===//
1+
//===--- Implementation of a Darwin mutex class -----------*- C++-*-===//
32
//
43
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
54
// See https://llvm.org/LICENSE.txt for license information.
65
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
76
//
8-
//===----------------------------------------------------------------------===//
7+
//===---------------------------------------------------------------===//
98

109
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H
1110
#define LLVM_LIBC_SRC___SUPPORT_THREADS_DARWIN_MUTEX_H

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ add_header_library(
2121
libc.src.__support.CPP.atomic
2222
libc.src.__support.CPP.limits
2323
libc.src.__support.CPP.optional
24-
libc.src.__support.time.linux.abs_timeout
24+
libc.src.__support.time.abs_timeout
2525
)
2626

2727
set(monotonicity_flags)
@@ -38,8 +38,8 @@ add_header_library(
3838
DEPENDS
3939
.futex_utils
4040
libc.src.__support.threads.sleep
41-
libc.src.__support.time.linux.abs_timeout
42-
libc.src.__support.time.linux.monotonicity
41+
libc.src.__support.time.abs_timeout
42+
libc.src.__support.time.monotonicity
4343
libc.src.__support.CPP.optional
4444
libc.hdr.types.pid_t
4545
COMPILE_OPTIONS

libc/src/__support/threads/mutex.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@
4040
// few global locks. So, to avoid static initialization order fiasco, we
4141
// want the constructors of the Mutex classes to be constexprs.
4242

43-
#if defined(__linux__)
44-
#include "src/__support/threads/linux/mutex.h"
45-
#elif defined(__APPLE__)
46-
#include "src/__support/threads/darwin/mutex.h"
43+
#if defined(__linux__) || defined(__APPLE__)
44+
#include "src/__support/threads/unix_mutex.h"
4745
#endif
4846

4947
#elif LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE

libc/src/__support/threads/linux/raw_mutex.h renamed to libc/src/__support/threads/raw_mutex.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
1-
//===--- Implementation of a Linux RawMutex class ---------------*- C++ -*-===//
1+
//===--- Implementation of the RawMutex class ---------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
7-
//===----------------------------------------------------------------------===//
8-
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_RAW_MUTEX_H
9-
#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_RAW_MUTEX_H
7+
//===------------------------------------------------------------------===//
8+
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H
9+
#define LLVM_LIBC_SRC___SUPPORT_THREADS_RAW_MUTEX_H
1010

1111
#include "src/__support/CPP/optional.h"
1212
#include "src/__support/common.h"
1313
#include "src/__support/libc_assert.h"
1414
#include "src/__support/macros/attributes.h"
1515
#include "src/__support/macros/config.h"
1616
#include "src/__support/macros/optimization.h"
17-
#include "src/__support/threads/linux/futex_utils.h"
18-
#include "src/__support/threads/linux/futex_word.h"
1917
#include "src/__support/threads/sleep.h"
2018
#include "src/__support/time/abs_timeout.h"
19+
#include "sys/errno.h"
20+
21+
#if defined(__linux__)
22+
#include "src/__support/threads/linux/futex_utils.h"
23+
#elif defined(__APPLE__)
24+
#include "src/__support/threads/darwin/futex_utils.h"
25+
#endif
2126

2227
#ifndef LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY
2328
#define LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY 1
2429
#endif
2530

31+
// TODO(bojle): check this for darwin impl
2632
#if LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY
27-
#include "src/__support/time/linux/monotonicity.h"
33+
#include "src/__support/time/monotonicity.h"
2834
#endif
2935

3036
#ifndef LIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT
@@ -93,7 +99,9 @@ class RawMutex {
9399
LIBC_INLINE void wake(bool is_pshared) { futex.notify_one(is_pshared); }
94100

95101
public:
96-
LIBC_INLINE static void init(RawMutex *mutex) { mutex->futex = UNLOCKED; }
102+
LIBC_INLINE static void init(RawMutex *mutex) {
103+
mutex->futex.store(UNLOCKED);
104+
}
97105
LIBC_INLINE constexpr RawMutex() : futex(UNLOCKED) {}
98106
[[nodiscard]] LIBC_INLINE bool try_lock() {
99107
FutexWordType expected = UNLOCKED;
@@ -122,7 +130,7 @@ class RawMutex {
122130
LIBC_ASSERT(lock->futex == UNLOCKED && "Mutex destroyed while used.");
123131
}
124132
LIBC_INLINE Futex &get_raw_futex() { return futex; }
125-
LIBC_INLINE void reset() { futex = UNLOCKED; }
133+
LIBC_INLINE void reset() { futex.store(UNLOCKED); }
126134
};
127135
} // namespace LIBC_NAMESPACE_DECL
128136

libc/src/__support/threads/linux/mutex.h renamed to libc/src/__support/threads/unix_mutex.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
//===--- Implementation of a Linux mutex class ------------------*- C++ -*-===//
1+
//===--- Implementation of a Unix mutex class ------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
10-
#define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
9+
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_UNIX_MUTEX_H
10+
#define LLVM_LIBC_SRC___SUPPORT_THREADS_UNIX_MUTEX_H
1111

1212
#include "hdr/types/pid_t.h"
1313
#include "src/__support/CPP/optional.h"
1414
#include "src/__support/libc_assert.h"
1515
#include "src/__support/macros/config.h"
16-
#include "src/__support/threads/linux/futex_utils.h"
17-
#include "src/__support/threads/linux/raw_mutex.h"
1816
#include "src/__support/threads/mutex_common.h"
17+
#include "src/__support/threads/raw_mutex.h"
1918

2019
namespace LIBC_NAMESPACE_DECL {
2120

0 commit comments

Comments
 (0)