Skip to content

Commit 5c9fc3c

Browse files
[libc] implement cached process/thread identity (#98989)
migrated from #95965 due to corrupted git history
1 parent 05275b0 commit 5c9fc3c

30 files changed

+363
-40
lines changed

libc/config/config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@
7575
"LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE": {
7676
"value": 1073741824,
7777
"doc": "Default size for the constinit freelist buffer used for the freelist malloc implementation (default 1o 1GB)."
78+
},
79+
},
80+
"unistd": {
81+
"LIBC_CONF_ENABLE_TID_CACHE": {
82+
"value": true,
83+
"doc": "Enable caching mechanism for gettid to avoid syscall (only effective in fullbuild mode, default to true). Please refer to Undefined Behavior documentation for implications."
84+
},
85+
"LIBC_CONF_ENABLE_PID_CACHE": {
86+
"value": true,
87+
"doc": "Enable caching mechanism for getpid to avoid syscall (default to true). Please refer to Undefined Behavior documentation for implications."
7888
}
7989
},
8090
"math": {

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ set(TARGET_LIBC_ENTRYPOINTS
297297
libc.src.unistd.geteuid
298298
libc.src.unistd.getpid
299299
libc.src.unistd.getppid
300+
libc.src.unistd.gettid
300301
libc.src.unistd.getuid
301302
libc.src.unistd.isatty
302303
libc.src.unistd.link

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ set(TARGET_LIBC_ENTRYPOINTS
296296
libc.src.unistd.geteuid
297297
libc.src.unistd.getpid
298298
libc.src.unistd.getppid
299+
libc.src.unistd.gettid
299300
libc.src.unistd.getuid
300301
libc.src.unistd.isatty
301302
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
@@ -315,6 +315,7 @@ set(TARGET_LIBC_ENTRYPOINTS
315315
libc.src.unistd.geteuid
316316
libc.src.unistd.getpid
317317
libc.src.unistd.getppid
318+
libc.src.unistd.gettid
318319
libc.src.unistd.getuid
319320
libc.src.unistd.isatty
320321
libc.src.unistd.link

libc/docs/configure.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ to learn about the defaults for your platform and target.
5252
* **"string" options**
5353
- ``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.
5454
- ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen.
55+
* **"unistd" options**
56+
- ``LIBC_CONF_ENABLE_PID_CACHE``: Enable caching mechanism for getpid to avoid syscall (default to true). Please refer to Undefined Behavior documentation for implications.
57+
- ``LIBC_CONF_ENABLE_TID_CACHE``: Enable caching mechanism for gettid to avoid syscall (only effective in fullbuild mode, default to true). Please refer to Undefined Behavior documentation for implications.

libc/docs/dev/undefined_behavior.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,26 @@ direction in this case.
9393
Non-const Constant Return Values
9494
--------------------------------
9595
Some libc functions, like ``dlerror()``, return ``char *`` instead of ``const char *`` and then tell the caller they promise not to to modify this value. Any modification of this value is undefined behavior.
96+
97+
Cached ``getpid/gettid``
98+
------------------------
99+
Since version ``2.25``, glibc removes its cache mechanism for ``getpid/gettid``
100+
(See the history section in https://man7.org/linux/man-pages/man2/getpid.2.html).
101+
LLVM's libc still implements the cache as it is useful for fast deadlock detection.
102+
The cache mechanism is also implemented in MUSL and bionic. The tid/pid cache can
103+
be disabled by setting ``LIBC_CONF_ENABLE_TID_CACHE`` and ``LIBC_CONF_ENABLE_PID_CACHE``
104+
to ``false`` respectively.
105+
106+
Unwrapped ``SYS_clone/SYS_fork/SYS_vfork``
107+
------------------------------------------
108+
It is highly discouraged to use unwrapped ``SYS_clone/SYS_fork/SYS_vfork``.
109+
First, calling such syscalls without provided libc wrappers ignores
110+
all the ``pthread_atfork`` entries as libc can no longer detect the ``fork``.
111+
Second, libc relies on the ``fork/clone`` wrappers to correctly maintain cache for
112+
process id and thread id, and other important process-specific states such as the list
113+
of robust mutexes. Third, even if the user is to call ``exec*`` functions immediately,
114+
there can still be other unexpected issues. For instance, there can be signal handlers
115+
inherited from parent process triggered inside the instruction window between ``fork``
116+
and ``exec*``. As libc failed to maintain its internal states correctly, even though the
117+
functions used inside the signal handlers are marked as ``async-signal-safe`` (such as
118+
``getpid``), they will still return wrong values or lead to other even worse situations.

libc/spec/posix.td

Lines changed: 5 additions & 10 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>,
@@ -601,16 +606,6 @@ def POSIX : StandardSpec<"POSIX"> {
601606
RetValSpec<IntType>,
602607
[ArgSpec<ConstCharPtr>]
603608
>,
604-
FunctionSpec<
605-
"getpid",
606-
RetValSpec<IntType>,
607-
[ArgSpec<VoidType>]
608-
>,
609-
FunctionSpec<
610-
"getppid",
611-
RetValSpec<IntType>,
612-
[ArgSpec<VoidType>]
613-
>,
614609
FunctionSpec<
615610
"link",
616611
RetValSpec<IntType>,

libc/src/__support/OSUtil/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,20 @@ add_object_library(
1515
DEPENDS
1616
${target_os_util}
1717
)
18+
19+
if (LIBC_CONF_ENABLE_PID_CACHE)
20+
set(libc_copt_enable_pid_cache 1)
21+
else()
22+
set(libc_copt_enable_pid_cache 0)
23+
endif()
24+
25+
if(TARGET libc.src.__support.OSUtil.${LIBC_TARGET_OS}.pid)
26+
add_object_library(
27+
pid
28+
ALIAS
29+
DEPENDS
30+
.${LIBC_TARGET_OS}.pid
31+
COMPILE_OPTIONS
32+
-DLIBC_COPT_ENABLE_PID_CACHE=${libc_copt_enable_pid_cache}
33+
)
34+
endif()

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,16 @@ add_object_library(
2323
libc.hdr.types.struct_f_owner_ex
2424
libc.hdr.types.off_t
2525
)
26+
27+
add_object_library(
28+
pid
29+
SRCS
30+
pid.cpp
31+
HDRS
32+
../pid.h
33+
DEPENDS
34+
libc.src.__support.OSUtil.osutil
35+
libc.src.__support.common
36+
libc.hdr.types.pid_t
37+
libc.include.sys_syscall
38+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===------------ pid_t utilities implementation ----------------*- 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+
#include "src/__support/OSUtil/pid.h"
10+
#include "src/__support/OSUtil/syscall.h"
11+
#include <sys/syscall.h>
12+
13+
namespace LIBC_NAMESPACE_DECL {
14+
15+
pid_t ProcessIdentity::cache = -1;
16+
pid_t ProcessIdentity::get_uncached() {
17+
return syscall_impl<pid_t>(SYS_getpid);
18+
}
19+
20+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)