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

Re: [Minios-devel] [UNIKRAFT PATCH v2 3/8] lib/uksched: Introduce thread attributes



Ah, one more thing about this patch: You change the signature of uk_sched_thread_create here, and there is a call in lib/uknetdev/netdev.c:292 that uses the old signature, so this should probably be changed just by adding NULL for the attributes.

Alternatively, this could be changed so that the code uses uk_thread_create instead, but this would probably require a bit more refactoring (for example, rx_conf might not even need to contain the scheduler any more because it could just always use the default scheduler?) But that's maybe more for Sharan as the original author of that code to look into.

Cheers,
Florian


On 1/11/19 12:22 AM, Costin Lupu wrote:
We introduce a thread attributes abstraction which is used for
configuring thread behavior. The set of currently available
attributes was inspired from the pthread interface.

Thread attributes can be set either when creating the threads or
during thread execution by calling the corresponding setters. If
an attribute is not supported by the underlying scheduler then
-EINVAL is returned by setters.

The detach attribute is common to all threads, regardless of the
scheduling policy, and if set it means that the thread resources
will be automatically freed on thread exit. By default, threads
are not detached. The complete detach support will be added in a
following commit.

Time slice and priority make sense only for preemptive schedulers.

Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
  lib/uksched/Makefile.uk              |   1 +
  lib/uksched/exportsyms.uk            |   8 ++
  lib/uksched/include/uk/sched.h       |  75 +++++++++++++++++--
  lib/uksched/include/uk/thread.h      |  12 ++-
  lib/uksched/include/uk/thread_attr.h |  81 ++++++++++++++++++++
  lib/uksched/sched.c                  |   5 +-
  lib/uksched/thread.c                 |  34 +++++++++
  lib/uksched/thread_attr.c            | 139 +++++++++++++++++++++++++++++++++++
  lib/ukschedcoop/schedcoop.c          |   6 +-
  9 files changed, 351 insertions(+), 10 deletions(-)
  create mode 100644 lib/uksched/include/uk/thread_attr.h
  create mode 100644 lib/uksched/thread_attr.c

diff --git a/lib/uksched/Makefile.uk b/lib/uksched/Makefile.uk
index 24816f6..229d847 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 45a9694..0b10405 100644
--- a/lib/uksched/exportsyms.uk
+++ b/lib/uksched/exportsyms.uk
@@ -14,3 +14,11 @@ uk_thread_fini
  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 d2fc8df..b21d65c 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,
+                       struct uk_thread_attr *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, struct uk_thread_attr *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, struct uk_thread_attr *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 e66a05b..5ff2dd6 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 0000000..93dcd5c
--- /dev/null
+++ b/lib/uksched/include/uk/thread_attr.h
@@ -0,0 +1,81 @@
+/* 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 <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 {
+       /**< Is non-zero if thread should detach */
+       int is_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 c3be206..e855298 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, struct uk_thread_attr *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 1236b99..9d06552 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 0000000..73845ec
--- /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->is_detached = 0;
+       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->is_detached = 1;
+
+       else if (state == UK_THREAD_ATTR_WAITABLE)
+               attr->is_detached = 0;
+
+       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->is_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 3e3a92f..97c0d7c 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,
+               struct uk_thread_attr *attr)
  {
        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;
  }


--
Dr. Florian Schmidt
フローリアン・シュミット
Research Scientist,
Systems and Machine Learning Group
NEC Laboratories Europe
Kurfürsten-Anlage 36, D-69115 Heidelberg
Tel.     +49 (0)6221 4342-265
Fax:     +49 (0)6221 4342-155
e-mail:  florian.schmidt@xxxxxxxxx
============================================================
Registered at Amtsgericht Mannheim, Germany, HRB728558

_______________________________________________
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®.