diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -26,8 +26,15 @@ 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/riscv64/entrypoints.txt b/libc/config/linux/riscv64/entrypoints.txt --- a/libc/config/linux/riscv64/entrypoints.txt +++ b/libc/config/linux/riscv64/entrypoints.txt @@ -26,8 +26,15 @@ 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 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -26,8 +26,15 @@ 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/llvm-libc-macros/linux/sched-macros.h b/libc/include/llvm-libc-macros/linux/sched-macros.h --- a/libc/include/llvm-libc-macros/linux/sched-macros.h +++ b/libc/include/llvm-libc-macros/linux/sched-macros.h @@ -9,6 +9,11 @@ #ifndef __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H #define __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H +#define SCHED_BATCH 3 +#define SCHED_ISO 4 +#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-macros/sched-macros.h b/libc/include/llvm-libc-macros/sched-macros.h --- a/libc/include/llvm-libc-macros/sched-macros.h +++ b/libc/include/llvm-libc-macros/sched-macros.h @@ -9,6 +9,10 @@ #ifndef __LLVM_LIBC_MACROS_SCHED_MACROS_H #define __LLVM_LIBC_MACROS_SCHED_MACROS_H +#define SCHED_OTHER 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 + #ifdef __unix__ #include "linux/sched-macros.h" #endif 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 --- /dev/null +++ b/libc/include/llvm-libc-types/struct_sched_param.h @@ -0,0 +1,38 @@ +//===-- 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 +#include +#include + +struct sched_param { + + // Process or thread execution scheduling priority. + int sched_priority; + + // This is for the SCHED_SPORADIC extension. Not yet implemented by linux (or + // anywhere AFAICT). +#if 0 + // Low scheduling priority for sporadic server. + int sched_ss_low_priority; + + // Maximum pending replenishments for sporadic server. + int sched_ss_max_repl; + + // Replenishment period for sporadic server. + struct timespec sched_ss_repl_period; + + // Initial budget for sporadic server. + struct timespec sched_ss_init_budget; +#endif +}; + +#endif // __LLVM_LIBC_TYPES_STRUCT_SCHED_PARAM_H__ diff --git a/libc/spec/linux.td b/libc/spec/linux.td --- a/libc/spec/linux.td +++ b/libc/spec/linux.td @@ -58,6 +58,19 @@ ] >; + HeaderSpec Sched = HeaderSpec< + "sched.h", + [ + 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 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -45,6 +45,10 @@ def StructTimeSpec : NamedType<"struct timespec">; def StructTimeSpecPtr : PtrType; +def StructSchedParam : NamedType<"struct sched_param">; +def StructTimeSpecPtr : PtrType; +def ConstStructTimeSpecPtr : ConstType; + def ExecArgvT : NamedType<"__exec_argv_t">; def ExecEnvpT : NamedType<"__exec_envp_t">; @@ -632,8 +636,12 @@ HeaderSpec Sched = HeaderSpec< "sched.h", - [], // Macros - [PidT, SizeTType, CpuSetT], // Types + [ + Macro<"SCHED_OTHER">, + Macro<"SCHED_FIFO">, + Macro<"SCHED_RR">, + ], + [PidT, TimeTType, StructTimeSpec, StructSchedParam], // Types [], // Enumerations [ FunctionSpec< @@ -641,6 +649,47 @@ RetValSpec, [] >, + FunctionSpec< + "sched_setparam", + RetValSpec, + [ArgSpec, ArgSpec] + >, + + FunctionSpec< + "sched_getparam", + RetValSpec, + [ArgSpec, ArgSpec] + >, + + FunctionSpec< + "sched_setscheduler", + RetValSpec, + [ArgSpec] + >, + + FunctionSpec< + "sched_getscheduler", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, + + FunctionSpec< + "sched_get_priority_min", + RetValSpec, + [ArgSpec] + >, + + FunctionSpec< + "sched_get_priority_max", + RetValSpec, + [ArgSpec] + >, + + FunctionSpec< + "sched_rr_get_interval", + RetValSpec, + [ArgSpec, ArgSpec] + >, ] >; diff --git a/libc/src/sched/CMakeLists.txt b/libc/src/sched/CMakeLists.txt --- a/libc/src/sched/CMakeLists.txt +++ b/libc/src/sched/CMakeLists.txt @@ -23,6 +23,55 @@ .${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 --- a/libc/src/sched/linux/CMakeLists.txt +++ b/libc/src/sched/linux/CMakeLists.txt @@ -43,3 +43,87 @@ 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 --- /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 // For syscall numbers. + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, sched_get_priority_max, (int policy)) { + long ret = __llvm_libc::syscall_impl(146, 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 --- /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 // 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 --- /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 // 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 --- /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 // 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 --- /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 // 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 --- /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 // 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 --- /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 // 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 --- /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 --- /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 --- /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 + +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 --- /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 + +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 --- /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 + +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 --- /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 + +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 --- /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 + +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 --- a/libc/test/src/sched/CMakeLists.txt +++ b/libc/test/src/sched/CMakeLists.txt @@ -27,6 +27,51 @@ 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 +) + +add_libc_unittest( + rr_get_interval_test + SUITE + libc_sched_unittests + SRCS + 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_get_rr_interval +) + 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 --- /dev/null +++ b/libc/test/src/sched/get_priority_test.cpp @@ -0,0 +1,53 @@ +//===-- 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 +TEST(LlvmLibcGetPriorityTest, SmokeTest) { + libc_errno = 0; + + // Linux specific test could also include: + // SCHED_BATCH, SCHED_ISO, SCHED_IDLE, SCHED_DEADLINE + auto TestPolicySuccess = [&](int policy) { + 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); + }; + + // Linux specific test could also include: + // SCHED_BATCH, SCHED_ISO, SCHED_IDLE, SCHED_DEADLINE + TestPolicySuccess(SCHED_OTHER); + TestPolicySuccess(SCHED_FIFO); + TestPolicySuccess(SCHED_RR); + + auto TestPolicyFailure = [&](int policy) { + 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); + }; + + // Arbitrary values for which there is no policy. + TestPolicyFailure(-1); + TestPolicyFailure(30); + TestPolicyFailure(80); + TestPolicyFailure(110); +} 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 --- /dev/null +++ b/libc/test/src/sched/param_and_scheduler_test.cpp @@ -0,0 +1,150 @@ +//===-- 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 "test/UnitTest/Test.h" + +#include +#include // getuid + +TEST(LlvmLibcParamAndSchedulerTest, SmokeTest) { + libc_errno = 0; + + auto TestPolicy = [&](int policy, bool req_admin) { + // 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. + + bool can_set = (!req_admin) || (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 + // different 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 param + ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, nullptr), -1); + ASSERT_EQ(libc_errno, EINVAL); + libc_errno = 0; + }; + + // Linux specific test could also include: + // SCHED_BATCH, SCHED_ISO, SCHED_IDLE, SCHED_DEADLINE + TestPolicy(SCHED_OTHER, /* req_admin */ false); + TestPolicy(SCHED_FIFO, /* req_admin */ true); + TestPolicy(SCHED_RR, /* req_admin */ true); + + // NULL param + 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/rr_get_interval_test.cpp b/libc/test/src/sched/rr_get_interval_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/sched/rr_get_interval_test.cpp @@ -0,0 +1,73 @@ +//===-- Unittests for sched_rr_get_internval -----------------------------===// +// +// 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 "test/UnitTest/Test.h" + +#include +TEST(LlvmLibcRRGetIntervalTest, 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 (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. +}