From 98d40ff15766b5fe719f8b7bceaa663e1302effa Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Mon, 28 Jul 2025 04:22:44 +0000 Subject: [PATCH 1/4] [libc] Add implementation of getcpu syscall wrapper This patch adds the getcpu syscall wrapper. This has been supported in glibc since v2.29. --- libc/config/linux/x86_64/entrypoints.txt | 1 + libc/include/sched.yaml | 7 ++++++ libc/src/sched/CMakeLists.txt | 7 ++++++ libc/src/sched/getcpu.h | 21 +++++++++++++++++ libc/src/sched/linux/CMakeLists.txt | 12 ++++++++++ libc/src/sched/linux/getcpu.cpp | 30 ++++++++++++++++++++++++ libc/test/src/sched/CMakeLists.txt | 12 ++++++++++ libc/test/src/sched/getcpu_test.cpp | 29 +++++++++++++++++++++++ 8 files changed, 119 insertions(+) create mode 100644 libc/src/sched/getcpu.h create mode 100644 libc/src/sched/linux/getcpu.cpp create mode 100644 libc/test/src/sched/getcpu_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 5e8278e586286..a1e93a133f262 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -36,6 +36,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.poll.poll # sched.h entrypoints + libc.src.sched.getcpu libc.src.sched.sched_get_priority_max libc.src.sched.sched_get_priority_min libc.src.sched.sched_getaffinity diff --git a/libc/include/sched.yaml b/libc/include/sched.yaml index 57871f524bf11..f14799ddf33fa 100644 --- a/libc/include/sched.yaml +++ b/libc/include/sched.yaml @@ -18,6 +18,13 @@ functions: arguments: - type: size_t - type: const cpu_set_t * + - name: getcpu + standards: + - POSIX + return_type: int + arguments: + - type: unsigned int * + - type: unsigned int * - name: sched_get_priority_max standards: - POSIX diff --git a/libc/src/sched/CMakeLists.txt b/libc/src/sched/CMakeLists.txt index e6c37d3b0433a..d1d1de0718c56 100644 --- a/libc/src/sched/CMakeLists.txt +++ b/libc/src/sched/CMakeLists.txt @@ -2,6 +2,13 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) endif() +add_entrypoint_object( + getcpu + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.getcpu +) + add_entrypoint_object( sched_getaffinity ALIAS diff --git a/libc/src/sched/getcpu.h b/libc/src/sched/getcpu.h new file mode 100644 index 0000000000000..ed3187a68fadc --- /dev/null +++ b/libc/src/sched/getcpu.h @@ -0,0 +1,21 @@ +//===-- Implementation header for getcpu ------------------------*- 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_SCHED_GETCPU_H +#define LLVM_LIBC_SRC_SCHED_GETCPU_H + +#include "src/__support/macros/config.h" +#include + +namespace LIBC_NAMESPACE_DECL { + +int getcpu(unsigned int *cpu, unsigned int *node); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_SCHED_GETCPU_H diff --git a/libc/src/sched/linux/CMakeLists.txt b/libc/src/sched/linux/CMakeLists.txt index e690e76fd7483..66ebaeab43c21 100644 --- a/libc/src/sched/linux/CMakeLists.txt +++ b/libc/src/sched/linux/CMakeLists.txt @@ -1,3 +1,15 @@ +add_entrypoint_object( + getcpu + SRCS + getcpu.cpp + HDRS + ../getcpu.h + DEPENDS + libc.include.sched + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( sched_getaffinity SRCS diff --git a/libc/src/sched/linux/getcpu.cpp b/libc/src/sched/linux/getcpu.cpp new file mode 100644 index 0000000000000..2726d2daca2c5 --- /dev/null +++ b/libc/src/sched/linux/getcpu.cpp @@ -0,0 +1,30 @@ +//===-- Implementation of getcpu ------------------------------------------===// +// +// 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/sched/getcpu.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/libc_errno.h" +#include "src/__support/macros/config.h" + +#include +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, getcpu, (unsigned int *cpu, unsigned int *node)) { + int ret = LIBC_NAMESPACE::syscall_impl(SYS_getcpu, cpu, node); + if (ret < 0) { + libc_errno = -ret; + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/sched/CMakeLists.txt b/libc/test/src/sched/CMakeLists.txt index 9dda4ea16e101..a5b00049df2ca 100644 --- a/libc/test/src/sched/CMakeLists.txt +++ b/libc/test/src/sched/CMakeLists.txt @@ -40,6 +40,18 @@ add_libc_unittest( libc.src.sched.sched_get_priority_max ) +add_libc_unittest( + getcpu_test + SUITE + libc_sched_unittests + SRCS + getcpu_test.cpp + DEPENDS + libc.include.sched + libc.src.errno.errno + libc.src.sched.getcpu +) + add_libc_unittest( scheduler_test SUITE diff --git a/libc/test/src/sched/getcpu_test.cpp b/libc/test/src/sched/getcpu_test.cpp new file mode 100644 index 0000000000000..5c3f531f76f72 --- /dev/null +++ b/libc/test/src/sched/getcpu_test.cpp @@ -0,0 +1,29 @@ +//===-- Unittests for getcpu ----------------------------------------------===// +// +// 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/__support/OSUtil/syscall.h" +#include "src/__support/libc_errno.h" +#include "src/sched/getcpu.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" + +#include + +TEST(LlvmLibcSchedGetCpuTest, SmokeTest) { + unsigned int current_cpu; + unsigned int current_node; + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + ASSERT_THAT(LIBC_NAMESPACE::getcpu(¤t_cpu, ¤t_node), Succeeds(0)); +} + +TEST(LlvmLibcSchedGetCpuTest, BadPointer) { + unsigned int current_cpu; + unsigned int *current_node = reinterpret_cast(-1); + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; + ASSERT_THAT(LIBC_NAMESPACE::getcpu(¤t_cpu, current_node), + Fails(EFAULT)); +} From fb71929b7109fd52ec997a5e0df3956dc775ad2c Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Tue, 29 Jul 2025 13:35:40 +0000 Subject: [PATCH 2/4] feedback --- libc/src/sched/getcpu.h | 1 - libc/src/sched/linux/getcpu.cpp | 1 - libc/test/src/sched/CMakeLists.txt | 1 + libc/test/src/sched/getcpu_test.cpp | 4 +++- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libc/src/sched/getcpu.h b/libc/src/sched/getcpu.h index ed3187a68fadc..4c90e646c7e7b 100644 --- a/libc/src/sched/getcpu.h +++ b/libc/src/sched/getcpu.h @@ -10,7 +10,6 @@ #define LLVM_LIBC_SRC_SCHED_GETCPU_H #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/sched/linux/getcpu.cpp b/libc/src/sched/linux/getcpu.cpp index 2726d2daca2c5..302e9fb6cacc6 100644 --- a/libc/src/sched/linux/getcpu.cpp +++ b/libc/src/sched/linux/getcpu.cpp @@ -13,7 +13,6 @@ #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" -#include #include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { diff --git a/libc/test/src/sched/CMakeLists.txt b/libc/test/src/sched/CMakeLists.txt index a5b00049df2ca..54c6d1d4f52c6 100644 --- a/libc/test/src/sched/CMakeLists.txt +++ b/libc/test/src/sched/CMakeLists.txt @@ -50,6 +50,7 @@ add_libc_unittest( libc.include.sched libc.src.errno.errno libc.src.sched.getcpu + libc.test.UnitTest.ErrnoCheckingTest ) add_libc_unittest( diff --git a/libc/test/src/sched/getcpu_test.cpp b/libc/test/src/sched/getcpu_test.cpp index 5c3f531f76f72..0e6806673a214 100644 --- a/libc/test/src/sched/getcpu_test.cpp +++ b/libc/test/src/sched/getcpu_test.cpp @@ -9,15 +9,17 @@ #include "src/__support/OSUtil/syscall.h" #include "src/__support/libc_errno.h" #include "src/sched/getcpu.h" +#include "test/UnitTest/ErrnoCheckingTest.h" #include "test/UnitTest/ErrnoSetterMatcher.h" -#include +using LlvmLibcSchedGetCpuTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; TEST(LlvmLibcSchedGetCpuTest, SmokeTest) { unsigned int current_cpu; unsigned int current_node; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; ASSERT_THAT(LIBC_NAMESPACE::getcpu(¤t_cpu, ¤t_node), Succeeds(0)); + ASSERT_ERRNO_SUCCESS(); } TEST(LlvmLibcSchedGetCpuTest, BadPointer) { From cf32e0fd542068d0508224fc5e2b4ce3f4ee9632 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Tue, 29 Jul 2025 18:15:15 +0000 Subject: [PATCH 3/4] feedback --- libc/test/src/sched/getcpu_test.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libc/test/src/sched/getcpu_test.cpp b/libc/test/src/sched/getcpu_test.cpp index 0e6806673a214..fc4ada8a722f5 100644 --- a/libc/test/src/sched/getcpu_test.cpp +++ b/libc/test/src/sched/getcpu_test.cpp @@ -14,15 +14,14 @@ using LlvmLibcSchedGetCpuTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; -TEST(LlvmLibcSchedGetCpuTest, SmokeTest) { +TEST_F(LlvmLibcSchedGetCpuTest, SmokeTest) { unsigned int current_cpu; unsigned int current_node; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; ASSERT_THAT(LIBC_NAMESPACE::getcpu(¤t_cpu, ¤t_node), Succeeds(0)); - ASSERT_ERRNO_SUCCESS(); } -TEST(LlvmLibcSchedGetCpuTest, BadPointer) { +TEST_F(LlvmLibcSchedGetCpuTest, BadPointer) { unsigned int current_cpu; unsigned int *current_node = reinterpret_cast(-1); using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; From 6d6ad77c12a3ecd469fc9eefca85b1a341dd4f08 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 30 Jul 2025 16:15:42 +0000 Subject: [PATCH 4/4] feedback --- libc/src/sched/linux/getcpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/sched/linux/getcpu.cpp b/libc/src/sched/linux/getcpu.cpp index 302e9fb6cacc6..a34b693fc148e 100644 --- a/libc/src/sched/linux/getcpu.cpp +++ b/libc/src/sched/linux/getcpu.cpp @@ -18,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(int, getcpu, (unsigned int *cpu, unsigned int *node)) { - int ret = LIBC_NAMESPACE::syscall_impl(SYS_getcpu, cpu, node); + int ret = LIBC_NAMESPACE::syscall_impl(SYS_getcpu, cpu, node, nullptr); if (ret < 0) { libc_errno = -ret; return -1;