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