[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
Yuri Volchkov <yuri.volchkov@xxxxxxxxx> writes: > 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). > >> + >> +/* 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? Oh, sorry, now i see it. Ignore this comment > >> + 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 -- 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 |