---
lib/uknetdev/netdev.c | 2 +-
lib/uksched/Makefile.uk | 1 +
lib/uksched/exportsyms.uk | 12 +++
lib/uksched/include/uk/sched.h | 75 +++++++++++++++++--
lib/uksched/include/uk/thread.h | 12 ++-
lib/uksched/include/uk/thread_attr.h | 82 +++++++++++++++++++++
lib/uksched/sched.c | 5 +-
lib/uksched/thread.c | 34 +++++++++
lib/uksched/thread_attr.c | 139 +++++++++++++++++++++++++++++++++++
lib/ukschedcoop/schedcoop.c | 6 +-
10 files changed, 357 insertions(+), 11 deletions(-)
create mode 100644 lib/uksched/include/uk/thread_attr.h
create mode 100644 lib/uksched/thread_attr.c
diff --git a/lib/uknetdev/netdev.c b/lib/uknetdev/netdev.c
index 3b92f622..cda8a82b 100644
--- a/lib/uknetdev/netdev.c
+++ b/lib/uknetdev/netdev.c
@@ -290,7 +290,7 @@ static int _create_event_handler(uk_netdev_queue_event_t
callback,
}
h->dispatcher = uk_sched_thread_create(h->dispatcher_s,
- h->dispatcher_name,
+ h->dispatcher_name, NULL,
_dispatcher, h);
if (!h->dispatcher) {
if (h->dispatcher_name)
diff --git a/lib/uksched/Makefile.uk b/lib/uksched/Makefile.uk
index 24816f6a..229d847b 100644
--- a/lib/uksched/Makefile.uk
+++ b/lib/uksched/Makefile.uk
@@ -5,3 +5,4 @@ CXXINCLUDES-$(CONFIG_LIBUKSCHED) +=
-I$(LIBUKSCHED_BASE)/include
LIBUKSCHED_SRCS-y += $(LIBUKSCHED_BASE)/sched.c
LIBUKSCHED_SRCS-y += $(LIBUKSCHED_BASE)/thread.c
+LIBUKSCHED_SRCS-y += $(LIBUKSCHED_BASE)/thread_attr.c
diff --git a/lib/uksched/exportsyms.uk b/lib/uksched/exportsyms.uk
index 45a9694a..df0bb4db 100644
--- a/lib/uksched/exportsyms.uk
+++ b/lib/uksched/exportsyms.uk
@@ -11,6 +11,18 @@ uk_sched_thread_sleep
uk_sched_thread_exit
uk_thread_init
uk_thread_fini
+uk_thread_set_prio
+uk_thread_get_prio
+uk_thread_set_timeslice
+uk_thread_get_timeslice
uk_thread_block_timeout
uk_thread_block
uk_thread_wake
+uk_thread_attr_init
+uk_thread_attr_fini
+uk_thread_attr_set_detachstate
+uk_thread_attr_get_detachstate
+uk_thread_attr_set_prio
+uk_thread_attr_get_prio
+uk_thread_attr_set_timeslice
+uk_thread_attr_get_timeslice
\ No newline at end of file
diff --git a/lib/uksched/include/uk/sched.h b/lib/uksched/include/uk/sched.h
index d2fc8df3..5f2d308f 100644
--- a/lib/uksched/include/uk/sched.h
+++ b/lib/uksched/include/uk/sched.h
@@ -60,16 +60,31 @@ typedef void (*uk_sched_yield_func_t)
(struct uk_sched *s);
typedef void (*uk_sched_thread_add_func_t)
- (struct uk_sched *s, struct uk_thread *t);
+ (struct uk_sched *s, struct uk_thread *t,
+ const uk_thread_attr_t *attr);
typedef void (*uk_sched_thread_remove_func_t)
(struct uk_sched *s, struct uk_thread *t);
+typedef int (*uk_sched_thread_set_prio_func_t)
+ (struct uk_sched *s, struct uk_thread *t, prio_t prio);
+typedef int (*uk_sched_thread_get_prio_func_t)
+ (struct uk_sched *s, const struct uk_thread *t, prio_t *prio);
+typedef int (*uk_sched_thread_set_tslice_func_t)
+ (struct uk_sched *s, struct uk_thread *t, int tslice);
+typedef int (*uk_sched_thread_get_tslice_func_t)
+ (struct uk_sched *s, const struct uk_thread *t, int *tslice);
+
struct uk_sched {
uk_sched_yield_func_t yield;
uk_sched_thread_add_func_t thread_add;
uk_sched_thread_remove_func_t thread_remove;
+ uk_sched_thread_set_prio_func_t thread_set_prio;
+ uk_sched_thread_get_prio_func_t thread_get_prio;
+ uk_sched_thread_set_tslice_func_t thread_set_tslice;
+ uk_sched_thread_get_tslice_func_t thread_get_tslice;
+
/* internal */
struct uk_thread idle;
struct ukplat_ctx_callbacks plat_ctx_cbs;
@@ -92,12 +107,12 @@ static inline void uk_sched_yield(void)
}
static inline void uk_sched_thread_add(struct uk_sched *s,
- struct uk_thread *t)
+ struct uk_thread *t, const uk_thread_attr_t *attr)
{
UK_ASSERT(s);
UK_ASSERT(t);
t->sched = s;
- s->thread_add(s, t);
+ s->thread_add(s, t, attr);
}
static inline void uk_sched_thread_remove(struct uk_sched *s,
@@ -109,6 +124,49 @@ static inline void uk_sched_thread_remove(struct uk_sched
*s,
t->sched = NULL;
}
+static inline int uk_sched_thread_set_prio(struct uk_sched *s,
+ struct uk_thread *t, prio_t prio)
+{
+ UK_ASSERT(s);
+
+ if (!s->thread_set_prio)
+ return -EINVAL;
+
+ return s->thread_set_prio(s, t, prio);
+}
+
+static inline int uk_sched_thread_get_prio(struct uk_sched *s,
+ const struct uk_thread *t, prio_t *prio)
+{
+ UK_ASSERT(s);
+
+ if (!s->thread_get_prio)
+ return -EINVAL;
+
+ return s->thread_get_prio(s, t, prio);
+}
+
+static inline int uk_sched_thread_set_timeslice(struct uk_sched *s,
+ struct uk_thread *t, int tslice)
+{
+ UK_ASSERT(s);
+
+ if (!s->thread_set_tslice)
+ return -EINVAL;
+
+ return s->thread_set_tslice(s, t, tslice);
+}
+
+static inline int uk_sched_thread_get_timeslice(struct uk_sched *s,
+ const struct uk_thread *t, int *tslice)
+{
+ UK_ASSERT(s);
+
+ if (!s->thread_get_tslice)
+ return -EINVAL;
+
+ return s->thread_get_tslice(s, t, tslice);
+}
/*
* Internal scheduler functions
@@ -132,11 +190,17 @@ static inline struct uk_thread *uk_sched_get_idle(struct
uk_sched *s)
void uk_sched_start(struct uk_sched *sched) __noreturn;
#define uk_sched_init(s, yield_func, \
- thread_add_func, thread_remove_func) \
+ thread_add_func, thread_remove_func, \
+ thread_set_prio_func, thread_get_prio_func, \
+ thread_set_tslice_func, thread_get_tslice_func) \
do { \
(s)->yield = yield_func; \
(s)->thread_add = thread_add_func; \
(s)->thread_remove = thread_remove_func; \
+ (s)->thread_set_prio = thread_set_prio_func; \
+ (s)->thread_get_prio = thread_get_prio_func; \
+ (s)->thread_set_tslice = thread_set_tslice_func; \
+ (s)->thread_get_tslice = thread_get_tslice_func; \
uk_sched_register((s)); \
} while (0)
@@ -146,7 +210,8 @@ void uk_sched_start(struct uk_sched *sched) __noreturn;
*/
struct uk_thread *uk_sched_thread_create(struct uk_sched *sched,
- const char *name, void (*function)(void *), void *arg);
+ const char *name, const uk_thread_attr_t *attr,
+ void (*function)(void *), void *arg);
void uk_sched_thread_destroy(struct uk_sched *sched,
struct uk_thread *thread);
diff --git a/lib/uksched/include/uk/thread.h b/lib/uksched/include/uk/thread.h
index e66a05b5..5ff2dd65 100644
--- a/lib/uksched/include/uk/thread.h
+++ b/lib/uksched/include/uk/thread.h
@@ -35,6 +35,7 @@
#include <uk/arch/lcpu.h>
#include <uk/arch/time.h>
#include <uk/plat/thread.h>
+#include <uk/thread_attr.h>
#include <uk/list.h>
#include <uk/essentials.h>
@@ -59,11 +60,20 @@ struct uk_thread {
UK_TAILQ_HEAD(uk_thread_list, struct uk_thread);
+#define uk_thread_create_attr(name, attr, function, data) \
+ uk_sched_thread_create(uk_sched_get_default(), \
+ name, attr, function, data)
#define uk_thread_create(name, function, data) \
- uk_sched_thread_create(uk_sched_get_default(), name, function, data)
+ uk_thread_create_attr(name, NULL, function, data)
#define uk_thread_destroy(thread) \
uk_sched_thread_destroy(thread->sched, thread)
+int uk_thread_set_prio(struct uk_thread *thread, prio_t prio);
+int uk_thread_get_prio(const struct uk_thread *thread, prio_t *prio);
+
+int uk_thread_set_timeslice(struct uk_thread *thread, int timeslice);
+int uk_thread_get_timeslice(const struct uk_thread *thread, int *timeslice);
+
static inline
struct uk_thread *uk_thread_current(void)
{
diff --git a/lib/uksched/include/uk/thread_attr.h
b/lib/uksched/include/uk/thread_attr.h
new file mode 100644
index 00000000..f4ba6cc3
--- /dev/null
+++ b/lib/uksched/include/uk/thread_attr.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. 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_SCHED_THREAD_ATTR_H__
+#define __UK_SCHED_THREAD_ATTR_H__
+
+#include <stdbool.h>
+#include <uk/arch/time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UK_THREAD_ATTR_WAITABLE 0
+#define UK_THREAD_ATTR_DETACHED 1
+
+#define UK_THREAD_ATTR_PRIO_INVALID (-1)
+#define UK_THREAD_ATTR_PRIO_MIN 0
+#define UK_THREAD_ATTR_PRIO_MAX 255
+#define UK_THREAD_ATTR_PRIO_DEFAULT 127
+
+#define UK_THREAD_ATTR_TIMESLICE_NIL 0
+
+typedef int prio_t;
+
+typedef struct uk_thread_attr {
+ /* True if thread should detach */
+ bool detached;
+ /* Priority */
+ prio_t prio;
+ /* Time slice in nanoseconds */
+ __nsec timeslice;
+} uk_thread_attr_t;
+
+int uk_thread_attr_init(uk_thread_attr_t *attr);
+int uk_thread_attr_fini(uk_thread_attr_t *attr);
+
+int uk_thread_attr_set_detachstate(uk_thread_attr_t *attr, int state);
+int uk_thread_attr_get_detachstate(const uk_thread_attr_t *attr, int *state);
+
+int uk_thread_attr_set_prio(uk_thread_attr_t *attr, prio_t prio);
+int uk_thread_attr_get_prio(const uk_thread_attr_t *attr, prio_t *prio);
+
+int uk_thread_attr_set_timeslice(uk_thread_attr_t *attr, __nsec timeslice);
+int uk_thread_attr_get_timeslice(const uk_thread_attr_t *attr, __nsec
*timeslice);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UK_SCHED_THREAD_ATTR_H__ */
diff --git a/lib/uksched/sched.c b/lib/uksched/sched.c
index c3be2060..d7ca7f35 100644
--- a/lib/uksched/sched.c
+++ b/lib/uksched/sched.c
@@ -170,7 +170,8 @@ void uk_sched_idle_init(struct uk_sched *sched,
}
struct uk_thread *uk_sched_thread_create(struct uk_sched *sched,
- const char *name, void (*function)(void *), void *arg)
+ const char *name, const uk_thread_attr_t *attr,
+ void (*function)(void *), void *arg)
{
struct uk_thread *thread = NULL;
void *stack = NULL;
@@ -195,7 +196,7 @@ struct uk_thread *uk_sched_thread_create(struct uk_sched
*sched,
if (rc)
goto err;
- uk_sched_thread_add(sched, thread);
+ uk_sched_thread_add(sched, thread, attr);
return thread;
diff --git a/lib/uksched/thread.c b/lib/uksched/thread.c
index 1236b998..9d065526 100644
--- a/lib/uksched/thread.c
+++ b/lib/uksched/thread.c
@@ -30,9 +30,11 @@
* Ported from Mini-OS
*/
#include <stdlib.h>
+#include <errno.h>
#include <uk/plat/config.h>
#include <uk/plat/time.h>
#include <uk/thread.h>
+#include <uk/sched.h>
#include <uk/print.h>
#include <uk/assert.h>
@@ -127,3 +129,35 @@ void uk_thread_wake(struct uk_thread *thread)
thread->wakeup_time = 0LL;
set_runnable(thread);
}
+
+int uk_thread_set_prio(struct uk_thread *thread, prio_t prio)
+{
+ if (!thread)
+ return -EINVAL;
+
+ return uk_sched_thread_set_prio(thread->sched, thread, prio);
+}
+
+int uk_thread_get_prio(const struct uk_thread *thread, prio_t *prio)
+{
+ if (!thread)
+ return -EINVAL;
+
+ return uk_sched_thread_get_prio(thread->sched, thread, prio);
+}
+
+int uk_thread_set_timeslice(struct uk_thread *thread, int timeslice)
+{
+ if (!thread)
+ return -EINVAL;
+
+ return uk_sched_thread_set_timeslice(thread->sched, thread, timeslice);
+}
+
+int uk_thread_get_timeslice(const struct uk_thread *thread, int *timeslice)
+{
+ if (!thread)
+ return -EINVAL;
+
+ return uk_sched_thread_get_timeslice(thread->sched, thread, timeslice);
+}
diff --git a/lib/uksched/thread_attr.c b/lib/uksched/thread_attr.c
new file mode 100644
index 00000000..52afe9f9
--- /dev/null
+++ b/lib/uksched/thread_attr.c
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. 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.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <uk/plat/time.h>
+#include <uk/thread_attr.h>
+#include <uk/assert.h>
+
+
+int uk_thread_attr_init(uk_thread_attr_t *attr)
+{
+ if (attr == NULL)
+ return -EINVAL;
+
+ attr->detached = false;
+ attr->prio = UK_THREAD_ATTR_PRIO_INVALID;
+ attr->timeslice = UK_THREAD_ATTR_TIMESLICE_NIL;
+
+ return 0;
+}
+
+int uk_thread_attr_fini(uk_thread_attr_t *attr)
+{
+ if (attr == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+
+int uk_thread_attr_set_detachstate(uk_thread_attr_t *attr, int state)
+{
+ if (attr == NULL)
+ return -EINVAL;
+
+ if (state == UK_THREAD_ATTR_DETACHED)
+ attr->detached = true;
+
+ else if (state == UK_THREAD_ATTR_WAITABLE)
+ attr->detached = false;
+
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+int uk_thread_attr_get_detachstate(const uk_thread_attr_t *attr, int *state)
+{
+ if (attr == NULL || state == NULL)
+ return -EINVAL;
+
+ if (attr->detached)
+ *state = UK_THREAD_ATTR_DETACHED;
+ else
+ *state = UK_THREAD_ATTR_WAITABLE;
+
+ return 0;
+}
+
+int uk_thread_attr_set_prio(uk_thread_attr_t *attr, prio_t prio)
+{
+ int rc = -EINVAL;
+
+ if (attr == NULL)
+ return rc;
+
+ if (prio >= UK_THREAD_ATTR_PRIO_MIN &&
+ prio <= UK_THREAD_ATTR_PRIO_MAX) {
+ attr->prio = prio;
+ rc = 0;
+ }
+
+ return rc;
+}
+
+int uk_thread_attr_get_prio(const uk_thread_attr_t *attr, prio_t *prio)
+{
+ if (attr == NULL || prio == NULL)
+ return -EINVAL;
+
+ *prio = attr->prio;
+
+ return 0;
+}
+
+int uk_thread_attr_set_timeslice(uk_thread_attr_t *attr, __nsec timeslice)
+{
+ if (attr == NULL)
+ return -EINVAL;
+
+ if (timeslice < UKPLAT_TIME_TICK_NSEC)
+ return -EINVAL;
+
+ attr->timeslice = timeslice;
+
+ return 0;
+}
+
+int uk_thread_attr_get_timeslice(const uk_thread_attr_t *attr, __nsec
*timeslice)
+{
+ if (attr == NULL || timeslice == NULL)
+ return -EINVAL;
+
+ *timeslice = attr->timeslice;
+
+ return 0;
+}
diff --git a/lib/ukschedcoop/schedcoop.c b/lib/ukschedcoop/schedcoop.c
index 3e3a92f5..6f46d49e 100644
--- a/lib/ukschedcoop/schedcoop.c
+++ b/lib/ukschedcoop/schedcoop.c
@@ -132,7 +132,8 @@ static void schedcoop_schedule(struct uk_sched *s)
}
}
-static void schedcoop_thread_add(struct uk_sched *s, struct uk_thread *t)
+static void schedcoop_thread_add(struct uk_sched *s, struct uk_thread *t,
+ const uk_thread_attr_t *attr __unused)
{
unsigned long flags;
struct schedcoop_private *prv = s->prv;
@@ -210,7 +211,8 @@ struct uk_sched *uk_schedcoop_init(struct uk_alloc *a)
uk_sched_init(sched,
schedcoop_yield,
schedcoop_thread_add,
- schedcoop_thread_remove);
+ schedcoop_thread_remove,
+ NULL, NULL, NULL, NULL);
return sched;
}