Skip to content

Commit 142afde

Browse files
[libc] rework mutex (#92168)
1 parent d337c50 commit 142afde

File tree

26 files changed

+404
-118
lines changed

26 files changed

+404
-118
lines changed

libc/config/config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,15 @@
4040
"value": true,
4141
"doc": "Enable -fstack-protector-strong to defend against stack smashing attack."
4242
}
43+
},
44+
"pthread": {
45+
"LIBC_CONF_TIMEOUT_ENSURE_MONOTONICITY": {
46+
"value": true,
47+
"doc": "Automatically adjust timeout to CLOCK_MONOTONIC (default to true). POSIX API may require CLOCK_REALTIME, which can be unstable and leading to unexpected behavior. This option will convert the real-time timestamp to monotonic timestamp relative to the time of call."
48+
},
49+
"LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT": {
50+
"value": 100,
51+
"doc": "Default number of spins before blocking if a mutex is in contention (default to 100)."
52+
}
4353
}
4454
}

libc/docs/configure.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ to learn about the defaults for your platform and target.
3434
- ``LIBC_CONF_PRINTF_DISABLE_INDEX_MODE``: Disable index mode in the printf format string.
3535
- ``LIBC_CONF_PRINTF_DISABLE_WRITE_INT``: Disable handling of %n in printf format string.
3636
- ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE``: Use large table for better printf long double performance.
37+
* **"pthread" options**
38+
- ``LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT``: Default number of spins before blocking if a mutex is in contention (default to 100).
39+
- ``LIBC_CONF_TIMEOUT_ENSURE_MONOTONICITY``: Automatically adjust timeout to CLOCK_MONOTONIC (default to true). POSIX API may require CLOCK_REALTIME, which can be unstable and leading to unexpected behavior. This option will convert the real-time timestamp to monotonic timestamp relative to the time of call.
3740
* **"string" options**
3841
- ``LIBC_CONF_MEMSET_X86_USE_SOFTWARE_PREFETCHING``: Inserts prefetch for write instructions (PREFETCHW) for memset on x86 to recover performance when hardware prefetcher is disabled.
3942
- ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen.

libc/hdr/types/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,12 @@ add_proxy_header_library(
108108
libc.include.llvm-libc-types.struct_timeval
109109
libc.include.sys_time
110110
)
111+
112+
add_proxy_header_library(
113+
pid_t
114+
HDRS
115+
pid_t.h
116+
FULL_BUILD_DEPENDS
117+
libc.include.llvm-libc-types.pid_t
118+
libc.include.sys_types
119+
)

libc/hdr/types/pid_t.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Proxy for pid_t ---------------------------------------------------===//
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+
9+
#ifndef LLVM_LIBC_HDR_TYPES_PID_T_H
10+
#define LLVM_LIBC_HDR_TYPES_PID_T_H
11+
12+
#ifdef LIBC_FULL_BUILD
13+
14+
#include "include/llvm-libc-types/pid_t.h"
15+
16+
#else // Overlay mode
17+
18+
#include <sys/types.h>
19+
20+
#endif // LLVM_LIBC_FULL_BUILD
21+
22+
#endif // LLVM_LIBC_HDR_TYPES_PID_T_H

libc/include/llvm-libc-types/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ add_header(__call_once_func_t HDR __call_once_func_t.h)
77
add_header(__exec_argv_t HDR __exec_argv_t.h)
88
add_header(__exec_envp_t HDR __exec_envp_t.h)
99
add_header(__futex_word HDR __futex_word.h)
10-
add_header(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word)
10+
add_header(pid_t HDR pid_t.h)
11+
add_header(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word .pid_t)
1112
add_header(__pthread_once_func_t HDR __pthread_once_func_t.h)
1213
add_header(__pthread_start_t HDR __pthread_start_t.h)
1314
add_header(__pthread_tss_dtor_t HDR __pthread_tss_dtor_t.h)
@@ -20,7 +21,7 @@ add_header(blksize_t HDR blksize_t.h)
2021
add_header(cc_t HDR cc_t.h)
2122
add_header(clock_t HDR clock_t.h)
2223
add_header(clockid_t HDR clockid_t.h)
23-
add_header(cnd_t HDR cnd_t.h)
24+
add_header(cnd_t HDR cnd_t.h DEPENDS .__futex_word)
2425
add_header(cookie_io_functions_t HDR cookie_io_functions_t.h DEPENDS .off64_t .ssize_t)
2526
add_header(cpu_set_t HDR cpu_set_t.h)
2627
add_header(double_t HDR double_t.h)
@@ -45,7 +46,6 @@ add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type)
4546
add_header(nlink_t HDR nlink_t.h)
4647
add_header(off_t HDR off_t.h)
4748
add_header(once_flag HDR once_flag.h DEPENDS .__futex_word)
48-
add_header(pid_t HDR pid_t.h)
4949
add_header(posix_spawn_file_actions_t HDR posix_spawn_file_actions_t.h)
5050
add_header(posix_spawnattr_t HDR posix_spawnattr_t.h)
5151
add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_t)

