[libc-commits] [libc] [libc] Refactor core Linux syscalls to use syscall_wrappers (PR #185983)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Tue Mar 17 08:15:33 PDT 2026
https://github.com/kaladron updated https://github.com/llvm/llvm-project/pull/185983
>From 3ed3d95cef99ea62188e8381058e0062a468a7fc Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Wed, 11 Mar 2026 20:27:50 +0000
Subject: [PATCH 1/2] [libc] Refactor core Linux syscalls to use
syscall_wrappers
This patch initiates the refactoring of Linux syscalls as described in
the RFC (https://discourse.llvm.org/t/rfc-linux-syscall-cleanup/87248/).
It introduces a new infrastructure in `src/__support/OSUtil/linux/syscall_wrappers/`
to house header-only syscall wrappers. These wrappers utilize `ErrorOr`
to provide a consistent, type-safe interface for error handling across
the library, standardizing how syscall return values are converted into
errno-compatible Error objects.
Summary of changes:
- Created the `syscall_wrappers` directory and added `close.h`, `read.h`,
`write.h`, and `open.h`.
- Moved the existing `getrandom.h` into the new `syscall_wrappers`
directory and updated its callers (including HashTable/randomness.h).
- Refactored core entrypoints (`close`, `read`, `write`, `open`) to use
the new wrappers, removing direct `syscall_impl` logic and manual
errno setting.
- Updated `shm_open.cpp` to use the new `open` wrapper.
- Cleaned up `OSUtil/linux/fcntl.cpp` by removing redundant internal
implementations of `open` and `close`.
- Added a developer guide in `docs/dev/syscall_wrapper_refactor.rst`
outlining the established pattern for future migrations.
Co-authored-by: Michael Jones <michaelrj at google.com>
---
libc/docs/dev/index.rst | 1 +
libc/docs/dev/syscall_wrapper_refactor.rst | 68 +++++++++++++++++++
libc/src/__support/HashTable/CMakeLists.txt | 2 +-
libc/src/__support/HashTable/randomness.h | 2 +-
.../src/__support/OSUtil/linux/CMakeLists.txt | 1 +
libc/src/__support/OSUtil/linux/fcntl.cpp | 22 ------
.../linux/syscall_wrappers/CMakeLists.txt | 64 +++++++++++++++++
.../OSUtil/linux/syscall_wrappers/close.h | 31 +++++++++
.../OSUtil/linux/syscall_wrappers/getrandom.h | 33 +++++++++
.../OSUtil/linux/syscall_wrappers/open.h | 37 ++++++++++
.../{getrandom.h => syscall_wrappers/read.h} | 17 ++---
.../OSUtil/linux/syscall_wrappers/write.h | 32 +++++++++
libc/src/fcntl/linux/CMakeLists.txt | 2 +-
libc/src/fcntl/linux/open.cpp | 2 +-
libc/src/sys/mman/linux/CMakeLists.txt | 2 +
libc/src/sys/mman/linux/shm_open.cpp | 2 +-
libc/src/sys/random/linux/CMakeLists.txt | 3 +-
libc/src/sys/random/linux/getrandom.cpp | 3 +-
libc/src/unistd/linux/CMakeLists.txt | 9 +--
libc/src/unistd/linux/close.cpp | 3 +-
libc/src/unistd/linux/read.cpp | 11 ++-
libc/src/unistd/linux/write.cpp | 13 ++--
22 files changed, 297 insertions(+), 63 deletions(-)
create mode 100644 libc/docs/dev/syscall_wrapper_refactor.rst
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/close.h
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/open.h
rename libc/src/__support/OSUtil/linux/{getrandom.h => syscall_wrappers/read.h} (60%)
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/write.h
diff --git a/libc/docs/dev/index.rst b/libc/docs/dev/index.rst
index 91fb0b682e469..c0085e63cbadb 100644
--- a/libc/docs/dev/index.rst
+++ b/libc/docs/dev/index.rst
@@ -21,3 +21,4 @@ Navigate to the links below for information on the respective topics:
implementation_standard
undefined_behavior
printf_behavior
+ syscall_wrapper_refactor
diff --git a/libc/docs/dev/syscall_wrapper_refactor.rst b/libc/docs/dev/syscall_wrapper_refactor.rst
new file mode 100644
index 0000000000000..edfcc69a25849
--- /dev/null
+++ b/libc/docs/dev/syscall_wrapper_refactor.rst
@@ -0,0 +1,68 @@
+.. _syscall_wrapper_refactor:
+
+==============================
+Syscall Wrapper Refactoring
+==============================
+
+Purpose
+=======
+
+LLVM-libc is transitioning to a centralized system for Linux syscalls. The goal
+is to move all direct ``syscall_impl`` calls into a dedicated directory:
+``src/__support/OSUtil/linux/syscall_wrappers/``.
+
+This refactor provides several benefits:
+
+* **Type Safety**: Using ``ErrorOr<T>`` ensures that error conditions are
+ handled explicitly.
+* **Consistency**: Standardizes the conversion of syscall return values into
+ errno-compatible objects.
+* **Maintainability**: Centralizes platform-specific syscall logic, making it
+ easier to audit and update.
+
+The Pattern
+===========
+
+Each syscall should have its own header-only library in the ``syscall_wrappers``
+directory. The wrapper function should return an ``ErrorOr<T>``.
+
+Example Wrapper (``src/__support/OSUtil/linux/syscall_wrappers/read.h``):
+--------------------------------------------------------------------------
+
+.. code-block:: c++
+
+ #include "src/__support/OSUtil/linux/syscall.h" // For syscall_impl
+ #include "src/__support/error_or.h"
+ #include "src/__support/common.h"
+ #include <sys/syscall.h> // For syscall numbers
+
+ namespace LIBC_NAMESPACE_DECL {
+ namespace internal {
+
+ LIBC_INLINE ErrorOr<ssize_t> read(int fd, void *buf, size_t count) {
+ ssize_t ret = syscall_impl<ssize_t>(SYS_read, fd, buf, count);
+ if (ret < 0) {
+ return Error(-static_cast<int>(ret));
+ }
+ return ret;
+ }
+
+ } // namespace internal
+ } // namespace LIBC_NAMESPACE_DECL
+
+How to Migrate
+==============
+
+1. **Create the Wrapper**: Add a new header file in
+ ``src/__support/OSUtil/linux/syscall_wrappers/``.
+2. **Update CMake**: Add a ``add_header_library`` target for the new wrapper in
+ ``src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt``.
+3. **Refactor Entrypoints**:
+
+ * Include the new wrapper header (e.g., ``read.h``).
+ * Replace direct ``syscall_impl`` calls with ``internal::<function_name>``.
+ * Update the entrypoint's ``DEPENDS`` in ``CMakeLists.txt`` to include the
+ new wrapper target.
+
+4. **Cleanup OSUtil**: If the syscall was previously implemented manually in
+ ``OSUtil/linux/fcntl.cpp`` (or similar), remove it to avoid name collisions.
diff --git a/libc/src/__support/HashTable/CMakeLists.txt b/libc/src/__support/HashTable/CMakeLists.txt
index d5861e7e825c2..82e88c02ae443 100644
--- a/libc/src/__support/HashTable/CMakeLists.txt
+++ b/libc/src/__support/HashTable/CMakeLists.txt
@@ -16,7 +16,7 @@ if (NOT ${getrandom_index} EQUAL -1)
message(STATUS "Using getrandom for hashtable randomness")
set(randomness_compile_flags -DLIBC_HASHTABLE_USE_GETRANDOM)
set(randomness_extra_depends
- libc.src.__support.OSUtil.linux.getrandom
+ libc.src.__support.OSUtil.linux.syscall_wrappers.getrandom
libc.hdr.errno_macros)
endif()
diff --git a/libc/src/__support/HashTable/randomness.h b/libc/src/__support/HashTable/randomness.h
index 7e54c9aa6ad1f..912b27629b533 100644
--- a/libc/src/__support/HashTable/randomness.h
+++ b/libc/src/__support/HashTable/randomness.h
@@ -15,7 +15,7 @@
#include "src/__support/macros/config.h"
#if defined(LIBC_HASHTABLE_USE_GETRANDOM)
#include "hdr/errno_macros.h"
-#include "src/__support/OSUtil/linux/getrandom.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/getrandom.h"
#endif
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 406c618eaba1c..8a686d4bce7dc 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -3,6 +3,7 @@ if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
endif()
add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
+add_subdirectory(syscall_wrappers)
add_object_library(
linux_util
diff --git a/libc/src/__support/OSUtil/linux/fcntl.cpp b/libc/src/__support/OSUtil/linux/fcntl.cpp
index 08db4859c6417..a31cb4ae3f600 100644
--- a/libc/src/__support/OSUtil/linux/fcntl.cpp
+++ b/libc/src/__support/OSUtil/linux/fcntl.cpp
@@ -116,27 +116,5 @@ ErrorOr<int> fcntl(int fd, int cmd, void *arg) {
return ret;
}
-ErrorOr<int> open(const char *path, int flags, mode_t mode_flags) {
-#ifdef SYS_open
- int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_open, path, flags, mode_flags);
-#else
- int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_openat, AT_FDCWD, path, flags,
- mode_flags);
-#endif
- if (fd < 0)
- return Error(-fd);
-
- return fd;
-}
-
-ErrorOr<int> close(int fd) {
- int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_close, fd);
-
- if (ret < 0)
- return Error(-ret);
-
- return ret;
-}
-
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
new file mode 100644
index 0000000000000..8bc266941347a
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -0,0 +1,64 @@
+add_header_library(
+ getrandom
+ HDRS
+ getrandom.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.hdr.types.ssize_t
+ libc.include.sys_syscall
+)
+
+add_header_library(
+ close
+ HDRS
+ close.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.include.sys_syscall
+)
+
+add_header_library(
+ read
+ HDRS
+ read.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.hdr.types.ssize_t
+ libc.include.sys_syscall
+)
+
+add_header_library(
+ write
+ HDRS
+ write.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.hdr.types.ssize_t
+ libc.include.sys_syscall
+)
+
+add_header_library(
+ open
+ HDRS
+ open.h
+ DEPENDS
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.hdr.fcntl_macros
+ libc.hdr.types.mode_t
+ libc.include.sys_syscall
+)
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h
new file mode 100644
index 0000000000000..b40b82a350d34
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h
@@ -0,0 +1,31 @@
+//===-- Implementation header for close -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CLOSE_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CLOSE_H
+
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+LIBC_INLINE ErrorOr<int> close(int fd) {
+ int ret = syscall_impl<int>(SYS_close, fd);
+ if (ret < 0)
+ return Error(-static_cast<int>(ret));
+ return ret;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CLOSE_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h
new file mode 100644
index 0000000000000..e06f53b3bef7b
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h
@@ -0,0 +1,33 @@
+//===-- Implementation header for getrandom ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_GETRANDOM_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_GETRANDOM_H
+
+#include "hdr/types/ssize_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+LIBC_INLINE ErrorOr<ssize_t> getrandom(void *buf, size_t buflen,
+ unsigned int flags) {
+ ssize_t ret = syscall_impl<ssize_t>(SYS_getrandom, buf, buflen, flags);
+ if (ret < 0)
+ return Error(-static_cast<int>(ret));
+ return ret;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_GETRANDOM_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h
new file mode 100644
index 0000000000000..3fad38cb1e86d
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h
@@ -0,0 +1,37 @@
+//===-- Implementation header for open --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_OPEN_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_OPEN_H
+
+#include "hdr/fcntl_macros.h"
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+LIBC_INLINE ErrorOr<int> open(const char *path, int flags, mode_t mode_flags) {
+#ifdef SYS_open
+ int fd = syscall_impl<int>(SYS_open, path, flags, mode_flags);
+#else
+ int fd = syscall_impl<int>(SYS_openat, AT_FDCWD, path, flags, mode_flags);
+#endif
+ if (fd < 0)
+ return Error(-fd);
+ return fd;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_OPEN_H
diff --git a/libc/src/__support/OSUtil/linux/getrandom.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/read.h
similarity index 60%
rename from libc/src/__support/OSUtil/linux/getrandom.h
rename to libc/src/__support/OSUtil/linux/syscall_wrappers/read.h
index 793639472fee7..7cdb5393a7756 100644
--- a/libc/src/__support/OSUtil/linux/getrandom.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/read.h
@@ -1,4 +1,4 @@
-//===------------ Implementation of getrandom function ----------*- C++ -*-===//
+//===-- Implementation header for read --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_GETRANDOM_H
-#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_GETRANDOM_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_READ_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_READ_H
#include "hdr/types/ssize_t.h"
#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
@@ -19,17 +19,14 @@
namespace LIBC_NAMESPACE_DECL {
namespace internal {
-LIBC_INLINE static ErrorOr<ssize_t> getrandom(void *buf, size_t buflen,
- unsigned int flags) {
- ssize_t ret =
- LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_getrandom, buf, buflen, flags);
- if (ret < 0) {
+LIBC_INLINE ErrorOr<ssize_t> read(int fd, void *buf, size_t count) {
+ ssize_t ret = syscall_impl<ssize_t>(SYS_read, fd, buf, count);
+ if (ret < 0)
return Error(-static_cast<int>(ret));
- }
return ret;
}
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
-#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_GETRANDOM_H
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_READ_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h
new file mode 100644
index 0000000000000..3a1b442e08a3c
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h
@@ -0,0 +1,32 @@
+//===-- Implementation header for write -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_WRITE_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_WRITE_H
+
+#include "hdr/types/ssize_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+LIBC_INLINE ErrorOr<ssize_t> write(int fd, const void *buf, size_t count) {
+ ssize_t ret = syscall_impl<ssize_t>(SYS_write, fd, buf, count);
+ if (ret < 0)
+ return Error(-static_cast<int>(ret));
+ return ret;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_WRITE_H
diff --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt
index c31eb3f438c10..4c151edc0ab49 100644
--- a/libc/src/fcntl/linux/CMakeLists.txt
+++ b/libc/src/fcntl/linux/CMakeLists.txt
@@ -31,7 +31,7 @@ add_entrypoint_object(
DEPENDS
libc.hdr.types.mode_t
libc.hdr.fcntl_macros
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.open
libc.src.errno.errno
)
diff --git a/libc/src/fcntl/linux/open.cpp b/libc/src/fcntl/linux/open.cpp
index 3a56d10554198..a759e93dcfee5 100644
--- a/libc/src/fcntl/linux/open.cpp
+++ b/libc/src/fcntl/linux/open.cpp
@@ -10,7 +10,7 @@
#include "hdr/fcntl_macros.h"
#include "hdr/types/mode_t.h"
-#include "src/__support/OSUtil/fcntl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 97c116f1d2e79..4c90ca0f01549 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -293,8 +293,10 @@ add_entrypoint_object(
HDRS
../shm_open.h
DEPENDS
+ libc.hdr.fcntl_macros
libc.hdr.types.mode_t
libc.src.errno.errno
+ libc.src.__support.OSUtil.linux.syscall_wrappers.open
.shm_common
)
diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index 46231ba1279a8..37dc512cfec20 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -10,7 +10,7 @@
#include "hdr/fcntl_macros.h"
#include "hdr/types/mode_t.h"
-#include "src/__support/OSUtil/fcntl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/sys/mman/linux/shm_common.h"
diff --git a/libc/src/sys/random/linux/CMakeLists.txt b/libc/src/sys/random/linux/CMakeLists.txt
index 474e275ee597a..60f6e486967ad 100644
--- a/libc/src/sys/random/linux/CMakeLists.txt
+++ b/libc/src/sys/random/linux/CMakeLists.txt
@@ -6,7 +6,6 @@ add_entrypoint_object(
../getrandom.h
DEPENDS
libc.include.sys_random
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.getrandom
libc.src.errno.errno
)
diff --git a/libc/src/sys/random/linux/getrandom.cpp b/libc/src/sys/random/linux/getrandom.cpp
index 4a95bddfa428e..789055b38fb0a 100644
--- a/libc/src/sys/random/linux/getrandom.cpp
+++ b/libc/src/sys/random/linux/getrandom.cpp
@@ -8,8 +8,7 @@
#include "src/sys/random/getrandom.h"
-#include "src/__support/OSUtil/linux/getrandom.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/getrandom.h"
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/libc_errno.h"
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 560c78552fec8..a5006fd6e9e63 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -47,8 +47,7 @@ add_entrypoint_object(
../close.h
DEPENDS
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
libc.src.errno.errno
)
@@ -502,8 +501,7 @@ add_entrypoint_object(
libc.hdr.types.ssize_t
libc.hdr.fcntl_macros
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.read
libc.src.__support.macros.sanitizer
libc.src.errno.errno
)
@@ -674,8 +672,7 @@ add_entrypoint_object(
libc.hdr.types.ssize_t
libc.hdr.fcntl_macros
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.src.__support.OSUtil.linux.syscall_wrappers.write
libc.src.errno.errno
)
diff --git a/libc/src/unistd/linux/close.cpp b/libc/src/unistd/linux/close.cpp
index 6ef3a3c6d63f0..c8ab7fe5e5eef 100644
--- a/libc/src/unistd/linux/close.cpp
+++ b/libc/src/unistd/linux/close.cpp
@@ -8,11 +8,10 @@
#include "src/unistd/close.h"
-#include "src/__support/OSUtil/fcntl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp
index 55676f3f7010a..4ac385b8149b7 100644
--- a/libc/src/unistd/linux/read.cpp
+++ b/libc/src/unistd/linux/read.cpp
@@ -8,25 +8,24 @@
#include "src/unistd/read.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/read.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON
-#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, read, (int fd, void *buf, size_t count)) {
- ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_read, fd, buf, count);
- if (ret < 0) {
- libc_errno = static_cast<int>(-ret);
+ auto result = internal::read(fd, buf, count);
+ if (!result.has_value()) {
+ libc_errno = result.error();
return -1;
}
// The cast is important since there is a check that dereferences the pointer
// which fails on void*.
MSAN_UNPOISON(reinterpret_cast<char *>(buf), count);
- return ret;
+ return result.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/write.cpp b/libc/src/unistd/linux/write.cpp
index eecb74429182a..30cea7d0c0845 100644
--- a/libc/src/unistd/linux/write.cpp
+++ b/libc/src/unistd/linux/write.cpp
@@ -8,23 +8,20 @@
#include "src/unistd/write.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/write.h"
#include "src/__support/common.h"
#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(ssize_t, write, (int fd, const void *buf, size_t count)) {
- ssize_t ret =
- LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_write, fd, buf, count);
- if (ret < 0) {
- libc_errno = static_cast<int>(-ret);
+ auto result = internal::write(fd, buf, count);
+ if (!result.has_value()) {
+ libc_errno = result.error();
return -1;
}
- return ret;
+ return result.value();
}
} // namespace LIBC_NAMESPACE_DECL
>From 087170883fdb2bac7b91ca4a96a46c9c526e6e17 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Tue, 17 Mar 2026 14:46:21 +0000
Subject: [PATCH 2/2] Address review feedback on syscall wrappers
- Add Reusability to the Purpose section of the developer guide, as
suggested by vonosmas.
- Rename namespace from 'internal' to 'linux_syscalls' to make call
sites self-documenting and clearly identify OS-specific code.
Note: 'linux' cannot be used as a bare namespace name because GCC
defines it as a predefined macro (#define linux 1) in -std=gnu++
modes.
- Update the developer guide example to match the actual header
includes used in the wrapper implementations.
- Reorder migration steps to put cleanup of existing implementations
first, before creating the new wrapper.
---
libc/docs/dev/syscall_wrapper_refactor.rst | 29 ++++++++++++-------
libc/src/__support/HashTable/randomness.h | 2 +-
.../OSUtil/linux/syscall_wrappers/close.h | 4 +--
.../OSUtil/linux/syscall_wrappers/getrandom.h | 4 +--
.../OSUtil/linux/syscall_wrappers/open.h | 4 +--
.../OSUtil/linux/syscall_wrappers/read.h | 4 +--
.../OSUtil/linux/syscall_wrappers/write.h | 4 +--
libc/src/fcntl/linux/open.cpp | 2 +-
libc/src/sys/mman/linux/shm_open.cpp | 2 +-
libc/src/sys/random/linux/getrandom.cpp | 2 +-
libc/src/unistd/linux/close.cpp | 2 +-
libc/src/unistd/linux/read.cpp | 2 +-
libc/src/unistd/linux/write.cpp | 2 +-
13 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/libc/docs/dev/syscall_wrapper_refactor.rst b/libc/docs/dev/syscall_wrapper_refactor.rst
index edfcc69a25849..40535b04d90eb 100644
--- a/libc/docs/dev/syscall_wrapper_refactor.rst
+++ b/libc/docs/dev/syscall_wrapper_refactor.rst
@@ -13,6 +13,8 @@ is to move all direct ``syscall_impl`` calls into a dedicated directory:
This refactor provides several benefits:
+* **Reusability**: Allows multiple entrypoints to share a single syscall
+ implementation without public APIs depending on other public APIs.
* **Type Safety**: Using ``ErrorOr<T>`` ensures that error conditions are
handled explicitly.
* **Consistency**: Standardizes the conversion of syscall return values into
@@ -24,20 +26,24 @@ The Pattern
===========
Each syscall should have its own header-only library in the ``syscall_wrappers``
-directory. The wrapper function should return an ``ErrorOr<T>``.
+directory. The wrapper function should return an ``ErrorOr<T>``. Wrappers live
+in the ``linux_syscalls`` namespace to make call sites self-documenting and to
+clearly identify any leakage into OS-generic code.
Example Wrapper (``src/__support/OSUtil/linux/syscall_wrappers/read.h``):
--------------------------------------------------------------------------
.. code-block:: c++
+ #include "hdr/types/ssize_t.h"
#include "src/__support/OSUtil/linux/syscall.h" // For syscall_impl
- #include "src/__support/error_or.h"
#include "src/__support/common.h"
+ #include "src/__support/error_or.h"
+ #include "src/__support/macros/config.h"
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
- namespace internal {
+ namespace linux_syscalls {
LIBC_INLINE ErrorOr<ssize_t> read(int fd, void *buf, size_t count) {
ssize_t ret = syscall_impl<ssize_t>(SYS_read, fd, buf, count);
@@ -47,22 +53,23 @@ Example Wrapper (``src/__support/OSUtil/linux/syscall_wrappers/read.h``):
return ret;
}
- } // namespace internal
+ } // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
How to Migrate
==============
-1. **Create the Wrapper**: Add a new header file in
+1. **Cleanup Existing Implementation**: If the syscall was previously
+ implemented in ``OSUtil/linux/fcntl.cpp`` (or similar), remove the old
+ implementation to replace it with the new wrapper.
+2. **Create the Wrapper**: Add a new header file in
``src/__support/OSUtil/linux/syscall_wrappers/``.
-2. **Update CMake**: Add a ``add_header_library`` target for the new wrapper in
+3. **Update CMake**: Add a ``add_header_library`` target for the new wrapper in
``src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt``.
-3. **Refactor Entrypoints**:
+4. **Refactor Entrypoints**:
* Include the new wrapper header (e.g., ``read.h``).
- * Replace direct ``syscall_impl`` calls with ``internal::<function_name>``.
+ * Replace direct ``syscall_impl`` calls with
+ ``linux_syscalls::<function_name>``.
* Update the entrypoint's ``DEPENDS`` in ``CMakeLists.txt`` to include the
new wrapper target.
-
-4. **Cleanup OSUtil**: If the syscall was previously implemented manually in
- ``OSUtil/linux/fcntl.cpp`` (or similar), remove it to avoid name collisions.
diff --git a/libc/src/__support/HashTable/randomness.h b/libc/src/__support/HashTable/randomness.h
index 912b27629b533..38dc703a0db9e 100644
--- a/libc/src/__support/HashTable/randomness.h
+++ b/libc/src/__support/HashTable/randomness.h
@@ -38,7 +38,7 @@ LIBC_INLINE uint64_t next_random_seed() {
size_t count = sizeof(entropy);
uint8_t *buffer = reinterpret_cast<uint8_t *>(entropy);
while (count > 0) {
- auto len = internal::getrandom(buffer, count, 0);
+ auto len = linux_syscalls::getrandom(buffer, count, 0);
if (!len.has_value()) {
if (len.error() == ENOSYS)
break;
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h
index b40b82a350d34..fe305af5051c0 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/close.h
@@ -16,7 +16,7 @@
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
-namespace internal {
+namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> close(int fd) {
int ret = syscall_impl<int>(SYS_close, fd);
@@ -25,7 +25,7 @@ LIBC_INLINE ErrorOr<int> close(int fd) {
return ret;
}
-} // namespace internal
+} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CLOSE_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h
index e06f53b3bef7b..b5ef6201a2dc5 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/getrandom.h
@@ -17,7 +17,7 @@
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
-namespace internal {
+namespace linux_syscalls {
LIBC_INLINE ErrorOr<ssize_t> getrandom(void *buf, size_t buflen,
unsigned int flags) {
@@ -27,7 +27,7 @@ LIBC_INLINE ErrorOr<ssize_t> getrandom(void *buf, size_t buflen,
return ret;
}
-} // namespace internal
+} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_GETRANDOM_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h
index 3fad38cb1e86d..f487f2bb91637 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/open.h
@@ -18,7 +18,7 @@
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
-namespace internal {
+namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> open(const char *path, int flags, mode_t mode_flags) {
#ifdef SYS_open
@@ -31,7 +31,7 @@ LIBC_INLINE ErrorOr<int> open(const char *path, int flags, mode_t mode_flags) {
return fd;
}
-} // namespace internal
+} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_OPEN_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/read.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/read.h
index 7cdb5393a7756..86123904fc6b2 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/read.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/read.h
@@ -17,7 +17,7 @@
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
-namespace internal {
+namespace linux_syscalls {
LIBC_INLINE ErrorOr<ssize_t> read(int fd, void *buf, size_t count) {
ssize_t ret = syscall_impl<ssize_t>(SYS_read, fd, buf, count);
@@ -26,7 +26,7 @@ LIBC_INLINE ErrorOr<ssize_t> read(int fd, void *buf, size_t count) {
return ret;
}
-} // namespace internal
+} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_READ_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h
index 3a1b442e08a3c..e57986d357a21 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/write.h
@@ -17,7 +17,7 @@
#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
-namespace internal {
+namespace linux_syscalls {
LIBC_INLINE ErrorOr<ssize_t> write(int fd, const void *buf, size_t count) {
ssize_t ret = syscall_impl<ssize_t>(SYS_write, fd, buf, count);
@@ -26,7 +26,7 @@ LIBC_INLINE ErrorOr<ssize_t> write(int fd, const void *buf, size_t count) {
return ret;
}
-} // namespace internal
+} // namespace linux_syscalls
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_WRITE_H
diff --git a/libc/src/fcntl/linux/open.cpp b/libc/src/fcntl/linux/open.cpp
index a759e93dcfee5..83a5cf8cc4346 100644
--- a/libc/src/fcntl/linux/open.cpp
+++ b/libc/src/fcntl/linux/open.cpp
@@ -29,7 +29,7 @@ LLVM_LIBC_FUNCTION(int, open, (const char *path, int flags, ...)) {
va_end(varargs);
}
- auto result = internal::open(path, flags, mode_flags);
+ auto result = linux_syscalls::open(path, flags, mode_flags);
if (!result.has_value()) {
libc_errno = result.error();
diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index 37dc512cfec20..9670e9abc4eac 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -27,7 +27,7 @@ LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
}
auto open_result =
- internal::open(path_result->data(), oflags | DEFAULT_OFLAGS, mode);
+ linux_syscalls::open(path_result->data(), oflags | DEFAULT_OFLAGS, mode);
if (!open_result.has_value()) {
libc_errno = open_result.error();
return -1;
diff --git a/libc/src/sys/random/linux/getrandom.cpp b/libc/src/sys/random/linux/getrandom.cpp
index 789055b38fb0a..48078e50c6309 100644
--- a/libc/src/sys/random/linux/getrandom.cpp
+++ b/libc/src/sys/random/linux/getrandom.cpp
@@ -18,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, getrandom,
(void *buf, size_t buflen, unsigned int flags)) {
- auto rand = internal::getrandom(buf, buflen, flags);
+ auto rand = linux_syscalls::getrandom(buf, buflen, flags);
if (!rand.has_value()) {
libc_errno = static_cast<int>(rand.error());
return -1;
diff --git a/libc/src/unistd/linux/close.cpp b/libc/src/unistd/linux/close.cpp
index c8ab7fe5e5eef..f625d417c1ff9 100644
--- a/libc/src/unistd/linux/close.cpp
+++ b/libc/src/unistd/linux/close.cpp
@@ -16,7 +16,7 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, close, (int fd)) {
- auto result = internal::close(fd);
+ auto result = linux_syscalls::close(fd);
if (!result.has_value()) {
libc_errno = result.error();
diff --git a/libc/src/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp
index 4ac385b8149b7..d39627e57a483 100644
--- a/libc/src/unistd/linux/read.cpp
+++ b/libc/src/unistd/linux/read.cpp
@@ -17,7 +17,7 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, read, (int fd, void *buf, size_t count)) {
- auto result = internal::read(fd, buf, count);
+ auto result = linux_syscalls::read(fd, buf, count);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
diff --git a/libc/src/unistd/linux/write.cpp b/libc/src/unistd/linux/write.cpp
index 30cea7d0c0845..d7e2d768d1b4c 100644
--- a/libc/src/unistd/linux/write.cpp
+++ b/libc/src/unistd/linux/write.cpp
@@ -16,7 +16,7 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(ssize_t, write, (int fd, const void *buf, size_t count)) {
- auto result = internal::write(fd, buf, count);
+ auto result = linux_syscalls::write(fd, buf, count);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
More information about the libc-commits
mailing list