|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v3 3/3] lib/ukmpi: Introduce mailboxes with libukmpi
Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
Simon Kuenzer <simon.kuenzer@xxxxxxxxx> writes:
> From: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
>
> Initial implementation for inter-thread communication with mailboxes.
> The implmentation is based on semaphores provided by libuklock.
>
> 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/ukmpi/Config.uk | 18 +++++
> lib/ukmpi/Makefile.uk | 6 ++
> lib/ukmpi/export.syms | 7 ++
> lib/ukmpi/include/uk/mbox.h | 67 ++++++++++++++++
> lib/ukmpi/mbox.c | 182
> ++++++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 282 insertions(+)
> create mode 100644 lib/ukmpi/Config.uk
> create mode 100644 lib/ukmpi/Makefile.uk
> create mode 100644 lib/ukmpi/export.syms
> create mode 100644 lib/ukmpi/include/uk/mbox.h
> create mode 100644 lib/ukmpi/mbox.c
>
> diff --git a/lib/Config.uk b/lib/Config.uk
> index 9e6b269..2f47fde 100644
> --- a/lib/Config.uk
> +++ b/lib/Config.uk
> @@ -34,4 +34,5 @@ source "lib/uksched/Config.uk"
> source "lib/ukschedcoop/Config.uk"
> source "lib/fdt/Config.uk"
> source "lib/uklock/Config.uk"
> +source "lib/ukmpi/Config.uk"
> source "lib/ukswrand/Config.uk"
> diff --git a/lib/Makefile.uk b/lib/Makefile.uk
> index a79ad0d..a632336 100644
> --- a/lib/Makefile.uk
> +++ b/lib/Makefile.uk
> @@ -17,3 +17,4 @@ $(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))
> +$(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukmpi))
> diff --git a/lib/ukmpi/Config.uk b/lib/ukmpi/Config.uk
> new file mode 100644
> index 0000000..0c3bb4c
> --- /dev/null
> +++ b/lib/ukmpi/Config.uk
> @@ -0,0 +1,18 @@
> +menuconfig LIBUKMPI
> + bool "ukmpi: Message Passing Interface"
> + select LIBNOLIBC if !HAVE_LIBC
> + select LIBUKDEBUG
> + default n
> + help
> + Provide inter-thread communication primitives
> +
> +if LIBUKMPI
> + config LIBUKMPI_MBOX
> + bool "Mailboxes"
> + select LIBUKALLOC
> + select LIBUKLOCK
> + select LIBUKLOCK_SEMAPHORE
> + default n
> + help
> + Provide mailbox communication interface
> +endif
> diff --git a/lib/ukmpi/Makefile.uk b/lib/ukmpi/Makefile.uk
> new file mode 100644
> index 0000000..fc8a360
> --- /dev/null
> +++ b/lib/ukmpi/Makefile.uk
> @@ -0,0 +1,6 @@
> +$(eval $(call addlib_s,libukmpi,$(CONFIG_LIBUKMPI)))
> +
> +CINCLUDES-$(CONFIG_LIBUKMPI) += -I$(LIBUKMPI_BASE)/include
> +CXXINCLUDES-$(CONFIG_LIBUKMPI) += -I$(LIBUKMPI_BASE)/include
> +
> +LIBUKMPI_SRCS-$(CONFIG_LIBUKMPI_MBOX) += $(LIBUKMPI_BASE)/mbox.c
> diff --git a/lib/ukmpi/export.syms b/lib/ukmpi/export.syms
> new file mode 100644
> index 0000000..4c4c887
> --- /dev/null
> +++ b/lib/ukmpi/export.syms
> @@ -0,0 +1,7 @@
> +uk_mbox_create
> +uk_mbox_free
> +uk_mbox_post
> +uk_mbox_post_try
> +uk_mbox_post_to
> +uk_mbox_recv_try
> +uk_mbox_recv_to
> diff --git a/lib/ukmpi/include/uk/mbox.h b/lib/ukmpi/include/uk/mbox.h
> new file mode 100644
> index 0000000..d2c48e5
> --- /dev/null
> +++ b/lib/ukmpi/include/uk/mbox.h
> @@ -0,0 +1,67 @@
> +/* 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_MBOX_H__
> +#define __UK_MBOX_H__
> +
> +#include <uk/config.h>
> +
> +#if CONFIG_LIBUKMPI_MBOX
> +#include <errno.h>
> +#include <uk/semaphore.h>
> +#include <uk/alloc.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +struct uk_mbox;
> +
> +struct uk_mbox *uk_mbox_create(struct uk_alloc *a, size_t size);
> +void uk_mbox_free(struct uk_alloc *a, struct uk_mbox *m);
> +
> +void uk_mbox_post(struct uk_mbox *m, void *msg);
> +int uk_mbox_post_try(struct uk_mbox *m, void *msg);
> +__nsec uk_mbox_post_to(struct uk_mbox *m, void *msg, __nsec timeout);
> +
> +int uk_mbox_recv_try(struct uk_mbox *m, void **msg);
> +__nsec uk_mbox_recv_to(struct uk_mbox *m, void **msg, __nsec timeout);
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* CONFIG_LIBMPI_UKMBOX */
> +#endif /* __UK_MBOX_H__ */
> diff --git a/lib/ukmpi/mbox.c b/lib/ukmpi/mbox.c
> new file mode 100644
> index 0000000..e15e894
> --- /dev/null
> +++ b/lib/ukmpi/mbox.c
> @@ -0,0 +1,182 @@
> +#include <uk/mbox.h>
> +#include <uk/assert.h>
> +#include <uk/arch/limits.h>
> +
> +struct uk_mbox {
> + size_t len;
> + struct uk_semaphore readsem;
> + long readpos;
> + struct uk_semaphore writesem;
> + long writepos;
> +
> + void *msgs[];
> +};
> +
> +struct uk_mbox *uk_mbox_create(struct uk_alloc *a, size_t size)
> +{
> + struct uk_mbox *m;
> +
> + UK_ASSERT(size <= __L_MAX);
> +
> + m = uk_malloc(a, sizeof(*m) + (sizeof(void *) * (size + 1)));
> + if (!m)
> + return NULL;
> +
> + m->len = size + 1;
> +
> + uk_semaphore_init(&m->readsem, 0);
> + m->readpos = 0;
> +
> + uk_semaphore_init(&m->writesem, (long) size);
> + m->writepos = 0;
> +
> + uk_printd(DLVL_EXTRA, "Created mailbox %p\n", m);
> + return m;
> +}
> +
> +/* Deallocates a mailbox. If there are messages still present in the
> + * mailbox when the mailbox is deallocated, it is an indication of a
> + * programming error in lwIP and the developer should be notified.
> + */
> +void uk_mbox_free(struct uk_alloc *a, struct uk_mbox *m)
> +{
> + uk_printd(DLVL_EXTRA, "Release mailbox %p\n", m);
> +
> + UK_ASSERT(a);
> + UK_ASSERT(m);
> + UK_ASSERT(m->readpos == m->writepos);
> +
> + uk_free(a, m);
> +}
> +
> +/* Posts the "msg" to the mailbox, internal version that actually does the
> + * post.
> + */
> +static inline void _do_mbox_post(struct uk_mbox *m, void *msg)
> +{
> + /* The caller got a semaphore token, so we are now allowed to increment
> + * writer, but we still need to prevent concurrency between writers
> + * (interrupt handler vs main)
> + */
> + unsigned long irqf;
> +
> + UK_ASSERT(m);
> +
> + irqf = ukplat_lcpu_save_irqf();
> + m->msgs[m->writepos] = msg;
> + m->writepos = (m->writepos + 1) % m->len;
> + UK_ASSERT(m->readpos != m->writepos);
> + ukplat_lcpu_restore_irqf(irqf);
> + uk_printd(DLVL_EXTRA, "Posted message %p to mailbox %p\n", msg, m);
> +
> + uk_semaphore_up(&m->readsem);
> +}
> +
> +void uk_mbox_post(struct uk_mbox *m, void *msg)
> +{
> + /* The caller got a semaphore token, so we are now allowed to increment
> + * writer, but we still need to prevent concurrency between writers
> + * (interrupt handler vs main)
> + */
> + UK_ASSERT(m);
> +
> + uk_semaphore_down(&m->writesem);
> + _do_mbox_post(m, msg);
> +}
> +
> +int uk_mbox_post_try(struct uk_mbox *m, void *msg)
> +{
> + UK_ASSERT(m);
> +
> + if (!uk_semaphore_down_try(&m->writesem))
> + return -ENOBUFS;
> + _do_mbox_post(m, msg);
> + return 0;
> +}
> +
> +__nsec uk_mbox_post_to(struct uk_mbox *m, void *msg, __nsec timeout)
> +{
> + __nsec ret;
> +
> + UK_ASSERT(m);
> +
> + ret = uk_semaphore_down_to(&m->writesem, timeout);
> + if (ret != __NSEC_MAX)
> + _do_mbox_post(m, msg);
> + return ret;
> +}
> +
> +/*
> + * Fetch a message from a mailbox. Internal version that actually does the
> + * fetch.
> + */
> +static inline void *_do_mbox_recv(struct uk_mbox *m)
> +{
> + unsigned long irqf;
> + void *ret;
> +
> + uk_printd(DLVL_EXTRA, "Receive message from mailbox %p\n", m);
> + irqf = ukplat_lcpu_save_irqf();
> + UK_ASSERT(m->readpos != m->writepos);
> + ret = m->msgs[m->readpos];
> + m->readpos = (m->readpos + 1) % m->len;
> + ukplat_lcpu_restore_irqf(irqf);
> +
> + uk_semaphore_up(&m->writesem);
> +
> + return ret;
> +}
> +
> +/* This is similar to uk_mbox_fetch, however if a message is not
> + * present in the mailbox, it immediately returns with the code
> + * SYS_MBOX_EMPTY. On success 0 is returned.
> + *
> + * To allow for efficient implementations, this can be defined as a
> + * function-like macro in sys_arch.h instead of a normal function. For
> + * example, a naive implementation could be:
> + * #define uk_mbox_tryfetch(mbox,msg) \
> + * uk_mbox_fetch(mbox,msg,1)
> + * although this would introduce unnecessary delays.
> + */
> +int uk_mbox_recv_try(struct uk_mbox *m, void **msg)
> +{
> + void *rmsg;
> +
> + UK_ASSERT(m);
> +
> + if (!uk_semaphore_down_try(&m->readsem))
> + return -ENOMSG;
> +
> + rmsg = _do_mbox_recv(m);
> + if (msg)
> + *msg = rmsg;
> + return 0;
> +}
> +
> +
> +/* Blocks the thread until a message arrives in the mailbox, but does
> + * not block the thread longer than "timeout" milliseconds (similar to
> + * the sys_arch_sem_wait() function). The "msg" argument is a result
> + * parameter that is set by the function (i.e., by doing "*msg =
> + * ptr"). The "msg" parameter maybe NULL to indicate that the message
> + * should be dropped.
> + *
> + * The return values are the same as for the sys_arch_sem_wait() function:
> + * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
> + * timeout.
> + */
> +__nsec uk_mbox_recv_to(struct uk_mbox *m, void **msg, __nsec timeout)
> +{
> + void *rmsg = NULL;
> + __nsec ret;
> +
> + UK_ASSERT(m);
> +
> + ret = uk_semaphore_down_to(&m->readsem, timeout);
> + if (ret != __NSEC_MAX)
> + rmsg = _do_mbox_recv(m);
> +
> + if (msg)
> + *msg = rmsg;
> + return ret;
> +}
> --
> 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |