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

[Minios-devel] [UNIKRAFT PATCH v3 2/3] lib/uklock: Introduce semaphores and mutexes with libuklock



From: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>

Provides implementation for 2 types of synchronization primitives:
* Semaphore
* Mutex
They are based on libuksched because they are using thread waiting
queues.

Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
---
 lib/Config.uk                     |   1 +
 lib/Makefile.uk                   |   1 +
 lib/uklock/Config.uk              |  20 ++++++
 lib/uklock/Makefile.uk            |   7 ++
 lib/uklock/export.syms            |   2 +
 lib/uklock/include/uk/mutex.h     | 113 +++++++++++++++++++++++++++++
 lib/uklock/include/uk/semaphore.h | 146 ++++++++++++++++++++++++++++++++++++++
 lib/uklock/mutex.c                |   7 ++
 lib/uklock/semaphore.c            |  10 +++
 9 files changed, 307 insertions(+)
 create mode 100644 lib/uklock/Config.uk
 create mode 100644 lib/uklock/Makefile.uk
 create mode 100644 lib/uklock/export.syms
 create mode 100644 lib/uklock/include/uk/mutex.h
 create mode 100644 lib/uklock/include/uk/semaphore.h
 create mode 100644 lib/uklock/mutex.c
 create mode 100644 lib/uklock/semaphore.c

diff --git a/lib/Config.uk b/lib/Config.uk
index 0a78a02..9e6b269 100644
--- a/lib/Config.uk
+++ b/lib/Config.uk
@@ -33,4 +33,5 @@ source "lib/ukallocbbuddy/Config.uk"
 source "lib/uksched/Config.uk"
 source "lib/ukschedcoop/Config.uk"
 source "lib/fdt/Config.uk"
+source "lib/uklock/Config.uk"
 source "lib/ukswrand/Config.uk"
