30 changes: 15 additions & 15 deletions libc/src/__support/OSUtil/linux/x86_64/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace __llvm_libc {

__attribute__((always_inline)) inline long syscall(long __number) {
__attribute__((always_inline)) inline long syscall_impl(long __number) {
long retcode;
LIBC_INLINE_ASM("syscall"
: "=a"(retcode)
Expand All @@ -24,7 +24,8 @@ __attribute__((always_inline)) inline long syscall(long __number) {
return retcode;
}

__attribute__((always_inline)) inline long syscall(long __number, long __arg1) {
__attribute__((always_inline)) inline long syscall_impl(long __number,
long __arg1) {
long retcode;
LIBC_INLINE_ASM("syscall"
: "=a"(retcode)
Expand All @@ -33,8 +34,8 @@ __attribute__((always_inline)) inline long syscall(long __number, long __arg1) {
return retcode;
}

__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
long __arg2) {
__attribute__((always_inline)) inline long
syscall_impl(long __number, long __arg1, long __arg2) {
long retcode;
LIBC_INLINE_ASM("syscall"
: "=a"(retcode)
Expand All @@ -43,8 +44,8 @@ __attribute__((always_inline)) inline long syscall(long __number, long __arg1,
return retcode;
}

__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
long __arg2, long __arg3) {
__attribute__((always_inline)) inline long
syscall_impl(long __number, long __arg1, long __arg2, long __arg3) {
long retcode;
LIBC_INLINE_ASM("syscall"
: "=a"(retcode)
Expand All @@ -54,7 +55,8 @@ __attribute__((always_inline)) inline long syscall(long __number, long __arg1,
}

__attribute__((always_inline)) inline long
syscall(long __number, long __arg1, long __arg2, long __arg3, long __arg4) {
syscall_impl(long __number, long __arg1, long __arg2, long __arg3,
long __arg4) {
long retcode;
register long r10 __asm__("r10") = __arg4;
LIBC_INLINE_ASM("syscall"
Expand All @@ -65,9 +67,9 @@ syscall(long __number, long __arg1, long __arg2, long __arg3, long __arg4) {
return retcode;
}

__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
long __arg2, long __arg3,
long __arg4, long __arg5) {
__attribute__((always_inline)) inline long
syscall_impl(long __number, long __arg1, long __arg2, long __arg3, long __arg4,
long __arg5) {
long retcode;
register long r10 __asm__("r10") = __arg4;
register long r8 __asm__("r8") = __arg5;
Expand All @@ -79,10 +81,9 @@ __attribute__((always_inline)) inline long syscall(long __number, long __arg1,
return retcode;
}

__attribute__((always_inline)) inline long syscall(long __number, long __arg1,
long __arg2, long __arg3,
long __arg4, long __arg5,
long __arg6) {
__attribute__((always_inline)) inline long
syscall_impl(long __number, long __arg1, long __arg2, long __arg3, long __arg4,
long __arg5, long __arg6) {
long retcode;
register long r10 __asm__("r10") = __arg4;
register long r8 __asm__("r8") = __arg5;
Expand All @@ -96,7 +97,6 @@ __attribute__((always_inline)) inline long syscall(long __number, long __arg1,
}

#undef SYSCALL_CLOBBER_LIST

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_X86_64_SYSCALL_H
13 changes: 7 additions & 6 deletions libc/src/__support/threads/linux/callonce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,20 @@ int callonce(CallOnceFlag *flag, CallOnceCallback *func) {
func();
auto status = futex_word->exchange(FINISH);
if (status == WAITING) {
__llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE,
INT_MAX, // Wake all waiters.
0, 0, 0);
__llvm_libc::syscall_impl(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE,
INT_MAX, // Wake all waiters.
0, 0, 0);
}
return 0;
}

FutexWordType status = START;
if (futex_word->compare_exchange_strong(status, WAITING) ||
status == WAITING) {
__llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE,
WAITING, // Block only if status is still |WAITING|.
0, 0, 0);
__llvm_libc::syscall_impl(
SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE,
WAITING, // Block only if status is still |WAITING|.
0, 0, 0);
}

return 0;
Expand Down
13 changes: 7 additions & 6 deletions libc/src/__support/threads/linux/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ struct Mutex {
// futex syscall will block if the futex data is still
// `LockState::Waiting` (the 4th argument to the syscall function
// below.)
__llvm_libc::syscall(SYS_futex, &futex_word.val, FUTEX_WAIT_PRIVATE,
FutexWordType(LockState::Waiting), 0, 0, 0);
__llvm_libc::syscall_impl(SYS_futex, &futex_word.val,
FUTEX_WAIT_PRIVATE,
FutexWordType(LockState::Waiting), 0, 0, 0);
was_waiting = true;
// Once woken up/unblocked, try everything all over.
continue;
Expand All @@ -90,8 +91,8 @@ struct Mutex {
// 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(SYS_futex, &futex_word, FUTEX_WAIT_PRIVATE,
FutexWordType(LockState::Waiting), 0, 0, 0);
__llvm_libc::syscall_impl(SYS_futex, &futex_word, FUTEX_WAIT_PRIVATE,
FutexWordType(LockState::Waiting), 0, 0, 0);
was_waiting = true;
}
continue;
Expand All @@ -108,8 +109,8 @@ struct Mutex {
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(SYS_futex, &futex_word, FUTEX_WAKE_PRIVATE, 1, 0,
0, 0);
__llvm_libc::syscall_impl(SYS_futex, &futex_word, FUTEX_WAKE_PRIVATE, 1,
0, 0, 0);
return MutexError::NONE;
}

Expand Down
55 changes: 29 additions & 26 deletions libc/src/__support/threads/linux/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,21 @@ static constexpr unsigned CLONE_SYSCALL_FLAGS =

static inline cpp::ErrorOr<void *> alloc_stack(size_t size) {
long mmap_result =
__llvm_libc::syscall(MMAP_SYSCALL_NUMBER,
0, // No special address
size,
PROT_READ | PROT_WRITE, // Read and write stack
MAP_ANONYMOUS | MAP_PRIVATE, // Process private
-1, // Not backed by any file
0 // No offset
__llvm_libc::syscall_impl(MMAP_SYSCALL_NUMBER,
0, // No special address
size,
PROT_READ | PROT_WRITE, // Read and write stack
MAP_ANONYMOUS | MAP_PRIVATE, // Process private
-1, // Not backed by any file
0 // No offset
);
if (mmap_result < 0 && (uintptr_t(mmap_result) >= UINTPTR_MAX - size))
return cpp::Error{int(-mmap_result)};
return reinterpret_cast<void *>(mmap_result);
}

static inline void free_stack(void *stack, size_t size) {
__llvm_libc::syscall(SYS_munmap, stack, size);
__llvm_libc::syscall_impl(SYS_munmap, stack, size);
}

struct Thread;
Expand Down Expand Up @@ -192,15 +192,15 @@ int Thread::run(ThreadStyle style, ThreadRunner runner, void *arg, void *stack,
// variables from this function will not be availalbe to the child thread.
#ifdef LLVM_LIBC_ARCH_X86_64
long register clone_result asm("rax");
clone_result = __llvm_libc::syscall(
clone_result = __llvm_libc::syscall_impl(
SYS_clone, CLONE_SYSCALL_FLAGS, adjusted_stack,
&attrib->tid, // The address where the child tid is written
&clear_tid->val, // The futex where the child thread status is signalled
tls.tp // The thread pointer value for the new thread.
);
#elif defined(LLVM_LIBC_ARCH_AARCH64)
long register clone_result asm("x0");
clone_result = __llvm_libc::syscall(
clone_result = __llvm_libc::syscall_impl(
SYS_clone, CLONE_SYSCALL_FLAGS, adjusted_stack,
&attrib->tid, // The address where the child tid is written
tls.tp, // The thread pointer value for the new thread.
Expand Down Expand Up @@ -264,8 +264,8 @@ void Thread::wait() {
while (clear_tid->load() != 0) {
// We cannot do a FUTEX_WAIT_PRIVATE here as the kernel does a
// FUTEX_WAKE and not a FUTEX_WAKE_PRIVATE.
__llvm_libc::syscall(SYS_futex, &clear_tid->val, FUTEX_WAIT,
CLEAR_TID_VALUE, nullptr);
__llvm_libc::syscall_impl(SYS_futex, &clear_tid->val, FUTEX_WAIT,
CLEAR_TID_VALUE, nullptr);
}
}

Expand Down Expand Up @@ -293,7 +293,7 @@ int Thread::set_name(const cpp::string_view &name) {
if (*this == self) {
// If we are setting the name of the current thread, then we can
// use the syscall to set the name.
int retval = __llvm_libc::syscall(SYS_prctl, PR_SET_NAME, name.data());
int retval = __llvm_libc::syscall_impl(SYS_prctl, PR_SET_NAME, name.data());
if (retval < 0)
return -retval;
else
Expand All @@ -304,15 +304,17 @@ int Thread::set_name(const cpp::string_view &name) {
cpp::StringStream path_stream(path_name_buffer);
construct_thread_name_file_path(path_stream, attrib->tid);
#ifdef SYS_open
int fd = __llvm_libc::syscall(SYS_open, path_name_buffer, O_RDWR);
int fd = __llvm_libc::syscall_impl(SYS_open, path_name_buffer, O_RDWR);
#else
int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, path_name_buffer, O_RDWR);
int fd =
__llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path_name_buffer, O_RDWR);
#endif
if (fd < 0)
return -fd;

int retval = __llvm_libc::syscall(SYS_write, fd, name.data(), name.size());
__llvm_libc::syscall(SYS_close, fd);
int retval =
__llvm_libc::syscall_impl(SYS_write, fd, name.data(), name.size());
__llvm_libc::syscall_impl(SYS_close, fd);

if (retval < 0)
return -retval;
Expand All @@ -331,7 +333,7 @@ int Thread::get_name(cpp::StringStream &name) const {
if (*this == self) {
// If we are getting the name of the current thread, then we can
// use the syscall to get the name.
int retval = __llvm_libc::syscall(SYS_prctl, PR_GET_NAME, name_buffer);
int retval = __llvm_libc::syscall_impl(SYS_prctl, PR_GET_NAME, name_buffer);
if (retval < 0)
return -retval;
name << name_buffer;
Expand All @@ -342,16 +344,17 @@ int Thread::get_name(cpp::StringStream &name) const {
cpp::StringStream path_stream(path_name_buffer);
construct_thread_name_file_path(path_stream, attrib->tid);
#ifdef SYS_open
int fd = __llvm_libc::syscall(SYS_open, path_name_buffer, O_RDONLY);
int fd = __llvm_libc::syscall_impl(SYS_open, path_name_buffer, O_RDONLY);
#else
int fd =
__llvm_libc::syscall(SYS_openat, AT_FDCWD, path_name_buffer, O_RDONLY);
int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path_name_buffer,
O_RDONLY);
#endif
if (fd < 0)
return -fd;

int retval = __llvm_libc::syscall(SYS_read, fd, name_buffer, NAME_SIZE_MAX);
__llvm_libc::syscall(SYS_close, fd);
int retval =
__llvm_libc::syscall_impl(SYS_read, fd, name_buffer, NAME_SIZE_MAX);
__llvm_libc::syscall_impl(SYS_close, fd);
if (retval < 0)
return -retval;
if (retval == NAME_SIZE_MAX)
Expand Down Expand Up @@ -385,13 +388,13 @@ void thread_exit(ThreadReturnValue retval, ThreadStyle style) {

// Set the CLEAR_TID address to nullptr to prevent the kernel
// from signalling at a non-existent futex location.
__llvm_libc::syscall(SYS_set_tid_address, 0);
__llvm_libc::syscall_impl(SYS_set_tid_address, 0);
}

if (style == ThreadStyle::POSIX)
__llvm_libc::syscall(SYS_exit, retval.posix_retval);
__llvm_libc::syscall_impl(SYS_exit, retval.posix_retval);
else
__llvm_libc::syscall(SYS_exit, retval.stdc_retval);
__llvm_libc::syscall_impl(SYS_exit, retval.stdc_retval);
}

} // namespace __llvm_libc
8 changes: 4 additions & 4 deletions libc/src/fcntl/linux/creat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, creat, (const char *path, int mode_flags)) {
#ifdef SYS_open
int fd = __llvm_libc::syscall(SYS_open, path, O_CREAT | O_WRONLY | O_TRUNC,
mode_flags);
int fd = __llvm_libc::syscall_impl(SYS_open, path,
O_CREAT | O_WRONLY | O_TRUNC, mode_flags);
#else
int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, path,
O_CREAT | O_WRONLY | O_TRUNC, mode_flags);
int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path,
O_CREAT | O_WRONLY | O_TRUNC, mode_flags);
#endif

if (fd > 0)
Expand Down
5 changes: 3 additions & 2 deletions libc/src/fcntl/linux/open.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ LLVM_LIBC_FUNCTION(int, open, (const char *path, int flags, ...)) {
}

#ifdef SYS_open
int fd = __llvm_libc::syscall(SYS_open, path, flags, mode_flags);
int fd = __llvm_libc::syscall_impl(SYS_open, path, flags, mode_flags);
#else
int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, path, flags, mode_flags);
int fd =
__llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path, flags, mode_flags);
#endif
if (fd > 0)
return fd;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/fcntl/linux/openat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ LLVM_LIBC_FUNCTION(int, openat, (int dfd, const char *path, int flags, ...)) {
va_end(varargs);
}

int fd = __llvm_libc::syscall(SYS_openat, dfd, path, flags, mode_flags);
int fd = __llvm_libc::syscall_impl(SYS_openat, dfd, path, flags, mode_flags);
if (fd > 0)
return fd;

Expand Down
2 changes: 1 addition & 1 deletion libc/src/sched/linux/sched_getaffinity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sched_getaffinity,
(pid_t tid, size_t cpuset_size, cpu_set_t *mask)) {
long ret =
__llvm_libc::syscall(SYS_sched_getaffinity, tid, cpuset_size, mask);
__llvm_libc::syscall_impl(SYS_sched_getaffinity, tid, cpuset_size, mask);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sched/linux/sched_setaffinity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sched_setaffinity,
(pid_t tid, size_t cpuset_size, const cpu_set_t *mask)) {
long ret =
__llvm_libc::syscall(SYS_sched_setaffinity, tid, cpuset_size, mask);
__llvm_libc::syscall_impl(SYS_sched_setaffinity, tid, cpuset_size, mask);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/signal/linux/__restore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ extern "C" void __restore_rt()
__attribute__((no_sanitize("all"),
hidden));

extern "C" void __restore_rt() { __llvm_libc::syscall(SYS_rt_sigreturn); }
extern "C" void __restore_rt() { __llvm_libc::syscall_impl(SYS_rt_sigreturn); }

} // namespace __llvm_libc
6 changes: 3 additions & 3 deletions libc/src/signal/linux/raise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, raise, (int sig)) {
::sigset_t sigset;
block_all_signals(sigset);
long pid = __llvm_libc::syscall(SYS_getpid);
long tid = __llvm_libc::syscall(SYS_gettid);
int ret = __llvm_libc::syscall(SYS_tgkill, pid, tid, sig);
long pid = __llvm_libc::syscall_impl(SYS_getpid);
long tid = __llvm_libc::syscall_impl(SYS_gettid);
int ret = __llvm_libc::syscall_impl(SYS_tgkill, pid, tid, sig);
restore_signals(sigset);
return ret;
}
Expand Down
5 changes: 3 additions & 2 deletions libc/src/signal/linux/sigaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ LLVM_LIBC_FUNCTION(int, sigaction,
}

KernelSigaction kernel_old;
int ret = syscall(SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr,
libc_old ? &kernel_old : nullptr, sizeof(sigset_t));
int ret = __llvm_libc::syscall_impl(
SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr,
libc_old ? &kernel_old : nullptr, sizeof(sigset_t));
if (ret) {
errno = -ret;
return -1;
Expand Down
8 changes: 4 additions & 4 deletions libc/src/signal/linux/signal_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ constexpr inline bool delete_signal(sigset_t &set, int signal) {

static inline int block_all_signals(sigset_t &set) {
sigset_t full = full_set();
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &full, &set,
sizeof(sigset_t));
return __llvm_libc::syscall_impl(SYS_rt_sigprocmask, SIG_BLOCK, &full, &set,
sizeof(sigset_t));
}

static inline int restore_signals(const sigset_t &set) {
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &set, nullptr,
sizeof(sigset_t));
return __llvm_libc::syscall_impl(SYS_rt_sigprocmask, SIG_SETMASK, &set,
nullptr, sizeof(sigset_t));
}

} // namespace __llvm_libc
Expand Down
4 changes: 2 additions & 2 deletions libc/src/signal/linux/sigprocmask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sigprocmask,
(int how, const sigset_t *__restrict set,
sigset_t *__restrict oldset)) {
int ret = __llvm_libc::syscall(SYS_rt_sigprocmask, how, set, oldset,
sizeof(sigset_t));
int ret = __llvm_libc::syscall_impl(SYS_rt_sigprocmask, how, set, oldset,
sizeof(sigset_t));
if (!ret)
return 0;

Expand Down
4 changes: 2 additions & 2 deletions libc/src/stdio/linux/remove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, remove, (const char *path)) {
// We first try unlinking it as a file. If it is ia file, it will succeed. If
// it fails with EISDIR, we will try unlinking it as a directory.
int ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, 0);
int ret = __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, 0);
if (ret == -EISDIR)
ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
ret = __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
if (ret >= 0)
return 0;
errno = -ret;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/stdlib/linux/_Exit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(void, _Exit, (int status)) {
for (;;) {
__llvm_libc::syscall(SYS_exit_group, status);
__llvm_libc::syscall(SYS_exit, status);
__llvm_libc::syscall_impl(SYS_exit_group, status);
__llvm_libc::syscall_impl(SYS_exit, status);
}
}

Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/mman/linux/madvise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ namespace __llvm_libc {
// This function is currently linux only. It has to be refactored suitably if
// madvise is to be supported on non-linux operating systems also.
LLVM_LIBC_FUNCTION(int, madvise, (void *addr, size_t size, int advice)) {
long ret_val = __llvm_libc::syscall(SYS_madvise, reinterpret_cast<long>(addr),
size, advice);
long ret_val = __llvm_libc::syscall_impl(
SYS_madvise, reinterpret_cast<long>(addr), size, advice);

// A negative return value indicates an error with the magnitude of the
// value being the error code.
Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/mman/linux/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ LLVM_LIBC_FUNCTION(void *, mmap,
#endif

long ret_val =
__llvm_libc::syscall(syscall_number, reinterpret_cast<long>(addr), size,
prot, flags, fd, offset);
__llvm_libc::syscall_impl(syscall_number, reinterpret_cast<long>(addr),
size, prot, flags, fd, offset);

// The mmap/mmap2 syscalls return negative values on error. These negative
// values are actually the negative values of the error codes. So, fix them
Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/mman/linux/mprotect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ namespace __llvm_libc {
// This function is currently linux only. It has to be refactored suitably if
// mprotect is to be supported on non-linux operating systems also.
LLVM_LIBC_FUNCTION(int, mprotect, (void *addr, size_t size, int prot)) {
long ret_val = __llvm_libc::syscall(SYS_mprotect,
reinterpret_cast<long>(addr), size, prot);
long ret_val = __llvm_libc::syscall_impl(
SYS_mprotect, reinterpret_cast<long>(addr), size, prot);

// A negative return value indicates an error with the magnitude of the
// value being the error code.
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/mman/linux/munmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace __llvm_libc {
// mmap is to be supported on non-linux operating systems also.
LLVM_LIBC_FUNCTION(int, munmap, (void *addr, size_t size)) {
long ret_val =
__llvm_libc::syscall(SYS_munmap, reinterpret_cast<long>(addr), size);
__llvm_libc::syscall_impl(SYS_munmap, reinterpret_cast<long>(addr), size);

// A negative return value indicates an error with the magnitude of the
// value being the error code.
Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/mman/linux/posix_madvise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ LLVM_LIBC_FUNCTION(int, posix_madvise, (void *addr, size_t size, int advice)) {
if (advice == POSIX_MADV_DONTNEED) {
return 0;
}
long ret_val = __llvm_libc::syscall(SYS_madvise, reinterpret_cast<long>(addr),
size, advice);
long ret_val = __llvm_libc::syscall_impl(
SYS_madvise, reinterpret_cast<long>(addr), size, advice);
return ret_val < 0 ? -ret_val : 0;
}

Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/resource/linux/getrlimit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, getrlimit, (int res, struct rlimit *limits)) {
long ret = __llvm_libc::syscall(SYS_prlimit64, 0, res, nullptr, limits);
long ret = __llvm_libc::syscall_impl(SYS_prlimit64, 0, res, nullptr, limits);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/resource/linux/setrlimit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, setrlimit, (int res, const struct rlimit *limits)) {
long ret = __llvm_libc::syscall(SYS_prlimit64, 0, res, limits, nullptr);
long ret = __llvm_libc::syscall_impl(SYS_prlimit64, 0, res, limits, nullptr);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
3 changes: 2 additions & 1 deletion libc/src/sys/sendfile/linux/sendfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(ssize_t, sendfile,
(int out_fd, int in_fd, off_t *offset, size_t count)) {
long ret = __llvm_libc::syscall(SYS_sendfile, in_fd, out_fd, offset, count);
long ret =
__llvm_libc::syscall_impl(SYS_sendfile, in_fd, out_fd, offset, count);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/stat/linux/chmod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, chmod, (const char *path, mode_t mode)) {
#ifdef SYS_chmod
long ret = __llvm_libc::syscall(SYS_chmod, path, mode);
long ret = __llvm_libc::syscall_impl(SYS_chmod, path, mode);
#elif defined(SYS_fchmodat)
long ret = __llvm_libc::syscall(SYS_fchmodat, AT_FDCWD, path, mode);
long ret = __llvm_libc::syscall_impl(SYS_fchmodat, AT_FDCWD, path, mode);
#else
#error "chmod and chmodat syscalls not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/stat/linux/fchmod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, fchmod, (int fd, mode_t mode)) {
long ret = __llvm_libc::syscall(SYS_fchmod, fd, mode);
long ret = __llvm_libc::syscall_impl(SYS_fchmod, fd, mode);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/stat/linux/fchmodat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, fchmodat,
(int dirfd, const char *path, mode_t mode, int flags)) {
long ret = __llvm_libc::syscall(SYS_fchmodat, dirfd, path, mode, flags);
long ret = __llvm_libc::syscall_impl(SYS_fchmodat, dirfd, path, mode, flags);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/stat/linux/kernel_statx.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ inline int statx(int dirfd, const char *__restrict path, int flags,
struct stat *__restrict statbuf) {
// We make a statx syscall and copy out the result into the |statbuf|.
::statx_buf xbuf;
long ret =
syscall(SYS_statx, dirfd, path, flags, ::STATX_BASIC_STATS_MASK, &xbuf);
long ret = __llvm_libc::syscall_impl(SYS_statx, dirfd, path, flags,
::STATX_BASIC_STATS_MASK, &xbuf);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/sys/stat/linux/mkdir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, mkdir, (const char *path, mode_t mode)) {
#ifdef SYS_mkdir
long ret = __llvm_libc::syscall(SYS_mkdir, path, mode);
long ret = __llvm_libc::syscall_impl(SYS_mkdir, path, mode);
#elif defined(SYS_mkdirat)
long ret = __llvm_libc::syscall(SYS_mkdirat, AT_FDCWD, path, mode);
long ret = __llvm_libc::syscall_impl(SYS_mkdirat, AT_FDCWD, path, mode);
#else
#error "mkdir and mkdirat syscalls not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/stat/linux/mkdirat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, mkdirat, (int dfd, const char *path, mode_t mode)) {
#ifdef SYS_mkdirat
long ret = __llvm_libc::syscall(SYS_mkdirat, dfd, path, mode);
long ret = __llvm_libc::syscall_impl(SYS_mkdirat, dfd, path, mode);
#else
#error "mkdirat syscalls not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/sys/utsname/linux/uname.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, uname, (struct utsname * name)) {
long ret = __llvm_libc::syscall(SYS_uname, name);
long ret = __llvm_libc::syscall_impl(SYS_uname, name);

if (ret >= 0)
return 1;
Expand Down
8 changes: 4 additions & 4 deletions libc/src/threads/linux/CndVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ struct CndVar {
}
}

__llvm_libc::syscall(SYS_futex, &waiter.futex_word.val, FUTEX_WAIT,
WS_Waiting, 0, 0, 0);
__llvm_libc::syscall_impl(SYS_futex, &waiter.futex_word.val, FUTEX_WAIT,
WS_Waiting, 0, 0, 0);

// At this point, if locking |m| fails, we can simply return as the
// queued up waiter would have been removed from the queue.
Expand All @@ -109,7 +109,7 @@ struct CndVar {

qmtx.futex_word = FutexWordType(Mutex::LockState::Free);

__llvm_libc::syscall(
__llvm_libc::syscall_impl(
SYS_futex, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1,
&first->futex_word.val,
FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting));
Expand All @@ -126,7 +126,7 @@ struct CndVar {
// atomically update the waiter status to WS_Signalled before waking
// up the waiter. A dummy location is used for the other futex of
// FUTEX_WAKE_OP.
__llvm_libc::syscall(
__llvm_libc::syscall_impl(
SYS_futex, &dummy_futex_word, FUTEX_WAKE_OP, 1, 1,
&waiter->futex_word.val,
FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting));
Expand Down
13 changes: 7 additions & 6 deletions libc/src/threads/linux/call_once.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,20 @@ LLVM_LIBC_FUNCTION(void, call_once,
func();
auto status = futex_word->exchange(FINISH);
if (status == WAITING) {
__llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE,
INT_MAX, // Wake all waiters.
0, 0, 0);
__llvm_libc::syscall_impl(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE,
INT_MAX, // Wake all waiters.
0, 0, 0);
}
return;
}

FutexWordType status = START;
if (futex_word->compare_exchange_strong(status, WAITING) ||
status == WAITING) {
__llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE,
WAITING, // Block only if status is still |WAITING|.
0, 0, 0);
__llvm_libc::syscall_impl(
SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE,
WAITING, // Block only if status is still |WAITING|.
0, 0, 0);
}
}

Expand Down
4 changes: 2 additions & 2 deletions libc/src/time/clock_gettime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, clock_gettime,
(clockid_t clockid, struct timespec *tp)) {
long ret_val =
__llvm_libc::syscall(SYS_clock_gettime, static_cast<long>(clockid),
reinterpret_cast<long>(tp));
__llvm_libc::syscall_impl(SYS_clock_gettime, static_cast<long>(clockid),
reinterpret_cast<long>(tp));
// A negative return value indicates an error with the magnitude of the
// value being the error code.
if (ret_val < 0) {
Expand Down
2 changes: 1 addition & 1 deletion libc/src/time/nanosleep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, nanosleep,
(const struct timespec *req, struct timespec *rem)) {
int ret = __llvm_libc::syscall(SYS_nanosleep, req, rem);
int ret = __llvm_libc::syscall_impl(SYS_nanosleep, req, rem);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
7 changes: 7 additions & 0 deletions libc/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.symlinkat
)

add_entrypoint_object(
__llvm_libc_syscall
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.__llvm_libc_syscall
)

add_entrypoint_object(
truncate
ALIAS
Expand Down
12 changes: 12 additions & 0 deletions libc/src/unistd/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,18 @@ add_entrypoint_object(
libc.src.errno.errno
)

add_entrypoint_object(
__llvm_libc_syscall
SRCS
syscall.cpp
HDRS
../syscall.h
DEPENDS
libc.include.unistd
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)

add_entrypoint_object(
truncate
SRCS
Expand Down
4 changes: 2 additions & 2 deletions libc/src/unistd/linux/access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, access, (const char *path, int mode)) {
#ifdef SYS_access
long ret = __llvm_libc::syscall(SYS_access, path, mode);
long ret = __llvm_libc::syscall_impl(SYS_access, path, mode);
#elif defined(SYS_faccessat)
long ret = __llvm_libc::syscall(SYS_faccessat, AT_FDCWD, path, mode, 0);
long ret = __llvm_libc::syscall_impl(SYS_faccessat, AT_FDCWD, path, mode, 0);
#else
#error "access syscalls not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/chdir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, chdir, (const char *path)) {
long ret = __llvm_libc::syscall(SYS_chdir, path);
long ret = __llvm_libc::syscall_impl(SYS_chdir, path);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/close.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, close, (int fd)) {
long ret = __llvm_libc::syscall(SYS_close, fd);
long ret = __llvm_libc::syscall_impl(SYS_close, fd);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/dup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, dup, (int fd)) {
long ret = __llvm_libc::syscall(SYS_dup, fd);
long ret = __llvm_libc::syscall_impl(SYS_dup, fd);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
6 changes: 3 additions & 3 deletions libc/src/unistd/linux/dup2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, dup2, (int oldfd, int newfd)) {
#ifdef SYS_dup2
// If dup2 syscall is available, we make use of directly.
long ret = __llvm_libc::syscall(SYS_dup2, oldfd, newfd);
long ret = __llvm_libc::syscall_impl(SYS_dup2, oldfd, newfd);
#elif defined(SYS_dup3)
// If dup2 syscall is not available, we try using the dup3 syscall. However,
// dup3 fails if oldfd is the same as newfd. So, we handle that case
// separately before making the dup3 syscall.
if (oldfd == newfd) {
// Check if oldfd is actually a valid file descriptor.
long ret = __llvm_libc::syscall(SYS_fcntl, oldfd, F_GETFD);
long ret = __llvm_libc::syscall_impl(SYS_fcntl, oldfd, F_GETFD);
if (ret >= 0)
return oldfd;
errno = -ret;
return -1;
}
long ret = __llvm_libc::syscall(SYS_dup3, oldfd, newfd, 0);
long ret = __llvm_libc::syscall_impl(SYS_dup3, oldfd, newfd, 0);
#else
#error "SYS_dup2 and SYS_dup3 not available for the target."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/dup3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, dup3, (int oldfd, int newfd, int flags)) {
// If dup2 syscall is available, we make use of directly.
long ret = __llvm_libc::syscall(SYS_dup3, oldfd, newfd, flags);
long ret = __llvm_libc::syscall_impl(SYS_dup3, oldfd, newfd, flags);
if (ret >= 0)
return ret;
errno = -ret;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/fchdir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, fchdir, (int fd)) {
long ret = __llvm_libc::syscall(SYS_fchdir, fd);
long ret = __llvm_libc::syscall_impl(SYS_fchdir, fd);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/fsync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, fsync, (int fd)) {
long ret = __llvm_libc::syscall(SYS_fsync, fd);
long ret = __llvm_libc::syscall_impl(SYS_fsync, fd);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/ftruncate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, ftruncate, (int fd, off_t len)) {
int ret = __llvm_libc::syscall(SYS_ftruncate, fd, len);
int ret = __llvm_libc::syscall_impl(SYS_ftruncate, fd, len);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/geteuid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(uid_t, geteuid, ()) {
return __llvm_libc::syscall(SYS_geteuid);
return __llvm_libc::syscall_impl(SYS_geteuid);
}

} // namespace __llvm_libc
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/getpid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(pid_t, getpid, ()) {
return __llvm_libc::syscall(SYS_getpid);
return __llvm_libc::syscall_impl(SYS_getpid);
}

} // namespace __llvm_libc
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/getppid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(pid_t, getppid, ()) {
return __llvm_libc::syscall(SYS_getppid);
return __llvm_libc::syscall_impl(SYS_getppid);
}

} // namespace __llvm_libc
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/getuid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(uid_t, getuid, ()) {
return __llvm_libc::syscall(SYS_getuid);
return __llvm_libc::syscall_impl(SYS_getuid);
}

} // namespace __llvm_libc
6 changes: 3 additions & 3 deletions libc/src/unistd/linux/link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, link, (const char *path1, const char *path2)) {
#ifdef SYS_link
long ret = __llvm_libc::syscall(SYS_link, path1, path2);
long ret = __llvm_libc::syscall_impl(SYS_link, path1, path2);
#elif defined(SYS_linkat)
long ret =
__llvm_libc::syscall(SYS_linkat, AT_FDCWD, path1, AT_FDCWD, path2, 0);
long ret = __llvm_libc::syscall_impl(SYS_linkat, AT_FDCWD, path1, AT_FDCWD,
path2, 0);
#else
#error "SYS_link or SYS_linkat not available."
#endif
Expand Down
3 changes: 2 additions & 1 deletion libc/src/unistd/linux/linkat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, linkat,
(int fd1, const char *path1, int fd2, const char *path2,
int flags)) {
long ret = __llvm_libc::syscall(SYS_linkat, fd1, path1, fd2, path2, flags);
long ret =
__llvm_libc::syscall_impl(SYS_linkat, fd1, path1, fd2, path2, flags);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
6 changes: 3 additions & 3 deletions libc/src/unistd/linux/lseek.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(off_t, lseek, (int fd, off_t offset, int whence)) {
off_t result;
#ifdef SYS_lseek
long ret = __llvm_libc::syscall(SYS_lseek, fd, offset, whence);
long ret = __llvm_libc::syscall_impl(SYS_lseek, fd, offset, whence);
result = ret;
#elif defined(SYS__llseek)
long ret = __llvm_libc::syscall(SYS__llseek, fd, offset >> 32, offset,
&result, whence);
long ret = __llvm_libc::syscall_impl(SYS__llseek, fd, offset >> 32, offset,
&result, whence);
#else
#error "lseek and _llseek syscalls not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/pread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(ssize_t, pread,
(int fd, void *buf, size_t count, off_t offset)) {
long ret = __llvm_libc::syscall(SYS_pread64, fd, buf, count, offset);
long ret = __llvm_libc::syscall_impl(SYS_pread64, fd, buf, count, offset);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/pwrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(ssize_t, pwrite,
(int fd, const void *buf, size_t count, off_t offset)) {
long ret = __llvm_libc::syscall(SYS_pwrite64, fd, buf, count, offset);
long ret = __llvm_libc::syscall_impl(SYS_pwrite64, fd, buf, count, offset);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(ssize_t, read, (int fd, void *buf, size_t count)) {
long ret = __llvm_libc::syscall(SYS_read, fd, buf, count);
long ret = __llvm_libc::syscall_impl(SYS_read, fd, buf, count);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/unistd/linux/readlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ LLVM_LIBC_FUNCTION(ssize_t, readlink,
(const char *__restrict path, char *__restrict buf,
size_t bufsize)) {
#ifdef SYS_readlink
ssize_t ret = __llvm_libc::syscall(SYS_readlink, path, buf, bufsize);
ssize_t ret = __llvm_libc::syscall_impl(SYS_readlink, path, buf, bufsize);
#elif defined(SYS_readlinkat)
ssize_t ret =
__llvm_libc::syscall(SYS_readlinkat, AT_FDCWD, path, buf, bufsize);
__llvm_libc::syscall_impl(SYS_readlinkat, AT_FDCWD, path, buf, bufsize);
#else
#error "SYS_readlink or SYS_readlinkat not available."
#endif
Expand Down
3 changes: 2 additions & 1 deletion libc/src/unistd/linux/readlinkat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ namespace __llvm_libc {
LLVM_LIBC_FUNCTION(ssize_t, readlinkat,
(int fd, const char *__restrict path, char *__restrict buf,
size_t bufsize)) {
ssize_t ret = __llvm_libc::syscall(SYS_readlinkat, fd, path, buf, bufsize);
ssize_t ret =
__llvm_libc::syscall_impl(SYS_readlinkat, fd, path, buf, bufsize);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
5 changes: 3 additions & 2 deletions libc/src/unistd/linux/rmdir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, rmdir, (const char *path)) {
#ifdef SYS_rmdir
long ret = __llvm_libc::syscall(SYS_rmdir, path);
long ret = __llvm_libc::syscall_impl(SYS_rmdir, path);
#elif defined(SYS_unlinkat)
long ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
long ret =
__llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
#else
#error "rmdir and unlinkat syscalls not available."
#endif
Expand Down
4 changes: 2 additions & 2 deletions libc/src/unistd/linux/symlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, symlink, (const char *path1, const char *path2)) {
#ifdef SYS_symlink
long ret = __llvm_libc::syscall(SYS_symlink, path1, path2);
long ret = __llvm_libc::syscall_impl(SYS_symlink, path1, path2);
#elif defined(SYS_symlinkat)
long ret = __llvm_libc::syscall(SYS_symlinkat, path1, AT_FDCWD, path2);
long ret = __llvm_libc::syscall_impl(SYS_symlinkat, path1, AT_FDCWD, path2);
#else
#error "SYS_symlink or SYS_symlinkat not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/symlinkat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, symlinkat,
(const char *path1, int fd, const char *path2)) {
long ret = __llvm_libc::syscall(SYS_symlinkat, path1, fd, path2);
long ret = __llvm_libc::syscall_impl(SYS_symlinkat, path1, fd, path2);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
33 changes: 33 additions & 0 deletions libc/src/unistd/linux/syscall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Linux implementation of syscall -----------------------------------===//
//
// 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/syscall.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"

#include <errno.h>
#include <stdarg.h>

namespace __llvm_libc {

LLVM_LIBC_FUNCTION(long, __llvm_libc_syscall,
(long number, long arg1, long arg2, long arg3, long arg4,
long arg5, long arg6)) {
long ret =
__llvm_libc::syscall_impl(number, arg1, arg2, arg3, arg4, arg5, arg6);
// Syscalls may return large positive values that overflow, but will never
// return values between -4096 and -1
if (static_cast<unsigned long>(ret) > -4096UL) {
errno = -ret;
return -1;
}
return ret;
}

} // namespace __llvm_libc
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/truncate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, truncate, (const char *path, off_t len)) {
int ret = __llvm_libc::syscall(SYS_truncate, path, len);
int ret = __llvm_libc::syscall_impl(SYS_truncate, path, len);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/unistd/linux/unlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, unlink, (const char *path)) {
#ifdef SYS_unlink
long ret = __llvm_libc::syscall(SYS_unlink, path);
long ret = __llvm_libc::syscall_impl(SYS_unlink, path);
#elif defined(SYS_unlinkat)
long ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, 0);
long ret = __llvm_libc::syscall_impl(SYS_unlinkat, AT_FDCWD, path, 0);
#else
#error "Unlink syscalls not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/unlinkat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace __llvm_libc {

LLVM_LIBC_FUNCTION(int, unlinkat, (int dfd, const char *path, int flags)) {
#ifdef SYS_unlinkat
long ret = __llvm_libc::syscall(SYS_unlinkat, dfd, path, flags);
long ret = __llvm_libc::syscall_impl(SYS_unlinkat, dfd, path, flags);
#else
#error "unlinkat syscall not available."
#endif
Expand Down
2 changes: 1 addition & 1 deletion libc/src/unistd/linux/write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
namespace __llvm_libc {

LLVM_LIBC_FUNCTION(ssize_t, write, (int fd, const void *buf, size_t count)) {
long ret = __llvm_libc::syscall(SYS_write, fd, buf, count);
long ret = __llvm_libc::syscall_impl(SYS_write, fd, buf, count);
if (ret < 0) {
errno = -ret;
return -1;
Expand Down
22 changes: 22 additions & 0 deletions libc/src/unistd/syscall.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for syscall -----------------------*- 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_SYSCALL_H
#define LLVM_LIBC_SRC_UNISTD_SYSCALL_H

#include <stdarg.h>
#include <unistd.h>

namespace __llvm_libc {

long __llvm_libc_syscall(long number, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_UNISTD_SYSCALL_H
19 changes: 10 additions & 9 deletions libc/test/src/__support/OSUtil/linux/x86_64/syscall_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,29 @@ TEST(LlvmLibcX86_64_SyscallTest, APITest) {

using __llvm_libc::cpp::function;

function<long(long)> f([](long n) { return __llvm_libc::syscall(n); });
function<long(long)> f([](long n) { return __llvm_libc::syscall_impl(n); });
function<long(long, long)> f1(
[](long n, long a1) { return __llvm_libc::syscall(n, a1); });
function<long(long, long, long)> f2(
[](long n, long a1, long a2) { return __llvm_libc::syscall(n, a1, a2); });
[](long n, long a1) { return __llvm_libc::syscall_impl(n, a1); });
function<long(long, long, long)> f2([](long n, long a1, long a2) {
return __llvm_libc::syscall_impl(n, a1, a2);
});
function<long(long, long, long, long)> f3(
[](long n, long a1, long a2, long a3) {
return __llvm_libc::syscall(n, a1, a2, a3);
return __llvm_libc::syscall_impl(n, a1, a2, a3);
});
function<long(long, long, long, long, long)> f4(
[](long n, long a1, long a2, long a3, long a4) {
return __llvm_libc::syscall(n, a1, a2, a3, a4);
return __llvm_libc::syscall_impl(n, a1, a2, a3, a4);
});
function<long(long, long, long, long, long, long)> f5(
[](long n, long a1, long a2, long a3, long a4, long a5) {
return __llvm_libc::syscall(n, a1, a2, a3, a4, a5);
return __llvm_libc::syscall_impl(n, a1, a2, a3, a4, a5);
});
function<long(long, long, long, long, long, long, long)> f6(
[](long n, long a1, long a2, long a3, long a4, long a5, long a6) {
return __llvm_libc::syscall(n, a1, a2, a3, a4, a5, a6);
return __llvm_libc::syscall_impl(n, a1, a2, a3, a4, a5, a6);
});

function<long(long, void *)> not_long_type(
[](long n, void *a1) { return __llvm_libc::syscall(n, a1); });
[](long n, void *a1) { return __llvm_libc::syscall_impl(n, a1); });
}
4 changes: 2 additions & 2 deletions libc/test/src/sched/affinity_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ TEST(LlvmLibcSchedAffinityTest, SmokeTest) {
cpu_set_t mask;
errno = 0;
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
pid_t tid = __llvm_libc::syscall(SYS_gettid);
pid_t tid = __llvm_libc::syscall_impl(SYS_gettid);
ASSERT_GT(tid, pid_t(0));
// We just get and set the same mask.
ASSERT_THAT(__llvm_libc::sched_getaffinity(tid, sizeof(cpu_set_t), &mask),
Expand All @@ -30,7 +30,7 @@ TEST(LlvmLibcSchedAffinityTest, SmokeTest) {

TEST(LlvmLibcSchedAffinityTest, BadMask) {
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
pid_t tid = __llvm_libc::syscall(SYS_gettid);
pid_t tid = __llvm_libc::syscall_impl(SYS_gettid);

errno = 0;
ASSERT_THAT(__llvm_libc::sched_getaffinity(tid, sizeof(cpu_set_t), nullptr),
Expand Down
15 changes: 15 additions & 0 deletions libc/test/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,18 @@ add_libc_unittest(
DEPENDS
libc.src.unistd.geteuid
)

add_libc_unittest(
syscall_test
SUITE
libc_unistd_unittests
SRCS
syscall_test.cpp
DEPENDS
libc.src.unistd.__llvm_libc_syscall
libc.include.errno
libc.include.unistd
libc.include.fcntl
libc.include.sys_syscall
libc.test.errno_setter_matcher
)
115 changes: 115 additions & 0 deletions libc/test/src/unistd/syscall_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//===-- Unittests for syscalls --------------------------------------------===//
//
// 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/syscall.h"
#include "test/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/syscall.h> // For syscall numbers.
#include <unistd.h>

using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;

// We only do a smoke test here. Actual functionality tests are
// done by the unit tests of the syscall wrappers like mmap.
// The goal is to test syscalls with a wide number of args.

// There is no function named "syscall" in llvm-libc, we instead use a macro to
// set up the arguments properly. We still need to specify the namespace though
// because the macro generates a call to the actual internal function
// (__llvm_libc_syscall) which is inside the namespace.
TEST(LlvmLibcSyscallTest, TrivialCall) {
errno = 0;

ASSERT_GE(__llvm_libc::syscall(SYS_gettid), 0l);
ASSERT_EQ(errno, 0);
}

TEST(LlvmLibcSyscallTest, SymlinkCreateDestroy) {
constexpr const char LINK_VAL[] = "syscall_readlink_test_value";
constexpr const char LINK[] = "testdata/syscall_readlink.test.link";

ASSERT_GE(__llvm_libc::syscall(SYS_symlink, LINK_VAL, LINK), 0l);
ASSERT_EQ(errno, 0);

char buf[sizeof(LINK_VAL)];

ASSERT_GE(__llvm_libc::syscall(SYS_readlink, LINK, buf, sizeof(buf)), 0l);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_unlink, LINK), 0l);
ASSERT_EQ(errno, 0);
}

TEST(LlvmLibcSyscallTest, FileReadWrite) {
constexpr const char HELLO[] = "hello";
constexpr int HELLO_SIZE = sizeof(HELLO);

constexpr const char *TEST_FILE = "testdata/syscall_pread_pwrite.test";

int fd =
__llvm_libc::syscall(SYS_open, TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
ASSERT_GT(fd, 0);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_pwrite64, fd, HELLO, HELLO_SIZE, 0), 0l);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_fsync, fd), 0l);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_close, fd), 0l);
ASSERT_EQ(errno, 0);
}

TEST(LlvmLibcSyscallTest, FileLinkCreateDestroy) {
constexpr const char *TEST_DIR = "testdata";
constexpr const char *TEST_FILE = "syscall_linkat.test";
constexpr const char *TEST_FILE_PATH = "testdata/syscall_linkat.test";
constexpr const char *TEST_FILE_LINK = "syscall_linkat.test.link";
constexpr const char *TEST_FILE_LINK_PATH =
"testdata/syscall_linkat.test.link";

// The test strategy is as follows:
// 1. Create a normal file
// 2. Create a link to that file.
// 3. Open the link to check that the link was created.
// 4. Cleanup the file and its link.

int write_fd = __llvm_libc::syscall(SYS_open, TEST_FILE_PATH,
O_WRONLY | O_CREAT, S_IRWXU);
ASSERT_GT(write_fd, 0);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_close, write_fd), 0l);
ASSERT_EQ(errno, 0);

int dir_fd = __llvm_libc::syscall(SYS_open, TEST_DIR, O_DIRECTORY, 0);
ASSERT_GT(dir_fd, 0);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_linkat, dir_fd, TEST_FILE, dir_fd,
TEST_FILE_LINK, 0),
0l);
ASSERT_EQ(errno, 0);

int link_fd = __llvm_libc::syscall(SYS_open, TEST_FILE_LINK_PATH, O_PATH, 0);
ASSERT_GT(link_fd, 0);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_unlink, TEST_FILE_PATH), 0l);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_unlink, TEST_FILE_LINK_PATH), 0l);
ASSERT_EQ(errno, 0);

ASSERT_GE(__llvm_libc::syscall(SYS_close, dir_fd), 0l);
ASSERT_EQ(errno, 0);
}