[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH 19/23] lib/ukschedpreempt: Handle thread attributes (priority, time slice)


  • To: minios-devel@xxxxxxxxxxxxx
  • From: Costin Lupu <costin.lupu@xxxxxxxxx>
  • Date: Mon, 8 Jul 2019 11:33:48 +0300
  • Cc: felipe.huici@xxxxxxxxx, simon.kuenzer@xxxxxxxxx
  • Delivery-date: Mon, 08 Jul 2019 08:50:25 +0000
  • Ironport-phdr: 9a23:OvvSiBSIBGLHlIz3sxpG29JG09psv+yvbD5Q0YIujvd0So/mwa6yYxGN2/xhgRfzUJnB7Loc0qyK6vqmBTRLucrJmUtBWaQEbwUCh8QSkl5oK+++Imq/EsTXaTcnFt9JTl5v8iLzG0FUHMHjew+a+SXqvnYdFRrlKAV6OPn+FJLMgMSrzeCy/IDYbxlViDanbr5+MQu6oR/eu8UKjoduNqk8wQbVr3VVfOhb2XlmLk+JkRbm4cew8p9j8yBOtP8k6sVNT6b0cbkmQLJBFDgpPHw768PttRnYUAuA/WAcXXkMkhpJGAfK8hf3VYrsvyTgt+p93C6aPdDqTb0xRD+v4btnRAPuhSwaMTMy7WPZhdFqjK9DoByvuQFxzYDXbo+SNvV+cLjQcc8GSWdbQspcTTBNDp+6YoASD+QBJ+FYr4zlqlYQqhu+HhWsBOLpyjRVgHH2wLU60/k8GgzBwAMgGMkOsGjVrNXzLqsSVf21zLHVzTjYc/xWwi3x6JDVch86u/2MR7VwfNPXxEIyFA3Flk2dpZHqMj+IzOgAsGiW4/B+We6xiWMrsQ98riCyysojl4XFnIEYx1De+Slnzos4K8e0RFN0bNK6FpZbqjuUOJFsQsw4RmFloCM6yrobtpGlZCUK05EnxwLHa/yAboiI/grvVOaPLjd8g3JoYKy/hxOo/kihzu3wTNW70E1Qoipdj9nDrWoB1wbU6sSfS/t9+Fmu2SqX2gzO5exIPFo4mKnbJpI73LI8iJgevV7NEyPunUX5lq6WdkEq+uiy7OTnZ63rqYObN49vlgH+M6Iulta7AeQlKggOQnOW9vin1LH55U35Xa5FgucskqneqJzaP9gUpralAw9J1YYu8xO/Dzag0NQZmnkHN0tJdw+ZgIj3JV7OJOv1DfO+g1S3jDdr3OrKP7L/DZXLNHTDl63hfbll4U5G1AUz1cxf545TCrwZLvL8REvxtN3ADhAnKQC0w/vnCNRh2YMfQm+PBLGWP7/WsVCS/e0jOfeDZJINsjbnN/cl/+LujWM+mVIFZqmp3J4XaHe+Hvh8IEWZfGTjgtEAEGgUpAozV+rqh0OeXj5XfXm9RLgw6S8mCNHuMYCWQ4GrgbuamSu2AJBSTmRHEUyXV2flccODQfhfRjiVJ5pKlScYVL7pb5I5yFn6vwjh17thaO7J4jAwvomlzMV/offUw0JhvQdoBtiQhjneB1p/mXkFEmc7
  • Ironport-sdr: qhSYQI1Iw3yX7xJsL80Lmv8aDu0YvUwyvHeVi8fb7s3GGGvV2riaF3vAF7zx3QK5RwRX7gqJiz kQ1VPciI6j8g==
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>

With preemptive scheduling, threads may have different priorities and they will
be scheduled accordingly. Besides that, our current implementation also adds
support for setting different time slices for threads.

Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
 .../include/uk/preempt_thread_attr.h          |  48 ++++++++
 lib/ukschedpreempt/include/uk/prioq.h         |   3 +-
 lib/ukschedpreempt/prioq.c                    |  38 +++++-
 lib/ukschedpreempt/schedpreempt.c             | 109 +++++++++++++++++-
 4 files changed, 189 insertions(+), 9 deletions(-)
 create mode 100644 lib/ukschedpreempt/include/uk/preempt_thread_attr.h

diff --git a/lib/ukschedpreempt/include/uk/preempt_thread_attr.h 
b/lib/ukschedpreempt/include/uk/preempt_thread_attr.h
new file mode 100644
index 00000000..054d0df6
--- /dev/null
+++ b/lib/ukschedpreempt/include/uk/preempt_thread_attr.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2019, University Politehnica of Bucharest. All rights 
reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#ifndef __UK_SCHEDPREEMPT_PREEMPT_THREAD_ATTR_H__
+#define __UK_SCHEDPREEMPT_PREEMPT_THREAD_ATTR_H__
+
+#include <uk/alloc.h>
+#include <uk/thread_attr.h>
+
+struct preempt_thread_attr {
+       prio_t prio_static;         /* static priority */
+       prio_t prio;                /* dynamic priority */
+       int timeslice;              /* remaining time slice in millis */
+       int timeslice_length;       /* configured time slice in millis */
+};
+
+#endif /* __UK_SCHEDPREEMPT_PREEMPT_THREAD_ATTR_H__ */
diff --git a/lib/ukschedpreempt/include/uk/prioq.h 
b/lib/ukschedpreempt/include/uk/prioq.h
index 592c0121..e01a3220 100644
--- a/lib/ukschedpreempt/include/uk/prioq.h
+++ b/lib/ukschedpreempt/include/uk/prioq.h
@@ -36,7 +36,7 @@
 #define __UK_SCHEDPREEMPT_PRIOQ_H__
 
 #include <uk/thread.h>
-#include <uk/thread_attr.h>
+#include <uk/preempt_thread_attr.h>
 #include <uk/list.h>
 #include <uk/bitmap.h>
 
