[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)
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |