[libc-commits] [libc] 0432b85 - [LIBC] Implement remainder of posix 'sched.h' minus `SCHED_SPORADIC`
Noah Goldstein via libc-commits
libc-commits at lists.llvm.org
Thu Apr 20 12:53:54 PDT 2023
Author: Noah Goldstein
Date: 2023-04-20T14:53:41-05:00
New Revision: 0432b85d8e800439e57642bb25e93c32fa864f5c
URL: https://github.com/llvm/llvm-project/commit/0432b85d8e800439e57642bb25e93c32fa864f5c
DIFF: https://github.com/llvm/llvm-project/commit/0432b85d8e800439e57642bb25e93c32fa864f5c.diff
LOG: [LIBC] Implement remainder of posix 'sched.h' minus `SCHED_SPORADIC`
Includes macros:
linux/SCHED_OTHER // posix req
linux/SCHED_FIFO // posix req
linux/SCHED_RR // posix req
linux/SCHED_BATCH
linux/SCHED_ISO
linux/SCHED_IDLE
linux/SCHED_DEADLINE
Includes types:
struct sched_param { int sched_priority; }
Includes functions:
sched_setparam
sched_getparam
sched_setscheduler
sched_getscheduler
sched_get_priority_max
sched_get_priority_min
sched_rr_get_interval
Reviewed By: michaelrj
Differential Revision: https://reviews.llvm.org/D148069
Added:
libc/include/llvm-libc-types/struct_sched_param.h
libc/src/sched/linux/sched_get_priority_max.cpp
libc/src/sched/linux/sched_get_priority_min.cpp
libc/src/sched/linux/sched_getparam.cpp
libc/src/sched/linux/sched_getscheduler.cpp
libc/src/sched/linux/sched_rr_get_interval.cpp
libc/src/sched/linux/sched_setparam.cpp
libc/src/sched/linux/sched_setscheduler.cpp
libc/src/sched/sched_get_priority_max.h
libc/src/sched/sched_get_priority_min.h
libc/src/sched/sched_getparam.h
libc/src/sched/sched_getscheduler.h
libc/src/sched/sched_rr_get_interval.h
libc/src/sched/sched_setparam.h
libc/src/sched/sched_setscheduler.h
libc/test/src/sched/get_priority_test.cpp
libc/test/src/sched/param_and_scheduler_test.cpp
libc/test/src/sched/sched_rr_get_interval_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/api.td
libc/config/linux/riscv64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/include/CMakeLists.txt
libc/include/llvm-libc-macros/linux/sched-macros.h
libc/include/llvm-libc-types/CMakeLists.txt
libc/spec/linux.td
libc/spec/posix.td
libc/src/sched/CMakeLists.txt
libc/src/sched/linux/CMakeLists.txt
libc/test/src/sched/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index a6413add96db5..38023e553a9c2 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -26,8 +26,15 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.fcntl.openat
# sched.h entrypoints
+ libc.src.sched.sched_get_priority_max
+ libc.src.sched.sched_get_priority_min
libc.src.sched.sched_getaffinity
+ libc.src.sched.sched_getparam
+ libc.src.sched.sched_getscheduler
+ libc.src.sched.sched_rr_get_interval
libc.src.sched.sched_setaffinity
+ libc.src.sched.sched_setparam
+ libc.src.sched.sched_setscheduler
libc.src.sched.sched_yield
# string.h entrypoints
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 10b4abfee7a43..8fac4e041f1bc 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -103,7 +103,15 @@ def TimeAPI : PublicAPI<"time.h"> {
}
def SchedAPI : PublicAPI<"sched.h"> {
- let Types = ["pid_t", "size_t", "cpu_set_t"];
+ let Types = [
+ "pid_t",
+ "size_t",
+ "cpu_set_t",
+ "struct sched_param",
+ // Needed according to posix standard
+ "time_t",
+ "struct timespec",
+ ];
}
def SysMManAPI : PublicAPI<"sys/mman.h"> {
diff --git a/libc/config/linux/riscv64/entrypoints.txt b/libc/config/linux/riscv64/entrypoints.txt
index 6e1f8e30dea92..dc700941c667c 100644
--- a/libc/config/linux/riscv64/entrypoints.txt
+++ b/libc/config/linux/riscv64/entrypoints.txt
@@ -26,8 +26,15 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.fcntl.openat
# sched.h entrypoints
+ libc.src.sched.sched_get_priority_max
+ libc.src.sched.sched_get_priority_min
libc.src.sched.sched_getaffinity
+ libc.src.sched.sched_getparam
+ libc.src.sched.sched_getscheduler
+ libc.src.sched.sched_rr_get_interval
libc.src.sched.sched_setaffinity
+ libc.src.sched.sched_setparam
+ libc.src.sched.sched_setscheduler
libc.src.sched.sched_yield
# string.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 0c084bba18cab..5ac24c6daade0 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -26,8 +26,15 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.fcntl.openat
# sched.h entrypoints
+ libc.src.sched.sched_get_priority_max
+ libc.src.sched.sched_get_priority_min
libc.src.sched.sched_getaffinity
+ libc.src.sched.sched_getparam
+ libc.src.sched.sched_getscheduler
+ libc.src.sched.sched_rr_get_interval
libc.src.sched.sched_setaffinity
+ libc.src.sched.sched_setparam
+ libc.src.sched.sched_setscheduler
libc.src.sched.sched_yield
# string.h entrypoints
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index bd2458eb3856a..f3b23a5e3e26a 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -248,9 +248,13 @@ add_gen_header(
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sched_macros
+ .llvm-libc-types.cpu_set_t
.llvm-libc-types.pid_t
.llvm-libc-types.size_t
- .llvm-libc-types.cpu_set_t
+ .llvm-libc-types.struct_sched_param
+ # Needed according to posix standard
+ .llvm-libc-types.time_t
+ .llvm-libc-types.struct_timespec
)
add_gen_header(
diff --git a/libc/include/llvm-libc-macros/linux/sched-macros.h b/libc/include/llvm-libc-macros/linux/sched-macros.h
index f9980b060fd37..0c574440ccbcf 100644
--- a/libc/include/llvm-libc-macros/linux/sched-macros.h
+++ b/libc/include/llvm-libc-macros/linux/sched-macros.h
@@ -9,6 +9,20 @@
#ifndef __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
+// Definitions of SCHED_* macros must match was linux as at:
+// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/sched.h
+
+// Posix required
+#define SCHED_OTHER 0
+#define SCHED_FIFO 1
+#define SCHED_RR 2
+
+// Linux extentions
+#define SCHED_BATCH 3
+#define SCHED_ISO 4 // Not yet implemented, reserved.
+#define SCHED_IDLE 5
+#define SCHED_DEADLINE 6
+
#define CPU_COUNT_S(setsize, set) __sched_getcpucount(setsize, set)
#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t), set)
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 289307b76bbdb..37230208e458a 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -60,6 +60,7 @@ add_header(struct_timeval HDR struct_timeval.h DEPENDS .suseconds_t .time_t)
add_header(struct_rlimit HDR struct_rlimit.h DEPENDS .rlim_t)
add_header(struct_rusage HDR struct_rusage.h DEPENDS .struct_timeval)
add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t)
+add_header(struct_sched_param HDR struct_sched_param.h)
add_header(union_sigval HDR union_sigval.h)
add_header(siginfo_t HDR siginfo_t.h DEPENDS .union_sigval .pid_t .uid_t)
add_header(sig_atomic_t HDR sig_atomic_t.h)
diff --git a/libc/include/llvm-libc-types/struct_sched_param.h b/libc/include/llvm-libc-types/struct_sched_param.h
new file mode 100644
index 0000000000000..4f31881ceeb6c
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_sched_param.h
@@ -0,0 +1,21 @@
+//===-- Definition of type struct sched_param -----------------------------===//
+//
+// 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_TYPES_STRUCT_SCHED_PARAM_H__
+#define __LLVM_LIBC_TYPES_STRUCT_SCHED_PARAM_H__
+
+#include <llvm-libc-types/pid_t.h>
+#include <llvm-libc-types/struct_timespec.h>
+#include <llvm-libc-types/time_t.h>
+
+struct sched_param {
+ // Process or thread execution scheduling priority.
+ int sched_priority;
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_SCHED_PARAM_H__
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index 5418c0bebf2ba..d5b876cadebe5 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -58,6 +58,22 @@ def Linux : StandardSpec<"Linux"> {
]
>;
+ HeaderSpec Sched = HeaderSpec<
+ "sched.h",
+ [
+ Macro<"SCHED_OTHER">,
+ Macro<"SCHED_FIFO">,
+ Macro<"SCHED_RR">,
+ Macro<"SCHED_BATCH">,
+ Macro<"SCHED_ISO">,
+ Macro<"SCHED_IDLE">,
+ Macro<"SCHED_DEADLINE">,
+ ],
+ [], // Types
+ [], // Enumerations
+ [] // Functions
+ >;
+
HeaderSpec SysMMan = HeaderSpec<
"sys/mman.h",
[Macro<"MAP_ANONYMOUS">]
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index f59891c00c3a9..2246e49eeaaa6 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -45,6 +45,10 @@ def ConstStructDirentPtrPtr : ConstType<StructDirentPtrPtr>;
def StructTimeSpec : NamedType<"struct timespec">;
def StructTimeSpecPtr : PtrType<StructTimeSpec>;
+def StructSchedParam : NamedType<"struct sched_param">;
+def StructSchedParamPtr : PtrType<StructSchedParam>;
+def ConstStructSchedParamPtr : ConstType<StructSchedParamPtr>;
+
def ExecArgvT : NamedType<"__exec_argv_t">;
def ExecEnvpT : NamedType<"__exec_envp_t">;
@@ -633,13 +637,54 @@ def POSIX : StandardSpec<"POSIX"> {
HeaderSpec Sched = HeaderSpec<
"sched.h",
[], // Macros
- [PidT, SizeTType, CpuSetT], // Types
+ [PidT, TimeTType, StructTimeSpec, StructSchedParam], // Types
[], // Enumerations
[
FunctionSpec<
"sched_yield",
RetValSpec<IntType>,
- []
+ [ArgSpec<VoidType>]
+ >,
+ FunctionSpec<
+ "sched_setparam",
+ RetValSpec<IntType>,
+ [ArgSpec<PidT>, ArgSpec<ConstStructSchedParamPtr>]
+ >,
+
+ FunctionSpec<
+ "sched_getparam",
+ RetValSpec<IntType>,
+ [ArgSpec<PidT>, ArgSpec<StructSchedParamPtr>]
+ >,
+
+ FunctionSpec<
+ "sched_setscheduler",
+ RetValSpec<IntType>,
+ [ArgSpec<PidT>]
+ >,
+
+ FunctionSpec<
+ "sched_getscheduler",
+ RetValSpec<IntType>,
+ [ArgSpec<PidT>, ArgSpec<IntType>, ArgSpec<ConstStructSchedParamPtr>]
+ >,
+
+ FunctionSpec<
+ "sched_get_priority_min",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+
+ FunctionSpec<
+ "sched_get_priority_max",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>]
+ >,
+
+ FunctionSpec<
+ "sched_rr_get_interval",
+ RetValSpec<IntType>,
+ [ArgSpec<PidT>, ArgSpec<StructTimeSpecPtr>]
>,
]
>;
diff --git a/libc/src/sched/CMakeLists.txt b/libc/src/sched/CMakeLists.txt
index 7b55be8a7156e..a98940c55abd5 100644
--- a/libc/src/sched/CMakeLists.txt
+++ b/libc/src/sched/CMakeLists.txt
@@ -23,6 +23,55 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.sched_yield
)
+add_entrypoint_object(
+ sched_setparam
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_setparam
+)
+
+add_entrypoint_object(
+ sched_getparam
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_getparam
+)
+
+add_entrypoint_object(
+ sched_setscheduler
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_setscheduler
+)
+
+add_entrypoint_object(
+ sched_getscheduler
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_getscheduler
+)
+
+add_entrypoint_object(
+ sched_get_priority_min
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_get_priority_min
+)
+
+add_entrypoint_object(
+ sched_get_priority_max
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_get_priority_max
+)
+
+add_entrypoint_object(
+ sched_rr_get_interval
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sched_rr_get_interval
+)
+
add_entrypoint_object(
__sched_getcpucount
ALIAS
diff --git a/libc/src/sched/linux/CMakeLists.txt b/libc/src/sched/linux/CMakeLists.txt
index 895ce1c202347..d53c6e5d45052 100644
--- a/libc/src/sched/linux/CMakeLists.txt
+++ b/libc/src/sched/linux/CMakeLists.txt
@@ -43,3 +43,87 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ sched_setparam
+ SRCS
+ sched_setparam.cpp
+ HDRS
+ ../sched_setparam.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sched_getparam
+ SRCS
+ sched_getparam.cpp
+ HDRS
+ ../sched_getparam.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sched_setscheduler
+ SRCS
+ sched_setscheduler.cpp
+ HDRS
+ ../sched_setscheduler.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sched_getscheduler
+ SRCS
+ sched_getscheduler.cpp
+ HDRS
+ ../sched_getscheduler.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sched_get_priority_min
+ SRCS
+ sched_get_priority_min.cpp
+ HDRS
+ ../sched_get_priority_min.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sched_get_priority_max
+ SRCS
+ sched_get_priority_max.cpp
+ HDRS
+ ../sched_get_priority_max.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sched_rr_get_interval
+ SRCS
+ sched_rr_get_interval.cpp
+ HDRS
+ ../sched_rr_get_interval.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
diff --git a/libc/src/sched/linux/sched_get_priority_max.cpp b/libc/src/sched/linux/sched_get_priority_max.cpp
new file mode 100644
index 0000000000000..87d52f43c915c
--- /dev/null
+++ b/libc/src/sched/linux/sched_get_priority_max.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of sched_get_priority_max --------------------------===//
+//
+// 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_get_priority_max.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_get_priority_max, (int policy)) {
+ long ret = __llvm_libc::syscall_impl(SYS_sched_get_priority_min, policy);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/linux/sched_get_priority_min.cpp b/libc/src/sched/linux/sched_get_priority_min.cpp
new file mode 100644
index 0000000000000..5e5e52eb16448
--- /dev/null
+++ b/libc/src/sched/linux/sched_get_priority_min.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of sched_get_priority_min --------------------------===//
+//
+// 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_get_priority_min.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_get_priority_min, (int policy)) {
+ long ret = __llvm_libc::syscall_impl(SYS_sched_get_priority_min, policy);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/linux/sched_getparam.cpp b/libc/src/sched/linux/sched_getparam.cpp
new file mode 100644
index 0000000000000..77743d30ae2a4
--- /dev/null
+++ b/libc/src/sched/linux/sched_getparam.cpp
@@ -0,0 +1,29 @@
+//===-- Implementation of sched_getparam ----------------------------------===//
+//
+// 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_getparam.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_getparam,
+ (pid_t tid, struct sched_param *param)) {
+ long ret = __llvm_libc::syscall_impl(SYS_sched_getparam, tid, param);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/linux/sched_getscheduler.cpp b/libc/src/sched/linux/sched_getscheduler.cpp
new file mode 100644
index 0000000000000..997aaac151a77
--- /dev/null
+++ b/libc/src/sched/linux/sched_getscheduler.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of sched_getscheduler ------------------------------===//
+//
+// 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_getscheduler.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_getscheduler, (pid_t tid)) {
+ long ret = __llvm_libc::syscall_impl(SYS_sched_getscheduler, tid);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/linux/sched_rr_get_interval.cpp b/libc/src/sched/linux/sched_rr_get_interval.cpp
new file mode 100644
index 0000000000000..418c3fdacdb35
--- /dev/null
+++ b/libc/src/sched/linux/sched_rr_get_interval.cpp
@@ -0,0 +1,29 @@
+//===-- Implementation of sched_rr_get_interval ---------------------------===//
+//
+// 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_rr_get_interval.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_rr_get_interval,
+ (pid_t tid, struct timespec *tp)) {
+ long ret = __llvm_libc::syscall_impl(SYS_sched_rr_get_interval, tid, tp);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/linux/sched_setparam.cpp b/libc/src/sched/linux/sched_setparam.cpp
new file mode 100644
index 0000000000000..e9061a8fc364b
--- /dev/null
+++ b/libc/src/sched/linux/sched_setparam.cpp
@@ -0,0 +1,29 @@
+//===-- Implementation of sched_setparam ----------------------------------===//
+//
+// 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_setparam.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_setparam,
+ (pid_t tid, const struct sched_param *param)) {
+ long ret = __llvm_libc::syscall_impl(SYS_sched_setparam, tid, param);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/linux/sched_setscheduler.cpp b/libc/src/sched/linux/sched_setscheduler.cpp
new file mode 100644
index 0000000000000..d91c69e333952
--- /dev/null
+++ b/libc/src/sched/linux/sched_setscheduler.cpp
@@ -0,0 +1,30 @@
+//===-- Implementation of sched_setscheduler ------------------------------===//
+//
+// 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_setscheduler.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, sched_setscheduler,
+ (pid_t tid, int policy, const struct sched_param *param)) {
+ long ret =
+ __llvm_libc::syscall_impl(SYS_sched_setscheduler, tid, policy, param);
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sched/sched_get_priority_max.h b/libc/src/sched/sched_get_priority_max.h
new file mode 100644
index 0000000000000..3ddcb08627836
--- /dev/null
+++ b/libc/src/sched/sched_get_priority_max.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for sched_get_priority_max ---------*- 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_GET_PRIORITY_MAX_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_GET_PRIORITY_MAX_H
+
+namespace __llvm_libc {
+
+int sched_get_priority_max(int policy);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_GET_PRIORITY_MAX_H
diff --git a/libc/src/sched/sched_get_priority_min.h b/libc/src/sched/sched_get_priority_min.h
new file mode 100644
index 0000000000000..10bca87beadcb
--- /dev/null
+++ b/libc/src/sched/sched_get_priority_min.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for sched_get_priority_min ---------*- 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_GET_PRIORITY_MIN_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_GET_PRIORITY_MIN_H
+
+namespace __llvm_libc {
+
+int sched_get_priority_min(int policy);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_GET_PRIORITY_MIN_H
diff --git a/libc/src/sched/sched_getparam.h b/libc/src/sched/sched_getparam.h
new file mode 100644
index 0000000000000..fcae11b71f8b5
--- /dev/null
+++ b/libc/src/sched/sched_getparam.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sched_getparam ----------------*- 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_GETPARAM_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_GETPARAM_H
+
+#include <sched.h>
+
+namespace __llvm_libc {
+
+int sched_getparam(pid_t tid, struct sched_param *param);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_GETPARAM_H
diff --git a/libc/src/sched/sched_getscheduler.h b/libc/src/sched/sched_getscheduler.h
new file mode 100644
index 0000000000000..543b72d5a66fc
--- /dev/null
+++ b/libc/src/sched/sched_getscheduler.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sched_getscheduler -------------*- 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_GETSCHEDULER_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_GETSCHEDULER_H
+
+#include <sched.h>
+
+namespace __llvm_libc {
+
+int sched_getscheduler(pid_t tid);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_GETSCHEDULER_H
diff --git a/libc/src/sched/sched_rr_get_interval.h b/libc/src/sched/sched_rr_get_interval.h
new file mode 100644
index 0000000000000..b90e4c3c26acc
--- /dev/null
+++ b/libc/src/sched/sched_rr_get_interval.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sched_rr_get_interval ----------*- 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_RR_GET_INTERVAL_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_RR_GET_INTERVAL_H
+
+#include <sched.h>
+
+namespace __llvm_libc {
+
+int sched_rr_get_interval(pid_t tid, struct timespec *tp);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_RR_GET_INTERVAL_H
diff --git a/libc/src/sched/sched_setparam.h b/libc/src/sched/sched_setparam.h
new file mode 100644
index 0000000000000..1707597045fd7
--- /dev/null
+++ b/libc/src/sched/sched_setparam.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sched_setparam ----------------*- 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_SETPARAM_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_SETPARAM_H
+
+#include <sched.h>
+
+namespace __llvm_libc {
+
+int sched_setparam(pid_t tid, const struct sched_param *param);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_SETPARAM_H
diff --git a/libc/src/sched/sched_setscheduler.h b/libc/src/sched/sched_setscheduler.h
new file mode 100644
index 0000000000000..2a56e27cdf138
--- /dev/null
+++ b/libc/src/sched/sched_setscheduler.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sched_setscheduler -------------*- 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_SETSCHEDULER_H
+#define LLVM_LIBC_SRC_SCHED_SCHED_SETSCHEDULER_H
+
+#include <sched.h>
+
+namespace __llvm_libc {
+
+int sched_setscheduler(pid_t tid, int policy, const struct sched_param *param);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SCHED_SCHED_SETSCHEDULER_H
diff --git a/libc/test/src/sched/CMakeLists.txt b/libc/test/src/sched/CMakeLists.txt
index 16ed8920e28f1..15a6257702346 100644
--- a/libc/test/src/sched/CMakeLists.txt
+++ b/libc/test/src/sched/CMakeLists.txt
@@ -27,6 +27,53 @@ add_libc_unittest(
libc.src.sched.sched_yield
)
+add_libc_unittest(
+ get_priority_test
+ SUITE
+ libc_sched_unittests
+ SRCS
+ get_priority_test.cpp
+ DEPENDS
+ libc.include.sched
+ libc.src.errno.errno
+ libc.src.sched.sched_get_priority_min
+ libc.src.sched.sched_get_priority_max
+)
+
+add_libc_unittest(
+ scheduler_test
+ SUITE
+ libc_sched_unittests
+ SRCS
+ param_and_scheduler_test.cpp
+ DEPENDS
+ libc.include.sched
+ libc.src.errno.errno
+ libc.src.sched.sched_getscheduler
+ libc.src.sched.sched_setscheduler
+ libc.src.sched.sched_getparam
+ libc.src.sched.sched_setparam
+ libc.src.sched.sched_get_priority_min
+ libc.src.sched.sched_get_priority_max
+ libc.src.unistd.getuid
+)
+
+add_libc_unittest(
+ sched_rr_get_interval_test
+ SUITE
+ libc_sched_unittests
+ SRCS
+ sched_rr_get_interval_test.cpp
+ DEPENDS
+ libc.include.sched
+ libc.src.errno.errno
+ libc.src.sched.sched_getscheduler
+ libc.src.sched.sched_setscheduler
+ libc.src.sched.sched_get_priority_min
+ libc.src.sched.sched_rr_get_interval
+ libc.src.unistd.getuid
+)
+
add_libc_unittest(
cpu_count_test
SUITE
diff --git a/libc/test/src/sched/get_priority_test.cpp b/libc/test/src/sched/get_priority_test.cpp
new file mode 100644
index 0000000000000..fb532e25688e9
--- /dev/null
+++ b/libc/test/src/sched/get_priority_test.cpp
@@ -0,0 +1,108 @@
+//===-- Unittests for sched_get_priority_{min,max} ------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/sched/sched_get_priority_max.h"
+#include "src/sched/sched_get_priority_min.h"
+#include "test/UnitTest/Test.h"
+
+#include <sched.h>
+
+TEST(LlvmLibcSchedGetPriorityTest, HandleBadPolicyTest) {
+
+ // Test arbitrary values for which there is no policy.
+ {
+ int policy = -1;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_EQ(max_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_EQ(min_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ }
+
+ {
+ int policy = 30;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_EQ(max_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_EQ(min_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ }
+
+ {
+ int policy = 80;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_EQ(max_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_EQ(min_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ }
+
+ {
+ int policy = 110;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_EQ(max_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_EQ(min_priority, -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ }
+}
+
+TEST(LlvmLibcSchedGetPriorityTest, SmokeTest) {
+ libc_errno = 0;
+
+ // We Test:
+ // SCHED_OTHER, SCHED_FIFO, SCHED_RR
+ // Linux specific test could also include:
+ // SCHED_BATCH, SCHED_ISO, SCHED_IDLE, SCHED_DEADLINE
+ {
+ int policy = SCHED_OTHER;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_GE(max_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ ASSERT_LE(max_priority, 99);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_GE(max_priority, min_priority);
+ }
+
+ {
+ int policy = SCHED_FIFO;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_GE(max_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ ASSERT_LE(max_priority, 99);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_GE(max_priority, min_priority);
+ }
+
+ {
+ int policy = SCHED_RR;
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_GE(max_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ ASSERT_LE(max_priority, 99);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_GE(max_priority, min_priority);
+ }
+}
diff --git a/libc/test/src/sched/param_and_scheduler_test.cpp b/libc/test/src/sched/param_and_scheduler_test.cpp
new file mode 100644
index 0000000000000..35e902cedface
--- /dev/null
+++ b/libc/test/src/sched/param_and_scheduler_test.cpp
@@ -0,0 +1,353 @@
+//===-- Unittests for sched_{set,get}{scheduler,param} --------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/sched/sched_get_priority_max.h"
+#include "src/sched/sched_get_priority_min.h"
+#include "src/sched/sched_getparam.h"
+#include "src/sched/sched_getscheduler.h"
+#include "src/sched/sched_setparam.h"
+#include "src/sched/sched_setscheduler.h"
+#include "src/unistd/getuid.h"
+#include "test/UnitTest/Test.h"
+
+#include <sched.h>
+
+// We Test:
+// SCHED_OTHER, SCHED_FIFO, SCHED_RR
+//
+// TODO: Missing two tests.
+// 1) Missing permissions -> EPERM. Maybe doable by finding
+// another pid that exists and changing its policy, but that
+// seems risky. Maybe something with fork/clone would work.
+//
+// 2) Unkown pid -> ESRCH. Probably safe to choose a large range
+// number or scanning current pids and getting one that doesn't
+// exist, but again seems like it may risk actually changing
+// sched policy on a running task.
+//
+// Linux specific test could also include:
+// SCHED_BATCH, SCHED_ISO, SCHED_IDLE, SCHED_DEADLINE
+
+TEST(LlvmLibcSchedParamAndSchedulerTest, SchedOtherTest) {
+ libc_errno = 0;
+
+ int policy = SCHED_OTHER;
+ bool can_set = true;
+
+ int init_policy = __llvm_libc::sched_getscheduler(0);
+ ASSERT_GE(init_policy, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_GE(max_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ struct sched_param param = {min_priority};
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(-1, policy, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getscheduler(-1), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Invalid Policy
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy | 128, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Out of bounds priority
+ param.sched_priority = min_priority - 1;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ param.sched_priority = max_priority + 1;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), -1);
+ // A bit hard to test as depending if we are root or not we can run into
+ //
diff erent issues.
+ ASSERT_TRUE(libc_errno == EINVAL || libc_errno == EPERM);
+ libc_errno = 0;
+
+ // Some sched policies require permissions, so skip
+ param.sched_priority = min_priority;
+ // Success / missing permissions.
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m),
+ can_set ? 0 : -1);
+ ASSERT_TRUE(can_set ? (libc_errno == 0)
+ : (libc_errno == EINVAL || libc_errno == EPERM));
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getscheduler(0), can_set ? policy : init_policy);
+ ASSERT_EQ(libc_errno, 0);
+
+ // Out of bounds priority
+ param.sched_priority = -1;
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ param.sched_priority = max_priority + 1;
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ for (int priority = min_priority; priority <= max_priority; ++priority) {
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+ int init_priority = param.sched_priority;
+
+ param.sched_priority = priority;
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_setparam(-1, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(-1, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Success / missing permissions
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), can_set ? 0 : -1);
+ ASSERT_TRUE(can_set ? (libc_errno == 0)
+ : (libc_errno == EINVAL || libc_errno == EPERM));
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ ASSERT_EQ(param.sched_priority, can_set ? priority : init_priority);
+ }
+ // Null test
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, nullptr), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+}
+
+TEST(LlvmLibcSchedParamAndSchedulerTest, SchedFIFOTest) {
+ libc_errno = 0;
+
+ int policy = SCHED_FIFO;
+ bool can_set = __llvm_libc::getuid() == 0;
+
+ int init_policy = __llvm_libc::sched_getscheduler(0);
+ ASSERT_GE(init_policy, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_GE(max_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ struct sched_param param = {min_priority};
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(-1, policy, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getscheduler(-1), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Invalid Policy
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy | 128, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Out of bounds priority
+ param.sched_priority = min_priority - 1;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ param.sched_priority = max_priority + 1;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), -1);
+ // A bit hard to test as depending if we are root or not we can run into
+ //
diff erent issues.
+ ASSERT_TRUE(libc_errno == EINVAL || libc_errno == EPERM);
+ libc_errno = 0;
+
+ // Some sched policies require permissions, so skip
+ param.sched_priority = min_priority;
+ // Success / missing permissions.
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m),
+ can_set ? 0 : -1);
+ ASSERT_TRUE(can_set ? (libc_errno == 0)
+ : (libc_errno == EINVAL || libc_errno == EPERM));
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getscheduler(0), can_set ? policy : init_policy);
+ ASSERT_EQ(libc_errno, 0);
+
+ // Out of bounds priority
+ param.sched_priority = -1;
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ param.sched_priority = max_priority + 1;
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ for (int priority = min_priority; priority <= max_priority; ++priority) {
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+ int init_priority = param.sched_priority;
+
+ param.sched_priority = priority;
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_setparam(-1, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(-1, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Success / missing permissions
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), can_set ? 0 : -1);
+ ASSERT_TRUE(can_set ? (libc_errno == 0)
+ : (libc_errno == EINVAL || libc_errno == EPERM));
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ ASSERT_EQ(param.sched_priority, can_set ? priority : init_priority);
+ }
+ // Null test
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, nullptr), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+}
+
+TEST(LlvmLibcSchedParamAndSchedulerTest, SchedRRTest) {
+ libc_errno = 0;
+
+ int policy = SCHED_RR;
+ bool can_set = __llvm_libc::getuid() == 0;
+
+ int init_policy = __llvm_libc::sched_getscheduler(0);
+ ASSERT_GE(init_policy, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ int max_priority = __llvm_libc::sched_get_priority_max(policy);
+ ASSERT_GE(max_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ struct sched_param param = {min_priority};
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(-1, policy, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getscheduler(-1), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Invalid Policy
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy | 128, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Out of bounds priority
+ param.sched_priority = min_priority - 1;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ param.sched_priority = max_priority + 1;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), -1);
+ // A bit hard to test as depending if we are root or not we can run into
+ //
diff erent issues.
+ ASSERT_TRUE(libc_errno == EINVAL || libc_errno == EPERM);
+ libc_errno = 0;
+
+ // Some sched policies require permissions, so skip
+ param.sched_priority = min_priority;
+ // Success / missing permissions.
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m),
+ can_set ? 0 : -1);
+ ASSERT_TRUE(can_set ? (libc_errno == 0)
+ : (libc_errno == EINVAL || libc_errno == EPERM));
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getscheduler(0), can_set ? policy : init_policy);
+ ASSERT_EQ(libc_errno, 0);
+
+ // Out of bounds priority
+ param.sched_priority = -1;
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ param.sched_priority = max_priority + 1;
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ for (int priority = min_priority; priority <= max_priority; ++priority) {
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+ int init_priority = param.sched_priority;
+
+ param.sched_priority = priority;
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_setparam(-1, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(-1, ¶m), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ // Success / missing permissions
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), can_set ? 0 : -1);
+ ASSERT_TRUE(can_set ? (libc_errno == 0)
+ : (libc_errno == EINVAL || libc_errno == EPERM));
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ ASSERT_EQ(param.sched_priority, can_set ? priority : init_priority);
+ }
+ // Null test
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, nullptr), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+}
+
+TEST(LlvmLibcSchedParamAndSchedulerTest, NullParamTest) {
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_setparam(0, nullptr), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+
+ ASSERT_EQ(__llvm_libc::sched_getparam(0, nullptr), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+}
diff --git a/libc/test/src/sched/sched_rr_get_interval_test.cpp b/libc/test/src/sched/sched_rr_get_interval_test.cpp
new file mode 100644
index 0000000000000..3315bf945db29
--- /dev/null
+++ b/libc/test/src/sched/sched_rr_get_interval_test.cpp
@@ -0,0 +1,74 @@
+//===-- Unittests for sched_rr_get_interval -------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/sched/sched_get_priority_min.h"
+#include "src/sched/sched_getscheduler.h"
+#include "src/sched/sched_rr_get_interval.h"
+#include "src/sched/sched_setscheduler.h"
+#include "src/unistd/getuid.h"
+#include "test/UnitTest/Test.h"
+
+#include <sched.h>
+
+TEST(LlvmLibcSchedRRGetIntervalTest, SmokeTest) {
+ libc_errno = 0;
+ auto SetSched = [&](int policy) {
+ int min_priority = __llvm_libc::sched_get_priority_min(policy);
+ ASSERT_GE(min_priority, 0);
+ ASSERT_EQ(libc_errno, 0);
+ struct sched_param param;
+ param.sched_priority = min_priority;
+ ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, ¶m), 0);
+ ASSERT_EQ(libc_errno, 0);
+ };
+
+ auto TimespecToNs = [](struct timespec t) {
+ return t.tv_sec * 1000UL * 1000UL * 1000UL + t.tv_nsec;
+ };
+
+ struct timespec ts;
+
+ // We can only set SCHED_RR with CAP_SYS_ADMIN
+ if (__llvm_libc::getuid() == 0)
+ SetSched(SCHED_RR);
+
+ int cur_policy = __llvm_libc::sched_getscheduler(0);
+ ASSERT_GE(cur_policy, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ // We can actually run meaningful tests.
+ if (cur_policy == SCHED_RR) {
+ // Success
+ ASSERT_EQ(__llvm_libc::sched_rr_get_interval(0, &ts), 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ // Check that numbers make sense (liberal bound of 10ns - 30sec)
+ ASSERT_GT(TimespecToNs(ts), 10UL);
+ ASSERT_LT(TimespecToNs(ts), 30UL * 1000UL * 1000UL * 1000UL);
+
+ // Null timespec
+ ASSERT_EQ(__llvm_libc::sched_rr_get_interval(0, nullptr), -1);
+ ASSERT_EQ(libc_errno, EFAULT);
+ libc_errno = 0;
+
+ // Negative pid
+ ASSERT_EQ(__llvm_libc::sched_rr_get_interval(-1, &ts), -1);
+ ASSERT_EQ(libc_errno, EINVAL);
+ libc_errno = 0;
+ }
+
+ // Negative tests don't have SCHED_RR set
+ SetSched(SCHED_OTHER);
+ ASSERT_EQ(__llvm_libc::sched_rr_get_interval(0, &ts), 0);
+ ASSERT_EQ(libc_errno, 0);
+ libc_errno = 0;
+
+ // TODO: Missing unkown pid -> ESRCH. This is read only so safe to try a few
+ // unlikely values.
+}
More information about the libc-commits
mailing list