diff options
author | Schrodinger ZHU Yifan <yifanzhu@rochester.edu> | 2024-07-18 13:27:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-18 13:27:50 -0700 |
commit | 5c9fc3cdd7acae4ede998f2983e6107f3c0ea36a (patch) | |
tree | 0ebf203e44f7d978ee7d3b3b1c2be49b8d724ede /libc/src | |
parent | 05275b05ca58e4d015eea1503f120e6967ef1b91 (diff) | |
download | llvm-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.txt | 17 | ||||
-rw-r--r-- | libc/src/__support/OSUtil/linux/CMakeLists.txt | 13 | ||||
-rw-r--r-- | libc/src/__support/OSUtil/linux/pid.cpp | 20 | ||||
-rw-r--r-- | libc/src/__support/OSUtil/pid.h | 41 | ||||
-rw-r--r-- | libc/src/__support/threads/CMakeLists.txt | 27 | ||||
-rw-r--r-- | libc/src/__support/threads/linux/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libc/src/__support/threads/linux/rwlock.h | 9 | ||||
-rw-r--r-- | libc/src/__support/threads/linux/thread.cpp | 2 | ||||
-rw-r--r-- | libc/src/__support/threads/thread.h | 27 | ||||
-rw-r--r-- | libc/src/__support/threads/tid.h | 34 | ||||
-rw-r--r-- | libc/src/unistd/CMakeLists.txt | 10 | ||||
-rw-r--r-- | libc/src/unistd/getpid.h | 4 | ||||
-rw-r--r-- | libc/src/unistd/gettid.cpp | 17 | ||||
-rw-r--r-- | libc/src/unistd/gettid.h | 21 | ||||
-rw-r--r-- | libc/src/unistd/linux/CMakeLists.txt | 4 | ||||
-rw-r--r-- | libc/src/unistd/linux/fork.cpp | 32 | ||||
-rw-r--r-- | libc/src/unistd/linux/getpid.cpp | 11 |
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 |