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.

Reply via email to