|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v2 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 | 114 +++++++++++++++++++++++++++++
lib/uklock/include/uk/semaphore.h | 147 ++++++++++++++++++++++++++++++++++++++
lib/uklock/mutex.c | 7 ++
lib/uklock/semaphore.c | 10 +++
9 files changed, 309 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..773213f
--- /dev/null
+++ b/lib/uklock/include/uk/mutex.h
@@ -0,0 +1,114 @@
+/* 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..1850d4b
--- /dev/null
+++ b/lib/uklock/include/uk/semaphore.h
@@ -0,0 +1,147 @@
+/* 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |