Skip to content

Commit 301db3d

Browse files
[libc] add simplified tid cache (#101620)
According to discussions on monthly meeting, we probably don't want to cache `getpid` anymore. glibc removes their cache. bionic is hesitating whether such cache is to be removed. `getpid` is async-signal-safe, so we must make sure it always work. However, for `gettid`, we have more freedom. Moreover, we are using `gettid` to examine deadlock such that the performance penalty is not negligible here. Thus, this patch is separated from previous patch to provide only `tid` caching. It is much more simplified. Hopefully, previous build issues can be resolved easily.
1 parent 982cfae commit 301db3d

File tree

16 files changed

+170
-9
lines changed

16 files changed

+170
-9
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ set(TARGET_LIBC_ENTRYPOINTS
299299
libc.src.unistd.geteuid
300300
libc.src.unistd.getpid
301301
libc.src.unistd.getppid
302+
libc.src.unistd.gettid
302303
libc.src.unistd.getuid
303304
libc.src.unistd.isatty
304305
libc.src.unistd.link

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ set(TARGET_LIBC_ENTRYPOINTS
318318
libc.src.unistd.geteuid
319319
libc.src.unistd.getpid
320320
libc.src.unistd.getppid
321+
libc.src.unistd.gettid
321322
libc.src.unistd.getuid
322323
libc.src.unistd.isatty
323324
libc.src.unistd.link

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ set(TARGET_LIBC_ENTRYPOINTS
318318
libc.src.unistd.geteuid
319319
libc.src.unistd.getpid
320320
libc.src.unistd.getppid
321+
libc.src.unistd.gettid
321322
libc.src.unistd.getuid
322323
libc.src.unistd.isatty
323324
libc.src.unistd.link

libc/newhdrgen/yaml/unistd.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,9 @@ functions:
307307
- type: const void *__restrict
308308
- type: void *
309309
- type: ssize_t
310+
- name: gettid
311+
standards:
312+
- Linux
313+
return_type: pid_t
314+
arguments:
315+
- type: void

libc/spec/posix.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,11 @@ def POSIX : StandardSpec<"POSIX"> {
546546
RetValSpec<PidT>,
547547
[ArgSpec<VoidType>]
548548
>,
549+
FunctionSpec<
550+
"gettid",
551+
RetValSpec<PidT>,
552+
[ArgSpec<VoidType>]
553+
>,
549554
FunctionSpec<
550555
"getuid",
551556
RetValSpec<UidT>,

libc/src/__support/threads/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,19 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.CndVar)
8989
.${LIBC_TARGET_OS}.CndVar
9090
)
9191
endif()
92+
93+
if (LLVM_LIBC_FULL_BUILD)
94+
set(identifier_dependency_on_thread libc.src.__support.threads.thread)
95+
endif()
96+
97+
add_header_library(
98+
identifier
99+
HDRS
100+
identifier.h
101+
DEPENDS
102+
libc.src.__support.OSUtil.osutil
103+
libc.src.__support.common
104+
libc.include.sys_syscall
105+
libc.hdr.types.pid_t
106+
${identifier_dependency_on_thread}
107+
)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===--- Thread Identifier Header --------------------------------*- C++-*-===//
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_SRC___SUPPORT_THREADS_IDENTIFIER_H
10+
#define LLVM_LIBC_SRC___SUPPORT_THREADS_IDENTIFIER_H
11+
12+
#ifdef LIBC_FULL_BUILD
13+
#include "src/__support/threads/thread.h"
14+
#endif // LIBC_FULL_BUILD
15+
16+
#include "hdr/types/pid_t.h"
17+
#include "src/__support/OSUtil/syscall.h"
18+
#include <sys/syscall.h>
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
namespace internal {
22+
23+
LIBC_INLINE pid_t *get_tid_cache() {
24+
#ifdef LIBC_FULL_BUILD
25+
return &self.attrib->tid;
26+
#else
27+
// in non-full build mode, we do not control the fork routine. Therefore,
28+
// we do not cache tid at all.
29+
return nullptr;
30+
#endif
31+
}
32+
33+
LIBC_INLINE pid_t gettid() {
34+
pid_t *cache = get_tid_cache();
35+
if (LIBC_UNLIKELY(!cache || *cache <= 0))
36+
return syscall_impl<pid_t>(SYS_gettid);
37+
return *cache;
38+
}
39+
40+
LIBC_INLINE void force_set_tid(pid_t tid) {
41+
pid_t *cache = get_tid_cache();
42+
if (cache)
43+
*cache = tid;
44+
}
45+
46+
} // namespace internal
47+
} // namespace LIBC_NAMESPACE_DECL
48+
49+
#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_IDENTIFIER_H

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ add_header_library(
5555
libc.src.__support.common
5656
libc.src.__support.OSUtil.osutil
5757
libc.src.__support.CPP.limits
58+
libc.src.__support.threads.identifier
5859
COMPILE_OPTIONS
5960
-DLIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT=${LIBC_CONF_RWLOCK_DEFAULT_SPIN_COUNT}
6061
${monotonicity_flags}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "src/__support/macros/attributes.h"
2020
#include "src/__support/macros/config.h"
2121
#include "src/__support/macros/optimization.h"
22+
#include "src/__support/threads/identifier.h"
2223
#include "src/__support/threads/linux/futex_utils.h"
2324
#include "src/__support/threads/linux/futex_word.h"
2425
#include "src/__support/threads/linux/raw_mutex.h"
@@ -336,8 +337,6 @@ class RwLock {
336337
LIBC_INLINE Role get_preference() const {
337338
return static_cast<Role>(preference);
338339
}
339-
// TODO: use cached thread id once implemented.
340-
LIBC_INLINE static pid_t gettid() { return syscall_impl<pid_t>(SYS_gettid); }
341340

342341
template <Role role> LIBC_INLINE LockResult try_lock(RwState &old) {
343342
if constexpr (role == Role::Reader) {
@@ -359,7 +358,7 @@ class RwLock {
359358
if (LIBC_LIKELY(old.compare_exchange_weak_with(
360359
state, old.set_writer_bit(), cpp::MemoryOrder::ACQUIRE,
361360
cpp::MemoryOrder::RELAXED))) {
362-
writer_tid.store(gettid(), cpp::MemoryOrder::RELAXED);
361+
writer_tid.store(internal::gettid(), cpp::MemoryOrder::RELAXED);
363362
return LockResult::Success;
364363
}
365364
// Notice that old is updated by the compare_exchange_weak_with
@@ -394,7 +393,7 @@ class RwLock {
394393
unsigned spin_count = LIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT) {
395394
// Phase 1: deadlock detection.
396395
// A deadlock happens if this is a RAW/WAW lock in the same thread.
397-
if (writer_tid.load(cpp::MemoryOrder::RELAXED) == gettid())
396+
if (writer_tid.load(cpp::MemoryOrder::RELAXED) == internal::gettid())
398397
return LockResult::Deadlock;
399398

400399
#if LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY
@@ -520,7 +519,7 @@ class RwLock {
520519
if (old.has_active_writer()) {
521520
// The lock is held by a writer.
522521
// Check if we are the owner of the lock.
523-
if (writer_tid.load(cpp::MemoryOrder::RELAXED) != gettid())
522+
if (writer_tid.load(cpp::MemoryOrder::RELAXED) != internal::gettid())
524523
return LockResult::PermissionDenied;
525524
// clear writer tid.
526525
writer_tid.store(0, cpp::MemoryOrder::RELAXED);

libc/src/unistd/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,13 @@ add_entrypoint_external(
333333
add_entrypoint_external(
334334
opterr
335335
)
336+
337+
add_entrypoint_object(
338+
gettid
339+
SRCS
340+
gettid.cpp
341+
HDRS
342+
gettid.h
343+
DEPENDS
344+
libc.src.__support.threads.identifier
345+
)

0 commit comments

Comments
 (0)