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