[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