[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, &param), -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, &param), -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, &param), -1);
+  ASSERT_EQ(libc_errno, EINVAL);
+  libc_errno = 0;
+
+  param.sched_priority = max_priority + 1;
+  ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, &param), -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, &param),
+            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, &param), -1);
+  ASSERT_EQ(libc_errno, EINVAL);
+  libc_errno = 0;
+
+  param.sched_priority = max_priority + 1;
+  ASSERT_EQ(__llvm_libc::sched_setparam(0, &param), -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, &param), 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, &param), -1);
+    ASSERT_EQ(libc_errno, EINVAL);
+    libc_errno = 0;
+
+    ASSERT_EQ(__llvm_libc::sched_getparam(-1, &param), -1);
+    ASSERT_EQ(libc_errno, EINVAL);
+    libc_errno = 0;
+
+    // Success / missing permissions
+    ASSERT_EQ(__llvm_libc::sched_setparam(0, &param), 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, &param), 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, &param), -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, &param), -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, &param), -1);
+  ASSERT_EQ(libc_errno, EINVAL);
+  libc_errno = 0;
+
+  param.sched_priority = max_priority + 1;
+  ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, &param), -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, &param),
+            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, &param), -1);
+  ASSERT_EQ(libc_errno, EINVAL);
+  libc_errno = 0;
+
+  param.sched_priority = max_priority + 1;
+  ASSERT_EQ(__llvm_libc::sched_setparam(0, &param), -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, &param), 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, &param), -1);
+    ASSERT_EQ(libc_errno, EINVAL);
+    libc_errno = 0;
+
+    ASSERT_EQ(__llvm_libc::sched_getparam(-1, &param), -1);
+    ASSERT_EQ(libc_errno, EINVAL);
+    libc_errno = 0;
+
+    // Success / missing permissions
+    ASSERT_EQ(__llvm_libc::sched_setparam(0, &param), 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, &param), 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, &param), -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, &param), -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, &param), -1);
+  ASSERT_EQ(libc_errno, EINVAL);
+  libc_errno = 0;
+
+  param.sched_priority = max_priority + 1;
+  ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, &param), -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, &param),
+            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, &param), -1);
+  ASSERT_EQ(libc_errno, EINVAL);
+  libc_errno = 0;
+
+  param.sched_priority = max_priority + 1;
+  ASSERT_EQ(__llvm_libc::sched_setparam(0, &param), -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, &param), 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, &param), -1);
+    ASSERT_EQ(libc_errno, EINVAL);
+    libc_errno = 0;
+
+    ASSERT_EQ(__llvm_libc::sched_getparam(-1, &param), -1);
+    ASSERT_EQ(libc_errno, EINVAL);
+    libc_errno = 0;
+
+    // Success / missing permissions
+    ASSERT_EQ(__llvm_libc::sched_setparam(0, &param), 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, &param), 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, &param), 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