[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.