This commit is contained in:
parent
afbfb16d29
commit
29be889c2c
@ -77,6 +77,16 @@
|
||||
"doc": "Default size for the constinit freelist buffer used for the freelist malloc implementation (default 1o 1GB)."
|
||||
}
|
||||
},
|
||||
"unistd": {
|
||||
"LIBC_CONF_ENABLE_TID_CACHE": {
|
||||
"value": true,
|
||||
"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."
|
||||
},
|
||||
"LIBC_CONF_ENABLE_PID_CACHE": {
|
||||
"value": true,
|
||||
"doc": "Enable caching mechanism for getpid to avoid syscall (default to true). Please refer to Undefined Behavior documentation for implications."
|
||||
}
|
||||
},
|
||||
"math": {
|
||||
"LIBC_CONF_MATH_OPTIMIZATIONS": {
|
||||
"value": 0,
|
||||
|
@ -297,6 +297,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
libc.src.unistd.geteuid
|
||||
libc.src.unistd.getpid
|
||||
libc.src.unistd.getppid
|
||||
libc.src.unistd.gettid
|
||||
libc.src.unistd.getuid
|
||||
libc.src.unistd.isatty
|
||||
libc.src.unistd.link
|
||||
|
@ -296,6 +296,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
libc.src.unistd.geteuid
|
||||
libc.src.unistd.getpid
|
||||
libc.src.unistd.getppid
|
||||
libc.src.unistd.gettid
|
||||
libc.src.unistd.getuid
|
||||
libc.src.unistd.isatty
|
||||
libc.src.unistd.link
|
||||
|
@ -315,6 +315,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
libc.src.unistd.geteuid
|
||||
libc.src.unistd.getpid
|
||||
libc.src.unistd.getppid
|
||||
libc.src.unistd.gettid
|
||||
libc.src.unistd.getuid
|
||||
libc.src.unistd.isatty
|
||||
libc.src.unistd.link
|
||||
|
@ -52,3 +52,6 @@ to learn about the defaults for your platform and target.
|
||||
* **"string" options**
|
||||
- ``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.
|
||||
- ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen.
|
||||
* **"unistd" options**
|
||||
- ``LIBC_CONF_ENABLE_PID_CACHE``: Enable caching mechanism for getpid to avoid syscall (default to true). Please refer to Undefined Behavior documentation for implications.
|
||||
- ``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.
|
||||
|
@ -93,3 +93,26 @@ direction in this case.
|
||||
Non-const Constant Return Values
|
||||
--------------------------------
|
||||
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.
|
||||
|
||||
Cached ``getpid/gettid``
|
||||
------------------------
|
||||
Since version ``2.25``, glibc removes its cache mechanism for ``getpid/gettid``
|
||||
(See the history section in https://man7.org/linux/man-pages/man2/getpid.2.html).
|
||||
LLVM's libc still implements the cache as it is useful for fast deadlock detection.
|
||||
The cache mechanism is also implemented in MUSL and bionic. The tid/pid cache can
|
||||
be disabled by setting ``LIBC_CONF_ENABLE_TID_CACHE`` and ``LIBC_CONF_ENABLE_PID_CACHE``
|
||||
to ``false`` respectively.
|
||||
|
||||
Unwrapped ``SYS_clone/SYS_fork/SYS_vfork``
|
||||
------------------------------------------
|
||||
It is highly discouraged to use unwrapped ``SYS_clone/SYS_fork/SYS_vfork``.
|
||||
First, calling such syscalls without provided libc wrappers ignores
|
||||
all the ``pthread_atfork`` entries as libc can no longer detect the ``fork``.
|
||||
Second, libc relies on the ``fork/clone`` wrappers to correctly maintain cache for
|
||||
process id and thread id, and other important process-specific states such as the list
|
||||
of robust mutexes. Third, even if the user is to call ``exec*`` functions immediately,
|
||||
there can still be other unexpected issues. For instance, there can be signal handlers
|
||||
inherited from parent process triggered inside the instruction window between ``fork``
|
||||
and ``exec*``. As libc failed to maintain its internal states correctly, even though the
|
||||
functions used inside the signal handlers are marked as ``async-signal-safe`` (such as
|
||||
``getpid``), they will still return wrong values or lead to other even worse situations.
|
||||
|
@ -546,6 +546,11 @@ def POSIX : StandardSpec<"POSIX"> {
|
||||
RetValSpec<PidT>,
|
||||
[ArgSpec<VoidType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"gettid",
|
||||
RetValSpec<PidT>,
|
||||
[ArgSpec<VoidType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"getuid",
|
||||
RetValSpec<UidT>,
|
||||
@ -601,16 +606,6 @@ def POSIX : StandardSpec<"POSIX"> {
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<ConstCharPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"getpid",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<VoidType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"getppid",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<VoidType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"link",
|
||||
RetValSpec<IntType>,
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
)
|
||||
|
20
libc/src/__support/OSUtil/linux/pid.cpp
Normal file
20
libc/src/__support/OSUtil/linux/pid.cpp
Normal file
@ -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
|
41
libc/src/__support/OSUtil/pid.h
Normal file
41
libc/src/__support/OSUtil/pid.h
Normal file
@ -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
|
@ -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}
|
||||
)
|
||||
|
@ -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}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
34
libc/src/__support/threads/tid.h
Normal file
34
libc/src/__support/threads/tid.h
Normal file
@ -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
|
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
||||
|
17
libc/src/unistd/gettid.cpp
Normal file
17
libc/src/unistd/gettid.cpp
Normal file
@ -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
|
21
libc/src/unistd/gettid.h
Normal file
21
libc/src/unistd/gettid.h
Normal file
@ -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
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -101,6 +101,7 @@ add_object_library(
|
||||
libc.include.llvm-libc-macros.link_macros
|
||||
libc.src.__support.threads.thread
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.__support.OSUtil.pid
|
||||
libc.src.stdlib.exit
|
||||
libc.src.stdlib.atexit
|
||||
libc.src.unistd.environ
|
||||
|
@ -7,6 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "startup/linux/do_start.h"
|
||||
#include "include/llvm-libc-macros/link-macros.h"
|
||||
#include "src/__support/OSUtil/pid.h"
|
||||
#include "src/__support/OSUtil/syscall.h"
|
||||
#include "src/__support/macros/config.h"
|
||||
#include "src/__support/threads/thread.h"
|
||||
@ -127,6 +128,10 @@ static ThreadAttributes main_thread_attrib;
|
||||
if (tls.size != 0 && !set_thread_ptr(tls.tp))
|
||||
syscall_impl<long>(SYS_exit, 1);
|
||||
|
||||
// Validate process identity cache (TLS needed).
|
||||
ProcessIdentity::refresh_cache();
|
||||
ProcessIdentity::end_fork();
|
||||
|
||||
self.attrib = &main_thread_attrib;
|
||||
main_thread_attrib.atexit_callback_mgr =
|
||||
internal::get_thread_atexit_callback_mgr();
|
||||
|
@ -31,6 +31,10 @@ add_integration_test(
|
||||
libc.src.sys.wait.wait4
|
||||
libc.src.sys.wait.waitpid
|
||||
libc.src.unistd.fork
|
||||
libc.src.unistd.getpid
|
||||
libc.src.unistd.gettid
|
||||
libc.src.stdlib.exit
|
||||
libc.include.sys_syscall
|
||||
)
|
||||
|
||||
if((${LIBC_TARGET_OS} STREQUAL "linux") AND (${LIBC_TARGET_ARCHITECTURE_IS_X86}))
|
||||
|
@ -6,17 +6,21 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/__support/OSUtil/syscall.h"
|
||||
#include "src/pthread/pthread_atfork.h"
|
||||
#include "src/signal/raise.h"
|
||||
#include "src/stdlib/exit.h"
|
||||
#include "src/sys/wait/wait.h"
|
||||
#include "src/sys/wait/wait4.h"
|
||||
#include "src/sys/wait/waitpid.h"
|
||||
#include "src/unistd/fork.h"
|
||||
|
||||
#include "src/unistd/getpid.h"
|
||||
#include "src/unistd/gettid.h"
|
||||
#include "test/IntegrationTest/test.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -140,7 +144,25 @@ void fork_with_atfork_callbacks() {
|
||||
ASSERT_NE(child, DONE);
|
||||
}
|
||||
|
||||
void fork_pid_tid_test() {
|
||||
pid_t pid = fork();
|
||||
ASSERT_TRUE(pid >= 0);
|
||||
ASSERT_EQ(LIBC_NAMESPACE::gettid(),
|
||||
LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_gettid));
|
||||
ASSERT_EQ(LIBC_NAMESPACE::getpid(),
|
||||
LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_getpid));
|
||||
|
||||
if (pid == 0) {
|
||||
LIBC_NAMESPACE::exit(0);
|
||||
} else {
|
||||
int status;
|
||||
LIBC_NAMESPACE::waitpid(pid, &status, 0);
|
||||
ASSERT_EQ(status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_MAIN(int argc, char **argv, char **envp) {
|
||||
fork_pid_tid_test();
|
||||
fork_and_wait_normal_exit();
|
||||
fork_and_wait4_normal_exit();
|
||||
fork_and_waitpid_normal_exit();
|
||||
|
@ -378,6 +378,16 @@ add_libc_unittest(
|
||||
libc.src.unistd.getpid
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
gettid_test
|
||||
SUITE
|
||||
libc_unistd_unittests
|
||||
SRCS
|
||||
gettid_test.cpp
|
||||
DEPENDS
|
||||
libc.src.unistd.gettid
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
getppid_test
|
||||
SUITE
|
||||
|
15
libc/test/src/unistd/gettid_test.cpp
Normal file
15
libc/test/src/unistd/gettid_test.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
//===-- Unittests for gettid ----------------------------------------------===//
|
||||
//
|
||||
// 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 "test/UnitTest/Test.h"
|
||||
|
||||
TEST(LlvmLibcGetTidTest, SmokeTest) {
|
||||
// gettid always succeeds. So, we just call it as a smoke test.
|
||||
ASSERT_GT(LIBC_NAMESPACE::gettid(), 0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user