[libc-commits] [libc] 6bf6e39 - [libc] Implement _SC_ARG_MAX, _SC_OPEN_MAX, and _SC_PHYS_PAGES (#204364)
via libc-commits
libc-commits at lists.llvm.org
Wed Jun 17 12:46:22 PDT 2026
Author: Jeff Bailey
Date: 2026-06-17T20:46:17+01:00
New Revision: 6bf6e39d3b07b2f7c6e83d1274deea15105f1b87
URL: https://github.com/llvm/llvm-project/commit/6bf6e39d3b07b2f7c6e83d1274deea15105f1b87
DIFF: https://github.com/llvm/llvm-project/commit/6bf6e39d3b07b2f7c6e83d1274deea15105f1b87.diff
LOG: [libc] Implement _SC_ARG_MAX, _SC_OPEN_MAX, and _SC_PHYS_PAGES (#204364)
This commit adds the sysinfo syscall wrapper and implements the
_SC_ARG_MAX, _SC_OPEN_MAX, and _SC_PHYS_PAGES options in sysconf.
- Added sysinfo inline syscall wrapper.
- Implemented _SC_ARG_MAX, _SC_OPEN_MAX, and _SC_PHYS_PAGES.
- Added integration tests.
Added:
libc/hdr/sys_resource_macros.h
libc/src/__support/OSUtil/linux/syscall_wrappers/sysinfo.h
Modified:
libc/hdr/CMakeLists.txt
libc/include/llvm-libc-macros/linux/unistd-macros.h
libc/include/unistd.yaml
libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
libc/src/unistd/linux/CMakeLists.txt
libc/src/unistd/linux/sysconf.cpp
libc/test/src/unistd/sysconf_test.cpp
Removed:
################################################################################
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index 0bc0202022680..c24b826a6ef14 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -287,6 +287,15 @@ add_proxy_header_library(
libc.include.sys_auxv
)
+add_proxy_header_library(
+ sys_resource_macros
+ HDRS
+ sys_resource_macros.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-macros.sys_resource_macros
+ libc.include.sys_resource
+)
+
add_header_library(wchar_overlay HDRS wchar_overlay.h)
add_header_library(uchar_overlay HDRS uchar_overlay.h)
diff --git a/libc/hdr/sys_resource_macros.h b/libc/hdr/sys_resource_macros.h
new file mode 100644
index 0000000000000..845584bfeb714
--- /dev/null
+++ b/libc/hdr/sys_resource_macros.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definition of macros from sys/resource.h
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_SYS_RESOURCE_MACROS_H
+#define LLVM_LIBC_HDR_SYS_RESOURCE_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/sys-resource-macros.h"
+
+#else // Overlay mode
+
+#include <sys/resource.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_SYS_RESOURCE_MACROS_H
diff --git a/libc/include/llvm-libc-macros/linux/unistd-macros.h b/libc/include/llvm-libc-macros/linux/unistd-macros.h
index 9bf9d0b1d90d3..9d6736cd9b342 100644
--- a/libc/include/llvm-libc-macros/linux/unistd-macros.h
+++ b/libc/include/llvm-libc-macros/linux/unistd-macros.h
@@ -20,11 +20,14 @@
#define W_OK 2
#define R_OK 4
+#define _SC_ARG_MAX 0
#define _SC_PAGESIZE 1
#define _SC_PAGE_SIZE _SC_PAGESIZE
+#define _SC_OPEN_MAX 4
+#define _SC_THREADS 67
#define _SC_NPROCESSORS_CONF 83
#define _SC_NPROCESSORS_ONLN 84
-#define _SC_THREADS 67
+#define _SC_PHYS_PAGES 85
#define _PC_FILESIZEBITS 0
#define _PC_LINK_MAX 1
diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index 308b2a4b20f2b..c1ae4567bfc02 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -14,15 +14,21 @@ macros:
macro_header: unistd-macros.h
- macro_name: STDERR_FILENO
macro_header: unistd-macros.h
+ - macro_name: _SC_ARG_MAX
+ macro_header: unistd-macros.h
- macro_name: _SC_PAGESIZE
macro_header: unistd-macros.h
- macro_name: _SC_PAGE_SIZE
macro_header: unistd-macros.h
+ - macro_name: _SC_OPEN_MAX
+ macro_header: unistd-macros.h
+ - macro_name: _SC_THREADS
+ macro_header: unistd-macros.h
- macro_name: _SC_NPROCESSORS_CONF
macro_header: unistd-macros.h
- macro_name: _SC_NPROCESSORS_ONLN
macro_header: unistd-macros.h
- - macro_name: _SC_THREADS
+ - macro_name: _SC_PHYS_PAGES
macro_header: unistd-macros.h
- macro_name: _POSIX_THREADS
macro_header: unistd-macros.h
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 731e5a1d462ab..a52be9676a3ca 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -774,3 +774,14 @@ add_header_library(
libc.include.sys_syscall
)
+add_header_library(
+ sysinfo
+ HDRS
+ sysinfo.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
+)
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/sysinfo.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/sysinfo.h
new file mode 100644
index 0000000000000..7487d05353c5b
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/sysinfo.h
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Syscall wrapper for sysinfo.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SYSINFO_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SYSINFO_H
+
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <linux/sysinfo.h> // For struct sysinfo
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> sysinfo(struct ::sysinfo *info) {
+ return syscall_checked<int>(SYS_sysinfo, info);
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_SYSINFO_H
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 5ae179736de05..04ccde414cd2f 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -592,10 +592,14 @@ add_entrypoint_object(
DEPENDS
libc.hdr.unistd_macros
libc.hdr.sys_auxv_macros
+ libc.hdr.sys_resource_macros
+ libc.hdr.types.struct_rlimit
libc.src.__support.libc_errno
libc.src.__support.macros.config
libc.src.__support.OSUtil.linux.sysinfo
libc.src.__support.OSUtil.linux.auxv
+ libc.src.__support.OSUtil.linux.syscall_wrappers.prlimit
+ libc.src.__support.OSUtil.linux.syscall_wrappers.sysinfo
)
add_entrypoint_object(
diff --git a/libc/src/unistd/linux/sysconf.cpp b/libc/src/unistd/linux/sysconf.cpp
index c8bcf66dcccbc..4785a8bac478d 100644
--- a/libc/src/unistd/linux/sysconf.cpp
+++ b/libc/src/unistd/linux/sysconf.cpp
@@ -16,16 +16,70 @@
#include "src/__support/common.h"
#include "hdr/sys_auxv_macros.h"
+#include "hdr/sys_resource_macros.h"
+#include "hdr/types/struct_rlimit.h"
#include "hdr/unistd_macros.h"
#include "src/__support/OSUtil/linux/auxv.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/prlimit.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/sysinfo.h"
#include "src/__support/OSUtil/linux/sysinfo.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include <linux/limits.h>
+#include <linux/sysinfo.h>
+
+// In overlay mode, system headers (like glibc's <bits/local_lim.h>) may
+// explicitly undefine ARG_MAX to indicate it is dynamic. We define a fallback
+// here using the standard Linux kernel minimum floor of 128KB.
+#ifndef ARG_MAX
+#define ARG_MAX 131072
+#endif
namespace LIBC_NAMESPACE_DECL {
namespace { // Anonymous namespace for internal helpers
+// Fallback value for ARG_MAX when RLIMIT_STACK is RLIM_INFINITY (unlimited).
+// When the stack is unlimited, the kernel caps the argument limit at 3/4 of the
+// default stack limit (_STK_LIM = 8MB), which yields 6MB.
+constexpr long DEFAULT_STACK_LIMIT = 8 * 1024 * 1024; // 8MB
+constexpr long ARG_MAX_FALLBACK = DEFAULT_STACK_LIMIT / 4 * 3; // 6MB
+
+// We define a local structure for prlimit64 to avoid type mismatches
+// and stack corruption on 32-bit systems when in overlay mode.
+struct rlimit64 {
+ uint64_t rlim_cur;
+ uint64_t rlim_max;
+};
+
+long get_arg_max() {
+ struct rlimit64 limits;
+ ErrorOr<int> ret = linux_syscalls::prlimit(
+ 0, RLIMIT_STACK, nullptr, reinterpret_cast<struct rlimit *>(&limits));
+ if (!ret) {
+ libc_errno = -ret.error();
+ return -1;
+ }
+ if (limits.rlim_cur == ~0ULL)
+ return ARG_MAX_FALLBACK;
+
+ long val = static_cast<long>(limits.rlim_cur / 4);
+ return val > ARG_MAX ? val : ARG_MAX;
+}
+
+long get_open_max() {
+ struct rlimit64 limits;
+ ErrorOr<int> ret = linux_syscalls::prlimit(
+ 0, RLIMIT_NOFILE, nullptr, reinterpret_cast<struct rlimit *>(&limits));
+ if (!ret) {
+ libc_errno = -ret.error();
+ return -1;
+ }
+ if (limits.rlim_cur == ~0ULL)
+ return -1;
+ return static_cast<long>(limits.rlim_cur);
+}
+
long get_page_size() {
cpp::optional<unsigned long> page_size = auxv::get(AT_PAGESZ);
if (page_size)
@@ -44,10 +98,35 @@ long get_nprocessors_onln() {
sysinfo::parse_nproc_with_fallback_from(sysinfo::ONLINE_NPROC_PATH));
}
+long get_phys_pages() {
+ struct ::sysinfo info;
+ ErrorOr<int> ret = linux_syscalls::sysinfo(&info);
+ if (!ret) {
+ libc_errno = -ret.error();
+ return -1;
+ }
+ cpp::optional<unsigned long> page_size = auxv::get(AT_PAGESZ);
+ if (!page_size) {
+ libc_errno = ENOSYS;
+ return -1;
+ }
+ unsigned long ps = *page_size;
+ unsigned long mem_unit = info.mem_unit;
+ unsigned long num = info.totalram;
+ if (mem_unit >= ps) {
+ num *= (mem_unit / ps);
+ } else {
+ num /= (ps / mem_unit);
+ }
+ return static_cast<long>(num);
+}
+
} // anonymous namespace
LLVM_LIBC_FUNCTION(long, sysconf, (int name)) {
switch (name) {
+ case _SC_ARG_MAX:
+ return get_arg_max();
case _SC_PAGESIZE:
return get_page_size();
case _SC_NPROCESSORS_CONF:
@@ -56,6 +135,10 @@ LLVM_LIBC_FUNCTION(long, sysconf, (int name)) {
return get_nprocessors_onln();
case _SC_THREADS:
return _POSIX_THREADS;
+ case _SC_OPEN_MAX:
+ return get_open_max();
+ case _SC_PHYS_PAGES:
+ return get_phys_pages();
default:
// TODO: Complete the rest of the sysconf options.
libc_errno = EINVAL;
diff --git a/libc/test/src/unistd/sysconf_test.cpp b/libc/test/src/unistd/sysconf_test.cpp
index 16882714cdf1c..b7b041d363dc0 100644
--- a/libc/test/src/unistd/sysconf_test.cpp
+++ b/libc/test/src/unistd/sysconf_test.cpp
@@ -35,3 +35,21 @@ TEST(LlvmLibcSysconfTest, ThreadsTest) {
long threads = LIBC_NAMESPACE::sysconf(_SC_THREADS);
ASSERT_EQ(threads, _POSIX_THREADS);
}
+
+TEST(LlvmLibcSysconfTest, ArgMaxTest) {
+ long arg_max = LIBC_NAMESPACE::sysconf(_SC_ARG_MAX);
+ ASSERT_GT(arg_max, 0L);
+ ASSERT_GE(arg_max, 131072L);
+}
+
+TEST(LlvmLibcSysconfTest, OpenMaxTest) {
+ long open_max = LIBC_NAMESPACE::sysconf(_SC_OPEN_MAX);
+ if (open_max == -1)
+ return;
+ ASSERT_GT(open_max, 0L);
+}
+
+TEST(LlvmLibcSysconfTest, PhysPagesTest) {
+ long phys_pages = LIBC_NAMESPACE::sysconf(_SC_PHYS_PAGES);
+ ASSERT_GT(phys_pages, 0L);
+}
More information about the libc-commits
mailing list