diff --git a/lib/Makefile.uk b/lib/Makefile.uk
index d549152..a79ad0d 100644
--- a/lib/Makefile.uk
+++ b/lib/Makefile.uk
@@ -16,3 +16,4 @@ $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uksched))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukschedcoop))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/fdt))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/vfscore))
+$(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uklock))
diff --git a/lib/uklock/Config.uk b/lib/uklock/Config.uk
new file mode 100644
index 0000000..5ce22c9
--- /dev/null
+++ b/lib/uklock/Config.uk
@@ -0,0 +1,20 @@
+menuconfig LIBUKLOCK
+       bool "uklock: Multi-task synchronization primitives"
+       select LIBUKDEBUG
+       default n
+
+if LIBUKLOCK
+       config LIBUKLOCK_SEMAPHORE
+               bool "Semaphores"
+               select LIBUKSCHED
+               default y
+               help
+                       Enable semaphore based synchornization
+
+       config LIBUKLOCK_MUTEX
+               bool "Mutexes"
+               select LIBUKSCHED
+               default y
+               help
+                       Enable mutex based synchornization
+endif
diff --git a/lib/uklock/Makefile.uk b/lib/uklock/Makefile.uk
new file mode 100644
index 0000000..396adee
--- /dev/null
+++ b/lib/uklock/Makefile.uk
@@ -0,0 +1,7 @@
+$(eval $(call addlib_s,libuklock,$(CONFIG_LIBUKLOCK)))
+
+CINCLUDES-$(CONFIG_LIBUKLOCK)   += -I$(LIBUKLOCK_BASE)/include
+CXXINCLUDES-$(CONFIG_LIBUKLOCK)        += -I$(LIBUKLOCK_BASE)/include
+
+LIBUKLOCK_SRCS-$(CONFIG_LIBUKLOCK_SEMAPHORE) += $(LIBUKLOCK_BASE)/semaphore.c
+LIBUKLOCK_SRCS-$(CONFIG_LIBUKLOCK_MUTEX)     += $(LIBUKLOCK_BASE)/mutex.c
diff --git a/lib/uklock/export.syms b/lib/uklock/export.syms
new file mode 100644
index 0000000..bbb4d12
--- /dev/null
+++ b/lib/uklock/export.syms
@@ -0,0 +1,2 @@
+uk_semaphore_init
+uk_mutex_init
diff --git a/lib/uklock/include/uk/mutex.h b/lib/uklock/include/uk/mutex.h
new file mode 100644
index 0000000..7b0208a
--- /dev/null
+++ b/lib/uklock/include/uk/mutex.h
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, 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_MUTEX_H__
+#define __UK_MUTEX_H__
+
+#include <uk/config.h>
+
+#if CONFIG_LIBUKLOCK_MUTEX
+#include <uk/assert.h>
+#include <uk/plat/lcpu.h>
+#include <uk/thread.h>
+#include <uk/wait.h>
+#include <uk/wait_types.h>
+#include <uk/plat/time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Mutex that relies on a scheduler
+ * uses wait queues for threads
+ */
+struct uk_mutex {
+       int locked;
+       struct uk_waitq wait;
+};
+
+void uk_mutex_init(struct uk_mutex *m);
+
+static inline void uk_mutex_hold(struct uk_mutex *m)
+{
+       unsigned long irqf;
+
+       UK_ASSERT(m);
+
+       for (;;) {
+               uk_waitq_wait_event(&m->wait, m->locked == 0);
+               irqf = ukplat_lcpu_save_irqf();
+               if (!m->locked)
+                       break;
+               ukplat_lcpu_restore_irqf(irqf);
+       }
+       m->locked = 1;
+       ukplat_lcpu_restore_irqf(irqf);
+}
+
+static inline int uk_mutex_hold_try(struct uk_mutex *m)
+{
+       unsigned long irqf;
+       int ret = 0;
+
+       UK_ASSERT(m);
+
+       irqf = ukplat_lcpu_save_irqf();
+       if (!m->locked)
+               ret = m->locked = 1;
+       ukplat_lcpu_restore_irqf(irqf);
+       return ret;
+}
+
+static inline void uk_mutex_release(struct uk_mutex *m)
+{
+       unsigned long irqf;
+
+       UK_ASSERT(m);
+
+       irqf = ukplat_lcpu_save_irqf();
+       UK_ASSERT(m->locked);
+       m->locked = 0;
+       uk_waitq_wake_up(&m->wait);
+       ukplat_lcpu_restore_irqf(irqf);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LIBUKLOCK_MUTEX */
+
+#endif /* __UK_MUTEX_H__ */
diff --git a/lib/uklock/include/uk/semaphore.h 
b/lib/uklock/include/uk/semaphore.h
new file mode 100644
index 0000000..fd181c8
--- /dev/null
+++ b/lib/uklock/include/uk/semaphore.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ */
+/* Taken and modified from Mini-OS (include/semphore.h) */
+#ifndef __UK_SEMAPHORE_H__
+#define __UK_SEMAPHORE_H__
+
+#include <uk/config.h>
+
+#if CONFIG_LIBUKLOCK_SEMAPHORE
+#include <uk/print.h>
+#include <uk/assert.h>
+#include <uk/plat/lcpu.h>
+#include <uk/thread.h>
+#include <uk/wait.h>
+#include <uk/wait_types.h>
+#include <uk/plat/time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Semaphore that relies on a scheduler
+ * uses wait queues for threads
+ */
+struct uk_semaphore {
+       long count;
+       struct uk_waitq wait;
+};
+
+void uk_semaphore_init(struct uk_semaphore *s, long count);
+
+static inline void uk_semaphore_down(struct uk_semaphore *s)
+{
+       unsigned long irqf;
+
+       UK_ASSERT(s);
+
+       for (;;) {
+               uk_waitq_wait_event(&s->wait, s->count > 0);
+               irqf = ukplat_lcpu_save_irqf();
+               if (s->count > 0)
+                       break;
+               ukplat_lcpu_restore_irqf(irqf);
+       }
+       --s->count;
+       uk_printd(DLVL_EXTRA, "Decreased semaphore %p to %ld\n", s, s->count);
+       ukplat_lcpu_restore_irqf(irqf);
+}
+
+static inline int uk_semaphore_down_try(struct uk_semaphore *s)
+{
+       unsigned long irqf;
+       int ret = 0;
+
+       UK_ASSERT(s);
+
+       irqf = ukplat_lcpu_save_irqf();
+       if (s->count > 0) {
+               ret = 1;
+               --s->count;
+               uk_printd(DLVL_EXTRA, "Decreased semaphore %p to %ld\n",
+                         s, s->count);
+       }
+       ukplat_lcpu_restore_irqf(irqf);
+       return ret;
+}
+
+/* Returns __NSEC_MAX on timeout, expired time when down was successful */
+static inline __nsec uk_semaphore_down_to(struct uk_semaphore *s,
+                                         __nsec timeout)
+{
+       unsigned long irqf;
+       __nsec then = ukplat_monotonic_clock();
+       __nsec deadline;
+
+       UK_ASSERT(s);
+
+       if (timeout == 0)
+               deadline = 0;
+       else
+               deadline = then + timeout;
+
+       for (;;) {
+               uk_waitq_wait_event_deadline(&s->wait, s->count > 0, deadline);
+               irqf = ukplat_lcpu_save_irqf();
+               if (s->count > 0 || (deadline &&
+                                    ukplat_monotonic_clock() >= deadline))
+                       break;
+               ukplat_lcpu_restore_irqf(irqf);
+       }
+       if (s->count > 0) {
+               s->count--;
+               uk_printd(DLVL_EXTRA, "Decreased semaphore %p to %ld\n",
+                         s, s->count);
+               ukplat_lcpu_restore_irqf(irqf);
+               return ukplat_monotonic_clock() - then;
+       }
+
+       ukplat_lcpu_restore_irqf(irqf);
+       uk_printd(DLVL_EXTRA, "Timed out while waiting for semaphore %p\n", s);
+       return __NSEC_MAX;
+}
+
+static inline void uk_semaphore_up(struct uk_semaphore *s)
+{
+       unsigned long irqf;
+
+       UK_ASSERT(s);
+
+       irqf = ukplat_lcpu_save_irqf();
+       ++s->count;
+       uk_printd(DLVL_EXTRA, "Increased semaphore %p to %ld\n",
+                 s, s->count);
+       uk_waitq_wake_up(&s->wait);
+       ukplat_lcpu_restore_irqf(irqf);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LIBUKLOCK_SEMAPHORE */
+
+#endif /* __UK_SEMAPHORE_H__ */
diff --git a/lib/uklock/mutex.c b/lib/uklock/mutex.c
new file mode 100644
index 0000000..183a01d
--- /dev/null
+++ b/lib/uklock/mutex.c
@@ -0,0 +1,7 @@
+#include <uk/mutex.h>
+
+void uk_mutex_init(struct uk_mutex *m)
+{
+       m->locked = 0;
+       uk_waitq_init(&m->wait);
+}
diff --git a/lib/uklock/semaphore.c b/lib/uklock/semaphore.c
new file mode 100644
index 0000000..0801bf6
--- /dev/null
+++ b/lib/uklock/semaphore.c
@@ -0,0 +1,10 @@
+#include <uk/semaphore.h>
+
+void uk_semaphore_init(struct uk_semaphore *s, long count)
+{
+       s->count = count;
+       uk_waitq_init(&s->wait);
+
+       uk_printd(DLVL_INFO, "Initialized semaphore %p with %ld\n",
+                 s, s->count);
+}
-- 
2.7.4


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