libc/include/llvm-libc-types/cnd_t.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
#ifndef LLVM_LIBC_TYPES_CND_T_H
1010
#define LLVM_LIBC_TYPES_CND_T_H
1111

12-
#include "mtx_t.h"
12+
#include "llvm-libc-types/__futex_word.h"
1313

1414
typedef struct {
1515
void *__qfront;
1616
void *__qback;
17-
mtx_t __qmtx;
17+
__futex_word __qmtx;
1818
} cnd_t;
1919

2020
#endif // LLVM_LIBC_TYPES_CND_T_H

libc/src/__support/File/dir.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,16 @@ class Dir {
5050
// A directory is to be opened by the static method open and closed
5151
// by the close method. So, all constructors and destructor are declared
5252
// as private. Inappropriate constructors are declared as deleted.
53-
Dir() = delete;
54-
Dir(const Dir &) = delete;
53+
LIBC_INLINE Dir() = delete;
54+
LIBC_INLINE Dir(const Dir &) = delete;
5555

56-
explicit Dir(int fdesc)
57-
: fd(fdesc), readptr(0), fillsize(0), mutex(false, false, false) {}
58-
~Dir() = default;
56+
LIBC_INLINE explicit Dir(int fdesc)
57+
: fd(fdesc), readptr(0), fillsize(0),
58+
mutex(/*timed=*/false, /*recursive=*/false, /*robust=*/false,
59+
/*pshared=*/false) {}
60+
LIBC_INLINE ~Dir() = default;
5961

60-
Dir &operator=(const Dir &) = delete;
62+
LIBC_INLINE Dir &operator=(const Dir &) = delete;
6163

6264
public:
6365
static ErrorOr<Dir *> open(const char *path);
@@ -69,7 +71,7 @@ class Dir {
6971
// cleaned up.
7072
int close();
7173

72-
int getfd() { return fd; }
74+
LIBC_INLINE int getfd() { return fd; }
7375
};
7476

7577
} // namespace LIBC_NAMESPACE

libc/src/__support/File/file.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,11 @@ class File {
154154
uint8_t *buffer, size_t buffer_size, int buffer_mode,
155155
bool owned, ModeFlags modeflags)
156156
: platform_write(wf), platform_read(rf), platform_seek(sf),
157-
platform_close(cf), mutex(false, false, false), ungetc_buf(0),
158-
buf(buffer), bufsize(buffer_size), bufmode(buffer_mode), own_buf(owned),
159-
mode(modeflags), pos(0), prev_op(FileOp::NONE), read_limit(0),
160-
eof(false), err(false) {
157+
platform_close(cf), mutex(/*timed=*/false, /*recursive=*/false,
158+
/*robust=*/false, /*pshared=*/false),
159+
ungetc_buf(0), buf(buffer), bufsize(buffer_size), bufmode(buffer_mode),
160+
own_buf(owned), mode(modeflags), pos(0), prev_op(FileOp::NONE),
161+
read_limit(0), eof(false), err(false) {
161162
adjust_buf();
162163
}
163164

libc/src/__support/threads/CndVar.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
#define LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_CNDVAR_H
1111

1212
#include "src/__support/threads/linux/futex_utils.h" // Futex
13+
#include "src/__support/threads/linux/raw_mutex.h" // RawMutex
1314
#include "src/__support/threads/mutex.h" // Mutex
1415

1516
#include <stdint.h> // uint32_t
1617

1718
namespace LIBC_NAMESPACE {
1819

19-
struct CndVar {
20+
class CndVar {
2021
enum CndWaiterStatus : uint32_t {
2122
WS_Waiting = 0xE,
2223
WS_Signalled = 0x5,
@@ -29,15 +30,16 @@ struct CndVar {
2930

3031
CndWaiter *waitq_front;
3132
CndWaiter *waitq_back;
32-
Mutex qmtx;
33+
RawMutex qmtx;
3334

34-
static int init(CndVar *cv) {
35+
public:
36+
LIBC_INLINE static int init(CndVar *cv) {
3537
cv->waitq_front = cv->waitq_back = nullptr;
36-
auto err = Mutex::init(&cv->qmtx, false, false, false);
37-
return err == MutexError::NONE ? 0 : -1;
38+
RawMutex::init(&cv->qmtx);
39+
return 0;
3840
}
3941

40-
static void destroy(CndVar *cv) {
42+
LIBC_INLINE static void destroy(CndVar *cv) {
4143
cv->waitq_front = cv->waitq_back = nullptr;
4244
}
4345

libc/src/__support/threads/fork_callbacks.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ class AtForkCallbackManager {
3333
size_t next_index;
3434

3535
public:
36-
constexpr AtForkCallbackManager() : mtx(false, false, false), next_index(0) {}
36+
constexpr AtForkCallbackManager()
37+
: mtx(/*timed=*/false, /*recursive=*/false, /*robust=*/false,
38+
/*pshared=*/false),
39+
next_index(0) {}
3740

3841
bool register_triple(const ForkCallbackTriple &triple) {
3942
cpp::lock_guard lock(mtx);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE {
1919
/// define the Mutex interface and require that only a single thread executes
2020
/// code requiring a mutex lock.
2121
struct Mutex {
22-
LIBC_INLINE constexpr Mutex(bool, bool, bool) {}
22+
LIBC_INLINE constexpr Mutex(bool, bool, bool, bool) {}
2323

2424
LIBC_INLINE MutexError lock() { return MutexError::NONE; }
2525
LIBC_INLINE MutexError unlock() { return MutexError::NONE; }

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,37 @@ add_header_library(
2222
libc.src.__support.time.linux.abs_timeout
2323
)
2424

25+
set(raw_mutex_additional_flags)
26+
if (LIBC_CONF_TIMEOUT_ENSURE_MONOTONICITY)
27+
set(raw_mutex_additional_flags -DLIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY=1)
28+
else()
29+
set(raw_mutex_additional_flags -DLIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY=0)
30+
endif()
31+
32+
add_header_library(
33+
raw_mutex
34+
HDRS
35+
mutex.h
36+
DEPENDS
37+
.futex_utils
38+
libc.src.__support.threads.sleep
39+
libc.src.__support.time.linux.abs_timeout
40+
libc.src.__support.time.linux.monotonicity
41+
libc.src.__support.CPP.optional
42+
libc.hdr.types.pid_t
43+
COMPILE_OPTIONS
44+
-DLIBC_COPT_RAW_MUTEX_DEFAULT_SPIN_COUNT=${LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT}
45+
${raw_mutex_additional_flags}
46+
47+
)
48+
2549
add_header_library(
2650
mutex
2751
HDRS
2852
mutex.h
2953
DEPENDS
3054
.futex_utils
55+
.raw_mutex
3156
libc.src.__support.threads.mutex_common
3257
)
3358

@@ -75,5 +100,6 @@ add_object_library(
75100
libc.src.__support.OSUtil.osutil
76101
libc.src.__support.threads.linux.futex_word_type
77102
libc.src.__support.threads.mutex
103+
libc.src.__support.threads.linux.raw_mutex
78104
libc.src.__support.CPP.mutex
79105
)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "src/__support/CPP/mutex.h"
1111
#include "src/__support/OSUtil/syscall.h" // syscall_impl
1212
#include "src/__support/threads/linux/futex_word.h" // FutexWordType
13+
#include "src/__support/threads/linux/raw_mutex.h" // RawMutex
1314
#include "src/__support/threads/mutex.h" // Mutex
1415

1516
#include <sys/syscall.h> // For syscall numbers.
@@ -74,11 +75,11 @@ void CndVar::notify_one() {
7475
if (waitq_front == nullptr)
7576
waitq_back = nullptr;
7677

77-
qmtx.futex_word = FutexWordType(Mutex::LockState::Free);
78+
qmtx.reset();
7879

7980
// this is a special WAKE_OP, so we use syscall directly
8081
LIBC_NAMESPACE::syscall_impl<long>(
81-
FUTEX_SYSCALL_ID, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1,
82+
FUTEX_SYSCALL_ID, &qmtx.get_raw_futex(), FUTEX_WAKE_OP, 1, 1,
8283
&first->futex_word.val,
8384
FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting));
8485
}

0 commit comments

Comments
 (0)