[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v2 3/3] lib/ukmpi: Introduce mailboxes with libukmpi
On 15.06.2018 11:27, Yuri Volchkov wrote: 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 | 176 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 276 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..474d377 --- /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. + +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..31546dd --- /dev/null +++ b/lib/ukmpi/mbox.c @@ -0,0 +1,176 @@ +#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); +}In the follow up patch we probably would want to add walking through remaining messages and killing them. Or sleeping util user will read them all (with a deadline) > This is good idea, but I suggest to do this with extra patches. We may need to add some clever mechanism to correctly unblock blocked threads. + +/* 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);Should this message go after actual receiving is happened?+ 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 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |