From: Claudio Fontana <
claudio...@huawei.com>
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 <
claudio...@huawei.com>
---
Makefile | 2 +
libc/pthread.cc | 22 -------
libc/sched.cc | 160 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 162 insertions(+), 22 deletions(-)
create mode 100644 libc/sched.cc
diff --git a/Makefile b/Makefile
index af0a9585..43755da3 100644
--- a/Makefile
+++ b/Makefile
@@ -1914,6 +1914,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..d363ecd6
--- /dev/null
+++ b/libc/sched.cc
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ * Since the SCHED_RR is currently not implemented, we don't
+ * implement this function 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)
+{
+ int res = -1;
+
+ if (!param) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (pid == 0) {
+ sched::thread *t = sched::thread::current();
+
+ res = sched_setparam_aux(t, policy, param->sched_priority);
+ } else {
+ sched::with_thread_by_id(pid, [param, policy, &res] (sched::thread *t) {
+ if (t) res = sched_setparam_aux(t, policy, param->sched_priority);
+ });
+ if (res == -1) {
+ errno = ESRCH;
+ }
+ }
+
+ return res;
+}
+
+int sched_getscheduler(pid_t pid)
+{
+ int res = -1;
+
+ if (pid == 0) {
+ sched::thread *t = sched::thread::current();
+
+ if (t->realtime_priority() == 0) {
+ res = SCHED_OTHER;
+ } else {
+ res = SCHED_FIFO;
+ };
+ } else {
+ sched::with_thread_by_id(pid, [&res] (sched::thread *t) {
+ if (t) {
+ if (t->realtime_priority() == 0) {
+ res = SCHED_OTHER;
+ } else {
+ res = SCHED_FIFO;
+ }
+ }
+ });
+ if (res == -1) {
+ errno = ESRCH;
+ }
+ }
+
+ return res;
+}
+
+int sched_getparam(pid_t pid, struct sched_param *param)
+{
+ int res = 0;
+
+ if (pid == 0) {
+ sched::thread *t = sched::thread::current();
+
+ param->sched_priority = t->realtime_priority();
+ } else {
+ sched::with_thread_by_id(pid, [param, &res] (sched::thread *t) {
+ if (t) {
+ param->sched_priority = t->realtime_priority();
+ } else {
+ res = -1;
+ }
+ });
+ if (res == -1) {
+ errno = ESRCH;
+ }
+ }
+
+ return res;
+}
--
2.30.2