aboutsummaryrefslogtreecommitdiff
path: root/libc/src
diff options
context:
space:
mode:
authorSchrodinger ZHU Yifan <yifanzhu@rochester.edu>2024-07-18 13:27:50 -0700
committerGitHub <noreply@github.com>2024-07-18 13:27:50 -0700
commit5c9fc3cdd7acae4ede998f2983e6107f3c0ea36a (patch)
tree0ebf203e44f7d978ee7d3b3b1c2be49b8d724ede /libc/src
parent05275b05ca58e4d015eea1503f120e6967ef1b91 (diff)
downloadllvm-5c9fc3cdd7acae4ede998f2983e6107f3c0ea36a.zip
llvm-5c9fc3cdd7acae4ede998f2983e6107f3c0ea36a.tar.gz
llvm-5c9fc3cdd7acae4ede998f2983e6107f3c0ea36a.tar.bz2
[libc] implement cached process/thread identity (#98989)
migrated from https://github.com/llvm/llvm-project/pull/95965 due to corrupted git history
Diffstat (limited to 'libc/src')
-rw-r--r--libc/src/__support/OSUtil/CMakeLists.txt17
-rw-r--r--libc/src/__support/OSUtil/linux/CMakeLists.txt13
-rw-r--r--libc/src/__support/OSUtil/linux/pid.cpp20
-rw-r--r--libc/src/__support/OSUtil/pid.h41
-rw-r--r--libc/src/__support/threads/CMakeLists.txt27
-rw-r--r--libc/src/__support/threads/linux/CMakeLists.txt1
-rw-r--r--libc/src/__support/threads/linux/rwlock.h9
-rw-r--r--libc/src/__support/threads/linux/thread.cpp2
-rw-r--r--libc/src/__support/threads/thread.h27
-rw-r--r--libc/src/__support/threads/tid.h34
-rw-r--r--libc/src/unistd/CMakeLists.txt10
-rw-r--r--libc/src/unistd/getpid.h4
-rw-r--r--libc/src/unistd/gettid.cpp17
-rw-r--r--libc/src/unistd/gettid.h21
-rw-r--r--libc/src/unistd/linux/CMakeLists.txt4
-rw-r--r--libc/src/unistd/linux/fork.cpp32
-rw-r--r--libc/src/unistd/linux/getpid.cpp11
17 files changed, 261 insertions, 29 deletions
diff --git a/libc/src/__support/OSUtil/CMakeLists.txt b/libc/src/__support/OSUtil/CMakeLists.txt
index 94d1042..517f888 100644
--- a/libc/src/__support/OSUtil/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/CMakeLists.txt
@@ -15,3 +15,20 @@ add_object_library(
DEPENDS
${target_os_util}
)
+
+if (LIBC_CONF_ENABLE_PID_CACHE)
+ set(libc_copt_enable_pid_cache 1)
+else()
+ set(libc_copt_enable_pid_cache 0)
+endif()
+
+if(TARGET libc.src.__support.OSUtil.${LIBC_TARGET_OS}.pid)
+ add_object_library(
+ pid
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.pid
+ COMPILE_OPTIONS
+ -DLIBC_COPT_ENABLE_PID_CACHE=${libc_copt_enable_pid_cache}
+ )
+endif()
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 089cad4..95a83d7 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -23,3 +23,16 @@ add_object_library(
libc.hdr.types.struct_f_owner_ex
libc.hdr.types.off_t
)
+
+add_object_library(
+ pid
+ SRCS
+ pid.cpp
+ HDRS
+ ../pid.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.hdr.types.pid_t
+ libc.include.sys_syscall
+)
diff --git a/libc/src/__support/OSUtil/linux/pid.cpp b/libc/src/__support/OSUtil/linux/pid.cpp
new file mode 100644
index 0000000..a8499af
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/pid.cpp
@@ -0,0 +1,20 @@
+//===------------ pid_t utilities implementation ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/OSUtil/pid.h"
+#include "src/__support/OSUtil/syscall.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+pid_t ProcessIdentity::cache = -1;
+pid_t ProcessIdentity::get_uncached() {
+ return syscall_impl<pid_t>(SYS_getpid);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/OSUtil/pid.h b/libc/src/__support/OSUtil/pid.h
new file mode 100644
index 0000000..d723abe
--- /dev/null
+++ b/libc/src/__support/OSUtil/pid.h
@@ -0,0 +1,41 @@
+//===------------ pid_t utilities -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_PID_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_PID_H
+#include "hdr/types/pid_t.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/optimization.h"
+
+#ifndef LIBC_COPT_ENABLE_PID_CACHE
+#define LIBC_COPT_ENABLE_PID_CACHE 1
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+
+class ProcessIdentity {
+ static LIBC_INLINE_VAR thread_local bool fork_inflight = true;
+ static pid_t cache;
+ static pid_t get_uncached();
+
+public:
+ LIBC_INLINE static void start_fork() { fork_inflight = true; }
+ LIBC_INLINE static void end_fork() { fork_inflight = false; }
+ LIBC_INLINE static void refresh_cache() { cache = get_uncached(); }
+ LIBC_INLINE static pid_t get() {
+#if LIBC_COPT_ENABLE_PID_CACHE
+ if (LIBC_LIKELY(!fork_inflight))
+ return cache;
+#endif
+ return get_uncached();
+ }
+};
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_PID_H
diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt
index d2e46b8..f1a2f16 100644
--- a/libc/src/__support/threads/CMakeLists.txt
+++ b/libc/src/__support/threads/CMakeLists.txt
@@ -44,6 +44,12 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex)
)
endif()
+if (LIBC_CONF_ENABLE_TID_CACHE)
+ set(libc_copt_enable_tid_cache 1)
+else()
+ set(libc_copt_enable_tid_cache 0)
+endif()
+
add_header_library(
thread_common
HDRS
@@ -54,6 +60,9 @@ add_header_library(
libc.src.__support.CPP.optional
libc.src.__support.CPP.string_view
libc.src.__support.CPP.stringstream
+ libc.hdr.types.pid_t
+ COMPILE_OPTIONS
+ -DLIBC_COPT_ENABLE_TID_CACHE=${libc_copt_enable_tid_cache}
)
if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.thread)
@@ -89,3 +98,21 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.CndVar)
.${LIBC_TARGET_OS}.CndVar
)
endif()
+
+set(tid_dep)
+if (LLVM_LIBC_FULL_BUILD)
+ list(APPEND tid_dep libc.src.__support.thread)
+else()
+ list(APPEND tid_dep libc.src.__support.OSUtil.osutil)
+ list(APPEND tid_dep libc.include.sys_syscall)
+endif()
+
+add_header_library(
+ tid
+ HDRS
+ tid.h
+ DEPENDS
+ libc.src.__support.common
+ libc.hdr.types.pid_t
+ ${tid_dep}
+)
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index 8b79715..d86441d 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -55,6 +55,7 @@ add_header_library(
libc.src.__support.common
libc.src.__support.OSUtil.osutil
libc.src.__support.CPP.limits
+ libc.src.__support.threads.tid
COMPILE_OPTIONS
-DLIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT=${LIBC_CONF_RWLOCK_DEFAULT_SPIN_COUNT}
${monotonicity_flags}
diff --git a/libc/src/__support/threads/linux/rwlock.h b/libc/src/__support/threads/linux/rwlock.h
index d2fb0ce..cae8aa6 100644
--- a/libc/src/__support/threads/linux/rwlock.h
+++ b/libc/src/__support/threads/linux/rwlock.h
@@ -23,6 +23,7 @@
#include "src/__support/threads/linux/futex_word.h"
#include "src/__support/threads/linux/raw_mutex.h"
#include "src/__support/threads/sleep.h"
+#include "src/__support/threads/tid.h"
#ifndef LIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT
#define LIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT 100
@@ -336,8 +337,6 @@ private:
LIBC_INLINE Role get_preference() const {
return static_cast<Role>(preference);
}
- // TODO: use cached thread id once implemented.
- LIBC_INLINE static pid_t gettid() { return syscall_impl<pid_t>(SYS_gettid); }
template <Role role> LIBC_INLINE LockResult try_lock(RwState &old) {
if constexpr (role == Role::Reader) {
@@ -359,7 +358,7 @@ private:
if (LIBC_LIKELY(old.compare_exchange_weak_with(
state, old.set_writer_bit(), cpp::MemoryOrder::ACQUIRE,
cpp::MemoryOrder::RELAXED))) {
- writer_tid.store(gettid(), cpp::MemoryOrder::RELAXED);
+ writer_tid.store(gettid_inline(), cpp::MemoryOrder::RELAXED);
return LockResult::Success;
}
// Notice that old is updated by the compare_exchange_weak_with
@@ -394,7 +393,7 @@ private:
unsigned spin_count = LIBC_COPT_RWLOCK_DEFAULT_SPIN_COUNT) {
// Phase 1: deadlock detection.
// A deadlock happens if this is a RAW/WAW lock in the same thread.
- if (writer_tid.load(cpp::MemoryOrder::RELAXED) == gettid())
+ if (writer_tid.load(cpp::MemoryOrder::RELAXED) == gettid_inline())
return LockResult::Deadlock;
#if LIBC_COPT_TIMEOUT_ENSURE_MONOTONICITY
@@ -520,7 +519,7 @@ public:
if (old.has_active_writer()) {
// The lock is held by a writer.
// Check if we are the owner of the lock.
- if (writer_tid.load(cpp::MemoryOrder::RELAXED) != gettid())
+ if (writer_tid.load(cpp::MemoryOrder::RELAXED) != gettid_inline())
return LockResult::PermissionDenied;
// clear writer tid.
writer_tid.store(0, cpp::MemoryOrder::RELAXED);
diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index 36b4a88..c8ad086 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -518,4 +518,6 @@ void thread_exit(ThreadReturnValue retval, ThreadStyle style) {
__builtin_unreachable();
}
+pid_t Thread::get_uncached_tid() { return syscall_impl<pid_t>(SYS_gettid); }
+
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/threads/thread.h b/libc/src/__support/threads/thread.h
index ce23a88..1805b6f 100644
--- a/libc/src/__support/threads/thread.h
+++ b/libc/src/__support/threads/thread.h
@@ -9,6 +9,11 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_THREAD_H
#define LLVM_LIBC_SRC___SUPPORT_THREADS_THREAD_H
+#ifndef LIBC_COPT_ENABLE_TID_CACHE
+#define LIBC_COPT_ENABLE_TID_CACHE 1
+#endif
+
+#include "hdr/types/pid_t.h"
#include "src/__support/CPP/atomic.h"
#include "src/__support/CPP/optional.h"
#include "src/__support/CPP/string_view.h"
@@ -103,7 +108,7 @@ struct alignas(STACK_ALIGNMENT) ThreadAttributes {
uintptr_t tls; // Address to the thread TLS memory
uintptr_t tls_size; // The size of area pointed to by |tls|.
unsigned char owned_stack; // Indicates if the thread owns this stack memory
- int tid;
+ pid_t tid;
ThreadStyle style;
ThreadReturnValue retval;
ThreadAtExitCallbackMgr *atexit_callback_mgr;
@@ -228,6 +233,26 @@ struct Thread {
// Return the name of the thread in |name|. Return the error number of error.
int get_name(cpp::StringStream &name) const;
+
+ static pid_t get_uncached_tid();
+
+ LIBC_INLINE void refresh_tid(pid_t cached = -1) {
+ if (cached >= 0)
+ this->attrib->tid = cached;
+ else
+ this->attrib->tid = get_uncached_tid();
+ }
+ LIBC_INLINE void invalidate_tid() { this->attrib->tid = -1; }
+
+ LIBC_INLINE pid_t get_tid() {
+#if LIBC_COPT_ENABLE_TID_CACHE
+ if (LIBC_UNLIKELY(this->attrib->tid < 0))
+ return get_uncached_tid();
+ return this->attrib->tid;
+#else
+ return get_uncached_tid();
+#endif
+ }
};
extern LIBC_THREAD_LOCAL Thread self;
diff --git a/libc/src/__support/threads/tid.h b/libc/src/__support/threads/tid.h
new file mode 100644
index 0000000..a575cff
--- /dev/null
+++ b/libc/src/__support/threads/tid.h
@@ -0,0 +1,34 @@
+//===--- Tid wrapper --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_TID_H
+#define LLVM_LIBC_SRC___SUPPORT_THREADS_TID_H
+
+// This header is for internal usage which automatically dispatches full build
+// and overlay build behaviors.
+
+#include "hdr/types/pid_t.h"
+#include "src/__support/common.h"
+#ifdef LIBC_FULL_BUILD
+#include "src/__support/threads/thread.h"
+#else
+#include "src/__support/OSUtil/syscall.h"
+#include <sys/syscall.h>
+#endif // LIBC_FULL_BUILD
+
+namespace LIBC_NAMESPACE_DECL {
+LIBC_INLINE pid_t gettid_inline() {
+#ifdef LIBC_FULL_BUILD
+ return self.get_tid();
+#else
+ return syscall_impl<pid_t>(SYS_gettid);
+#endif
+}
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_TID_H
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index ddafcd7..ec76712 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -333,3 +333,13 @@ add_entrypoint_external(
add_entrypoint_external(
opterr
)
+
+add_entrypoint_object(
+ gettid
+ SRCS
+ gettid.cpp
+ HDRS
+ gettid.h
+ DEPENDS
+ libc.src.__support.threads.tid
+)
diff --git a/libc/src/unistd/getpid.h b/libc/src/unistd/getpid.h
index c3c55b0..5812df0 100644
--- a/libc/src/unistd/getpid.h
+++ b/libc/src/unistd/getpid.h
@@ -9,12 +9,12 @@
#ifndef LLVM_LIBC_SRC_UNISTD_GETPID_H
#define LLVM_LIBC_SRC_UNISTD_GETPID_H
+#include "hdr/types/pid_t.h"
#include "src/__support/macros/config.h"
-#include <unistd.h>
namespace LIBC_NAMESPACE_DECL {
-pid_t getpid();
+pid_t getpid(void);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/gettid.cpp b/libc/src/unistd/gettid.cpp
new file mode 100644
index 0000000..6d8ed65
--- /dev/null
+++ b/libc/src/unistd/gettid.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation file for gettid --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/gettid.h"
+#include "src/__support/common.h"
+#include "src/__support/threads/tid.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(pid_t, gettid, (void)) { return gettid_inline(); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/gettid.h b/libc/src/unistd/gettid.h
new file mode 100644
index 0000000..4228319
--- /dev/null
+++ b/libc/src/unistd/gettid.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for gettid ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_GETTID_H
+#define LLVM_LIBC_SRC_UNISTD_GETTID_H
+
+#include "hdr/types/pid_t.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+pid_t gettid(void);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_GETTID_H
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 7e733d7..651ea60 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -101,6 +101,7 @@ add_entrypoint_object(
libc.include.sys_syscall
libc.src.__support.threads.fork_callbacks
libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.pid
libc.src.__support.threads.thread
libc.src.errno.errno
)
@@ -204,8 +205,7 @@ add_entrypoint_object(
../getpid.h
DEPENDS
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.pid
)
add_entrypoint_object(
diff --git a/libc/src/unistd/linux/fork.cpp b/libc/src/unistd/linux/fork.cpp
index 7d47665..8fe1881 100644
--- a/libc/src/unistd/linux/fork.cpp
+++ b/libc/src/unistd/linux/fork.cpp
@@ -8,13 +8,14 @@
#include "src/unistd/fork.h"
+#include "src/__support/OSUtil/pid.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/threads/fork_callbacks.h"
#include "src/__support/threads/thread.h" // For thread self object
-
#include "src/errno/libc_errno.h"
+
#include <signal.h> // For SIGCHLD
#include <sys/syscall.h> // For syscall numbers.
@@ -25,6 +26,14 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(pid_t, fork, (void)) {
invoke_prepare_callbacks();
+
+ // Invalidate tid/pid cache before fork to avoid post fork signal handler from
+ // getting wrong values. gettid() is not async-signal-safe, but let's provide
+ // our best efforts here.
+ pid_t parent_tid = self.get_tid();
+ self.invalidate_tid();
+ ProcessIdentity::start_fork();
+
#ifdef SYS_fork
pid_t ret = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_fork);
#elif defined(SYS_clone)
@@ -32,15 +41,6 @@ LLVM_LIBC_FUNCTION(pid_t, fork, (void)) {
#else
#error "fork and clone syscalls not available."
#endif
- if (ret == 0) {
- // Return value is 0 in the child process.
- // The child is created with a single thread whose self object will be a
- // copy of parent process' thread which called fork. So, we have to fix up
- // the child process' self object with the new process' tid.
- self.attrib->tid = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_gettid);
- invoke_child_callbacks();
- return 0;
- }
if (ret < 0) {
// Error case, a child process was not created.
@@ -48,6 +48,18 @@ LLVM_LIBC_FUNCTION(pid_t, fork, (void)) {
return -1;
}
+ // Child process
+ if (ret == 0) {
+ self.refresh_tid();
+ ProcessIdentity::refresh_cache();
+ ProcessIdentity::end_fork();
+ invoke_child_callbacks();
+ return 0;
+ }
+
+ // Parent process
+ self.refresh_tid(parent_tid);
+ ProcessIdentity::end_fork();
invoke_parent_callbacks();
return ret;
}
diff --git a/libc/src/unistd/linux/getpid.cpp b/libc/src/unistd/linux/getpid.cpp
index b24c86a..65d6c8a 100644
--- a/libc/src/unistd/linux/getpid.cpp
+++ b/libc/src/unistd/linux/getpid.cpp
@@ -7,17 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/unistd/getpid.h"
-
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/pid.h"
#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-
-#include <sys/syscall.h> // For syscall numbers.
-
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(pid_t, getpid, ()) {
- return LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_getpid);
-}
+LLVM_LIBC_FUNCTION(pid_t, getpid, (void)) { return ProcessIdentity::get(); }
} // namespace LIBC_NAMESPACE_DECL