@@ -62,6 +62,7 @@ struct prioq {
 void prioq_init(struct prioq *q);
 void prioq_enqueue(struct prioq *q, struct uk_thread *thread);
 void prioq_dequeue(struct prioq *q, struct uk_thread *thread);
+void prioq_set_priority(struct prioq *q, struct uk_thread *thread, prio_t 
prio);
 prio_t prioq_highest_prio(struct prioq *q);
 
 #define prioq_first_for_prio(q, prio) \
diff --git a/lib/ukschedpreempt/prioq.c b/lib/ukschedpreempt/prioq.c
index d8fd1a80..b1e36bc3 100644
--- a/lib/ukschedpreempt/prioq.c
+++ b/lib/ukschedpreempt/prioq.c
@@ -35,6 +35,7 @@
 #include <string.h>
 #include <uk/arch/atomic.h>
 #include <uk/prioq.h>
+#include <uk/preempt_thread_attr.h>
 #include <uk/assert.h>
 
 
@@ -48,14 +49,16 @@ void prioq_init(struct prioq *q)
 
 void prioq_enqueue(struct prioq *q, struct uk_thread *thread)
 {
+       struct preempt_thread_attr *tip;
        prio_t prio;
        unsigned long l1_index, l2_index;
 
        UK_ASSERT(q != NULL);
        UK_ASSERT(thread != NULL);
 
-       /* TODO get thread prio */
-       prio = 0;
+       tip = thread->sched_prv;
+       prio = tip->prio;
+       PRIO_ASSERT(prio);
 
        /* add to list */
        UK_TAILQ_INSERT_TAIL(&q->thread_list[prio], thread, thread_list);
@@ -68,14 +71,16 @@ void prioq_enqueue(struct prioq *q, struct uk_thread 
*thread)
 
 void prioq_dequeue(struct prioq *q, struct uk_thread *thread)
 {
+       struct preempt_thread_attr *tip;
        prio_t prio;
        unsigned long l1_index, l2_index;
 
        UK_ASSERT(q != NULL);
        UK_ASSERT(thread != NULL);
 
-       /* TODO get thread prio */
-       prio = 0;
+       tip = thread->sched_prv;
+       prio = tip->prio;
+       PRIO_ASSERT(prio);
 
        /* remove from list */
        UK_TAILQ_REMOVE(&q->thread_list[prio], thread, thread_list);
@@ -89,6 +94,31 @@ void prioq_dequeue(struct prioq *q, struct uk_thread *thread)
        }
 }
 
+void prioq_set_priority(struct prioq *q, struct uk_thread *thread, prio_t prio)
+{
+       struct preempt_thread_attr *tip;
+
+       UK_ASSERT(q != NULL);
+       UK_ASSERT(thread != NULL);
+       PRIO_ASSERT(prio);
+
+       tip = thread->sched_prv;
+
+       /* Set static priority */
+       tip->prio_static = prio;
+
+       if (tip->prio != prio) {
+               if (is_runnable(thread) && thread != uk_thread_current()) {
+                       /* runnable, but not running */
+                       prioq_dequeue(q, thread);
+                       tip->prio = prio;
+                       prioq_enqueue(q, thread);
+
+               } else
+                       tip->prio = prio;
+       }
+}
+
 prio_t prioq_highest_prio(struct prioq *q)
 {
        prio_t prio;
diff --git a/lib/ukschedpreempt/schedpreempt.c 
b/lib/ukschedpreempt/schedpreempt.c
index fdd9681c..c6963b2f 100644
--- a/lib/ukschedpreempt/schedpreempt.c
+++ b/lib/ukschedpreempt/schedpreempt.c
@@ -33,8 +33,10 @@
  */
 
 #include <uk/plat/lcpu.h>
+#include <uk/plat/time.h>
 #include <uk/schedpreempt.h>
 #include <uk/prioq.h>
+#include <uk/preempt_thread_attr.h>
 
 
 struct schedpreempt_private {
@@ -42,6 +44,43 @@ struct schedpreempt_private {
        struct uk_thread_list sleeping_threads;
 };
 
+
+static
+struct preempt_thread_attr *preempt_thread_attr_create(struct uk_alloc *a,
+               const struct uk_thread_attr *attr)
+{
+       struct preempt_thread_attr *preempt_attr;
+       __nsec tick_length;
+
+       UK_ASSERT(a != NULL);
+
+       preempt_attr = uk_malloc(a, sizeof(struct preempt_thread_attr));
+       if (preempt_attr == NULL) {
+               uk_pr_warn("Could not allocate thread info.");
+               return NULL;
+       }
+
+       /* priority */
+       if (attr && attr->prio != UK_THREAD_ATTR_PRIO_INVALID)
+               preempt_attr->prio_static = attr->prio;
+       else
+               preempt_attr->prio_static = UK_THREAD_ATTR_PRIO_DEFAULT;
+
+       preempt_attr->prio = preempt_attr->prio_static;
+
+       /* time slice */
+       tick_length = UKPLAT_TIME_TICK_MSEC;
+       if (attr && attr->timeslice >= tick_length)
+               preempt_attr->timeslice_length = attr->timeslice;
+       else
+               /* TODO find a proper default time slice */
+               preempt_attr->timeslice_length = tick_length;
+
+       preempt_attr->timeslice = preempt_attr->timeslice_length;
+
+       return preempt_attr;
+}
+
 static
 int schedpreempt_thread_add(struct uk_sched *s, struct uk_thread *t,
                const struct uk_thread_attr *attr)
@@ -49,6 +88,12 @@ int schedpreempt_thread_add(struct uk_sched *s, struct 
uk_thread *t,
        unsigned long flags;
        struct schedpreempt_private *prv = s->prv;
 
+       t->sched_prv = preempt_thread_attr_create(s->allocator, attr);
+       if (t->sched_prv == NULL) {
+               uk_pr_warn("Could not create thread info.");
+               return -EINVAL;
+       }
+
        set_runnable(t);
 
        flags = ukplat_lcpu_save_irqf();
@@ -103,6 +148,62 @@ void schedpreempt_thread_woken(struct uk_sched *s, struct 
uk_thread *t)
                prioq_enqueue(&prv->ready_queue, t);
 }
 
+static
+int schedpreempt_thread_set_prio(struct uk_sched *s,
+               struct uk_thread *t, prio_t prio)
+{
+       struct schedpreempt_private *prv = s->prv;
+       unsigned long flags;
+
+       if (prio < UK_THREAD_ATTR_PRIO_MIN || prio > UK_THREAD_ATTR_PRIO_MAX)
+               return -EINVAL;
+
+       flags = ukplat_lcpu_save_irqf();
+       prioq_set_priority(&prv->ready_queue, t, prio);
+       ukplat_lcpu_restore_irqf(flags);
+
+       return 0;
+}
+
+static
+int schedpreempt_thread_get_prio(struct uk_sched *s __unused,
+               const struct uk_thread *t, prio_t *prio)
+{
+       struct preempt_thread_attr *attr;
+
+       attr = t->sched_prv;
+       *prio = attr->prio_static;
+
+       return 0;
+}
+
+static
+int schedpreempt_thread_set_tslice(struct uk_sched *s __unused,
+               struct uk_thread *t, int tslice)
+{
+       struct preempt_thread_attr *attr;
+
+       if (tslice < (int) UKPLAT_TIME_TICK_MSEC)
+               return -EINVAL;
+
+       attr = t->sched_prv;
+       attr->timeslice_length = tslice;
+
+       return 0;
+}
+
+static
+int schedpreempt_thread_get_tslice(struct uk_sched *s __unused,
+               const struct uk_thread *t, int *tslice)
+{
+       struct preempt_thread_attr *attr;
+
+       attr = t->sched_prv;
+       *tslice = attr->timeslice_length;
+
+       return 0;
+}
+
 struct uk_sched *uk_schedpreempt_init(struct uk_alloc *a)
 {
        struct uk_sched *sched = NULL;
@@ -126,10 +227,10 @@ struct uk_sched *uk_schedpreempt_init(struct uk_alloc *a)
                        schedpreempt_thread_remove,
                        schedpreempt_thread_blocked,
                        schedpreempt_thread_woken,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL);
+                       schedpreempt_thread_set_prio,
+                       schedpreempt_thread_get_prio,
+                       schedpreempt_thread_set_tslice,
+                       schedpreempt_thread_get_tslice);
 
        return sched;
 
-- 
2.20.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.