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

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



Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>

Simon Kuenzer <simon.kuenzer@xxxxxxxxx> writes:

> 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
>

-- 
Yuri Volchkov
Software Specialist

NEC Europe Ltd
Kurfürsten-Anlage 36
D-69115 Heidelberg

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