diff --git a/libc/src/sched/linux/sched_getscheduler.cpp b/libc/src/sched/linux/sched_getscheduler.cpp --- a/libc/src/sched/linux/sched_getscheduler.cpp +++ b/libc/src/sched/linux/sched_getscheduler.cpp @@ -22,7 +22,7 @@ libc_errno = -ret; return -1; } - return 0; + return ret; } } // namespace __llvm_libc diff --git a/libc/src/sched/linux/sched_setscheduler.cpp b/libc/src/sched/linux/sched_setscheduler.cpp --- a/libc/src/sched/linux/sched_setscheduler.cpp +++ b/libc/src/sched/linux/sched_setscheduler.cpp @@ -24,7 +24,7 @@ libc_errno = -ret; return -1; } - return 0; + return ret; } } // namespace __llvm_libc diff --git a/libc/test/src/sched/param_and_scheduler_test.cpp b/libc/test/src/sched/param_and_scheduler_test.cpp --- a/libc/test/src/sched/param_and_scheduler_test.cpp +++ b/libc/test/src/sched/param_and_scheduler_test.cpp @@ -32,313 +32,124 @@ // sched policy on a running task. // // Linux specific test could also include: -// SCHED_BATCH, SCHED_ISO, SCHED_IDLE, SCHED_DEADLINE +// SCHED_ISO, 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 - // 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; +class SchedTest : public __llvm_libc::testing::Test { +public: + void testSched(int policy, bool can_set) { + 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; + int init_policy = __llvm_libc::sched_getscheduler(0); + ASSERT_GE(init_policy, 0); + ASSERT_EQ(libc_errno, 0); - for (int priority = min_priority; priority <= max_priority; ++priority) { - ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 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); - int init_priority = param.sched_priority; - param.sched_priority = priority; + struct sched_param param = {min_priority}; // Negative pid - ASSERT_EQ(__llvm_libc::sched_setparam(-1, ¶m), -1); + ASSERT_EQ(__llvm_libc::sched_setscheduler(-1, policy, ¶m), -1); ASSERT_EQ(libc_errno, EINVAL); libc_errno = 0; - ASSERT_EQ(__llvm_libc::sched_getparam(-1, ¶m), -1); + ASSERT_EQ(__llvm_libc::sched_getscheduler(-1), -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)); + // Invalid Policy + ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy | 128, ¶m), -1); + ASSERT_EQ(libc_errno, EINVAL); 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 - // 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); + // 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; - ASSERT_EQ(__llvm_libc::sched_getparam(-1, ¶m), -1); - ASSERT_EQ(libc_errno, EINVAL); + 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; - // Success / missing permissions - ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), can_set ? 0 : -1); + // 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_getparam(0, ¶m), 0); + ASSERT_EQ(__llvm_libc::sched_getscheduler(0), + can_set ? policy : init_policy); 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; + // 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; - // Invalid Policy - ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy | 128, ¶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; - // 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; + 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 = 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; + param.sched_priority = priority; - // 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; + // Negative pid + ASSERT_EQ(__llvm_libc::sched_setparam(-1, ¶m), -1); + ASSERT_EQ(libc_errno, EINVAL); + libc_errno = 0; - ASSERT_EQ(__llvm_libc::sched_getscheduler(0), can_set ? policy : init_policy); - ASSERT_EQ(libc_errno, 0); + ASSERT_EQ(__llvm_libc::sched_getparam(-1, ¶m), -1); + ASSERT_EQ(libc_errno, EINVAL); + 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; + // 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; - param.sched_priority = max_priority + 1; - ASSERT_EQ(__llvm_libc::sched_setparam(0, ¶m), -1); - ASSERT_EQ(libc_errno, EINVAL); - libc_errno = 0; + ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0); + ASSERT_EQ(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; + ASSERT_EQ(param.sched_priority, can_set ? priority : init_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); + // Null test + ASSERT_EQ(__llvm_libc::sched_setscheduler(0, policy, nullptr), -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; +#define LIST_SCHED_TESTS(policy, can_set) \ + using LlvmLibcSchedTest = SchedTest; \ + TEST_F(LlvmLibcSchedTest, Sched_##policy) { testSched(policy, can_set); } - ASSERT_EQ(__llvm_libc::sched_getparam(0, ¶m), 0); - ASSERT_EQ(libc_errno, 0); +// Root is required to set these policies. +LIST_SCHED_TESTS(SCHED_FIFO, __llvm_libc::getuid() == 0) +LIST_SCHED_TESTS(SCHED_RR, __llvm_libc::getuid() == 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; -} +// No root is required to set these policies. +LIST_SCHED_TESTS(SCHED_OTHER, true) +LIST_SCHED_TESTS(SCHED_BATCH, true) +LIST_SCHED_TESTS(SCHED_IDLE, true) TEST(LlvmLibcSchedParamAndSchedulerTest, NullParamTest) { libc_errno = 0;