diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -218,7 +218,7 @@ } def SysWaitAPI : PublicAPI<"sys/wait.h"> { - let Types = ["pid_t", "struct rusage"]; + let Types = ["pid_t", "struct rusage", "siginfo_t"]; } def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> { diff --git a/libc/config/linux/syscall_numbers.h.inc b/libc/config/linux/syscall_numbers.h.inc --- a/libc/config/linux/syscall_numbers.h.inc +++ b/libc/config/linux/syscall_numbers.h.inc @@ -422,6 +422,10 @@ #define SYS_futex __NR_futex #endif +#ifdef __NR_futex_time64 +#define SYS_futex_time64 __NR_futex_time64 +#endif + #ifdef __NR_futimesat #define SYS_futimesat __NR_futimesat #endif @@ -1730,6 +1734,10 @@ #define SYS_sched_rr_get_interval __NR_sched_rr_get_interval #endif +#ifdef __NR_sched_rr_get_interval_time64 +#define SYS_sched_rr_get_interval_time64 __NR_sched_rr_get_interval_time64 +#endif + #ifdef __NR_sched_set_affinity #define SYS_sched_set_affinity __NR_sched_set_affinity #endif @@ -2317,4 +2325,3 @@ #ifdef __NR_writev #define SYS_writev __NR_writev #endif - diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -459,6 +459,7 @@ .llvm-libc-macros.sys_wait_macros .llvm-libc-types.pid_t .llvm-libc-types.struct_rusage + .llvm-libc-types.siginfo_t ) add_gen_header( diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -1200,7 +1200,7 @@ HeaderSpec SysWait = HeaderSpec< "sys/wait.h", [], // Macros - [PidT, StructRUsage], + [PidT, StructRUsage, SigInfoType], [], // Enumerations [ FunctionSpec< diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp --- a/libc/src/__support/File/linux/file.cpp +++ b/libc/src/__support/File/linux/file.cpp @@ -68,12 +68,14 @@ #ifdef SYS_lseek int ret = __llvm_libc::syscall_impl(SYS_lseek, lf->get_fd(), offset, whence); result = ret; +#elif defined(SYS_llseek) + int ret = __llvm_libc::syscall_impl(SYS_llseek, lf->get_fd(), offset, whence); + result = ret; #elif defined(SYS__llseek) - long result; int ret = __llvm_libc::syscall_impl(SYS__llseek, lf->get_fd(), offset >> 32, offset, &result, whence); #else -#error "lseek and _llseek syscalls not available to perform a seek operation." +#error "lseek, llseek and _llseek syscalls not available." #endif if (ret < 0) diff --git a/libc/src/__support/threads/linux/futex_word.h b/libc/src/__support/threads/linux/futex_word.h --- a/libc/src/__support/threads/linux/futex_word.h +++ b/libc/src/__support/threads/linux/futex_word.h @@ -10,12 +10,21 @@ #define LLVM_LIBC_SRC_SUPPORT_THREADS_LINUX_FUTEX_WORD_H #include +#include namespace __llvm_libc { // Futexes are 32 bits in size on all platforms, including 64-bit platforms. using FutexWordType = uint32_t; +#if SYS_futex +constexpr auto FUTEX_SYSCALL_ID = SYS_futex; +#elif defined(SYS_futex_time64) +constexpr auto FUTEX_SYSCALL_ID = SYS_futex_time64; +#else +#error "futex and futex_time64 syscalls not available." +#endif + } // namespace __llvm_libc #endif // LLVM_LIBC_SRC_SUPPORT_THREADS_LINUX_FUTEX_WORD_H diff --git a/libc/src/__support/threads/linux/mutex.h b/libc/src/__support/threads/linux/mutex.h --- a/libc/src/__support/threads/linux/mutex.h +++ b/libc/src/__support/threads/linux/mutex.h @@ -76,7 +76,7 @@ // futex syscall will block if the futex data is still // `LockState::Waiting` (the 4th argument to the syscall function // below.) - __llvm_libc::syscall_impl(SYS_futex, &futex_word.val, + __llvm_libc::syscall_impl(FUTEX_SYSCALL_ID, &futex_word.val, FUTEX_WAIT_PRIVATE, FutexWordType(LockState::Waiting), 0, 0, 0); was_waiting = true; @@ -91,7 +91,8 @@ // we will wait for the futex to be woken up. Note again that the // following syscall will block only if the futex data is still // `LockState::Waiting`. - __llvm_libc::syscall_impl(SYS_futex, &futex_word, FUTEX_WAIT_PRIVATE, + __llvm_libc::syscall_impl(FUTEX_SYSCALL_ID, &futex_word, + FUTEX_WAIT_PRIVATE, FutexWordType(LockState::Waiting), 0, 0, 0); was_waiting = true; } @@ -109,8 +110,8 @@ if (futex_word.compare_exchange_strong(mutex_status, FutexWordType(LockState::Free))) { // If any thread is waiting to be woken up, then do it. - __llvm_libc::syscall_impl(SYS_futex, &futex_word, FUTEX_WAKE_PRIVATE, 1, - 0, 0, 0); + __llvm_libc::syscall_impl(FUTEX_SYSCALL_ID, &futex_word, + FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); return MutexError::NONE; } diff --git a/libc/src/sched/linux/sched_rr_get_interval.cpp b/libc/src/sched/linux/sched_rr_get_interval.cpp --- a/libc/src/sched/linux/sched_rr_get_interval.cpp +++ b/libc/src/sched/linux/sched_rr_get_interval.cpp @@ -12,13 +12,30 @@ #include "src/__support/common.h" #include "src/errno/libc_errno.h" +#include // For __kernel_timespec. #include // For syscall numbers. namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, sched_rr_get_interval, (pid_t tid, struct timespec *tp)) { +#ifdef SYS_sched_rr_get_interval long ret = __llvm_libc::syscall_impl(SYS_sched_rr_get_interval, tid, tp); +#elif defined(SYS_sched_rr_get_interval_time64) + // The difference between the and SYS_sched_rr_get_interval + // SYS_sched_rr_get_interval_time64 syscalls is the data type used for the + // time interval parameter: the latter takes a struct __kernel_timespec + struct __kernel_timespec ts32; + long ret = + __llvm_libc::syscall_impl(SYS_sched_rr_get_interval_time64, tid, &ts32); + if (ret > 0) { + tp->tv_sec = ts32.tv_sec; + tp->tv_nsec = ts32.tv_nsec; + } +#else +#error \ + "sched_rr_get_interval and sched_rr_get_interval_time64 syscalls not available." +#endif if (ret < 0) { libc_errno = -ret; return -1; diff --git a/libc/src/sys/sendfile/linux/sendfile.cpp b/libc/src/sys/sendfile/linux/sendfile.cpp --- a/libc/src/sys/sendfile/linux/sendfile.cpp +++ b/libc/src/sys/sendfile/linux/sendfile.cpp @@ -19,8 +19,17 @@ LLVM_LIBC_FUNCTION(ssize_t, sendfile, (int out_fd, int in_fd, off_t *offset, size_t count)) { +#ifdef SYS_sendfile long ret = __llvm_libc::syscall_impl(SYS_sendfile, in_fd, out_fd, offset, count); +#elif defined(SYS_sendfile64) + // Same as sendfile but can handle large offsets + static_assert(sizeof(off_t) == 8); + long ret = + __llvm_libc::syscall_impl(SYS_sendfile64, in_fd, out_fd, offset, count); +#else +#error "sendfile and sendfile64 syscalls not available." +#endif if (ret < 0) { libc_errno = -ret; return -1; diff --git a/libc/src/sys/wait/linux/wait.cpp b/libc/src/sys/wait/linux/wait.cpp --- a/libc/src/sys/wait/linux/wait.cpp +++ b/libc/src/sys/wait/linux/wait.cpp @@ -7,9 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/sys/wait/wait.h" +#include "src/sys/wait/wait4.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" +#include "src/__support/libc_assert.h" #include "src/errno/libc_errno.h" #include // For syscall numbers. @@ -21,14 +23,7 @@ // functionality and standard compliance in future. LLVM_LIBC_FUNCTION(pid_t, wait, (int *wait_status)) { - pid_t pid = __llvm_libc::syscall_impl(SYS_wait4, -1, wait_status, 0, 0); - if (pid < 0) { - // Error case, a child process was not created. - libc_errno = -pid; - return -1; - } - - return pid; + return wait4(-1, wait_status, 0, 0); } } // namespace __llvm_libc diff --git a/libc/src/sys/wait/linux/wait4.cpp b/libc/src/sys/wait/linux/wait4.cpp --- a/libc/src/sys/wait/linux/wait4.cpp +++ b/libc/src/sys/wait/linux/wait4.cpp @@ -10,6 +10,7 @@ #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" +#include "src/__support/libc_assert.h" #include "src/errno/libc_errno.h" #include // For syscall numbers. @@ -20,7 +21,51 @@ LLVM_LIBC_FUNCTION(pid_t, wait4, (pid_t pid, int *wait_status, int options, struct rusage *usage)) { +#if SYS_wait4 pid = __llvm_libc::syscall_impl(SYS_wait4, pid, wait_status, options, usage); +#elif defined(SYS_waitid) + int idtype = P_PID; + if (pid < -1) { + idtype = P_PGID; + pid *= -1; + } else if (pid == -1) { + idtype = P_ALL; + } else if (pid == 0) { + idtype = P_PGID; + } + + siginfo_t info; + pid = __llvm_libc::syscall_impl(SYS_waitid, idtype, pid, &info, + options | WEXITED, usage); + if (pid > 0) { + if (wait_status) { + switch (info.si_code) { + case CLD_EXITED: + *wait_status = W_EXITCODE(info.si_status, 0); + break; + case CLD_DUMPED: + *wait_status = WCOREFLAG | info.si_status; + break; + case CLD_KILLED: + *wait_status = info.si_status; + break; + case CLD_TRAPPED: + case CLD_STOPPED: + *wait_status = W_STOPCODE(info.si_status); + break; + case CLD_CONTINUED: + *wait_status = WCONTINUED; + break; + default: + *wait_status = 0; + break; + } + } + pid = info.si_pid; + } +#else +#error "wait4 and waitid syscalls not available." +#endif if (pid < 0) { libc_errno = -pid; return -1; diff --git a/libc/src/sys/wait/linux/waitpid.cpp b/libc/src/sys/wait/linux/waitpid.cpp --- a/libc/src/sys/wait/linux/waitpid.cpp +++ b/libc/src/sys/wait/linux/waitpid.cpp @@ -7,9 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/sys/wait/waitpid.h" +#include "src/sys/wait/wait4.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" +#include "src/__support/libc_assert.h" #include "src/errno/libc_errno.h" #include // For syscall numbers. @@ -18,12 +20,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(pid_t, waitpid, (pid_t pid, int *wait_status, int options)) { - pid = __llvm_libc::syscall_impl(SYS_wait4, pid, wait_status, options, 0); - if (pid < 0) { - libc_errno = -pid; - return -1; - } - return pid; + return wait4(pid, wait_status, options, 0); } } // namespace __llvm_libc diff --git a/libc/src/unistd/linux/dup2.cpp b/libc/src/unistd/linux/dup2.cpp --- a/libc/src/unistd/linux/dup2.cpp +++ b/libc/src/unistd/linux/dup2.cpp @@ -27,7 +27,15 @@ // separately before making the dup3 syscall. if (oldfd == newfd) { // Check if oldfd is actually a valid file descriptor. +#if SYS_fcntl long ret = __llvm_libc::syscall_impl(SYS_fcntl, oldfd, F_GETFD); +#elif defined(SYS_fcntl64) + // Same as fcntl but can handle large offsets + static_assert(sizeof(off_t) == 8); + long ret = __llvm_libc::syscall_impl(SYS_fcntl64, oldfd, F_GETFD); +#else +#error "SYS_fcntl and SYS_fcntl64 syscalls not available." +#endif if (ret >= 0) return oldfd; libc_errno = -ret; diff --git a/libc/src/unistd/linux/ftruncate.cpp b/libc/src/unistd/linux/ftruncate.cpp --- a/libc/src/unistd/linux/ftruncate.cpp +++ b/libc/src/unistd/linux/ftruncate.cpp @@ -18,7 +18,16 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, ftruncate, (int fd, off_t len)) { +#ifdef SYS_ftruncate int ret = __llvm_libc::syscall_impl(SYS_ftruncate, fd, len); +#elif defined(SYS_ftruncate64) + // Same as ftruncate but can handle large offsets + static_assert(sizeof(off_t) == 8); + int ret = __llvm_libc::syscall_impl(SYS_ftruncate64, fd, len); +#else +#error "ftruncate and ftruncate64 syscalls not available." +#endif + if (ret < 0) { libc_errno = -ret; return -1; diff --git a/libc/src/unistd/linux/lseek.cpp b/libc/src/unistd/linux/lseek.cpp --- a/libc/src/unistd/linux/lseek.cpp +++ b/libc/src/unistd/linux/lseek.cpp @@ -22,11 +22,14 @@ #ifdef SYS_lseek long ret = __llvm_libc::syscall_impl(SYS_lseek, fd, offset, whence); result = ret; +#elif defined(SYS_llseek) + long ret = __llvm_libc::syscall_impl(SYS_llseek, fd, offset, whence); + result = ret; #elif defined(SYS__llseek) long ret = __llvm_libc::syscall_impl(SYS__llseek, fd, offset >> 32, offset, &result, whence); #else -#error "lseek and _llseek syscalls not available." +#error "lseek, llseek and _llseek syscalls not available." #endif if (ret < 0) { diff --git a/libc/src/unistd/linux/truncate.cpp b/libc/src/unistd/linux/truncate.cpp --- a/libc/src/unistd/linux/truncate.cpp +++ b/libc/src/unistd/linux/truncate.cpp @@ -18,7 +18,15 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, truncate, (const char *path, off_t len)) { +#ifdef SYS_truncate int ret = __llvm_libc::syscall_impl(SYS_truncate, path, len); +#elif defined(SYS_truncate64) + // Same as truncate but can handle large offsets + static_assert(sizeof(off_t) == 8); + int ret = __llvm_libc::syscall_impl(SYS_truncate64, path, len); +#else +#error "truncate and truncate64 syscalls not available." +#endif if (ret < 0) { libc_errno = -ret; return -1;