[libc-commits] [libc] [llvm] [libc][NFC] Port raw syscall users to existing syscall_wrappers (PR #208039)
Mikhail R. Gadelha via libc-commits
libc-commits at lists.llvm.org
Wed Jul 8 08:25:59 PDT 2026
https://github.com/mikhailramalho updated https://github.com/llvm/llvm-project/pull/208039
>From b5b0a16cabfb183f82c560573a63e56629971db2 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Mon, 6 Jul 2026 22:26:14 -0300
Subject: [PATCH 1/4] [libc][NFC] Port raw syscall users to existing
syscall_wrappers
Several call sites still invoked syscall_impl directly (or carried
their own SYS_* fallback ladders) for syscalls that already have a
wrapper in src/__support/OSUtil/linux/syscall_wrappers:
- shm_unlink: drop the local SYS_unlink/SYS_unlinkat ladder, use
linux_syscalls::unlink (resolves the TODO).
- remove: use linux_syscalls::unlinkat.
- sched_getaffinity: use linux_syscalls::sched_getaffinity.
- ftok: use linux_syscalls::statx with the shared kernel_statx_types
and delete the private sys/ipc/linux/kernel_statx.h wrapper.
- File/linux/file.cpp, File/linux/dir.cpp, threads/linux/thread.cpp:
use the read/write/close wrappers.
No functional change intended.
---
libc/src/__support/File/linux/CMakeLists.txt | 4 +++
libc/src/__support/File/linux/dir.cpp | 7 ++--
libc/src/__support/File/linux/file.cpp | 29 ++++++++--------
.../__support/threads/linux/CMakeLists.txt | 3 ++
libc/src/__support/threads/linux/thread.cpp | 26 ++++++++------
libc/src/sched/linux/CMakeLists.txt | 3 +-
libc/src/sched/linux/sched_getaffinity.cpp | 14 ++++----
libc/src/stdio/linux/CMakeLists.txt | 4 +--
libc/src/stdio/linux/remove.cpp | 15 ++++----
libc/src/sys/ipc/linux/CMakeLists.txt | 15 ++------
libc/src/sys/ipc/linux/ftok.cpp | 12 ++++---
libc/src/sys/ipc/linux/kernel_statx.h | 34 -------------------
libc/src/sys/mman/linux/CMakeLists.txt | 1 +
libc/src/sys/mman/linux/shm_unlink.cpp | 23 ++++---------
.../llvm-project-overlay/libc/BUILD.bazel | 10 +++---
15 files changed, 82 insertions(+), 118 deletions(-)
delete mode 100644 libc/src/sys/ipc/linux/kernel_statx.h
diff --git a/libc/src/__support/File/linux/CMakeLists.txt b/libc/src/__support/File/linux/CMakeLists.txt
index ba64ecf41a76e..bd2a20439b999 100644
--- a/libc/src/__support/File/linux/CMakeLists.txt
+++ b/libc/src/__support/File/linux/CMakeLists.txt
@@ -13,8 +13,11 @@ add_object_library(
libc.include.sys_stat
libc.src.__support.CPP.new
libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
libc.src.__support.OSUtil.linux.syscall_wrappers.lseek
libc.src.__support.OSUtil.linux.syscall_wrappers.open
+ libc.src.__support.OSUtil.linux.syscall_wrappers.read
+ libc.src.__support.OSUtil.linux.syscall_wrappers.write
libc.src.__support.error_or
libc.src.__support.File.file
libc.src.errno.errno
@@ -31,6 +34,7 @@ add_object_library(
libc.hdr.sys_stat_macros
libc.src.__support.OSUtil.linux.stat.kernel_statx_types
libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
libc.src.__support.OSUtil.linux.syscall_wrappers.open
libc.src.__support.OSUtil.linux.syscall_wrappers.statx
libc.src.__support.OSUtil.linux.syscall_wrappers.fcntl
diff --git a/libc/src/__support/File/linux/dir.cpp b/libc/src/__support/File/linux/dir.cpp
index 77f9a51952c3b..e2b93271107c5 100644
--- a/libc/src/__support/File/linux/dir.cpp
+++ b/libc/src/__support/File/linux/dir.cpp
@@ -15,6 +15,7 @@
#include "hdr/fcntl_macros.h" // For open flags
#include "hdr/sys_stat_macros.h" // For S_ISDIR
#include "src/__support/OSUtil/linux/stat/kernel_statx_types.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/fcntl.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/statx.h"
@@ -42,9 +43,9 @@ ErrorOr<size_t> platform_fetch_dirents(int fd, cpp::span<uint8_t> buffer) {
}
int platform_closedir(int fd) {
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_close, fd);
- if (ret < 0)
- return static_cast<int>(-ret);
+ auto ret = linux_syscalls::close(fd);
+ if (!ret)
+ return ret.error();
return 0;
}
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index e89b3d118deb1..b022037673762 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -13,37 +13,36 @@
#include "src/__support/CPP/new.h"
#include "src/__support/File/file.h"
#include "src/__support/OSUtil/fcntl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/lseek.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/read.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/write.h"
#include "src/__support/alloc-checker.h"
#include "src/__support/libc_errno.h" // For error macros
#include "src/__support/macros/config.h"
#include "hdr/fcntl_macros.h" // For mode_t and other flags to the open syscall
#include <sys/stat.h> // For S_IS*, S_IF*, and S_IR* flags.
-#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
FileIOResult linux_file_write(File *f, const void *data, size_t size) {
auto *lf = reinterpret_cast<LinuxFile *>(f);
- int ret =
- LIBC_NAMESPACE::syscall_impl<int>(SYS_write, lf->get_fd(), data, size);
- if (ret < 0) {
- return {0, -ret};
+ auto ret = linux_syscalls::write(lf->get_fd(), data, size);
+ if (!ret) {
+ return {0, ret.error()};
}
- return ret;
+ return static_cast<size_t>(ret.value());
}
FileIOResult linux_file_read(File *f, void *buf, size_t size) {
auto *lf = reinterpret_cast<LinuxFile *>(f);
- int ret =
- LIBC_NAMESPACE::syscall_impl<int>(SYS_read, lf->get_fd(), buf, size);
- if (ret < 0) {
- return {0, -ret};
+ auto ret = linux_syscalls::read(lf->get_fd(), buf, size);
+ if (!ret) {
+ return {0, ret.error()};
}
- return ret;
+ return static_cast<size_t>(ret.value());
}
ErrorOr<off_t> linux_file_seek(File *f, off_t offset, int whence) {
@@ -54,9 +53,9 @@ ErrorOr<off_t> linux_file_seek(File *f, off_t offset, int whence) {
int linux_file_close(File *f) {
File::remove_file(f);
auto *lf = reinterpret_cast<LinuxFile *>(f);
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_close, lf->get_fd());
- if (ret < 0) {
- return -ret;
+ auto ret = linux_syscalls::close(lf->get_fd());
+ if (!ret) {
+ return ret.error();
}
delete lf;
return 0;
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index 8344c6c0462a3..f9f2a455cd7a1 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -41,10 +41,13 @@ add_object_library(
libc.src.__support.CPP.string_view
libc.src.__support.common
libc.src.__support.error_or
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
libc.src.__support.OSUtil.linux.syscall_wrappers.mprotect
libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
libc.src.__support.OSUtil.linux.syscall_wrappers.open
+ libc.src.__support.OSUtil.linux.syscall_wrappers.read
+ libc.src.__support.OSUtil.linux.syscall_wrappers.write
libc.src.__support.threads.thread_common
COMPILE_OPTIONS
${libc_opt_high_flag}
diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index 64e043862ff74..1983ff67768bc 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -11,10 +11,13 @@
#include "src/__support/CPP/atomic.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/CPP/stringstream.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/mmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/mprotect.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/read.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/write.h"
#include "src/__support/OSUtil/syscall.h" // For syscall functions.
#include "src/__support/common.h"
#include "src/__support/error_or.h"
@@ -435,13 +438,13 @@ int Thread::set_name(const cpp::string_view &name) {
if (!fd)
return fd.error();
- int retval = LIBC_NAMESPACE::syscall_impl<int>(SYS_write, fd.value(),
- name.data(), name.size());
- LIBC_NAMESPACE::syscall_impl<long>(SYS_close, fd.value());
+ auto write_result = linux_syscalls::write(fd.value(), name.data(),
+ name.size());
+ linux_syscalls::close(fd.value());
- if (retval < 0)
- return -retval;
- else if (retval != int(name.size()))
+ if (!write_result)
+ return write_result.error();
+ else if (write_result.value() != static_cast<ssize_t>(name.size()))
return EIO;
else
return 0;
@@ -471,11 +474,12 @@ int Thread::get_name(cpp::StringStream &name) const {
if (!fd)
return fd.error();
- int retval = LIBC_NAMESPACE::syscall_impl<int>(SYS_read, fd.value(),
- name_buffer, NAME_SIZE_MAX);
- LIBC_NAMESPACE::syscall_impl<long>(SYS_close, fd.value());
- if (retval < 0)
- return -retval;
+ auto read_result =
+ linux_syscalls::read(fd.value(), name_buffer, NAME_SIZE_MAX);
+ linux_syscalls::close(fd.value());
+ if (!read_result)
+ return read_result.error();
+ int retval = static_cast<int>(read_result.value());
if (retval == NAME_SIZE_MAX)
return ERANGE;
if (name_buffer[retval - 1] == '\n')
diff --git a/libc/src/sched/linux/CMakeLists.txt b/libc/src/sched/linux/CMakeLists.txt
index 9ffb59b8c0d06..85d298f311d38 100644
--- a/libc/src/sched/linux/CMakeLists.txt
+++ b/libc/src/sched/linux/CMakeLists.txt
@@ -20,7 +20,8 @@ add_entrypoint_object(
libc.hdr.types.cpu_set_t
libc.hdr.types.pid_t
libc.hdr.types.size_t
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.CPP.span
+ libc.src.__support.OSUtil.linux.syscall_wrappers.sched_getaffinity
libc.src.errno.errno
)
diff --git a/libc/src/sched/linux/sched_getaffinity.cpp b/libc/src/sched/linux/sched_getaffinity.cpp
index d652f7f7ddc35..ddb34aed5e3b4 100644
--- a/libc/src/sched/linux/sched_getaffinity.cpp
+++ b/libc/src/sched/linux/sched_getaffinity.cpp
@@ -9,7 +9,8 @@
#include "src/sched/sched_getaffinity.h"
#include "hdr/stdint_proxy.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/CPP/span.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/sched_getaffinity.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
@@ -17,18 +18,19 @@
#include "hdr/types/cpu_set_t.h"
#include "hdr/types/pid_t.h"
#include "hdr/types/size_t.h"
-#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, sched_getaffinity,
(pid_t tid, size_t cpuset_size, cpu_set_t *mask)) {
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_sched_getaffinity, tid,
- cpuset_size, mask);
- if (ret < 0) {
- libc_errno = -ret;
+ auto result = linux_syscalls::sched_getaffinity(
+ tid, cpp::span<unsigned char>(reinterpret_cast<unsigned char *>(mask),
+ cpuset_size));
+ if (!result) {
+ libc_errno = result.error();
return -1;
}
+ int ret = result.value();
if (size_t(ret) < cpuset_size) {
// This means that only |ret| bytes in |mask| have been set. We will have to
// zero out the remaining bytes.
diff --git a/libc/src/stdio/linux/CMakeLists.txt b/libc/src/stdio/linux/CMakeLists.txt
index 1552060c52550..218875c78e246 100644
--- a/libc/src/stdio/linux/CMakeLists.txt
+++ b/libc/src/stdio/linux/CMakeLists.txt
@@ -5,10 +5,10 @@ add_entrypoint_object(
HDRS
../remove.h
DEPENDS
+ libc.hdr.errno_macros
libc.hdr.fcntl_macros
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.unlinkat
libc.src.errno.errno
)
diff --git a/libc/src/stdio/linux/remove.cpp b/libc/src/stdio/linux/remove.cpp
index ac755db0bc781..2e1a581474359 100644
--- a/libc/src/stdio/linux/remove.cpp
+++ b/libc/src/stdio/linux/remove.cpp
@@ -8,26 +8,25 @@
#include "src/stdio/remove.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/unlinkat.h"
#include "src/__support/common.h"
+#include "hdr/errno_macros.h" // For EISDIR.
#include "hdr/fcntl_macros.h" // For AT_* macros.
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
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 = LIBC_NAMESPACE::syscall_impl<int>(SYS_unlinkat, AT_FDCWD, path, 0);
- if (ret == -EISDIR)
- ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_unlinkat, AT_FDCWD, path,
- AT_REMOVEDIR);
- if (ret >= 0)
+ auto ret = linux_syscalls::unlinkat(AT_FDCWD, path, 0);
+ if (!ret && ret.error() == EISDIR)
+ ret = linux_syscalls::unlinkat(AT_FDCWD, path, AT_REMOVEDIR);
+ if (ret)
return 0;
- libc_errno = -ret;
+ libc_errno = ret.error();
return -1;
}
diff --git a/libc/src/sys/ipc/linux/CMakeLists.txt b/libc/src/sys/ipc/linux/CMakeLists.txt
index d5b2d1b8ab77c..b237e998e6e2c 100644
--- a/libc/src/sys/ipc/linux/CMakeLists.txt
+++ b/libc/src/sys/ipc/linux/CMakeLists.txt
@@ -1,14 +1,3 @@
-add_header_library(
- kernel_statx
- HDRS
- kernel_statx.h
- DEPENDS
- libc.hdr.fcntl_macros
- libc.include.sys_syscall
- libc.src.__support.error_or
- libc.src.__support.OSUtil.osutil
-)
-
add_entrypoint_object(
ftok
SRCS
@@ -16,8 +5,10 @@ add_entrypoint_object(
HDRS
../ftok.h
DEPENDS
- .kernel_statx
+ libc.hdr.fcntl_macros
libc.hdr.types.key_t
+ libc.src.__support.OSUtil.linux.stat.kernel_statx_types
+ libc.src.__support.OSUtil.linux.syscall_wrappers.statx
libc.src.__support.common
libc.src.errno.errno
)
diff --git a/libc/src/sys/ipc/linux/ftok.cpp b/libc/src/sys/ipc/linux/ftok.cpp
index 28762ac6e33f1..1aa78292bfc62 100644
--- a/libc/src/sys/ipc/linux/ftok.cpp
+++ b/libc/src/sys/ipc/linux/ftok.cpp
@@ -7,18 +7,20 @@
//===----------------------------------------------------------------------===//
#include "src/sys/ipc/ftok.h"
+#include "hdr/fcntl_macros.h" // For AT_FDCWD.
+#include "src/__support/OSUtil/linux/stat/kernel_statx_types.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/statx.h"
#include "src/__support/common.h"
-#include "src/__support/error_or.h"
#include "src/__support/libc_errno.h"
-#include "kernel_statx.h"
-
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(key_t, ftok, (const char *path, int id)) {
- struct statx xbuf;
+ internal::kernel_statx_buf xbuf;
- ErrorOr<int> err = statx_for_ftok(path, xbuf);
+ auto err = linux_syscalls::statx(AT_FDCWD, path, 0,
+ internal::KERNEL_STATX_BASIC_STATS_MASK,
+ &xbuf);
if (!err.has_value()) {
libc_errno = err.error();
diff --git a/libc/src/sys/ipc/linux/kernel_statx.h b/libc/src/sys/ipc/linux/kernel_statx.h
deleted file mode 100644
index 7613e1b50f20d..0000000000000
--- a/libc/src/sys/ipc/linux/kernel_statx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===-- Wrapper over SYS_statx syscall for ftok ---------------------------===//
-//
-// 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_SYS_IPC_LINUX_KERNEL_STATX_H
-#define LLVM_LIBC_SRC_SYS_IPC_LINUX_KERNEL_STATX_H
-
-#include "hdr/fcntl_macros.h"
-#include "src/__support/OSUtil/syscall.h"
-#include "src/__support/error_or.h"
-#include "sys/syscall.h"
-
-#include <linux/stat.h>
-
-namespace LIBC_NAMESPACE_DECL {
-
-LIBC_INLINE ErrorOr<int> statx_for_ftok(const char *path, struct statx &xbuf) {
-
- // store the file stats metadata into xbuf
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_statx, AT_FDCWD, path, 0,
- STATX_BASIC_STATS, &xbuf);
-
- if (ret < 0)
- return Error(-ret);
- return 0;
-}
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_SYS_IPC_LINUX_KERNEL_STATX_H
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index e8d9ed384c9b0..6987261e53e07 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -306,6 +306,7 @@ add_entrypoint_object(
HDRS
../shm_unlink.h
DEPENDS
+ libc.src.__support.OSUtil.linux.syscall_wrappers.unlink
libc.src.errno.errno
.shm_common
)
diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index 7671b1918b83c..70eab7e9b4bff 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -8,37 +8,26 @@
#include "src/sys/mman/shm_unlink.h"
-#include "hdr/fcntl_macros.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
-#include "src/__support/libc_errno.h" // For internal errno.
+#include "src/__support/OSUtil/linux/syscall_wrappers/unlink.h"
+#include "src/__support/libc_errno.h" // For internal errno.
#include "src/__support/macros/config.h"
#include "src/sys/mman/linux/shm_common.h"
-#include <sys/syscall.h> // For SYS_unlink, SYS_unlinkat
namespace LIBC_NAMESPACE_DECL {
-// TODO: move the unlink syscall to a shared utility.
-
LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
auto path_result = shm_common::translate_name(name);
if (!path_result.has_value()) {
libc_errno = path_result.error();
return -1;
}
-#ifdef SYS_unlink
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_unlink, path_result->data());
-#elif defined(SYS_unlinkat)
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_unlinkat, AT_FDCWD,
- path_result->data(), 0);
-#else
-#error "unlink and unlinkat syscalls not available."
-#endif
- if (ret < 0) {
- libc_errno = -ret;
+ auto result = linux_syscalls::unlink(path_result->data());
+ if (!result) {
+ libc_errno = result.error();
return -1;
}
- return ret;
+ return 0;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 56ef8876c9e2d..59be503e06502 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -1553,9 +1553,11 @@ libc_support_library(
":__support_libc_errno",
":__support_macros_config",
":__support_osutil_fcntl",
+ ":__support_osutil_linux_syscall_wrappers_close",
":__support_osutil_linux_syscall_wrappers_lseek",
":__support_osutil_linux_syscall_wrappers_open",
- ":__support_osutil_syscall",
+ ":__support_osutil_linux_syscall_wrappers_read",
+ ":__support_osutil_linux_syscall_wrappers_write",
":hdr_fcntl_macros",
":hdr_stdint_proxy",
":hdr_stdio_macros",
@@ -15447,8 +15449,9 @@ libc_function(
":__support_common",
":__support_libc_errno",
":__support_macros_config",
- ":__support_osutil_syscall",
+ ":__support_osutil_linux_syscall_wrappers_unlinkat",
":errno",
+ ":hdr_errno_macros",
":hdr_fcntl_macros",
":hdr_stdio_overlay",
":types_FILE",
@@ -15835,9 +15838,8 @@ libc_function(
":__support_common",
":__support_libc_errno",
":__support_macros_config",
- ":__support_osutil_syscall",
+ ":__support_osutil_linux_syscall_wrappers_unlink",
":errno",
- ":hdr_fcntl_macros",
":shm_common",
":types_mode_t",
],
>From 3dcb792c8521a6bfb160f1127d7602473e58b7ba Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Tue, 7 Jul 2026 12:37:01 -0300
Subject: [PATCH 2/4] [libc][NFC] Port more raw syscall users to existing
syscall_wrappers
Use the read/close wrappers in auxv.h, the close wrapper in posix_spawn,
and the getrandom wrapper in the x86_64 startup TLS setup (safe pre-TLS
since wrappers report errors via ErrorOr, not errno). Also drop the
redundant SYS_utimensat guard in utimes.cpp; the wrapper owns syscall
selection and already has the #error fallback.
---
.../src/__support/OSUtil/linux/CMakeLists.txt | 3 +++
libc/src/__support/OSUtil/linux/auxv.h | 21 ++++++++++++-------
libc/src/spawn/linux/CMakeLists.txt | 1 +
libc/src/spawn/linux/posix_spawn.cpp | 3 ++-
libc/src/sys/time/linux/CMakeLists.txt | 2 --
libc/src/sys/time/linux/utimes.cpp | 8 -------
libc/startup/linux/x86_64/CMakeLists.txt | 1 +
libc/startup/linux/x86_64/tls.cpp | 11 +++++-----
8 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 1f11067f0154f..b237cc0a811ef 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -32,12 +32,15 @@ add_header_library(
HDRS
auxv.h
DEPENDS
+ libc.hdr.errno_macros
libc.hdr.fcntl_macros
libc.hdr.sys_auxv_macros
libc.hdr.sys_mman_macros
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
libc.src.__support.OSUtil.linux.syscall_wrappers.open
+ libc.src.__support.OSUtil.linux.syscall_wrappers.read
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.__support.CPP.optional
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
index b4c990f9721bc..a6c28e078fdb8 100644
--- a/libc/src/__support/OSUtil/linux/auxv.h
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -9,12 +9,15 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AUXV_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AUXV_H
+#include "hdr/errno_macros.h" // For EINTR
#include "hdr/fcntl_macros.h" // For open flags
#include "hdr/sys_auxv_macros.h" // For AT_ macros
#include "hdr/sys_mman_macros.h" // For mmap flags
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/mmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/read.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/common.h"
#include "src/__support/threads/callonce.h"
@@ -122,18 +125,20 @@ LIBC_INLINE void Vector::fallback_initialize_unsync() {
uint8_t *cursor = reinterpret_cast<uint8_t *>(vector);
bool has_error = false;
while (avaiable_size != 0) {
- long bytes_read =
- syscall_impl<long>(SYS_read, fd.value(), cursor, avaiable_size);
- if (bytes_read <= 0) {
- if (bytes_read == -EINTR)
+ ErrorOr<ssize_t> bytes_read =
+ linux_syscalls::read(fd.value(), cursor, avaiable_size);
+ if (!bytes_read.has_value()) {
+ if (bytes_read.error() == EINTR)
continue;
- has_error = bytes_read < 0;
+ has_error = true;
break;
}
- avaiable_size -= bytes_read;
- cursor += bytes_read;
+ if (bytes_read.value() == 0)
+ break;
+ avaiable_size -= bytes_read.value();
+ cursor += bytes_read.value();
}
- syscall_impl<long>(SYS_close, fd.value());
+ linux_syscalls::close(fd.value());
if (has_error) {
linux_syscalls::munmap(vector, AUXV_MMAP_SIZE);
return;
diff --git a/libc/src/spawn/linux/CMakeLists.txt b/libc/src/spawn/linux/CMakeLists.txt
index 42057e9f12fec..6d1db1a2a1ec4 100644
--- a/libc/src/spawn/linux/CMakeLists.txt
+++ b/libc/src/spawn/linux/CMakeLists.txt
@@ -11,6 +11,7 @@ add_entrypoint_object(
libc.include.sys_syscall
libc.include.signal
libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
libc.src.__support.OSUtil.linux.syscall_wrappers.open
libc.src.spawn.file_actions
libc.src.signal.linux.signal_utils
diff --git a/libc/src/spawn/linux/posix_spawn.cpp b/libc/src/spawn/linux/posix_spawn.cpp
index 301be6d7c8762..75084a94f26f0 100644
--- a/libc/src/spawn/linux/posix_spawn.cpp
+++ b/libc/src/spawn/linux/posix_spawn.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/spawn/posix_spawn.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
@@ -39,7 +40,7 @@ pid_t fork() {
#endif
}
-void close(int fd) { LIBC_NAMESPACE::syscall_impl<long>(SYS_close, fd); }
+void close(int fd) { linux_syscalls::close(fd); }
// We use dup3 if dup2 is not available, similar to our implementation of dup2
bool dup2(int fd, int newfd) {
diff --git a/libc/src/sys/time/linux/CMakeLists.txt b/libc/src/sys/time/linux/CMakeLists.txt
index 60fbd14f73174..52724268c73ba 100644
--- a/libc/src/sys/time/linux/CMakeLists.txt
+++ b/libc/src/sys/time/linux/CMakeLists.txt
@@ -8,10 +8,8 @@ add_entrypoint_object(
libc.hdr.types.struct_timespec
libc.hdr.types.struct_timeval
libc.hdr.fcntl_macros
- libc.src.__support.OSUtil.osutil
libc.src.__support.OSUtil.linux.syscall_wrappers.utimensat
libc.include.sys_stat
- libc.include.sys_syscall
libc.include.fcntl
libc.src.__support.libc_errno
)
diff --git a/libc/src/sys/time/linux/utimes.cpp b/libc/src/sys/time/linux/utimes.cpp
index abb56183cf7c3..02101c3e38314 100644
--- a/libc/src/sys/time/linux/utimes.cpp
+++ b/libc/src/sys/time/linux/utimes.cpp
@@ -13,17 +13,12 @@
#include "hdr/types/struct_timeval.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/utimensat.h"
-#include "src/__support/OSUtil/syscall.h"
#include "src/__support/libc_errno.h"
-#include <sys/syscall.h>
-
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, utimes,
(const char *path, const struct timeval times[2])) {
-#if defined(SYS_utimensat) || defined(SYS_utimensat_time64)
-
// the utimensat syscall requires a timespec struct, not timeval.
struct timespec ts[2];
struct timespec *ts_ptr = nullptr; // default value if times is nullptr
@@ -64,8 +59,5 @@ LLVM_LIBC_FUNCTION(int, utimes,
}
return 0;
-#else
-#error "utimensat or utimensat_time64 syscalls not available."
-#endif // SYS_utimensat || SYS_utimensat_time64
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/startup/linux/x86_64/CMakeLists.txt b/libc/startup/linux/x86_64/CMakeLists.txt
index 12dc0eeef42e9..19417b345d7cf 100644
--- a/libc/startup/linux/x86_64/CMakeLists.txt
+++ b/libc/startup/linux/x86_64/CMakeLists.txt
@@ -7,6 +7,7 @@ add_startup_object(
libc.hdr.sys_mman_macros
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.getrandom
libc.src.__support.OSUtil.linux.syscall_wrappers.mmap
libc.src.__support.OSUtil.linux.syscall_wrappers.munmap
libc.src.string.memory_utils.inline_memcpy
diff --git a/libc/startup/linux/x86_64/tls.cpp b/libc/startup/linux/x86_64/tls.cpp
index 7856bdd14daae..98c5fbeb9d84b 100644
--- a/libc/startup/linux/x86_64/tls.cpp
+++ b/libc/startup/linux/x86_64/tls.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "hdr/sys_mman_macros.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/getrandom.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/mmap.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
#include "src/__support/macros/config.h"
@@ -57,11 +58,11 @@ void init_tls(TLSDescriptor &tls_descriptor) {
// Setting the stack guard to a random value.
// We cannot call the get_random function here as the function sets errno on
// failure. Since errno is implemented via a thread local variable, we cannot
- // use errno before TLS is setup.
- long stack_guard_retval =
- syscall_impl(SYS_getrandom, reinterpret_cast<long>(stack_guard_addr),
- sizeof(uint64_t), 0);
- if (stack_guard_retval < 0)
+ // use errno before TLS is setup. The linux_syscalls wrapper is safe as it
+ // reports errors via ErrorOr instead of errno.
+ ErrorOr<ssize_t> stack_guard_retval =
+ linux_syscalls::getrandom(stack_guard_addr, sizeof(uint64_t), 0);
+ if (!stack_guard_retval.has_value())
syscall_impl(SYS_exit, 1);
tls_descriptor = {tls_size_with_addr, reinterpret_cast<uintptr_t>(tls_addr),
>From 93b087d1cc2d5a84d9edad194844321bb88a3d9e Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Tue, 7 Jul 2026 12:40:51 -0300
Subject: [PATCH 3/4] [libc][bazel] Add missing auxv deps for syscall wrapper
port
Follow-up to 3dcb792c8521: mirror the new close/read wrapper and
errno_macros dependencies of auxv.h in the Bazel overlay.
---
utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 3 +++
1 file changed, 3 insertions(+)
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 59be503e06502..b749584409395 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2715,11 +2715,14 @@ libc_support_library(
}),
deps = [
":__support_common",
+ ":__support_osutil_linux_syscall_wrappers_close",
":__support_osutil_linux_syscall_wrappers_mmap",
":__support_osutil_linux_syscall_wrappers_munmap",
":__support_osutil_linux_syscall_wrappers_open",
+ ":__support_osutil_linux_syscall_wrappers_read",
":__support_osutil_syscall",
":__support_threads_callonce",
+ ":hdr_errno_macros",
":hdr_fcntl_macros",
":hdr_sys_auxv_macros",
":hdr_sys_mman_macros",
>From 8834f42249f2f9db94e6bd3149759cc9c53342cf Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Wed, 8 Jul 2026 12:25:02 -0300
Subject: [PATCH 4/4] [libc][NFC] Drop the close helper in posix_spawn
The helper became a trivial forward to linux_syscalls::close after the
syscall wrapper port, and the dup2 equivalent was already removed when
posix_spawn switched to calling the wrappers directly.
---
libc/src/spawn/linux/posix_spawn.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/libc/src/spawn/linux/posix_spawn.cpp b/libc/src/spawn/linux/posix_spawn.cpp
index ce752b3de834e..17f985cbc9fc7 100644
--- a/libc/src/spawn/linux/posix_spawn.cpp
+++ b/libc/src/spawn/linux/posix_spawn.cpp
@@ -41,8 +41,6 @@ pid_t fork() {
#endif
}
-void close(int fd) { linux_syscalls::close(fd); }
-
// All exits from child_process are error exits. So, we use a simple
// exit implementation which exits with code 127.
void exit() {
@@ -76,7 +74,7 @@ void child_process(const char *__restrict path,
if (actual_fd != open_act->fd) {
bool dup2_result =
linux_syscalls::dup2(actual_fd, open_act->fd).has_value();
- close(actual_fd); // The old fd is not needed anymore.
+ linux_syscalls::close(actual_fd); // The old fd is not needed anymore.
if (!dup2_result)
exit();
}
@@ -84,7 +82,7 @@ void child_process(const char *__restrict path,
}
case BaseSpawnFileAction::CLOSE: {
auto *close_act = reinterpret_cast<SpawnFileCloseAction *>(act);
- close(close_act->fd);
+ linux_syscalls::close(close_act->fd);
break;
}
case BaseSpawnFileAction::DUP2: {
More information about the libc-commits
mailing list