From: Claudio Fontana <[email protected]> implement the sched_ API using the OSv realtime scheduler implementation.
This includes: sched_setscheduler, sched_getscheduler, sched_setparam, sched_getparam, sched_get_priority_min, sched_get_priority_max, and a stub for Linux-only sched_rr_get_interval. They are implemented together as they are tightly integrated, and one calls the other. Signed-off-by: Claudio Fontana <[email protected]> --- Makefile | 2 + libc/pthread.cc | 22 ------- libc/sched.cc | 143 ++++++++++++++++++++++++++++++++++++++++ tests/misc-scheduler.cc | 6 +- 4 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 libc/sched.cc diff --git a/Makefile b/Makefile index ea6f1c0d..b626a1f2 100644 --- a/Makefile +++ b/Makefile @@ -1913,6 +1913,8 @@ libc += mallopt.o libc += linux/makedev.o +libc += sched.o + musl += fenv/fegetexceptflag.o musl += fenv/feholdexcept.o musl += fenv/fesetexceptflag.o diff --git a/libc/pthread.cc b/libc/pthread.cc index de5979e8..76e6d982 100644 --- a/libc/pthread.cc +++ b/libc/pthread.cc @@ -960,28 +960,6 @@ void pthread_exit(void *retval) t->_thread->exit(); } -// Following 4 functions provide minimal implementation -// that ONLY covers default Linux SCHED_OTHER policy -int sched_get_priority_min(int policy) -{ - switch (policy) { - case SCHED_OTHER: - return 0; - default: - return EINVAL; - } -} - -int sched_get_priority_max(int policy) -{ - switch (policy) { - case SCHED_OTHER: - return 0; - default: - return EINVAL; - } -} - int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param) { diff --git a/libc/sched.cc b/libc/sched.cc new file mode 100644 index 00000000..733dc6ae --- /dev/null +++ b/libc/sched.cc @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2014 Huawei Technologies Duesseldorf GmbH + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#include <errno.h> +#include <api/sched.h> +#include <api/sys/resource.h> +#include <osv/sched.hh> + +#include <osv/stubbing.hh> + +#define SCHED_PRIO_MIN 1 +#define SCHED_PRIO_MAX 99 + +/* sched_rr_get_interval writes the time quantum for SCHED_RR + * processes to the tp timespec structure. + * This is Linux-specific, and we don't implement this yet. + */ + +int sched_rr_get_interval(pid_t pid, struct timespec * tp) +{ + WARN_STUBBED(); + errno = ENOSYS; + return -1; +} + +static int sched_get_priority_minmax(int policy, int value) +{ + switch (policy) { + case SCHED_OTHER: + return 0; + case SCHED_FIFO: + return value; + default: + errno = EINVAL; + /* error return value unfortunately overlaps with allowed + * POSIX API allowed range. Another good reason to have + * only rt priorities > 0. + */ + return -1; + } +} + +int sched_get_priority_min(int policy) +{ + return sched_get_priority_minmax(policy, SCHED_PRIO_MIN); +} + +int sched_get_priority_max(int policy) +{ + return sched_get_priority_minmax(policy, SCHED_PRIO_MAX); +} + +static int sched_setparam_aux(sched::thread *t, int policy, int prio) +{ + switch (policy) { + case SCHED_OTHER: + if (prio != 0) { + errno = EINVAL; + return -1; + } + break; + case SCHED_FIFO: + if (prio < SCHED_PRIO_MIN || prio > SCHED_PRIO_MAX) { + errno = EINVAL; + return -1; + } + break; + default: + errno = EINVAL; + return -1; + } + + t->set_realtime_priority(prio); + return 0; +} + +int sched_setscheduler(pid_t pid, int policy, + const struct sched_param *param) +{ + sched::thread *t = sched::thread::current(); + + if (pid != 0 && pid != getpid()) { + errno = ESRCH; + return -1; + } + if (!param) { + errno = EINVAL; + return -1; + } + + return sched_setparam_aux(t, policy, param->sched_priority); +} + +int sched_getscheduler(pid_t pid) +{ + sched::thread *t = sched::thread::current(); + + if (pid != 0 && pid != getpid()) { + errno = ESRCH; + return -1; + } + + if (t->realtime_priority() == 0) { + return SCHED_OTHER; + }; + + return SCHED_FIFO; +} + +/* +int sched_setparam(pid_t pid, const struct sched_param *param) +{ + sched::thread *t = sched::thread::current(); + + if (pid != 0 && pid != getpid()) { + errno = ESRCH; + return -1; + } + if (!param) { + errno = EINVAL; + return -1; + } + + return sched_setparam_aux(t, t->get_realtime().policy(), param->sched_priority); +} +*/ + +int sched_getparam(pid_t pid, struct sched_param *param) +{ + sched::thread *t = sched::thread::current(); + + if (pid != 0 && pid != getpid()) { + errno = ESRCH; + return -1; + } + + param->sched_priority = t->realtime_priority(); + return 0; +} diff --git a/tests/misc-scheduler.cc b/tests/misc-scheduler.cc index 578fabe1..d36201e7 100644 --- a/tests/misc-scheduler.cc +++ b/tests/misc-scheduler.cc @@ -140,13 +140,15 @@ void priority_test(std::vector<float> ps) #endif #ifdef __OSV__ -void realtime_test(std::vector<int> ps) +void realtime_test(int policy, std::vector<int> ps) { + assert(policy == SCHED_RR || policy == SCHED_FIFO); std::cerr << "Starting realtime test\n"; std::vector<std::thread> threads; mutex mtx; for (auto p : ps) { - threads.push_back(std::thread([p]() { + assert(p >= SCHED_PRIO_MIN && p <= SCHED_PRIO_MAX); + threads.push_back(std::thread([policy, p]() { sched::thread::current()->set_realtime_priority(p); std::cout << "Starting thread with realtime priority " << p << "\n"; // Sleep a bit, to let all test threads get started. The thread -- 2.30.2 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20230510085745.11416-4-luca.abeni%40santannapisa.it.
