[libc-commits] [libc] [libc] Implement CPU_ALLOC and CPU_FREE (PR #202349)
via libc-commits
libc-commits at lists.llvm.org
Mon Jun 8 07:53:01 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Pavel Labath (labath)
<details>
<summary>Changes</summary>
Like the other macros, this commit uses an internal (__-prefixed) entrypoint.
I added an internal typedef for the mask type to make bit set calculations slightly safer. I also removed the comment about supporting larger cpu counts, as increasing the struct size is not necessary to do that -- that's what these macros are for. Increasing it would be necessary to support operations on the fixed-size cpu sets, but that cannot be done lightly due to ABI stability.
I added a test that checks allocations for both small and large cpu set sizes.
Assisted by Gemini.
---
Full diff: https://github.com/llvm/llvm-project/pull/202349.diff
14 Files Affected:
- (modified) libc/config/linux/aarch64/entrypoints.txt (+2)
- (modified) libc/config/linux/riscv/entrypoints.txt (+2)
- (modified) libc/config/linux/x86_64/entrypoints.txt (+2)
- (modified) libc/include/llvm-libc-macros/linux/sched-macros.h (+5)
- (modified) libc/include/llvm-libc-types/cpu_set_t.h (+2-3)
- (modified) libc/include/sched.yaml (+12)
- (modified) libc/src/sched/CMakeLists.txt (+14)
- (modified) libc/src/sched/linux/CMakeLists.txt (+32)
- (added) libc/src/sched/linux/sched_cpualloc.cpp (+32)
- (added) libc/src/sched/linux/sched_cpufree.cpp (+22)
- (added) libc/src/sched/sched_cpualloc.h (+21)
- (added) libc/src/sched/sched_cpufree.h (+21)
- (modified) libc/test/src/sched/CMakeLists.txt (+17)
- (added) libc/test/src/sched/cpu_alloc_test.cpp (+69)
``````````diff
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 590b8c19bf1ef..55a36b05ea033 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1092,6 +1092,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_setspecific
# sched.h entrypoints
+ libc.src.sched.__sched_cpualloc
+ libc.src.sched.__sched_cpufree
libc.src.sched.__sched_getcpucount
libc.src.sched.__sched_setcpuzero
libc.src.sched.__sched_setcpuset
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5cea007a6c3ae..0aaba580826e0 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1225,6 +1225,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_setspecific
# sched.h entrypoints
+ libc.src.sched.__sched_cpualloc
+ libc.src.sched.__sched_cpufree
libc.src.sched.__sched_getcpucount
libc.src.sched.__sched_setcpuzero
libc.src.sched.__sched_setcpuset
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 0bf88f504cd3c..2ff189a59d24f 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1287,6 +1287,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.pthread.pthread_setspecific
# sched.h entrypoints
+ libc.src.sched.__sched_cpualloc
+ libc.src.sched.__sched_cpufree
libc.src.sched.__sched_getcpucount
libc.src.sched.__sched_setcpuzero
libc.src.sched.__sched_setcpuset
diff --git a/libc/include/llvm-libc-macros/linux/sched-macros.h b/libc/include/llvm-libc-macros/linux/sched-macros.h
index 4d8aafbc2df21..539b3530f6e14 100644
--- a/libc/include/llvm-libc-macros/linux/sched-macros.h
+++ b/libc/include/llvm-libc-macros/linux/sched-macros.h
@@ -34,4 +34,9 @@
#define CPU_ISSET_S(cpu, setsize, set) __sched_getcpuisset(cpu, setsize, set)
#define CPU_ISSET(cpu, set) CPU_ISSET_S(cpu, sizeof(cpu_set_t), set)
+#define CPU_ALLOC_SIZE(count) \
+ ((((count) + NCPUBITS - 1) / NCPUBITS) * sizeof(__cpu_set_mask_t))
+#define CPU_ALLOC(count) __sched_cpualloc(count)
+#define CPU_FREE(set) __sched_cpufree(set)
+
#endif // LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
diff --git a/libc/include/llvm-libc-types/cpu_set_t.h b/libc/include/llvm-libc-types/cpu_set_t.h
index 8c6859de5f1d4..420b0aa002402 100644
--- a/libc/include/llvm-libc-types/cpu_set_t.h
+++ b/libc/include/llvm-libc-types/cpu_set_t.h
@@ -11,11 +11,10 @@
#define __CPU_SETSIZE 1024
#define __NCPUBITS (8 * sizeof(unsigned long))
+typedef unsigned long __cpu_set_mask_t;
typedef struct {
- // If a processor with more than 1024 CPUs is to be supported in future,
- // we need to adjust the size of this array.
- unsigned long __mask[128 / sizeof(unsigned long)];
+ __cpu_set_mask_t __mask[__CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;
#endif // LLVM_LIBC_TYPES_CPU_SET_T_H
diff --git a/libc/include/sched.yaml b/libc/include/sched.yaml
index f34fc73f9e8b2..82cc618fc8395 100644
--- a/libc/include/sched.yaml
+++ b/libc/include/sched.yaml
@@ -18,6 +18,18 @@ types:
enums: []
objects: []
functions:
+ - name: __sched_cpualloc
+ standards:
+ - llvm_libc_ext
+ return_type: cpu_set_t *
+ arguments:
+ - type: int
+ - name: __sched_cpufree
+ standards:
+ - llvm_libc_ext
+ return_type: void
+ arguments:
+ - type: cpu_set_t *
- name: __sched_getcpucount
standards:
- llvm_libc_ext
diff --git a/libc/src/sched/CMakeLists.txt b/libc/src/sched/CMakeLists.txt
index 39ac8c8c6f247..3aef41f996962 100644
--- a/libc/src/sched/CMakeLists.txt
+++ b/libc/src/sched/CMakeLists.txt
@@ -86,6 +86,20 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.sched_rr_get_interval
)
+add_entrypoint_object(
+ __sched_cpualloc
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.__sched_cpualloc
+)
+
+add_entrypoint_object(
+ __sched_cpufree
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.__sched_cpufree
+)
+
add_entrypoint_object(
__sched_getcpucount
ALIAS
diff --git a/libc/src/sched/linux/CMakeLists.txt b/libc/src/sched/linux/CMakeLists.txt
index 6cc41e97baa00..b8662c6383e74 100644
--- a/libc/src/sched/linux/CMakeLists.txt
+++ b/libc/src/sched/linux/CMakeLists.txt
@@ -168,6 +168,38 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ __sched_cpualloc
+ SRCS
+ sched_cpualloc.cpp
+ HDRS
+ ../sched_cpualloc.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.sched_macros
+ libc.hdr.stdint_proxy
+ libc.hdr.types.cpu_set_t
+ libc.src.__support.alloc_checker
+ libc.src.__support.common
+ libc.src.__support.CPP.new
+ libc.src.__support.macros.config
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ __sched_cpufree
+ SRCS
+ sched_cpufree.cpp
+ HDRS
+ ../sched_cpufree.h
+ DEPENDS
+ libc.hdr.stdint_proxy
+ libc.hdr.types.cpu_set_t
+ libc.src.__support.common
+ libc.src.__support.CPP.new
+ libc.src.__support.macros.config
+)
+
add_entrypoint_object(
__sched_setcpuzero
SRCS
diff --git a/libc/src/sched/linux/sched_cpualloc.cpp b/libc/src/sched/linux/sched_cpualloc.cpp
new file mode 100644
index 0000000000000..d1ed5c933d683
--- /dev/null
+++ b/libc/src/sched/linux/sched_cpualloc.cpp
@@ -0,0 +1,32 @@
+//===-- Implementation of sched_cpualloc ----------------------------------===//
+//
+// 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/sched_cpualloc.h"
+#include "hdr/errno_macros.h"
+#include "hdr/sched_macros.h"
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/cpu_set_t.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(cpu_set_t *, __sched_cpualloc, (int count)) {
+ AllocChecker ac;
+ uint8_t *bytes = new (ac) uint8_t[CPU_ALLOC_SIZE(count)];
+ if (!ac) {
+ libc_errno = ENOMEM;
+ return nullptr;
+ }
+ return reinterpret_cast<cpu_set_t *>(bytes);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sched/linux/sched_cpufree.cpp b/libc/src/sched/linux/sched_cpufree.cpp
new file mode 100644
index 0000000000000..74e9f7d3600a6
--- /dev/null
+++ b/libc/src/sched/linux/sched_cpufree.cpp
@@ -0,0 +1,22 @@
+//===-- Implementation of sched_cpufree -----------------------------------===//
+//
+// 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/sched_cpufree.h"
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/cpu_set_t.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(void, __sched_cpufree, (cpu_set_t * set)) {
+ delete[] reinterpret_cast<uint8_t *>(set);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sched/sched_cpualloc.h b/libc/src/sched/sched_cpualloc.h
new file mode 100644
index 0000000000000..1780e5f03afb3
--- /dev/null
+++ b/libc/src/sched/sched_cpualloc.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sched_cpualloc ----------------*- 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_SCHED_CPUALLOC_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_CPUALLOC_H
+
+#include "hdr/types/cpu_set_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+cpu_set_t *__sched_cpualloc(int count);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_CPUALLOC_H
diff --git a/libc/src/sched/sched_cpufree.h b/libc/src/sched/sched_cpufree.h
new file mode 100644
index 0000000000000..b8ee9e3ff5a5c
--- /dev/null
+++ b/libc/src/sched/sched_cpufree.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sched_cpufree -----------------*- 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_SCHED_CPUFREE_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_CPUFREE_H
+
+#include "hdr/types/cpu_set_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+void __sched_cpufree(cpu_set_t *set);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_CPUFREE_H
diff --git a/libc/test/src/sched/CMakeLists.txt b/libc/test/src/sched/CMakeLists.txt
index 421be2cf2743f..b8dbf609ecd0f 100644
--- a/libc/test/src/sched/CMakeLists.txt
+++ b/libc/test/src/sched/CMakeLists.txt
@@ -106,6 +106,23 @@ add_libc_unittest(
libc.test.UnitTest.ErrnoCheckingTest
)
+add_libc_unittest(
+ cpu_alloc_test
+ SUITE
+ libc_sched_unittests
+ SRCS
+ cpu_alloc_test.cpp
+ DEPENDS
+ libc.hdr.sched_macros
+ libc.hdr.types.cpu_set_t
+ libc.src.sched.__sched_cpualloc
+ libc.src.sched.__sched_cpufree
+ libc.src.sched.__sched_getcpucount
+ libc.src.sched.__sched_getcpuisset
+ libc.src.sched.__sched_setcpuset
+ libc.src.sched.__sched_setcpuzero
+)
+
add_libc_unittest(
cpu_count_test
SUITE
diff --git a/libc/test/src/sched/cpu_alloc_test.cpp b/libc/test/src/sched/cpu_alloc_test.cpp
new file mode 100644
index 0000000000000..3749d6a3d8393
--- /dev/null
+++ b/libc/test/src/sched/cpu_alloc_test.cpp
@@ -0,0 +1,69 @@
+//===-- Unittests for __sched_cpualloc and __sched_cpufree ----------------===//
+//
+// 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 "hdr/sched_macros.h"
+#include "hdr/types/cpu_set_t.h"
+#include "src/sched/sched_cpualloc.h"
+#include "src/sched/sched_cpufree.h"
+#include "src/sched/sched_getcpucount.h"
+#include "src/sched/sched_getcpuisset.h"
+#include "src/sched/sched_setcpuset.h"
+#include "src/sched/sched_setcpuzero.h"
+#include "test/UnitTest/Test.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+using LlvmLibcSchedCpuAllocTest = testing::Test;
+
+TEST_F(LlvmLibcSchedCpuAllocTest, AllocAndFreeSmall) {
+ int num_cpus = 10;
+ size_t alloc_size = CPU_ALLOC_SIZE(num_cpus);
+ cpu_set_t *mask = CPU_ALLOC(num_cpus);
+ ASSERT_NE(mask, static_cast<cpu_set_t *>(nullptr));
+
+ CPU_ZERO_S(alloc_size, mask);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 0);
+ ASSERT_EQ(CPU_ISSET_S(1, alloc_size, mask), 0);
+
+ CPU_SET_S(1, alloc_size, mask);
+ ASSERT_EQ(CPU_ISSET_S(1, alloc_size, mask), 1);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 1);
+
+ CPU_SET_S(5, alloc_size, mask);
+ ASSERT_EQ(CPU_ISSET_S(5, alloc_size, mask), 1);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 2);
+
+ CPU_FREE(mask);
+}
+
+TEST_F(LlvmLibcSchedCpuAllocTest, AllocAndFreeLarge) {
+ int num_cpus = 4096;
+ size_t alloc_size = CPU_ALLOC_SIZE(num_cpus);
+ cpu_set_t *mask = CPU_ALLOC(num_cpus);
+ ASSERT_NE(mask, static_cast<cpu_set_t *>(nullptr));
+
+ CPU_ZERO_S(alloc_size, mask);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 0);
+ ASSERT_EQ(CPU_ISSET_S(1, alloc_size, mask), 0);
+
+ CPU_SET_S(1, alloc_size, mask);
+ ASSERT_EQ(CPU_ISSET_S(1, alloc_size, mask), 1);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 1);
+
+ CPU_SET_S(500, alloc_size, mask);
+ ASSERT_EQ(CPU_ISSET_S(500, alloc_size, mask), 1);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 2);
+
+ CPU_SET_S(4095, alloc_size, mask);
+ ASSERT_EQ(CPU_ISSET_S(4095, alloc_size, mask), 1);
+ ASSERT_EQ(CPU_COUNT_S(alloc_size, mask), 3);
+
+ CPU_FREE(mask);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
``````````
</details>
https://github.com/llvm/llvm-project/pull/202349
More information about the libc-commits
mailing list