From 01dd6786fe658fa53fc2b16ad279044fa0a0dbdf Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 04:28:22 +0800 Subject: [PATCH 01/13] patina: Implement the initial version of patina Signed-off-by: msdx321 --- src/components/lib/patina/Makefile | 63 ++++++ src/components/lib/patina/doc.md | 9 + src/components/lib/patina/patina.h | 10 + src/components/lib/patina/patina_chan.c | 250 +++++++++++++++++++++++ src/components/lib/patina/patina_chan.h | 26 +++ src/components/lib/patina/patina_evt.c | 200 ++++++++++++++++++ src/components/lib/patina/patina_evt.h | 25 +++ src/components/lib/patina/patina_mutex.c | 124 +++++++++++ src/components/lib/patina/patina_mutex.h | 17 ++ src/components/lib/patina/patina_sem.c | 127 ++++++++++++ src/components/lib/patina/patina_sem.h | 17 ++ src/components/lib/patina/patina_timer.c | 207 +++++++++++++++++++ src/components/lib/patina/patina_timer.h | 37 ++++ src/components/lib/patina/patina_types.h | 17 ++ 14 files changed, 1129 insertions(+) create mode 100644 src/components/lib/patina/Makefile create mode 100644 src/components/lib/patina/doc.md create mode 100644 src/components/lib/patina/patina.h create mode 100644 src/components/lib/patina/patina_chan.c create mode 100644 src/components/lib/patina/patina_chan.h create mode 100644 src/components/lib/patina/patina_evt.c create mode 100644 src/components/lib/patina/patina_evt.h create mode 100644 src/components/lib/patina/patina_mutex.c create mode 100644 src/components/lib/patina/patina_mutex.h create mode 100644 src/components/lib/patina/patina_sem.c create mode 100644 src/components/lib/patina/patina_sem.h create mode 100644 src/components/lib/patina/patina_timer.c create mode 100644 src/components/lib/patina/patina_timer.h create mode 100644 src/components/lib/patina/patina_types.h diff --git a/src/components/lib/patina/Makefile b/src/components/lib/patina/Makefile new file mode 100644 index 0000000000..297100059c --- /dev/null +++ b/src/components/lib/patina/Makefile @@ -0,0 +1,63 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The library names associated with .a files output that are linked +# (via, for example, -lpatina) into dependents. This list should be +# "patina" for output files such as libpatina.a. +LIBRARY_OUTPUT = patina +# The .o files that are mandatorily linked into dependents. This is +# rarely used, and only when normal .a linking rules will avoid +# linking some necessary objects. This list is of names (for example, +# patina) which will generate patina.lib.o. Do NOT include the list of .o +# files here. Please note that using this list is *very rare* and +# should only be used when the .a support above is not appropriate. +OBJECT_OUTPUT = +# The path within this directory that holds the .h files for +# dependents to compile with (./ by default). Will be fed into the -I +# compiler arguments. +INCLUDE_PATHS = . +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = evt +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component crt util chan tmr sl +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +# There are two different *types* of Makefiles for libraries. +# 1. Those that are Composite-specific, and simply need an easy way to +# compile and itegrate their code. +# 2. Those that aim to integrate external libraries into +# Composite. These focus on "driving" the build process of the +# external library, then pulling out the resulting files and +# directories. These need to be flexible as all libraries are +# different. + +# Type 1, Composite library: This is the default Makefile for +# libraries written for composite. Get rid of this if you require a +# custom Makefile (e.g. if you use an existing +# (non-composite-specific) library. An example of this is `kernel`. +include Makefile.lib + +## Type 2, external library: If you need to specialize the Makefile +## for an external library, you can add the external code as a +## subdirectory, and drive its compilation, and integration with the +## system using a specialized Makefile. The Makefile must generate +## lib$(LIBRARY_OUTPUT).a and $(OBJECT_OUTPUT).lib.o, and have all of +## the necessary include paths in $(INCLUDE_PATHS). +## +## To access the Composite Makefile definitions, use the following. An +## example of a Makefile written in this way is in `ps/`. +# +# include Makefile.src Makefile.comp Makefile.dependencies +# .PHONY: all clean init distclean +## Fill these out with your implementation +# all: +# clean: +# +## Default rules: +# init: clean all +# distclean: clean diff --git a/src/components/lib/patina/doc.md b/src/components/lib/patina/doc.md new file mode 100644 index 0000000000..922f4810fe --- /dev/null +++ b/src/components/lib/patina/doc.md @@ -0,0 +1,9 @@ +## patina + +This is the skeleton library used by the `mklib.sh` script to aid in the creation of a new library. +It provides no functionality, and should never be depended on! +This documentation should be *replaced* in the documentation for a new library. + +### Description + +### Usage and Assumptions diff --git a/src/components/lib/patina/patina.h b/src/components/lib/patina/patina.h new file mode 100644 index 0000000000..9312578ada --- /dev/null +++ b/src/components/lib/patina/patina.h @@ -0,0 +1,10 @@ +#ifndef PATINA_H +#define PATINA_H + +#include +#include +#include +#include +#include + +#endif diff --git a/src/components/lib/patina/patina_chan.c b/src/components/lib/patina/patina_chan.c new file mode 100644 index 0000000000..9e2558060f --- /dev/null +++ b/src/components/lib/patina/patina_chan.c @@ -0,0 +1,250 @@ +/** + * Redistribution of this file is permitted under the BSD two clause license. + * + * Copyright 2020, The George Washington University + * Author: Bite Ye, bitye@gwu.edu + */ + +#include +#include +#include +#include +#include + +/** + * This is a wrapper of patina's native channel library. + * For detail API usage guide, please check source codes + * under 'src/components/lib/chan' + */ + +SS_STATIC_SLAB(chan, struct chan, PATINA_MAX_NUM_CHAN); +SS_STATIC_SLAB(chan_rcv, struct chan_rcv, PATINA_MAX_NUM_CHAN); +SS_STATIC_SLAB(chan_snd, struct chan_snd, PATINA_MAX_NUM_CHAN); + +/** + * Create a channel + * + * Currently we only support CHAN_DEFAULT as flag, hence + * the arugment 'flags' has no effect + * Also note that name as arugment is not supported. + * + * Arguments: + * - @type_size: size of the item in this channel + * - @queue_length: size of this channel + * - @ch_name: no effect + * - @falgs: no effect + * + * @return: id of the channel just been created. + */ +patina_chan_t +patina_channel_create(size_t type_size, size_t queue_length, int ch_name, size_t flags) +{ + assert(type_size & queue_length); + + struct chan *c = ss_chan_alloc(); + assert(c); + + assert(chan_init(c, type_size, queue_length, CHAN_DEFAULT)); + + ss_chan_activate(c); + + return (patina_chan_t)c | PATINA_T_CHAN; +} + +/** + * Get recv endpoint of a channel + * + * Arguments: + * - @cid: channel id + * + * @return: id of the recv endpoint + */ +patina_chan_r_t +patina_channel_get_recv(patina_chan_t cid) +{ + assert(cid); + + struct chan * c = (struct chan *)(cid & PATINA_T_MASK); + struct chan_rcv *r = ss_chan_rcv_alloc(); + assert(r); + + assert(!chan_rcv_init(r, c)); + + ss_chan_rcv_activate(r); + + return (patina_chan_r_t)r | PATINA_T_CHAN_R; +} + +/** + * Get send endpoint + * + * Arugments: + * - @cid: channel id + * + * @return: id of the send endpoint + */ +patina_chan_s_t +patina_channel_get_send(patina_chan_t cid) +{ + assert(cid); + + struct chan * c = (struct chan *)(cid & PATINA_T_MASK); + struct chan_snd *s = ss_chan_snd_alloc(); + assert(s); + + assert(!chan_snd_init(s, c)); + + ss_chan_snd_activate(s); + + return (patina_chan_s_t)s | PATINA_T_CHAN_S; +} + +/** + * Get recv endpoint using ch_name (which currently being allocated while booting, + * see chanmgr for more detail). + * + * Arguments: + * - @type_size: size of the item in this channel + * - @queue_length: size of the channel + * - @ch_name: id of the channel + * + * @return: id of the recv endpoint + */ +patina_chan_r_t +patina_channel_retrieve_recv(size_t type_size, size_t queue_length, int ch_name) +{ + assert(type_size & queue_length); + + struct chan_rcv *r = ss_chan_rcv_alloc(); + assert(r); + + assert(!chan_rcv_init_with(r, ch_name, type_size, queue_length, CHAN_DEFAULT)); + + ss_chan_rcv_activate(r); + + return (patina_chan_s_t)r | PATINA_T_CHAN_R; +} + +/** + * Get send endpoint using ch_name (which currently being allocated while booting, + * see chanmgr for more detail). + * + * Arguments: + * - @type_size: size of the item in this channel + * - @queue_length: size of the channel + * - @ch_name: id of the channel + * + * @return: id of the send endpoint + */ +patina_chan_s_t +patina_channel_retrieve_send(size_t type_size, size_t queue_length, int ch_name) +{ + assert(type_size & queue_length); + + struct chan_snd *s = ss_chan_snd_alloc(); + assert(s); + + assert(!chan_snd_init_with(s, ch_name, type_size, queue_length, CHAN_DEFAULT)); + + ss_chan_snd_activate(s); + + return (patina_chan_s_t)s | PATINA_T_CHAN_S; +} + +/** + * Close a channel (this func close channel endpoint) + * + * Arguments: + * - @eid: id of the endpoint + * + * @return: always success (return 0). + */ +int +patina_channel_close(size_t eid) +{ + assert(eid); + + if ((eid & (~PATINA_T_MASK)) == PATINA_T_CHAN_R) { + struct chan_rcv *r = (struct chan_rcv *)(eid & PATINA_T_MASK); + + chan_rcv_teardown(r); + ss_chan_rcv_free(r); + } else if ((eid & (~PATINA_T_MASK)) == PATINA_T_CHAN_S) { + struct chan_snd *s = (struct chan_snd *)(eid & PATINA_T_MASK); + + chan_snd_teardown(s); + ss_chan_snd_free(s); + } + + return 0; +} + +/** + * Close a channel (close THE channel) + * + * Arguments: + * - @cid: id of the channel + * + * @return: always return 0 + */ +int +patina_channel_destroy(patina_chan_t cid) +{ + assert(cid); + + struct chan *c = (struct chan *)(cid & PATINA_T_MASK); + + chan_teardown(c); + ss_chan_free(c); + + return 0; +} + +/** + * Send data through channel + * + * For the flags, currently we don't do any translate so please use native chan lib's + * flags. + * + * Arguments: + * - @scid: id of send endpoint + * - @len: no effect + * - @flags: native chan lib's flags + * + * @return: return 'chan_send's return + */ +patina_channel_send(patina_chan_s_t scid, void *data, size_t len, size_t flags) +{ + assert(scid & data & len); + + return chan_send((struct chan_snd *)(scid & PATINA_T_MASK), data, (chan_flags_t)flags); +} + +/** + * Receive data through channel + * + * For the flags, currently we don't do any translate so please use native chan lib's + * flags. + * + * Arguments: + * - @scid: id of recv endpoint + * - @len: no effect + * - @flags: native chan lib's flags + * + * @return: return 'chan_recv's return + */ +int +patina_channel_recv(patina_chan_r_t rcid, void *buf, size_t len, size_t flags) +{ + assert(rcid & buf & len); + + return chan_recv((struct chan_rcv *)(rcid & PATINA_T_MASK), buf, (chan_flags_t)flags); +} + +/* NOT IMPLEMENTED */ +int +patina_channel_get_status(size_t cid, struct patina_channel_status *status) +{ + assert(0); + return 0; +} diff --git a/src/components/lib/patina/patina_chan.h b/src/components/lib/patina/patina_chan.h new file mode 100644 index 0000000000..3dc0dac6d2 --- /dev/null +++ b/src/components/lib/patina/patina_chan.h @@ -0,0 +1,26 @@ +#ifndef PATINA_CHAN_H +#define PATINA_CHAN_H + +#include +#include + +#define PATINA_MAX_NUM_CHAN 32 + +typedef size_t patina_chan_t; +typedef size_t patina_chan_s_t; +typedef size_t patina_chan_r_t; + +struct patina_channel_status; + +patina_chan_t patina_channel_create(size_t type_size, size_t queue_length, int ch_name, size_t flags); +patina_chan_r_t patina_channel_get_recv(patina_chan_t cid); +patina_chan_s_t patina_channel_get_send(patina_chan_t cid); +patina_chan_r_t patina_channel_retrieve_recv(size_t type_size, size_t queue_length, int ch_name); +patina_chan_s_t patina_channel_retrieve_send(size_t type_size, size_t queue_length, int ch_name); +int patina_channel_close(size_t cid); +int patina_channel_destroy(patina_chan_t cid); +int patina_channel_send(patina_chan_s_t scid, void *data, size_t len, size_t flags); +int patina_channel_recv(patina_chan_r_t rcid, void *buf, size_t len, size_t flags); +int patina_channel_get_status(size_t cid, struct patina_channel_status *status); + +#endif diff --git a/src/components/lib/patina/patina_evt.c b/src/components/lib/patina/patina_evt.c new file mode 100644 index 0000000000..e6e149c3c2 --- /dev/null +++ b/src/components/lib/patina/patina_evt.c @@ -0,0 +1,200 @@ +/** + * Redistribution of this file is permitted under the BSD two clause license. + * + * Copyright 2020, The George Washington University + * Author: Bite Ye, bitye@gwu.edu + */ + +#include +#include +#include +#include +#include + +/** + * This is a wrapper of patina's native evt interface. + * For detail API usage guide, please check source codes + * under 'src/components/interface/evt.h' + */ + +/** + * Create a event + * + * Arguments: + * - @eid: id of the event (a struct, see 'patina_evt.h') + * - @n_sources: number of sources can be hold in this event + * + * @return: id of the event + */ +int +patina_event_create(patina_event_t *eid, uint32_t n_sources) +{ + assert(eid & n_sources); + + return evt_init((struct evt *)eid, n_sources); +} + + +/** + * Add a source to a event + * + * Currently we don't support any flags + * + * Arguments: + * - @eid: id of the event + * - @src: id of the source + * - @flags: no effect + * + * @return: always return 0 for timer and return corresponding native APIs' returns for others + */ +int +patina_event_add(patina_event_t *eid, size_t src, size_t flags) +{ + assert(eid & src); + + evt_res_id_t id; + + if (!eid || !src) { return -1; } + + id = evt_add((struct evt *)eid, 0, 0); + assert(id); + + if ((src & (~PATINA_T_MASK)) == PATINA_T_TIMER) { + ((struct patina_tmr *)(src & PATINA_T_MASK))->eid = eid; + return 0; + } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_CHAN) { + return chan_evt_associate((struct chan *)(src & PATINA_T_MASK), id); + } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_CHAN_R) { + return chan_rcv_evt_associate((struct chan_rcv *)(src & PATINA_T_MASK), id); + } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_CHAN_S) { + return chan_snd_evt_associate((struct chan_snd *)(src & PATINA_T_MASK), id); + } + + assert(0); +} + +/** + * Remove a source from a event + * + * Arguments: + * - @eid: id of the event + * - @src: id of the source + * - @flags: no effect + * + * @return: return native APIs' returns + */ +int +patina_event_remove(patina_event_t *eid, size_t src, size_t flags) +{ + assert(eid & src); + + evt_res_id_t id = 0; + + if (!eid || !src) { return -1; } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_TIMER) { + id = tmr_evt_associated((struct tmr *)(src & PATINA_T_MASK)); + tmr_evt_disassociate((struct tmr *)(src & PATINA_T_MASK)); + } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_CHAN) { + id = chan_evt_associated((struct chan *)(src & PATINA_T_MASK)); + chan_evt_disassociate((struct chan *)(src & PATINA_T_MASK)); + } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_CHAN_R) { + id = chan_rcv_evt_associated((struct chan_rcv *)(src & PATINA_T_MASK)); + chan_rcv_evt_disassociate((struct chan_rcv *)(src & PATINA_T_MASK)); + } + + if ((src & (~PATINA_T_MASK)) == PATINA_T_CHAN_S) { + id = chan_snd_evt_associated((struct chan_snd *)(src & PATINA_T_MASK)); + chan_snd_evt_disassociate((struct chan_snd *)(src & PATINA_T_MASK)); + } + + return evt_rem((struct evt *)eid, id); +} + +/** + * Delete a event + * + * Arguments: + * - @eid: id of the event + * + * @return: return 'evt_teardown's return + */ +int +patina_event_delete(patina_event_t *eid) +{ + assert(eid); + + return evt_teardown((struct evt *)eid); +} + +/** + * Wait on a event (blocking) + * + * Arguments: + * - @eid: id of the event + * - @events: holder of event info (an array, allow batching) + * - @num: number of events client wants + * + * @return: return 'evt_get's return + */ +int +patina_event_wait(patina_event_t *eid, struct patina_event_info events[], size_t num) +{ + assert(eid & events & num); + + word_t tmp; + + return evt_get((struct evt *)eid, EVT_WAIT_DEFAULT, &tmp, &tmp); +} + +/** + * Check on a event (non-blocking) + * + * Arguments: + * - @eid: id of the event + * - @events: holder of event info (an array, allow batching) + * - @num: number of events client wants + * + * @return: return 'evt_get's return + */ +int +patina_event_check(patina_event_t *eid, struct patina_event_info events[], size_t num) +{ + assert(eid & events & num); + + word_t tmp; + + return evt_get((struct evt *)eid, EVT_WAIT_NONBLOCKING, &tmp, &tmp); +} + +/** + * DEBUG usage + */ +evt_res_id_t +patina_event_debug_fake_add(patina_event_t *eid) +{ + assert(eid); + + return evt_add((struct evt *)eid, 0, 0); +} + +/** + * DEBUG usage + */ +int +patina_event_debug_trigger(evt_res_id_t rid) +{ + assert(rid); + + return evt_trigger(rid); +} \ No newline at end of file diff --git a/src/components/lib/patina/patina_evt.h b/src/components/lib/patina/patina_evt.h new file mode 100644 index 0000000000..956a1274fc --- /dev/null +++ b/src/components/lib/patina/patina_evt.h @@ -0,0 +1,25 @@ +#ifndef PATINA_EVT_H +#define PATINA_EVT_H + +#include +#include +#include +#include + +#define PATINA_MAX_NUM_EVT 32 + +typedef struct evt patina_event_t; + +struct patina_event_info { + size_t event_src_id; + size_t event_type; +}; + +int patina_event_create(patina_event_t *eid, uint32_t n_sources); +int patina_event_add(patina_event_t *eid, size_t src, size_t flags); +int patina_event_remove(patina_event_t *eid, size_t src, size_t flags); +int patina_event_delete(patina_event_t *eid); +int patina_event_wait(patina_event_t *eid, struct patina_event_info events[], size_t num); +int patina_event_check(patina_event_t *eid, struct patina_event_info events[], size_t num); + +#endif diff --git a/src/components/lib/patina/patina_mutex.c b/src/components/lib/patina/patina_mutex.c new file mode 100644 index 0000000000..82b1c9a862 --- /dev/null +++ b/src/components/lib/patina/patina_mutex.c @@ -0,0 +1,124 @@ +/** + * Redistribution of this file is permitted under the BSD two clause license. + * + * Copyright 2020, The George Washington University + * Author: Bite Ye, bitye@gwu.edu + */ + +#include +#include +#include +#include + +/** + * This is a wrapper of patina's native crt lib. + * For detail API usage guide, please check source codes + * under 'src/components/lib/crt/' + */ + +SS_STATIC_SLAB(lock, struct crt_lock, PATINA_MAX_NUM_MUTEX); + +/** + * Create a mutex + * Currently we don't support any flags + * + * Arguments: + * - @flags: no effect + * + * @return: id of the mutex + */ +patina_mutex_t +patina_mutex_create(size_t flags) +{ + struct crt_lock *l = ss_lock_alloc(); + if (!l) { return -1; } + + assert(!crt_lock_init(l)) + + ss_lock_activate(l); + + patina_mutex_t mid = (patina_mutex_t)l | PATINA_T_MUTEX; + + return mid; +} + +/** + * Lock a mutex (blocking) + * + * Arugments: + * - @mid: id of the mutex + * + * @return: always success + */ +int +patina_mutex_lock(patina_mutex_t mid) +{ + assert(mid); + + struct crt_lock *l = (struct crt_lock *)(mid & PATINA_T_MASK); + + crt_lock_take(l); + + return 0; +} + +/** + * Try to lock a mutex (non-blocking) + * + * Arugments: + * - @mid: id of the mutex + * + * @return: always success + */ +int +patina_mutex_try_lock(patina_mutex_t mid) +{ + assert(mid); + + struct crt_lock *l = (struct crt_lock *)(mid & PATINA_T_MASK); + + crt_lock_try_take(l); + + return 0; +} + +/** + * Unlock a mutex + * + * Arugments: + * - @mid: id of the mutex + * + * @return: always success + */ +int +patina_mutex_unlock(patina_mutex_t mid) +{ + assert(mid); + + struct crt_lock *l = (struct crt_lock *)(mid & PATINA_T_MASK); + + crt_lock_release(l); + + return 0; +} + +/** + * Destroy a mutex + * + * Arugments: + * - @mid: id of the mutex + * + * @return: always success + */ +int +patina_mutex_destroy(patina_mutex_t mid) +{ + assert(mid); + + struct crt_lock *l = (struct crt_lock *)(mid & PATINA_T_MASK); + + crt_lock_teardown(l); + ss_lock_free(l); + + return 0; +} diff --git a/src/components/lib/patina/patina_mutex.h b/src/components/lib/patina/patina_mutex.h new file mode 100644 index 0000000000..6e7a9f02a4 --- /dev/null +++ b/src/components/lib/patina/patina_mutex.h @@ -0,0 +1,17 @@ +#ifndef PATINA_MUTEX_H +#define PATINA_MUTEX_H + +#include +#include + +#define PATINA_MAX_NUM_MUTEX 32 + +typedef size_t patina_mutex_t; + +patina_mutex_t patina_mutex_create(size_t flags); +int patina_mutex_lock(patina_mutex_t mid); +int patina_mutex_try_lock(patina_mutex_t mid); +int patina_mutex_unlock(patina_mutex_t mid); +int patina_mutex_destroy(patina_mutex_t mid); + +#endif diff --git a/src/components/lib/patina/patina_sem.c b/src/components/lib/patina/patina_sem.c new file mode 100644 index 0000000000..84f9b054b1 --- /dev/null +++ b/src/components/lib/patina/patina_sem.c @@ -0,0 +1,127 @@ +/** + * Redistribution of this file is permitted under the BSD two clause license. + * + * Copyright 2020, The George Washington University + * Author: Bite Ye, bitye@gwu.edu + */ + +#include +#include +#include +#include + +/** + * This is a wrapper of patina's native crt lib. + * For detail API usage guide, please check source codes + * under 'src/components/lib/crt/' + */ + +SS_STATIC_SLAB(sem, struct crt_sem, PATINA_MAX_NUM_SEM); + +/** + * Create a semaphore + * Currently we don't support any flags + * + * Arguments: + * - @init_value: inital value + * - @flags: no effect + * + * @return: id of the semaphore + */ +patina_sem_t +patina_sem_create(size_t init_value, size_t flags) +{ + assert(init_value); + + struct crt_sem *s = ss_sem_alloc(); + if (!s) { return -1; } + + assert(!crt_sem_init(s, (unsigned long)init_value)) + + ss_sem_activate(s); + + patina_sem_t sid = (patina_sem_t)s | PATINA_T_SEM; + + return sid; +} + +/** + * Take a sempahore (blocking) + * + * Arugments: + * - @mid: id of the semaphore + * + * @return: always success + */ +int +patina_sem_take(patina_sem_t sid) +{ + assert(sid); + + struct crt_sem *s = (struct crt_sem *)(sid & PATINA_T_MASK); + + crt_sem_take(s); + + return 0; +} + +/** + * Try to take a sempahore (non-blocking) + * + * Arugments: + * - @mid: id of the semaphore + * + * @return: always success + */ +int +patina_sem_try_take(patina_sem_t sid) +{ + assert(sid); + + struct crt_sem *s = (struct crt_sem *)(sid & PATINA_T_MASK); + + crt_sem_try_take(s); + + return 0; +} + +/** + * Give a sempahore + * + * Arugments: + * - @mid: id of the semaphore + * + * @return: always success + */ +int +patina_sem_give(patina_sem_t sid) +{ + assert(sid); + + struct crt_sem *s = (struct crt_sem *)(sid & PATINA_T_MASK); + + crt_sem_give(s); + + return 0; +} + +/** + * Destroy a sempahore + * + * Arugments: + * - @mid: id of the semaphore + * + * @return: always success + */ +int +patina_sem_destroy(patina_sem_t sid) +{ + assert(sid); + + struct crt_sem *s = (struct crt_sem *)(sid & PATINA_T_MASK); + + crt_sem_teardown(s); + ss_sem_free(s); + + return 0; +} diff --git a/src/components/lib/patina/patina_sem.h b/src/components/lib/patina/patina_sem.h new file mode 100644 index 0000000000..720fb48aae --- /dev/null +++ b/src/components/lib/patina/patina_sem.h @@ -0,0 +1,17 @@ +#ifndef PATINA_SEM_H +#define PATINA_SEM_H + +#include +#include + +#define PATINA_MAX_NUM_SEM 32 + +typedef size_t patina_sem_t; + +patina_sem_t patina_sem_create(size_t init_value, size_t flags); +int patina_sem_take(patina_sem_t sid); +int patina_sem_try_take(patina_sem_t sid); +int patina_sem_give(patina_sem_t sid); +int patina_sem_destroy(patina_sem_t sid); + +#endif diff --git a/src/components/lib/patina/patina_timer.c b/src/components/lib/patina/patina_timer.c new file mode 100644 index 0000000000..39223178fd --- /dev/null +++ b/src/components/lib/patina/patina_timer.c @@ -0,0 +1,207 @@ +/** + * Redistribution of this file is permitted under the BSD two clause license. + * + * Copyright 2020, The George Washington University + * Author: Bite Ye, bitye@gwu.edu + */ + +#include +#include +#include +#include +#include + +/** + * This is a wrapper of patina's native tmr lib. + * For detail API usage guide, please check source codes + * under 'src/components/lib/tmr/' + */ + +SS_STATIC_SLAB(patina_tmr, struct patina_tmr, PATINA_MAX_NUM_TIMER); + +/** + * Get current time (in sec + usec format) + * + * Arguments: + * - @result: time struct (see 'patina_timer.h') + * + * @return: void + */ +void +patina_time_current(struct time *result) +{ + assert(result); + + u64_t time_now = time_now_usec(); + + result->sec = time_now / (1000 * 1000); + result->usec = time_now % (1000 * 1000); + + return; +} + +/** + * Create a time struct + * + * Arguments: + * - @a: time struct + * - @sec: seconds + * - @usec: micro seconds + * + * @return: void + */ +void +patina_time_create(struct time *a, u64_t sec, u32_t usec) +{ + assert(a); + + a->sec = sec; + a->usec = usec; +} + +/** + * Add some time to a time struct + * + * Arguments: + * - @a: the target time struct + * - @b: how many time client wants to add + * + * @return: always success + */ +int +patina_time_add(struct time *a, struct time *b) +{ + assert(a & b); + assert(!(a->sec + b->sec < a->sec || a->usec + b->usec < a->usec)) + + a->sec = a->sec + b->sec; + a->usec = a->usec + b->usec; + + return 0; +} + +/** + * Subtract some time from a time struct + * + * Arguments: + * - @a: the target time struct + * - @b: how many time client wants to subtract + * + * @return: always success + */ +int +patina_time_sub(struct time *a, struct time *b) +{ + assert(a & b); + assert(!(a->sec - b->sec > a->sec || a->usec - b->usec > a->usec)) + + a->sec = a->sec - b->sec; + a->usec = a->usec - b->usec; + + return 0; +} + +/* CURRENTLY NOT SUPORTTED! */ +u32_t +patina_timer_precision() +{ + assert(0); + + return 0; +} + +/** + * Create a timer + * + * @return: return id of the timer + */ +patina_timer_t +patina_timer_create() +{ + struct patina_tmr *t = ss_patina_tmr_alloc(); + assert(t); + + t->eid = NULL; + + patina_timer_t tid = (patina_timer_t)t | PATINA_T_TIMER; + + return tid; +} + +/** + * Start a timer (one-shot) + * + * Arguments: + * - @tid: id of the timer + * - @time: delay time + * + * @return: always success + */ +int +patina_timer_start(patina_timer_t tid, struct time *time) +{ + assert(tid & time); + struct patina_tmr *t = (struct patina_tmr *)(tid & PATINA_T_MASK); + + assert(!tmr_init(&t->tmr, (time->sec * 1000 * 1000) + time->usec - time_now_usec(), TMR_ONESHOT)); + + if (t->eid) { + evt_res_id_t id = evt_add((struct evt *)t->eid, 0, 0); + tmr_evt_associate(&t->tmr, id); + } + + assert(!tmr_start(&t->tmr)); + + return 0; +} + +/** + * Start a timer (periodic) + * + * Arguments: + * - @tid: id of the timer + * - @offset: offset time to the first trigger + * - @period: period of the timer + * + * @return: always success + */ +int +patina_timer_periodic(patina_timer_t tid, struct time *offset, struct time *period) +{ + struct patina_tmr *t = (struct patina_tmr *)(tid & PATINA_T_MASK); + + assert(!tmr_init(&t->tmr, (period->sec * 1000 * 1000) + period->usec, TMR_PERIODIC)); + + if (t->eid) { + evt_res_id_t id = evt_add((struct evt *)t->eid, 0, 0); + tmr_evt_associate(&t->tmr, id); + } + + assert(!tmr_start(&t->tmr)); + + return 0; +} + + +/** + * Cancel a timer + * + * Arguments: + * - @tid: id of the timer + * + * @return: return 'tmr_stop's return + */ +int +patina_timer_cancel(patina_timer_t tid) +{ + return tmr_stop(&(((struct patina_tmr *)(tid & PATINA_T_MASK))->tmr)); +} + +/* CURRENTLY NOT SUPPORTED! */ +int +patina_timer_free(patina_timer_t tid) +{ + assert(0); + + return 0; +} diff --git a/src/components/lib/patina/patina_timer.h b/src/components/lib/patina/patina_timer.h new file mode 100644 index 0000000000..ee2db42471 --- /dev/null +++ b/src/components/lib/patina/patina_timer.h @@ -0,0 +1,37 @@ +#ifndef PATINA_TIMER_H +#define PATINA_TIMER_H + +#include +#include +#include + +#define PATINA_MAX_NUM_TIMER 32 + +typedef size_t patina_timer_t; + +struct patina_tmr { + struct tmr tmr; + patina_event_t *eid; +}; + +/** + * Time struct + * hold time in sec + usec format + */ +typedef struct time { + u64_t sec; + u32_t usec; +} patina_time_t; + +void patina_time_current(struct time *result); +void patina_time_create(struct time *a, u64_t sec, u32_t usec); +int patina_time_add(struct time *a, struct time *b); +int patina_time_sub(struct time *a, struct time *b); +u32_t patina_timer_precision(); +patina_timer_t patina_timer_create(); +int patina_timer_start(patina_timer_t tid, struct time *time); +int patina_timer_periodic(patina_timer_t tid, struct time *offset, struct time *period); +int patina_timer_cancel(patina_timer_t tid); +int patina_timer_free(patina_timer_t tid); + +#endif diff --git a/src/components/lib/patina/patina_types.h b/src/components/lib/patina/patina_types.h new file mode 100644 index 0000000000..0a82732a7e --- /dev/null +++ b/src/components/lib/patina/patina_types.h @@ -0,0 +1,17 @@ +#ifndef PATINA_TYPES_H +#define PATINA_TYPES_H + +#define PATINA_T_MASK 0xFFFFFFFC + +typedef enum +{ + PATINA_T_MUTEX = 0, + PATINA_T_SEM = 0, + PATINA_T_TIMER = 0, + PATINA_T_CHAN = 1, + PATINA_T_CHAN_R = 2, + PATINA_T_CHAN_S = 3, + PATINA_T_EVENT = 0, +} patina_types_t; + +#endif From d56903114c6f968ac5de7dc960c78ce523116fde Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 04:37:09 +0800 Subject: [PATCH 02/13] patina_bench: Implement initial benchmarking for patina_chan Signed-off-by: msdx321 --- .../tests/patina_chan_bench/Makefile | 18 ++ .../tests/patina_chan_bench/doc.md | 9 + .../patina_chan_bench/patina_chan_bench.c | 215 ++++++++++++++++++ .../patina_chan_bench_inter_recv/Makefile | 18 ++ .../tests/patina_chan_bench_inter_recv/doc.md | 9 + .../patina_chan_bench_inter_recv.c | 110 +++++++++ .../patina_chan_bench_inter_send/Makefile | 18 ++ .../tests/patina_chan_bench_inter_send/doc.md | 9 + .../patina_chan_bench_inter_send.c | 159 +++++++++++++ src/composer/patina_chan_bench.toml | 52 +++++ src/composer/patina_chan_bench_inter.toml | 58 +++++ 11 files changed, 675 insertions(+) create mode 100644 src/components/implementation/tests/patina_chan_bench/Makefile create mode 100644 src/components/implementation/tests/patina_chan_bench/doc.md create mode 100644 src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c create mode 100644 src/components/implementation/tests/patina_chan_bench_inter_recv/Makefile create mode 100644 src/components/implementation/tests/patina_chan_bench_inter_recv/doc.md create mode 100644 src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c create mode 100644 src/components/implementation/tests/patina_chan_bench_inter_send/Makefile create mode 100644 src/components/implementation/tests/patina_chan_bench_inter_send/doc.md create mode 100644 src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c create mode 100644 src/composer/patina_chan_bench.toml create mode 100644 src/composer/patina_chan_bench_inter.toml diff --git a/src/components/implementation/tests/patina_chan_bench/Makefile b/src/components/implementation/tests/patina_chan_bench/Makefile new file mode 100644 index 0000000000..6abccaba96 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_chan_bench/doc.md b/src/components/implementation/tests/patina_chan_bench/doc.md new file mode 100644 index 0000000000..68560c8d20 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench/doc.md @@ -0,0 +1,9 @@ +## tests + +This is the skeleton interface used by the `mkcomponent.sh` script to aid in the creation of a new component. +It provides no functionality, and should never be depended on! +This documentation should be *replaced* in the documentation for a new component. + +### Description + +### Usage and Assumptions diff --git a/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c b/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c new file mode 100644 index 0000000000..8412fdbe75 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c @@ -0,0 +1,215 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include + +#include +#include + +#undef PATINA_CHAN_TRACE_DEBUG +#ifdef PATINA_CHAN_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +/* One low-priority thread and one high-priority thread contends on the lock */ +#define ITERATION 10 * 10 +/* #define PRINT_ALL */ + +/* Two options are available: Sender at low/high prio, data words 4 */ +#undef READER_HIGH +#define DATA_WORDS 2 + +thdid_t chan_reader = 0, chan_writer = 0; + +typedef unsigned int cycles_32_t; + +volatile cycles_32_t tmp[DATA_WORDS] = { + 0, +}; +volatile cycles_32_t ts1[DATA_WORDS] = { + 0, +}; +volatile cycles_32_t ts2[DATA_WORDS] = { + 0, +}; +volatile cycles_32_t ts3[DATA_WORDS] = { + 0, +}; + +struct perfdata perf1, perf2, perf3; +cycles_t result1[ITERATION] = { + 0, +}; +cycles_t result2[ITERATION] = { + 0, +}; +cycles_t result3[ITERATION] = { + 0, +}; + +patina_chan_t cid; +patina_chan_t cid2; +patina_chan_r_t rid; +patina_chan_r_t rid2; +patina_chan_s_t sid; +patina_chan_s_t sid2; + +/*** + * The two threads reciprocally sends and receives. + */ +void +chan_reader_thd(void *d) +{ + /* Never stops running; writer controls how many iters to run. */ + while (1) { + debug("r1,"); + patina_channel_recv(rid, tmp, 0, 0); + debug("tsr1: %d,", tmp[0]); + debug("r2,"); + tmp[0] = time_now(); + debug("tsr2: %d,", tmp[0]); + debug("r3,"); + patina_channel_send(sid2, tmp, 0, 0); + debug("r4,"); + } +} + +void +chan_writer_thd(void *d) +{ + int i; + int first = 0; + + for (int i = 0; i < ITERATION + 1; i++) { + debug("w1,"); + ts1[0] = time_now(); + debug("ts1: %d,", ts1[0]); + debug("w2,"); + patina_channel_send(sid, ts1, 0, 0); + debug("w3,"); + patina_channel_recv(rid2, ts2, 0, 0); + debug("ts2: %d,", ts2[0]); + debug("w4,"); + ts3[0] = time_now(); + debug("w5,"); + + if (first == 0) + first = 1; + else { + if (ts2[0] > ts1[0] && ts3[0] > ts2[0]) { + perfdata_add(&perf1, ts2[0] - ts1[0]); + perfdata_add(&perf2, ts3[0] - ts2[0]); + perfdata_add(&perf3, ts3[0] - ts1[0]); + } + } + } + + perfdata_calc(&perf1); + perfdata_calc(&perf2); + perfdata_calc(&perf3); +#ifdef PRINT_ALL +#ifdef READER_HIGH + perfdata_all(&perf1); +#else + perfdata_all(&perf2); +#endif + perfdata_all(&perf3); +#else +#ifdef READER_HIGH + perfdata_print(&perf1); +#else + perfdata_print(&perf2); +#endif + perfdata_print(&perf3); +#endif + + while (1) + ; +} + +void +test_chan(void) +{ + int i; + int first = 0; + cycles_t begin, end; + +#ifdef READER_HIGH + sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; +#else + sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 6), SCHED_PARAM_CONS(SCHEDP_PRIO, 4)}; +#endif + + /* Uncontended lock taking/releasing */ + perfdata_init(&perf1, "Uncontended channel - selfloop", result1, ITERATION); + for (i = 0; i < ITERATION + 1; i++) { + begin = time_now(); + + debug("send\n"); + patina_channel_send(sid, tmp, 1, 0); + debug("recv\n"); + patina_channel_recv(rid, tmp, 1, 0); + + end = time_now(); + if (first == 0) + first = 1; + else + perfdata_add(&perf1, end - begin); + } + perfdata_calc(&perf1); +#ifdef PRINT_ALL + perfdata_all(&perf1); +#else + perfdata_print(&perf1); +#endif + + perfdata_init(&perf1, "Contended channel - reader high use this", result1, ITERATION); + perfdata_init(&perf2, "Contended channel - writer high use this", result2, ITERATION); + perfdata_init(&perf3, "Contended channel - roundtrip", result3, ITERATION); + + printc("Create threads:\n"); + + chan_reader = sched_thd_create(chan_reader_thd, NULL); + printc("\tcreating reader thread %d at prio %d\n", chan_reader, sps[0]); + sched_thd_param_set(chan_reader, sps[0]); + + chan_writer = sched_thd_create(chan_writer_thd, NULL); + printc("\tcreating writer thread %d at prio %d\n", chan_writer, sps[1]); + sched_thd_param_set(chan_writer, sps[1]); +} + +void +cos_init(void) +{ + printc("Benchmark for the patina chan (w/sched interface).\n"); +} + +int +main(void) +{ + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000 * 1000)); + + printc("Initializing channel\n"); + + cid = patina_channel_create(sizeof(cycles_32_t), DATA_WORDS, 0, CHAN_DEFAULT); + cid2 = patina_channel_create(sizeof(cycles_32_t), DATA_WORDS, 0, CHAN_DEFAULT); + + printc("Initializing end points\n"); + + sid = patina_channel_get_send(cid); + rid = patina_channel_get_recv(cid); + sid2 = patina_channel_get_send(cid2); + rid2 = patina_channel_get_recv(cid2); + + test_chan(); + + printc("Running benchmark, exiting main thread...\n"); + + return 0; +} diff --git a/src/components/implementation/tests/patina_chan_bench_inter_recv/Makefile b/src/components/implementation/tests/patina_chan_bench_inter_recv/Makefile new file mode 100644 index 0000000000..6abccaba96 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench_inter_recv/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_chan_bench_inter_recv/doc.md b/src/components/implementation/tests/patina_chan_bench_inter_recv/doc.md new file mode 100644 index 0000000000..68560c8d20 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench_inter_recv/doc.md @@ -0,0 +1,9 @@ +## tests + +This is the skeleton interface used by the `mkcomponent.sh` script to aid in the creation of a new component. +It provides no functionality, and should never be depended on! +This documentation should be *replaced* in the documentation for a new component. + +### Description + +### Usage and Assumptions diff --git a/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c b/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c new file mode 100644 index 0000000000..929f69aec4 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c @@ -0,0 +1,110 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include +#include +#include +#include + +#undef CHAN_TRACE_DEBUG +#ifdef CHAN_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +patina_chan_s_t sid; +patina_chan_r_t rid; +struct evt e; + +/* Keep these settings below consistent with the sender side */ +#undef READER_HIGH +#undef USE_EVTMGR + +#define TEST_CHAN_ITEM_SZ sizeof(u32_t) +#define TEST_CHAN_NSLOTS 2 +#define TEST_CHAN_SEND_ID 3 +#define TEST_CHAN_RECV_ID 4 +/* We are the receiver, and we don't care about data gathering */ +#ifdef READER_HIGH +#define TEST_CHAN_PRIO_SELF 4 +#else +#define TEST_CHAN_PRIO_SELF 5 +#endif + +typedef unsigned int cycles_32_t; + +int +main(void) +{ + cycles_t wakeup; + cycles_32_t tmp; +#ifdef USE_EVTMGR + evt_res_id_t evt_id; + evt_res_data_t evtdata; + evt_res_type_t evtsrc; +#endif + + printc("Component chan receiver: executing main.\n"); + + /* See if event manager is in use. If yes, log the receiver channel into it */ +#ifdef USE_EVTMGR + assert(evt_init(&e, 2) == 0); + evt_id = evt_add(&e, 0, (evt_res_data_t)&r); + assert(evt_id != 0); + assert(chan_rcv_evt_associate(&r, evt_id) == 0); + printc("Receiver side event created.\n"); +#endif + + /* + * This sleep in both hi and lo comps lets the benchmark run + * more predictably on HW and on Qemu. + * + * Likely because this helps the priority change in cos_init take effect! + * Or because this lets the initialization of both ends of channels complete before tests start! + */ + wakeup = time_now() + time_usec2cyc(100 * 1000); + sched_thd_block_timeout(0, wakeup); + + /* Never stops running; sender controls how many iters to run. */ + while (1) { + debug("r1,"); +#ifdef USE_EVTMGR + /* Receive from the events then the channel */ + while (chan_recv(&r, &tmp, CHAN_NONBLOCKING) == CHAN_TRY_AGAIN) + evt_get(&e, EVT_WAIT_DEFAULT, &evtsrc, &evtdata); +#else + patina_channel_recv(rid, &tmp, 1, 0); +#endif + debug("tsr1: %d,", tmp); + debug("r2,"); + tmp = time_now(); + debug("tsr2: %d,", tmp); + debug("r3,"); + patina_channel_send(sid, &tmp, 1, 0); + debug("r4,"); + } +} + + +/* We initialize channel and threads before executing main - here the scheduler doesn't even work so we guarantee good + * init */ +void +cos_init(void) +{ + printc("Component chan receiver initializing:\n\tCreate channel %d\n", TEST_CHAN_SEND_ID); + sid = patina_channel_retrieve_send(TEST_CHAN_ITEM_SZ, TEST_CHAN_NSLOTS, TEST_CHAN_SEND_ID); + + printc("\tCreate channel %d\n", TEST_CHAN_RECV_ID); + rid = patina_channel_retrieve_recv(TEST_CHAN_ITEM_SZ, TEST_CHAN_NSLOTS, TEST_CHAN_RECV_ID); + + printc("\tPriority %d for self!\n", TEST_CHAN_PRIO_SELF); + if (sched_thd_param_set(cos_thdid(), sched_param_pack(SCHEDP_PRIO, TEST_CHAN_PRIO_SELF))) { + printc("sched_thd_param_set failed.\n"); + assert(0); + } +} diff --git a/src/components/implementation/tests/patina_chan_bench_inter_send/Makefile b/src/components/implementation/tests/patina_chan_bench_inter_send/Makefile new file mode 100644 index 0000000000..6abccaba96 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench_inter_send/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_chan_bench_inter_send/doc.md b/src/components/implementation/tests/patina_chan_bench_inter_send/doc.md new file mode 100644 index 0000000000..68560c8d20 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench_inter_send/doc.md @@ -0,0 +1,9 @@ +## tests + +This is the skeleton interface used by the `mkcomponent.sh` script to aid in the creation of a new component. +It provides no functionality, and should never be depended on! +This documentation should be *replaced* in the documentation for a new component. + +### Description + +### Usage and Assumptions diff --git a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c new file mode 100644 index 0000000000..69691edd88 --- /dev/null +++ b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c @@ -0,0 +1,159 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include +#include +#include +#include + +#undef CHAN_TRACE_DEBUG +#ifdef CHAN_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +patina_chan_s_t sid; +patina_chan_r_t rid; +struct evt e; + +#define ITERATION 10 * 1000 +#undef READER_HIGH +#undef USE_EVTMGR +/* #define PRINT_ALL */ + +#define TEST_CHAN_ITEM_SZ sizeof(u32_t) +#define TEST_CHAN_NSLOTS 2 +#define TEST_CHAN_SEND_ID 4 +#define TEST_CHAN_RECV_ID 3 +/* We are the sender, and we will be responsible for collecting resulting data */ +#ifdef READER_HIGH +#define TEST_CHAN_PRIO_SELF 5 +#else +#define TEST_CHAN_PRIO_SELF 4 +#endif + +typedef unsigned int cycles_32_t; + +struct perfdata perf1, perf2, perf3; +cycles_t result1[ITERATION] = { + 0, +}; +cycles_t result2[ITERATION] = { + 0, +}; +cycles_t result3[ITERATION] = { + 0, +}; + +int +main(void) +{ + int i; + cycles_t wakeup; + cycles_32_t ts1, ts2, ts3; + int first = 0; +#ifdef USE_EVTMGR + evt_res_id_t evt_id; + evt_res_data_t evtdata; + evt_res_type_t evtsrc; +#endif + + printc("Component chan sender: executing main.\n"); + + /* Send data to receiver so it can register for channels */ + +#ifdef USE_EVTMGR + assert(evt_init(&e, 2) == 0); + evt_id = evt_add(&e, 0, (evt_res_data_t)&r); + assert(evt_id != 0); + assert(chan_rcv_evt_associate(&r, evt_id) == 0); + printc("Sender side event created.\n"); +#endif + + /* + * This sleep in both hi and lo comps lets the benchmark run + * more predictably on HW and on Qemu. + * + * Likely because this helps the priority change in cos_init take effect! + * Or because this lets the initialization of both ends of channels complete before tests start! + */ + wakeup = time_now() + time_usec2cyc(100 * 1000); + sched_thd_block_timeout(0, wakeup); + + for (int i = 0; i < ITERATION + 1; i++) { + debug("w1,"); + ts1 = time_now(); + debug("ts1: %d,", ts1); + debug("w2,"); + patina_channel_send(sid, &ts1, 1, 0); + debug("w3,"); +#ifdef USE_EVTMGR + /* Receive from the events then the channel */ + while (chan_recv(&r, &ts2, CHAN_NONBLOCKING) == CHAN_TRY_AGAIN) + evt_get(&e, EVT_WAIT_DEFAULT, &evtsrc, &evtdata); +#else + patina_channel_recv(rid, &ts2, 1, 0); +#endif + debug("ts2: %d,", ts2); + debug("w4,"); + ts3 = time_now(); + debug("w5,"); + + if (first == 0) + first = 1; + else { + if (ts2 > ts1 && ts3 > ts2) { + perfdata_add(&perf1, ts2 - ts1); + perfdata_add(&perf2, ts3 - ts2); + perfdata_add(&perf3, ts3 - ts1); + } + } + } + + perfdata_calc(&perf1); + perfdata_calc(&perf2); + perfdata_calc(&perf3); +#ifdef PRINT_ALL +#ifdef READER_HIGH + perfdata_all(&perf1); +#else + perfdata_all(&perf2); +#endif + perfdata_all(&perf3); +#else +#ifdef READER_HIGH + perfdata_print(&perf1); +#else + perfdata_print(&perf2); +#endif + perfdata_print(&perf3); +#endif + + while (1) + ; +} + +void +cos_init(void) +{ + perfdata_init(&perf1, "IPC channel - reader high use this", result1, ITERATION); + perfdata_init(&perf2, "IPC channel - writer high use this", result2, ITERATION); + perfdata_init(&perf3, "IPC channel - roundtrip", result3, ITERATION); + + printc("Component chan sender initializing:\n\tJoin channel %d\n", TEST_CHAN_SEND_ID); + sid = patina_channel_retrieve_send(TEST_CHAN_ITEM_SZ, TEST_CHAN_NSLOTS, TEST_CHAN_SEND_ID); + + printc("\tJoin channel %d\n", TEST_CHAN_RECV_ID); + rid = patina_channel_retrieve_recv(TEST_CHAN_ITEM_SZ, TEST_CHAN_NSLOTS, TEST_CHAN_RECV_ID); + + printc("\tPriority %d for self!\n", TEST_CHAN_PRIO_SELF); + if (sched_thd_param_set(cos_thdid(), sched_param_pack(SCHEDP_PRIO, TEST_CHAN_PRIO_SELF))) { + printc("sched_thd_param_set failed.\n"); + BUG(); + } +} diff --git a/src/composer/patina_chan_bench.toml b/src/composer/patina_chan_bench.toml new file mode 100644 index 0000000000..d8465ec3c0 --- /dev/null +++ b/src/composer/patina_chan_bench.toml @@ -0,0 +1,52 @@ +[system] +description = "Simplest system with crt tests." + +[[components]] +name = "booter" +img = "no_interface.llbooter" +implements = [{interface = "init"}, {interface = "addr"}] +deps = [{srv = "kernel", interface = "init", variant = "kernel"}] +constructor = "kernel" + +[[components]] +name = "capmgr" +img = "capmgr.simple" +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] +constructor = "booter" + +[[components]] +name = "sched" +img = "sched.root_fprr" +deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}] +implements = [{interface = "sched"}, {interface = "init"}] +constructor = "booter" + +[[components]] +name = "chanmgr" +img = "chanmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "capmgr"}] +implements = [{interface = "chanmgr"}, {interface = "chanmgr_evt"}] +constructor = "booter" + +[[components]] +name = "evtmgr" +img = "evt.evtmgr" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}] +implements = [{interface = "evt"}] +constructor = "booter" + +[[components]] +name = "tmrmgr" +img = "tmrmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "evtmgr", interface = "evt"}] +implements = [{interface = "tmrmgr"}] +constructor = "booter" + +[[components]] +name = "tests" +img = "tests.patina_chan_bench" +implements = [{interface = "init"}] +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" diff --git a/src/composer/patina_chan_bench_inter.toml b/src/composer/patina_chan_bench_inter.toml new file mode 100644 index 0000000000..8a6037c160 --- /dev/null +++ b/src/composer/patina_chan_bench_inter.toml @@ -0,0 +1,58 @@ +[system] +description = "Simplest system with crt tests." + +[[components]] +name = "booter" +img = "no_interface.llbooter" +implements = [{interface = "init"}, {interface = "addr"}] +deps = [{srv = "kernel", interface = "init", variant = "kernel"}] +constructor = "kernel" + +[[components]] +name = "capmgr" +img = "capmgr.simple" +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] +constructor = "booter" + +[[components]] +name = "sched" +img = "sched.root_fprr" +deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}] +implements = [{interface = "sched"}, {interface = "init"}] +constructor = "booter" + +[[components]] +name = "chanmgr" +img = "chanmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "capmgr"}] +implements = [{interface = "chanmgr"}, {interface = "chanmgr_evt"}] +constructor = "booter" + +[[components]] +name = "evtmgr" +img = "evt.evtmgr" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}] +implements = [{interface = "evt"}] +constructor = "booter" + +[[components]] +name = "tmrmgr" +img = "tmrmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "evtmgr", interface = "evt"}] +implements = [{interface = "tmrmgr"}] +constructor = "booter" + +[[components]] +name = "chan_snd" +img = "tests.patina_chan_bench_inter_send" +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" + +[[components]] +name = "chan_rcv" +img = "tests.patina_chan_bench_inter_recv" +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" From 2752cd9f8b8a1f7eb308d42574f29c1373a77161 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 04:39:14 +0800 Subject: [PATCH 03/13] patina_bench: Implement initial benchmarking for patina_mutex Signed-off-by: msdx321 --- .../tests/patina_mutex_bench/Makefile | 18 ++ .../patina_mutex_bench/patina_mutex_bench.c | 155 ++++++++++++++++++ src/composer/patina_mutex_bench.toml | 52 ++++++ 3 files changed, 225 insertions(+) create mode 100644 src/components/implementation/tests/patina_mutex_bench/Makefile create mode 100644 src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c create mode 100644 src/composer/patina_mutex_bench.toml diff --git a/src/components/implementation/tests/patina_mutex_bench/Makefile b/src/components/implementation/tests/patina_mutex_bench/Makefile new file mode 100644 index 0000000000..70ed7df4c4 --- /dev/null +++ b/src/components/implementation/tests/patina_mutex_bench/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c new file mode 100644 index 0000000000..c9371475dc --- /dev/null +++ b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c @@ -0,0 +1,155 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include + +#include +#include + +#undef LOCK_TRACE_DEBUG +#ifdef LOCK_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +/* One low-priority thread and one high-priority thread contends on the lock */ +#define ITERATION 10 * 1000 +#undef PRINT_ALL + +patina_mutex_t mid; +thdid_t lock_hi = 0, lock_lo = 0; +volatile int flag = 0; + +volatile cycles_t start; +volatile cycles_t end; + +struct perfdata perf; +cycles_t result[ITERATION] = { + 0, +}; + +/*** + * The high priority thread periodically challenges the lock while the low priority thread keeps spinning. + * When the low-priority thread detects that the flag is changed, it knows that the lock is challenged. + * Execution: hi take -> lo release -> hi release, there is 1 contended take, 1 release, and 2 ctxsws. + */ +void +lock_hi_thd(void *d) +{ + /* Never stops running; low priority controls how many iters to run. */ + while (1) { + debug("h1,"); + sched_thd_block(0); + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000)); + + debug("h2,"); + flag = 1; + start = time_now(); + patina_mutex_lock(mid); + patina_mutex_unlock(mid); + + end = time_now(); + debug("h3,"); + } +} + +void +lock_lo_thd(void *d) +{ + int i; + int first = 0; + + for (i = 0; i < ITERATION + 1; i++) { + debug("l1,"); + sched_thd_wakeup(lock_hi); + + debug("l2,"); + flag = 0; + patina_mutex_lock(mid); + + debug("l3,"); + while (flag != 1) {} + patina_mutex_unlock(mid); + + if (first == 0) + first = 1; + else + perfdata_add(&perf, end - start); + debug("l4,"); + } + + perfdata_calc(&perf); +#ifdef PRINT_ALL + perfdata_all(&perf); +#else + perfdata_print(&perf); +#endif + + while (1) + ; +} + +void +test_lock(void) +{ + int i; + int first = 0; + + sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; + + mid = patina_mutex_create(0); + + /* Uncontended lock taking/releasing */ + perfdata_init(&perf, "Uncontended lock - take+release", result, ITERATION); + for (i = 0; i < ITERATION + 1; i++) { + start = time_now(); + + patina_mutex_lock(mid); + patina_mutex_unlock(mid); + + end = time_now(); + if (first == 0) + first = 1; + else + perfdata_add(&perf, end - start); + } + perfdata_calc(&perf); +#ifdef PRINT_ALL + perfdata_all(&perf); +#else + perfdata_print(&perf); +#endif + + perfdata_init(&perf, "Contended lock - take+release", result, ITERATION); + + printc("Create threads:\n"); + + lock_lo = sched_thd_create(lock_lo_thd, NULL); + printc("\tcreating lo thread %d at prio %d\n", lock_lo, sps[1]); + sched_thd_param_set(lock_lo, sps[1]); + + lock_hi = sched_thd_create(lock_hi_thd, NULL); + printc("\tcreating hi thread %d at prio %d\n", lock_hi, sps[0]); + sched_thd_param_set(lock_hi, sps[0]); +} + +void +cos_init(void) +{ + printc("Benchmark for the crt_lock (w/sched interface).\n"); +} + +int +main(void) +{ + test_lock(); + + printc("Running benchmark, exiting main thread...\n"); + + return 0; +} diff --git a/src/composer/patina_mutex_bench.toml b/src/composer/patina_mutex_bench.toml new file mode 100644 index 0000000000..d1748b1e68 --- /dev/null +++ b/src/composer/patina_mutex_bench.toml @@ -0,0 +1,52 @@ +[system] +description = "Simplest system with crt tests." + +[[components]] +name = "booter" +img = "no_interface.llbooter" +implements = [{interface = "init"}, {interface = "addr"}] +deps = [{srv = "kernel", interface = "init", variant = "kernel"}] +constructor = "kernel" + +[[components]] +name = "capmgr" +img = "capmgr.simple" +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] +constructor = "booter" + +[[components]] +name = "sched" +img = "sched.root_fprr" +deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}] +implements = [{interface = "sched"}, {interface = "init"}] +constructor = "booter" + +[[components]] +name = "chanmgr" +img = "chanmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "capmgr"}] +implements = [{interface = "chanmgr"}, {interface = "chanmgr_evt"}] +constructor = "booter" + +[[components]] +name = "evtmgr" +img = "evt.evtmgr" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}] +implements = [{interface = "evt"}] +constructor = "booter" + +[[components]] +name = "tmrmgr" +img = "tmrmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "evtmgr", interface = "evt"}] +implements = [{interface = "tmrmgr"}] +constructor = "booter" + +[[components]] +name = "tests" +img = "tests.patina_mutex_bench" +implements = [{interface = "init"}] +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" From a35e8f0be1fed3053706e626aca242a438b2fedf Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 04:40:17 +0800 Subject: [PATCH 04/13] patina_bench: Implement initial benchmarking for patina_sem Signed-off-by: msdx321 --- .../tests/patina_sem_bench/Makefile | 18 ++ .../tests/patina_sem_bench/patina_sem_bench.c | 158 ++++++++++++++++++ src/composer/patina_sem_bench.toml | 52 ++++++ 3 files changed, 228 insertions(+) create mode 100644 src/components/implementation/tests/patina_sem_bench/Makefile create mode 100644 src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c create mode 100644 src/composer/patina_sem_bench.toml diff --git a/src/components/implementation/tests/patina_sem_bench/Makefile b/src/components/implementation/tests/patina_sem_bench/Makefile new file mode 100644 index 0000000000..70ed7df4c4 --- /dev/null +++ b/src/components/implementation/tests/patina_sem_bench/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c new file mode 100644 index 0000000000..4e740c571f --- /dev/null +++ b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c @@ -0,0 +1,158 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include + +#include +#include + +#undef SEM_TRACE_DEBUG +#ifdef SEM_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +/* One low-priority thread and one high-priority thread contends on the semaphore */ +#define ITERATION 10 * 1000 +#undef PRINT_ALL + +patina_sem_t sid; +thdid_t sem_hi = 0, sem_lo = 0; +volatile int flag = 0; + +volatile cycles_t start; +volatile cycles_t end; + +struct perfdata perf; +cycles_t result[ITERATION] = { + 0, +}; + +/*** + * The high priority thread periodically challenges the sem while the low priority thread keeps spinning. + * When the low-priority thread detects that the flag is changed, it knows that the sem is challenged. + * Execution: hi take -> lo release -> hi release, there is 1 contended take, 1 give, and 2 ctxsws. + */ +void +sem_hi_thd(void *d) +{ + /* Never stops running; low priority controls how many iters to run. */ + while (1) { + debug("h1"); + sched_thd_block(0); + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000)); + + debug("h2"); + flag = 1; + start = time_now(); + + patina_sem_take(sid); + patina_sem_give(sid); + + end = time_now(); + debug("h3"); + } +} + +void +sem_lo_thd(void *d) +{ + int i; + int first = 0; + + for (i = 0; i < ITERATION + 1; i++) { + debug("l1"); + sched_thd_wakeup(sem_hi); + + debug("l2"); + flag = 0; + patina_sem_take(sid); + + debug("l3"); + while (flag != 1) {} + + patina_sem_give(sid); + + if (first == 0) + first = 1; + else + perfdata_add(&perf, end - start); + debug("l4"); + } + + perfdata_calc(&perf); +#ifdef PRINT_ALL + perfdata_all(&perf); +#else + perfdata_print(&perf); +#endif + + while (1) + ; +} + +void +test_sem(void) +{ + int i; + int first = 0; + cycles_t start, end; + + sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; + + sid = patina_sem_create(1, 0); + + /* Uncontended semaphore taking/releasing */ + perfdata_init(&perf, "Uncontended semaphore - take+give", result, ITERATION); + for (i = 0; i < ITERATION + 1; i++) { + start = time_now(); + + patina_sem_take(sid); + patina_sem_give(sid); + + end = time_now(); + if (first == 0) + first = 1; + else + perfdata_add(&perf, end - start); + } + perfdata_calc(&perf); +#ifdef PRINT_ALL + perfdata_all(&perf); +#else + perfdata_print(&perf); +#endif + + perfdata_init(&perf, "Contended semaphore - take+give", result, ITERATION); + + printc("Create threads:\n"); + + sem_lo = sched_thd_create(sem_lo_thd, NULL); + printc("\tcreating lo thread %d at prio %d\n", sem_lo, sps[1]); + sched_thd_param_set(sem_lo, sps[1]); + + sem_hi = sched_thd_create(sem_hi_thd, NULL); + printc("\tcreating hi thread %d at prio %d\n", sem_hi, sps[0]); + sched_thd_param_set(sem_hi, sps[0]); +} + +void +cos_init(void) +{ + printc("Benchmark for the crt_sem (w/sched interface).\n"); +} + +int +main(void) +{ + test_sem(); + + printc("Running benchmark, exiting main thread...\n"); + + return 0; +} diff --git a/src/composer/patina_sem_bench.toml b/src/composer/patina_sem_bench.toml new file mode 100644 index 0000000000..e234496179 --- /dev/null +++ b/src/composer/patina_sem_bench.toml @@ -0,0 +1,52 @@ +[system] +description = "Simplest system with crt tests." + +[[components]] +name = "booter" +img = "no_interface.llbooter" +implements = [{interface = "init"}, {interface = "addr"}] +deps = [{srv = "kernel", interface = "init", variant = "kernel"}] +constructor = "kernel" + +[[components]] +name = "capmgr" +img = "capmgr.simple" +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] +constructor = "booter" + +[[components]] +name = "sched" +img = "sched.root_fprr" +deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}] +implements = [{interface = "sched"}, {interface = "init"}] +constructor = "booter" + +[[components]] +name = "chanmgr" +img = "chanmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "capmgr"}] +implements = [{interface = "chanmgr"}, {interface = "chanmgr_evt"}] +constructor = "booter" + +[[components]] +name = "evtmgr" +img = "evt.evtmgr" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}] +implements = [{interface = "evt"}] +constructor = "booter" + +[[components]] +name = "tmrmgr" +img = "tmrmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "evtmgr", interface = "evt"}] +implements = [{interface = "tmrmgr"}] +constructor = "booter" + +[[components]] +name = "tests" +img = "tests.patina_sem_bench" +implements = [{interface = "init"}] +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" From 4c93731c60355ae034ccb502adc92e877485aeb9 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 04:42:10 +0800 Subject: [PATCH 05/13] patina_bench: Implement initial benchmarking for patina_timer Signed-off-by: msdx321 --- .../tests/patina_timer_bench/Makefile | 18 +++ .../tests/patina_timer_bench/bench_tmr.c | 138 ++++++++++++++++++ src/composer/patina_timer_bench.toml | 52 +++++++ 3 files changed, 208 insertions(+) create mode 100644 src/components/implementation/tests/patina_timer_bench/Makefile create mode 100644 src/components/implementation/tests/patina_timer_bench/bench_tmr.c create mode 100644 src/composer/patina_timer_bench.toml diff --git a/src/components/implementation/tests/patina_timer_bench/Makefile b/src/components/implementation/tests/patina_timer_bench/Makefile new file mode 100644 index 0000000000..70ed7df4c4 --- /dev/null +++ b/src/components/implementation/tests/patina_timer_bench/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_timer_bench/bench_tmr.c b/src/components/implementation/tests/patina_timer_bench/bench_tmr.c new file mode 100644 index 0000000000..1dbcd0a82b --- /dev/null +++ b/src/components/implementation/tests/patina_timer_bench/bench_tmr.c @@ -0,0 +1,138 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include + +#include +#include + +#undef TMR_TRACE_DEBUG +#ifdef TMR_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +/* High-priority thread interrupts the low-priority thread by timer ticks */ +#define ITERATION 10 * 1000 +#define TMR_PERIODIC_TIME 10 * 1000 +#define DROP_THRESHOLD 0x1000000U + +#undef PRINT_ALL + +thdid_t tmr_hi = 0, tmr_lo = 0; + +typedef unsigned int cycles_32_t; +volatile cycles_32_t start; +volatile cycles_32_t end; + +struct perfdata perf; +cycles_t result[ITERATION] = { + 0, +}; + +/*** + * The high priority thread sets up a periodic timer while the low priority thread keeps looping and updating + * the timing value variable. The variable is a 32-bit one so that it can be updated atomically. We always + * drop values larger than DROP_THRESHOLD (clearly impossible; appears due to counter overflow). + */ +void +tmr_hi_thd(void *d) +{ + int i; + patina_time_t t; + patina_timer_t tid; + patina_event_t evt; + int first = 0; + + printc("Call into timer manager to make a timer.\n"); + tid = patina_timer_create(); + + printc("Call into event manager to make a event.\n"); + patina_event_create(&evt, 1); + + /* + * Add the timer event to the event set, the associate the timer with that event ID so + * the timer manager knows which event to trigger when the timer expires. + */ + patina_event_add(&evt, tid, 0); + + /* Start the timer */ + patina_time_create(&t, 0, TMR_PERIODIC_TIME); + patina_timer_periodic(tid, NULL, &t); + + /* Event loop */ + i = 0; + while (i < ITERATION + 1) { + patina_event_wait(&evt, NULL, 0); + end = (cycles_32_t)time_now(); + + if ((end - start) > DROP_THRESHOLD) continue; + + if (first == 0) + first = 1; + else + perfdata_add(&perf, end - start); + debug("%lld.\n", end - start); + + i++; + } + + perfdata_calc(&perf); +#ifdef PRINT_ALL + perfdata_all(&perf); +#else + perfdata_print(&perf); +#endif + + while (1) + ; +} + +void +tmr_lo_thd(void *d) +{ + /* Runs indefinitely */ + while (1) { start = (cycles_32_t)time_now(); } +} + +void +test_tmr(void) +{ + int i; + + sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; + + + perfdata_init(&perf, "Timer latency - total", result, ITERATION); + + printc("Create threads:\n"); + + tmr_lo = sched_thd_create(tmr_lo_thd, NULL); + printc("\tcreating lo thread %d at prio %d\n", tmr_lo, sps[1]); + sched_thd_param_set(tmr_lo, sps[1]); + + tmr_hi = sched_thd_create(tmr_hi_thd, NULL); + printc("\tcreating hi thread %d at prio %d\n", tmr_hi, sps[0]); + sched_thd_param_set(tmr_hi, sps[0]); +} + +void +cos_init(void) +{ + printc("Benchmark for the tmrmgr (w/sched & evt interface).\n"); +} + +int +main(void) +{ + test_tmr(); + + printc("Running benchmark, exiting main thread...\n"); + + return 0; +} diff --git a/src/composer/patina_timer_bench.toml b/src/composer/patina_timer_bench.toml new file mode 100644 index 0000000000..096098214b --- /dev/null +++ b/src/composer/patina_timer_bench.toml @@ -0,0 +1,52 @@ +[system] +description = "Simplest system with crt tests." + +[[components]] +name = "booter" +img = "no_interface.llbooter" +implements = [{interface = "init"}, {interface = "addr"}] +deps = [{srv = "kernel", interface = "init", variant = "kernel"}] +constructor = "kernel" + +[[components]] +name = "capmgr" +img = "capmgr.simple" +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] +constructor = "booter" + +[[components]] +name = "sched" +img = "sched.root_fprr" +deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}] +implements = [{interface = "sched"}, {interface = "init"}] +constructor = "booter" + +[[components]] +name = "chanmgr" +img = "chanmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "capmgr"}] +implements = [{interface = "chanmgr"}, {interface = "chanmgr_evt"}] +constructor = "booter" + +[[components]] +name = "evtmgr" +img = "evt.evtmgr" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}] +implements = [{interface = "evt"}] +constructor = "booter" + +[[components]] +name = "tmrmgr" +img = "tmrmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "evtmgr", interface = "evt"}] +implements = [{interface = "tmrmgr"}] +constructor = "booter" + +[[components]] +name = "tests" +img = "tests.patina_timer_bench" +implements = [{interface = "init"}] +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" From 5d2b74aef9553c45b609bed486d3c10e73430689 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 05:14:36 +0800 Subject: [PATCH 06/13] patina_bench: Implement initial benchmarking for patina_event Signed-off-by: msdx321 --- .../tests/patina_event_bench/Makefile | 18 +++ .../patina_event_bench/patina_event_bench.c | 123 ++++++++++++++++++ src/components/lib/patina/patina_evt.c | 2 +- src/components/lib/patina/patina_evt.h | 3 + src/composer/patina_event_bench.toml | 52 ++++++++ 5 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/components/implementation/tests/patina_event_bench/Makefile create mode 100644 src/components/implementation/tests/patina_event_bench/patina_event_bench.c create mode 100644 src/composer/patina_event_bench.toml diff --git a/src/components/implementation/tests/patina_event_bench/Makefile b/src/components/implementation/tests/patina_event_bench/Makefile new file mode 100644 index 0000000000..70ed7df4c4 --- /dev/null +++ b/src/components/implementation/tests/patina_event_bench/Makefile @@ -0,0 +1,18 @@ +# Required variables used to drive the compilation process. It is OK +# for many of these to be empty. +# +# The set of interfaces that this component exports for use by other +# components. This is a list of the interface names. +INTERFACE_EXPORTS = +# The interfaces this component is dependent on for compilation (this +# is a list of directory names in interface/) +INTERFACE_DEPENDENCIES = +# The library dependencies this component is reliant on for +# compilation/linking (this is a list of directory names in lib/) +LIBRARY_DEPENDENCIES = component patina ubench +# Note: Both the interface and library dependencies should be +# *minimal*. That is to say that removing a dependency should cause +# the build to fail. The build system does not validate this +# minimality; that's on you! + +include Makefile.subsubdir diff --git a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c new file mode 100644 index 0000000000..31e7e6c0a3 --- /dev/null +++ b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c @@ -0,0 +1,123 @@ +/* + * Copyright 2020, Bite Ye, Runyu Pan and Gabriel Parmer, GWU, gparmer@gwu.edu. + * + * This uses a two clause BSD License. + */ + +#include +#include + +#include +#include + +#undef EVENT_TRACE_DEBUG +#ifdef EVENT_TRACE_DEBUG +#define debug(format, ...) printc(format, ##__VA_ARGS__) +#else +#define debug(format, ...) +#endif + +#define ITERATION 10 * 1000 +#undef PRINT_ALL + +patina_sem_t sid; +patina_event_t evt; +evt_res_id_t rid; + +thdid_t evt_hi = 0, evt_lo = 0; +volatile int flag = 0; + +volatile cycles_t start; +volatile cycles_t end; + +struct perfdata perf; +cycles_t result[ITERATION] = { + 0, +}; + +void +evt_hi_thd(void *d) +{ + int i; + int first = 0; + + for (i = 0; i < ITERATION + 1; i++) { + debug("h1"); + patina_event_wait(&evt, NULL, 0); + end = time_now(); + + debug("h2"); + if (first == 0) + first = 1; + else + perfdata_add(&perf, end - start); + + debug("h3"); + patina_sem_give(sid); + } + + perfdata_calc(&perf); +#ifdef PRINT_ALL + perfdata_all(&perf); +#else + perfdata_print(&perf); +#endif + + while (1) + ; +} + +void +evt_lo_thd(void *d) +{ + while (1) { + debug("l1"); + start = time_now(); + patina_event_debug_trigger(rid); + + debug("l2"); + patina_sem_take(sid); + } +} + +void +test_evt(void) +{ + int i; + int first = 0; + cycles_t start, end; + + sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; + + sid = patina_sem_create(0, 0); + patina_event_create(&evt, 1); + rid = patina_event_debug_fake_add(&evt); + + perfdata_init(&perf, "Event latency - total", result, ITERATION); + + printc("Create threads:\n"); + + evt_lo = sched_thd_create(evt_lo_thd, NULL); + printc("\tcreating lo thread %d at prio %d\n", evt_lo, sps[1]); + sched_thd_param_set(evt_lo, sps[1]); + + evt_hi = sched_thd_create(evt_hi_thd, NULL); + printc("\tcreating hi thread %d at prio %d\n", evt_hi, sps[0]); + sched_thd_param_set(evt_hi, sps[0]); +} + +void +cos_init(void) +{ + printc("Benchmark for the event (w/sched interface).\n"); +} + +int +main(void) +{ + test_evt(); + + printc("Running benchmark, exiting main thread...\n"); + + return 0; +} diff --git a/src/components/lib/patina/patina_evt.c b/src/components/lib/patina/patina_evt.c index e6e149c3c2..cf83e41b6c 100644 --- a/src/components/lib/patina/patina_evt.c +++ b/src/components/lib/patina/patina_evt.c @@ -197,4 +197,4 @@ patina_event_debug_trigger(evt_res_id_t rid) assert(rid); return evt_trigger(rid); -} \ No newline at end of file +} diff --git a/src/components/lib/patina/patina_evt.h b/src/components/lib/patina/patina_evt.h index 956a1274fc..4179720afa 100644 --- a/src/components/lib/patina/patina_evt.h +++ b/src/components/lib/patina/patina_evt.h @@ -22,4 +22,7 @@ int patina_event_delete(patina_event_t *eid); int patina_event_wait(patina_event_t *eid, struct patina_event_info events[], size_t num); int patina_event_check(patina_event_t *eid, struct patina_event_info events[], size_t num); +evt_res_id_t patina_event_debug_fake_add(patina_event_t *eid); +int patina_event_debug_trigger(evt_res_id_t rid); + #endif diff --git a/src/composer/patina_event_bench.toml b/src/composer/patina_event_bench.toml new file mode 100644 index 0000000000..dbb73615b9 --- /dev/null +++ b/src/composer/patina_event_bench.toml @@ -0,0 +1,52 @@ +[system] +description = "Simplest system with crt tests." + +[[components]] +name = "booter" +img = "no_interface.llbooter" +implements = [{interface = "init"}, {interface = "addr"}] +deps = [{srv = "kernel", interface = "init", variant = "kernel"}] +constructor = "kernel" + +[[components]] +name = "capmgr" +img = "capmgr.simple" +deps = [{srv = "booter", interface = "init"}, {srv = "booter", interface = "addr"}] +implements = [{interface = "capmgr"}, {interface = "init"}, {interface = "memmgr"}, {interface = "capmgr_create"}] +constructor = "booter" + +[[components]] +name = "sched" +img = "sched.root_fprr" +deps = [{srv = "capmgr", interface = "init"}, {srv = "capmgr", interface = "capmgr"}, {srv = "capmgr", interface = "memmgr"}] +implements = [{interface = "sched"}, {interface = "init"}] +constructor = "booter" + +[[components]] +name = "chanmgr" +img = "chanmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "capmgr", interface = "capmgr"}] +implements = [{interface = "chanmgr"}, {interface = "chanmgr_evt"}] +constructor = "booter" + +[[components]] +name = "evtmgr" +img = "evt.evtmgr" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}] +implements = [{interface = "evt"}] +constructor = "booter" + +[[components]] +name = "tmrmgr" +img = "tmrmgr.simple" +deps = [{srv = "sched", interface = "init"}, {srv = "sched", interface = "sched"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "evtmgr", interface = "evt"}] +implements = [{interface = "tmrmgr"}] +constructor = "booter" + +[[components]] +name = "tests" +img = "tests.patina_event_bench" +implements = [{interface = "init"}] +deps = [{srv = "sched", interface = "sched"}, {srv = "sched", interface = "init"}, {srv = "capmgr", interface = "capmgr_create"}, {srv = "capmgr", interface = "memmgr"}, {srv = "evtmgr", interface = "evt"}, {srv = "tmrmgr", interface = "tmrmgr"}, {srv = "chanmgr", interface = "chanmgr"}, {srv = "chanmgr", interface = "chanmgr_evt"}] +baseaddr = "0x1600000" +constructor = "booter" From d7138f64e701bc0b4a9aefa5ab1e1226aaf98823 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Fri, 16 Oct 2020 17:07:48 +0800 Subject: [PATCH 07/13] patina_bench: Delay the benches by 1s Signed-off-by: msdx321 --- .../tests/patina_event_bench/patina_event_bench.c | 2 ++ .../tests/patina_mutex_bench/patina_mutex_bench.c | 2 ++ .../implementation/tests/patina_sem_bench/patina_sem_bench.c | 2 ++ .../implementation/tests/patina_timer_bench/bench_tmr.c | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c index 31e7e6c0a3..6ff6776433 100644 --- a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c +++ b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c @@ -115,6 +115,8 @@ cos_init(void) int main(void) { + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000 * 1000)); + test_evt(); printc("Running benchmark, exiting main thread...\n"); diff --git a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c index c9371475dc..1d150d6234 100644 --- a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c +++ b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c @@ -147,6 +147,8 @@ cos_init(void) int main(void) { + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000 * 1000)); + test_lock(); printc("Running benchmark, exiting main thread...\n"); diff --git a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c index 4e740c571f..dff2b4264a 100644 --- a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c +++ b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c @@ -150,6 +150,8 @@ cos_init(void) int main(void) { + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000 * 1000)); + test_sem(); printc("Running benchmark, exiting main thread...\n"); diff --git a/src/components/implementation/tests/patina_timer_bench/bench_tmr.c b/src/components/implementation/tests/patina_timer_bench/bench_tmr.c index 1dbcd0a82b..78aa1a1263 100644 --- a/src/components/implementation/tests/patina_timer_bench/bench_tmr.c +++ b/src/components/implementation/tests/patina_timer_bench/bench_tmr.c @@ -130,6 +130,8 @@ cos_init(void) int main(void) { + sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000 * 1000)); + test_tmr(); printc("Running benchmark, exiting main thread...\n"); From ccc03b8c3b3eee4585cf5504442eaa79872fd4b3 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Sat, 17 Oct 2020 02:29:51 +0800 Subject: [PATCH 08/13] patina_bench: event: Implement event variant Signed-off-by: msdx321 --- .../patina_chan_bench_inter_recv.c | 16 +++++++--------- .../patina_chan_bench_inter_send.c | 16 +++++++--------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c b/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c index 929f69aec4..267e074879 100644 --- a/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c +++ b/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c @@ -19,11 +19,11 @@ patina_chan_s_t sid; patina_chan_r_t rid; -struct evt e; +patina_event_t evt; /* Keep these settings below consistent with the sender side */ #undef READER_HIGH -#undef USE_EVTMGR +#define USE_EVTMGR #define TEST_CHAN_ITEM_SZ sizeof(u32_t) #define TEST_CHAN_NSLOTS 2 @@ -53,10 +53,8 @@ main(void) /* See if event manager is in use. If yes, log the receiver channel into it */ #ifdef USE_EVTMGR - assert(evt_init(&e, 2) == 0); - evt_id = evt_add(&e, 0, (evt_res_data_t)&r); - assert(evt_id != 0); - assert(chan_rcv_evt_associate(&r, evt_id) == 0); + patina_event_create(&evt, 1); + patina_event_add(&evt, rid, 0); printc("Receiver side event created.\n"); #endif @@ -67,7 +65,7 @@ main(void) * Likely because this helps the priority change in cos_init take effect! * Or because this lets the initialization of both ends of channels complete before tests start! */ - wakeup = time_now() + time_usec2cyc(100 * 1000); + wakeup = time_now() + time_usec2cyc(1000 * 1000); sched_thd_block_timeout(0, wakeup); /* Never stops running; sender controls how many iters to run. */ @@ -75,8 +73,8 @@ main(void) debug("r1,"); #ifdef USE_EVTMGR /* Receive from the events then the channel */ - while (chan_recv(&r, &tmp, CHAN_NONBLOCKING) == CHAN_TRY_AGAIN) - evt_get(&e, EVT_WAIT_DEFAULT, &evtsrc, &evtdata); + while (patina_channel_recv(rid, &tmp, 1, CHAN_NONBLOCKING) == CHAN_TRY_AGAIN) + patina_event_wait(&evt, NULL, 0); #else patina_channel_recv(rid, &tmp, 1, 0); #endif diff --git a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c index 69691edd88..b1a529cbea 100644 --- a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c +++ b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c @@ -19,11 +19,11 @@ patina_chan_s_t sid; patina_chan_r_t rid; -struct evt e; +patina_event_t evt; #define ITERATION 10 * 1000 #undef READER_HIGH -#undef USE_EVTMGR +#define USE_EVTMGR /* #define PRINT_ALL */ #define TEST_CHAN_ITEM_SZ sizeof(u32_t) @@ -68,10 +68,8 @@ main(void) /* Send data to receiver so it can register for channels */ #ifdef USE_EVTMGR - assert(evt_init(&e, 2) == 0); - evt_id = evt_add(&e, 0, (evt_res_data_t)&r); - assert(evt_id != 0); - assert(chan_rcv_evt_associate(&r, evt_id) == 0); + patina_event_create(&evt, 1); + patina_event_add(&evt, rid, 0); printc("Sender side event created.\n"); #endif @@ -82,7 +80,7 @@ main(void) * Likely because this helps the priority change in cos_init take effect! * Or because this lets the initialization of both ends of channels complete before tests start! */ - wakeup = time_now() + time_usec2cyc(100 * 1000); + wakeup = time_now() + time_usec2cyc(1000 * 1000); sched_thd_block_timeout(0, wakeup); for (int i = 0; i < ITERATION + 1; i++) { @@ -94,8 +92,8 @@ main(void) debug("w3,"); #ifdef USE_EVTMGR /* Receive from the events then the channel */ - while (chan_recv(&r, &ts2, CHAN_NONBLOCKING) == CHAN_TRY_AGAIN) - evt_get(&e, EVT_WAIT_DEFAULT, &evtsrc, &evtdata); + while (patina_channel_recv(rid, &ts2, 1, CHAN_NONBLOCKING) == CHAN_TRY_AGAIN) + patina_event_wait(&evt, NULL, 0); #else patina_channel_recv(rid, &ts2, 1, 0); #endif From d6c05394b528fcfbcce00f6cbf8ddcbb576ee279 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Sat, 17 Oct 2020 02:56:19 +0800 Subject: [PATCH 09/13] patina_bench: Print all results for CDFs Signed-off-by: msdx321 --- .../tests/patina_chan_bench/patina_chan_bench.c | 4 ++-- .../patina_chan_bench_inter_send.c | 2 +- .../tests/patina_event_bench/patina_event_bench.c | 2 +- .../tests/patina_mutex_bench/patina_mutex_bench.c | 2 +- .../implementation/tests/patina_sem_bench/patina_sem_bench.c | 2 +- .../implementation/tests/patina_timer_bench/bench_tmr.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c b/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c index 8412fdbe75..8856ce9467 100644 --- a/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c +++ b/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c @@ -18,8 +18,8 @@ #endif /* One low-priority thread and one high-priority thread contends on the lock */ -#define ITERATION 10 * 10 -/* #define PRINT_ALL */ +#define ITERATION 10 * 1000 +#define PRINT_ALL /* Two options are available: Sender at low/high prio, data words 4 */ #undef READER_HIGH diff --git a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c index b1a529cbea..40dc28eeb2 100644 --- a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c +++ b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c @@ -24,7 +24,7 @@ patina_event_t evt; #define ITERATION 10 * 1000 #undef READER_HIGH #define USE_EVTMGR -/* #define PRINT_ALL */ +#define PRINT_ALL #define TEST_CHAN_ITEM_SZ sizeof(u32_t) #define TEST_CHAN_NSLOTS 2 diff --git a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c index 6ff6776433..e0baac548c 100644 --- a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c +++ b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c @@ -18,7 +18,7 @@ #endif #define ITERATION 10 * 1000 -#undef PRINT_ALL +#define PRINT_ALL patina_sem_t sid; patina_event_t evt; diff --git a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c index 1d150d6234..7a1b5cebbf 100644 --- a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c +++ b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c @@ -19,7 +19,7 @@ /* One low-priority thread and one high-priority thread contends on the lock */ #define ITERATION 10 * 1000 -#undef PRINT_ALL +#define PRINT_ALL patina_mutex_t mid; thdid_t lock_hi = 0, lock_lo = 0; diff --git a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c index dff2b4264a..23c7030f60 100644 --- a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c +++ b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c @@ -19,7 +19,7 @@ /* One low-priority thread and one high-priority thread contends on the semaphore */ #define ITERATION 10 * 1000 -#undef PRINT_ALL +#define PRINT_ALL patina_sem_t sid; thdid_t sem_hi = 0, sem_lo = 0; diff --git a/src/components/implementation/tests/patina_timer_bench/bench_tmr.c b/src/components/implementation/tests/patina_timer_bench/bench_tmr.c index 78aa1a1263..8d475cc300 100644 --- a/src/components/implementation/tests/patina_timer_bench/bench_tmr.c +++ b/src/components/implementation/tests/patina_timer_bench/bench_tmr.c @@ -22,7 +22,7 @@ #define TMR_PERIODIC_TIME 10 * 1000 #define DROP_THRESHOLD 0x1000000U -#undef PRINT_ALL +#define PRINT_ALL thdid_t tmr_hi = 0, tmr_lo = 0; From be22c1f5ebbec6067fdaf44e1d9698f7ee379d4e Mon Sep 17 00:00:00 2001 From: msdx321 Date: Tue, 20 Oct 2020 06:23:21 +0800 Subject: [PATCH 10/13] patina_bench: Fix file name for patina_timer_bench Signed-off-by: msdx321 --- .../patina_timer_bench/{bench_tmr.c => patina_timer_bench.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/components/implementation/tests/patina_timer_bench/{bench_tmr.c => patina_timer_bench.c} (100%) diff --git a/src/components/implementation/tests/patina_timer_bench/bench_tmr.c b/src/components/implementation/tests/patina_timer_bench/patina_timer_bench.c similarity index 100% rename from src/components/implementation/tests/patina_timer_bench/bench_tmr.c rename to src/components/implementation/tests/patina_timer_bench/patina_timer_bench.c From 2147dfacf618d79228cffaa45124f89af5815030 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Tue, 20 Oct 2020 07:48:02 +0800 Subject: [PATCH 11/13] perfdata: Add perfdata_raw() Signed-off-by: msdx321 --- src/components/lib/ubench/perfdata.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/components/lib/ubench/perfdata.h b/src/components/lib/ubench/perfdata.h index 73936a84d5..b60bcbb11e 100644 --- a/src/components/lib/ubench/perfdata.h +++ b/src/components/lib/ubench/perfdata.h @@ -248,4 +248,18 @@ perfdata_all(struct perfdata *pd) printc("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); } +static void +perfdata_raw(struct perfdata *pd) +{ + int i; + + printc("#PD:%s\n", pd->name); + printc("#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); + + printc("#Latency\n"); + for (i = 0 ; i < pd->sz ; i++) printc("V: %llu\n", pd->values[i]); + + printc("#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); +} + #endif /* PERFDATA_H */ From 673f5d8ad692c73cdeb5b5ac2b24d728d17f54fd Mon Sep 17 00:00:00 2001 From: msdx321 Date: Thu, 22 Oct 2020 21:14:13 +0800 Subject: [PATCH 12/13] pingpong: Use perfdata Signed-off-by: msdx321 --- .../implementation/tests/unit_pingpong/ping.c | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/components/implementation/tests/unit_pingpong/ping.c b/src/components/implementation/tests/unit_pingpong/ping.c index c5e24908cb..c3fa43181b 100644 --- a/src/components/implementation/tests/unit_pingpong/ping.c +++ b/src/components/implementation/tests/unit_pingpong/ping.c @@ -1,12 +1,18 @@ #include #include +#include #include #include -#define ITER 1024 +#define ITER 10 * 1000 +#define PRINT_ALL volatile ps_tsc_t fast_path, all_args; +struct perfdata perf1, perf2; +ps_tsc_t result1[ITER] = {0, }; +ps_tsc_t result2[ITER] = {0, }; + void cos_init(void) { @@ -23,6 +29,7 @@ cos_init(void) printc("Ping component %ld: cos_init execution\n", cos_compid()); + pong_call(); ret = pong_ret(); assert(ret == 42); @@ -48,19 +55,27 @@ cos_init(void) tid = pong_ids(&us, &them); assert(cos_thdid() == tid && us != them && us == cos_compid()); - begin = ps_tsc(); + perfdata_init(&perf1, "Ping-pong - fast_path", result1, ITER); + for (i = 0; i < ITER; i++) { + begin = ps_tsc(); pong_call(); + end = ps_tsc(); + + perfdata_add(&perf1, end - begin); } - end = ps_tsc(); - fast_path = (end - begin)/ITER; - begin = ps_tsc(); + + perfdata_init(&perf2, "Ping-pong - three_return", result2, ITER); + for (i = 0; i < ITER; i++) { + begin = ps_tsc(); pong_argsrets(0, 0, 0, 0, &r0, &r1); + end = ps_tsc(); + + perfdata_add(&perf2, end - begin); } - end = ps_tsc(); - all_args = (end - begin)/ITER; + return; } @@ -68,9 +83,19 @@ cos_init(void) int main(void) { - printc("Ping component %ld: main execution\n", cos_compid()); - printc("Fast-path invocation: %llu cycles\n", fast_path); - printc("Three return value invocation: %llu cycles\n", all_args); +#ifdef PRINT_ALL + perfdata_raw(&perf1); +#endif + perfdata_calc(&perf1); + perfdata_print(&perf1); + +#ifdef PRINT_ALL + perfdata_raw(&perf2); +#endif + perfdata_calc(&perf2); + perfdata_print(&perf2); + + while(1); return 0; } From 869996190dc24b6bca87c2f72c6451e5dcdb0b53 Mon Sep 17 00:00:00 2001 From: msdx321 Date: Mon, 9 Nov 2020 14:36:15 +0800 Subject: [PATCH 13/13] patina_bench: Misc tweaks Signed-off-by: msdx321 --- .../bench_sched_yield/bench_sched_yield.c | 41 ++++++--- .../tests/bench_sl_yield/bench_sl_yield.c | 37 +++++--- .../patina_chan_bench/patina_chan_bench.c | 92 +++++++++++-------- .../patina_chan_bench_inter_recv.c | 8 +- .../patina_chan_bench_inter_send.c | 40 +++----- .../patina_event_bench/patina_event_bench.c | 17 ++-- .../patina_mutex_bench/patina_mutex_bench.c | 69 +++++++++----- .../tests/patina_sem_bench/patina_sem_bench.c | 30 ++---- .../patina_timer_bench/patina_timer_bench.c | 50 ++++++++-- src/components/implementation/tests/test.c | 8 ++ .../tests/unit_pingpong/Makefile | 2 +- src/components/lib/ubench/perfdata.h | 6 +- 12 files changed, 233 insertions(+), 167 deletions(-) create mode 100644 src/components/implementation/tests/test.c diff --git a/src/components/implementation/tests/bench_sched_yield/bench_sched_yield.c b/src/components/implementation/tests/bench_sched_yield/bench_sched_yield.c index aba0f30143..8d53abe7ae 100644 --- a/src/components/implementation/tests/bench_sched_yield/bench_sched_yield.c +++ b/src/components/implementation/tests/bench_sched_yield/bench_sched_yield.c @@ -17,36 +17,47 @@ /* lo and hi is actually running at the same prio */ #define ITERATION 10000 -/* #define PRINT_ALL */ +#define PRINT_ALL thdid_t yield_hi = 0, yield_lo = 0; + volatile cycles_t start; -volatile cycles_t end; +volatile int count; struct perfdata perf; cycles_t result[ITERATION] = {0, }; /*** - * We're measuring 2-way context switch time. + * We're measuring one-way context switch time. */ void yield_hi_thd(void *d) { - /* Never stops running; low priority controls how many iters to run. */ - while (1) { + cycles_t end; + + while (count < ITERATION) { debug("h1,"); + + start = time_now(); sched_thd_yield_to(yield_lo); + end = time_now(); + debug("h2,"); + + perfdata_add(&perf, end - start); + + count++; } + + while (1) ; } void yield_lo_thd(void *d) { - int i; - int first = 0; + cycles_t end; - for (i = 0; i < ITERATION + 1; i++) { + while (count < ITERATION) { debug("l1,"); start = time_now(); @@ -55,16 +66,16 @@ yield_lo_thd(void *d) debug("l2,"); - if (first == 0) first = 1; - else perfdata_add(&perf, end - start); + perfdata_add(&perf, end - start); + + count++; } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); while (1) ; } @@ -77,6 +88,8 @@ test_yield(void) SCHED_PARAM_CONS(SCHEDP_PRIO, 6) }; + count = 0; + perfdata_init(&perf, "Context switch time", result, ITERATION); printc("Create threads:\n"); diff --git a/src/components/implementation/tests/bench_sl_yield/bench_sl_yield.c b/src/components/implementation/tests/bench_sl_yield/bench_sl_yield.c index 75a27832bc..aa1091a1ea 100644 --- a/src/components/implementation/tests/bench_sl_yield/bench_sl_yield.c +++ b/src/components/implementation/tests/bench_sl_yield/bench_sl_yield.c @@ -19,7 +19,7 @@ /* lo and hi is actually running at the same prio */ #define ITERATION 10000 -/* #define PRINT_ALL */ +#define PRINT_ALL /* Ensure this is the same as what is in sl_mod_fprr.c */ #define SL_FPRR_NPRIOS 32 @@ -32,7 +32,7 @@ struct sl_thd *testing_thread; thdid_t thdid1, thdid2; volatile cycles_t start; -volatile cycles_t end; +volatile int count; struct perfdata perf; cycles_t result[ITERATION] = {0, }; @@ -40,21 +40,32 @@ cycles_t result[ITERATION] = {0, }; static void thd1_fn() { - /* Never stops running; low priority controls how many iters to run. */ - while (1) { + cycles_t end; + + while (count < ITERATION) { debug("h1,"); + + start = time_now(); sl_thd_yield(thdid2); + end = time_now(); + debug("h2,"); + + perfdata_add(&perf, end - start); + + count++; } + + while (1); } static void thd2_fn() { int i; - int first = 0; + cycles_t end; - for (i = 0; i < ITERATION + 1; i++) { + while (count < ITERATION) { debug("l1,"); start = time_now(); @@ -63,16 +74,16 @@ thd2_fn() debug("l2,"); - if (first == 0) first = 1; - else perfdata_add(&perf, end - start); + perfdata_add(&perf, end - start); + + count++; } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); while (1) ; } @@ -104,6 +115,8 @@ cos_init(void) struct cos_defcompinfo *defci = cos_defcompinfo_curr_get(); struct cos_compinfo *ci = cos_compinfo_get(defci); + count = 0; + PRINTC("Thread switch benchmark for the scheduling library (sl)\n"); cos_meminfo_init(&(ci->mi), BOOT_MEM_KM_BASE, COS_MEM_KERN_PA_SZ, BOOT_CAPTBL_SELF_UNTYPED_PT); cos_defcompinfo_init(); diff --git a/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c b/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c index 8856ce9467..527902d983 100644 --- a/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c +++ b/src/components/implementation/tests/patina_chan_bench/patina_chan_bench.c @@ -10,6 +10,20 @@ #include #include +#define COLD_CACHE +#ifdef COLD_CACHE +#define cache_flush() __cache_flush() +#define COLD_OFFSET 1 +#define COLD_INDEX 0 +#else +#define cache_flush() +#define COLD_OFFSET 0 +#define COLD_INDEX -1 +#endif + +#define CACHE_SIZE 512 * 1024 +#define CACHE_LINE_SIZE 32 + #undef PATINA_CHAN_TRACE_DEBUG #ifdef PATINA_CHAN_TRACE_DEBUG #define debug(format, ...) printc(format, ##__VA_ARGS__) @@ -18,11 +32,14 @@ #endif /* One low-priority thread and one high-priority thread contends on the lock */ +#ifdef COLD_CACHE +#define ITERATION 10 * 10 +#else #define ITERATION 10 * 1000 -#define PRINT_ALL +#endif +#undef PRINT_ALL /* Two options are available: Sender at low/high prio, data words 4 */ -#undef READER_HIGH #define DATA_WORDS 2 thdid_t chan_reader = 0, chan_writer = 0; @@ -60,6 +77,20 @@ patina_chan_r_t rid2; patina_chan_s_t sid; patina_chan_s_t sid2; +volatile char pool[CACHE_SIZE * 4] = { + 0, +}; + +void +__cache_flush() +{ + int agg = 1; + for (int i = 0; i < CACHE_SIZE * 4; i += CACHE_LINE_SIZE) { + pool[i] += agg; + agg = pool[i]; + } +} + /*** * The two threads reciprocally sends and receives. */ @@ -84,10 +115,10 @@ void chan_writer_thd(void *d) { int i; - int first = 0; - for (int i = 0; i < ITERATION + 1; i++) { + for (int i = 0; i < ITERATION + COLD_OFFSET; i++) { debug("w1,"); + cache_flush(); ts1[0] = time_now(); debug("ts1: %d,", ts1[0]); debug("w2,"); @@ -99,35 +130,25 @@ chan_writer_thd(void *d) ts3[0] = time_now(); debug("w5,"); - if (first == 0) - first = 1; - else { - if (ts2[0] > ts1[0] && ts3[0] > ts2[0]) { - perfdata_add(&perf1, ts2[0] - ts1[0]); - perfdata_add(&perf2, ts3[0] - ts2[0]); - perfdata_add(&perf3, ts3[0] - ts1[0]); - } + if (ts2[0] > ts1[0] && ts3[0] > ts2[0] && i != COLD_INDEX) { + perfdata_add(&perf1, ts2[0] - ts1[0]); + perfdata_add(&perf2, ts3[0] - ts2[0]); + perfdata_add(&perf3, ts3[0] - ts1[0]); } } +#ifdef PRINT_ALL + perfdata_raw(&perf1); + perfdata_raw(&perf2); + perfdata_raw(&perf3); +#endif perfdata_calc(&perf1); perfdata_calc(&perf2); perfdata_calc(&perf3); -#ifdef PRINT_ALL -#ifdef READER_HIGH - perfdata_all(&perf1); -#else - perfdata_all(&perf2); -#endif - perfdata_all(&perf3); -#else -#ifdef READER_HIGH + perfdata_print(&perf1); -#else perfdata_print(&perf2); -#endif perfdata_print(&perf3); -#endif while (1) ; @@ -137,18 +158,13 @@ void test_chan(void) { int i; - int first = 0; cycles_t begin, end; -#ifdef READER_HIGH sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; -#else - sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 6), SCHED_PARAM_CONS(SCHEDP_PRIO, 4)}; -#endif /* Uncontended lock taking/releasing */ perfdata_init(&perf1, "Uncontended channel - selfloop", result1, ITERATION); - for (i = 0; i < ITERATION + 1; i++) { + for (i = 0; i < ITERATION; i++) { begin = time_now(); debug("send\n"); @@ -157,17 +173,13 @@ test_chan(void) patina_channel_recv(rid, tmp, 1, 0); end = time_now(); - if (first == 0) - first = 1; - else - perfdata_add(&perf1, end - begin); + perfdata_add(&perf1, end - begin); } - perfdata_calc(&perf1); #ifdef PRINT_ALL - perfdata_all(&perf1); -#else - perfdata_print(&perf1); + perfdata_raw(&perf1); #endif + perfdata_calc(&perf1); + perfdata_print(&perf1); perfdata_init(&perf1, "Contended channel - reader high use this", result1, ITERATION); perfdata_init(&perf2, "Contended channel - writer high use this", result2, ITERATION); @@ -176,11 +188,11 @@ test_chan(void) printc("Create threads:\n"); chan_reader = sched_thd_create(chan_reader_thd, NULL); - printc("\tcreating reader thread %d at prio %d\n", chan_reader, sps[0]); + printc("\tcreating reader thread %d at prio %d\n", chan_reader, sps[1]); sched_thd_param_set(chan_reader, sps[0]); chan_writer = sched_thd_create(chan_writer_thd, NULL); - printc("\tcreating writer thread %d at prio %d\n", chan_writer, sps[1]); + printc("\tcreating writer thread %d at prio %d\n", chan_writer, sps[0]); sched_thd_param_set(chan_writer, sps[1]); } diff --git a/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c b/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c index 267e074879..2f291e0269 100644 --- a/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c +++ b/src/components/implementation/tests/patina_chan_bench_inter_recv/patina_chan_bench_inter_recv.c @@ -22,19 +22,13 @@ patina_chan_r_t rid; patina_event_t evt; /* Keep these settings below consistent with the sender side */ -#undef READER_HIGH -#define USE_EVTMGR +#undef USE_EVTMGR #define TEST_CHAN_ITEM_SZ sizeof(u32_t) #define TEST_CHAN_NSLOTS 2 #define TEST_CHAN_SEND_ID 3 #define TEST_CHAN_RECV_ID 4 -/* We are the receiver, and we don't care about data gathering */ -#ifdef READER_HIGH #define TEST_CHAN_PRIO_SELF 4 -#else -#define TEST_CHAN_PRIO_SELF 5 -#endif typedef unsigned int cycles_32_t; diff --git a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c index 40dc28eeb2..aff9d84926 100644 --- a/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c +++ b/src/components/implementation/tests/patina_chan_bench_inter_send/patina_chan_bench_inter_send.c @@ -22,8 +22,7 @@ patina_chan_r_t rid; patina_event_t evt; #define ITERATION 10 * 1000 -#undef READER_HIGH -#define USE_EVTMGR +#undef USE_EVTMGR #define PRINT_ALL #define TEST_CHAN_ITEM_SZ sizeof(u32_t) @@ -31,11 +30,7 @@ patina_event_t evt; #define TEST_CHAN_SEND_ID 4 #define TEST_CHAN_RECV_ID 3 /* We are the sender, and we will be responsible for collecting resulting data */ -#ifdef READER_HIGH #define TEST_CHAN_PRIO_SELF 5 -#else -#define TEST_CHAN_PRIO_SELF 4 -#endif typedef unsigned int cycles_32_t; @@ -56,7 +51,6 @@ main(void) int i; cycles_t wakeup; cycles_32_t ts1, ts2, ts3; - int first = 0; #ifdef USE_EVTMGR evt_res_id_t evt_id; evt_res_data_t evtdata; @@ -83,7 +77,7 @@ main(void) wakeup = time_now() + time_usec2cyc(1000 * 1000); sched_thd_block_timeout(0, wakeup); - for (int i = 0; i < ITERATION + 1; i++) { + for (int i = 0; i < ITERATION; i++) { debug("w1,"); ts1 = time_now(); debug("ts1: %d,", ts1); @@ -102,35 +96,25 @@ main(void) ts3 = time_now(); debug("w5,"); - if (first == 0) - first = 1; - else { - if (ts2 > ts1 && ts3 > ts2) { - perfdata_add(&perf1, ts2 - ts1); - perfdata_add(&perf2, ts3 - ts2); - perfdata_add(&perf3, ts3 - ts1); - } + if (ts2 > ts1 && ts3 > ts2) { + perfdata_add(&perf1, ts2 - ts1); + perfdata_add(&perf2, ts3 - ts2); + perfdata_add(&perf3, ts3 - ts1); } } +#ifdef PRINT_ALL + perfdata_raw(&perf1); + perfdata_raw(&perf2); + perfdata_raw(&perf3); +#endif perfdata_calc(&perf1); perfdata_calc(&perf2); perfdata_calc(&perf3); -#ifdef PRINT_ALL -#ifdef READER_HIGH - perfdata_all(&perf1); -#else - perfdata_all(&perf2); -#endif - perfdata_all(&perf3); -#else -#ifdef READER_HIGH + perfdata_print(&perf1); -#else perfdata_print(&perf2); -#endif perfdata_print(&perf3); -#endif while (1) ; diff --git a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c index e0baac548c..391a7c9f4f 100644 --- a/src/components/implementation/tests/patina_event_bench/patina_event_bench.c +++ b/src/components/implementation/tests/patina_event_bench/patina_event_bench.c @@ -39,29 +39,24 @@ void evt_hi_thd(void *d) { int i; - int first = 0; - for (i = 0; i < ITERATION + 1; i++) { + for (i = 0; i < ITERATION; i++) { debug("h1"); patina_event_wait(&evt, NULL, 0); end = time_now(); debug("h2"); - if (first == 0) - first = 1; - else - perfdata_add(&perf, end - start); + perfdata_add(&perf, end - start); debug("h3"); patina_sem_give(sid); } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); while (1) ; @@ -98,7 +93,7 @@ test_evt(void) printc("Create threads:\n"); evt_lo = sched_thd_create(evt_lo_thd, NULL); - printc("\tcreating lo thread %d at prio %d\n", evt_lo, sps[1]); + printc("\tcreating lo thread %d at prio %d\n", evt_lo, sps[0]); sched_thd_param_set(evt_lo, sps[1]); evt_hi = sched_thd_create(evt_hi_thd, NULL); diff --git a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c index 7a1b5cebbf..7c362b1337 100644 --- a/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c +++ b/src/components/implementation/tests/patina_mutex_bench/patina_mutex_bench.c @@ -10,6 +10,20 @@ #include #include +#define COLD_CACHE +#ifdef COLD_CACHE +#define cache_flush() __cache_flush() +#define COLD_OFFSET 1 +#define COLD_INDEX 0 +#else +#define cache_flush() +#define COLD_OFFSET 0 +#define COLD_INDEX -1 +#endif + +#define CACHE_SIZE 512 * 1024 +#define CACHE_LINE_SIZE 32 + #undef LOCK_TRACE_DEBUG #ifdef LOCK_TRACE_DEBUG #define debug(format, ...) printc(format, ##__VA_ARGS__) @@ -18,7 +32,14 @@ #endif /* One low-priority thread and one high-priority thread contends on the lock */ +#ifdef COLD_CACHE +#define ITERATION 10 * 10 +#define SLEEP_TIME 100 * 1000 +#else #define ITERATION 10 * 1000 +#define SLEEP_TIME 1000 +#endif + #define PRINT_ALL patina_mutex_t mid; @@ -33,6 +54,20 @@ cycles_t result[ITERATION] = { 0, }; +volatile char pool[CACHE_SIZE * 4] = { + 0, +}; + +void +__cache_flush() +{ + int agg = 1; + for (int i = 0; i < CACHE_SIZE * 4; i += CACHE_LINE_SIZE) { + pool[i] += agg; + agg = pool[i]; + } +} + /*** * The high priority thread periodically challenges the lock while the low priority thread keeps spinning. * When the low-priority thread detects that the flag is changed, it knows that the lock is challenged. @@ -45,9 +80,10 @@ lock_hi_thd(void *d) while (1) { debug("h1,"); sched_thd_block(0); - sched_thd_block_timeout(0, time_now() + time_usec2cyc(1000)); + sched_thd_block_timeout(0, time_now() + time_usec2cyc(SLEEP_TIME)); debug("h2,"); + cache_flush(); flag = 1; start = time_now(); patina_mutex_lock(mid); @@ -62,9 +98,8 @@ void lock_lo_thd(void *d) { int i; - int first = 0; - for (i = 0; i < ITERATION + 1; i++) { + for (i = 0; i < ITERATION + COLD_OFFSET; i++) { debug("l1,"); sched_thd_wakeup(lock_hi); @@ -76,19 +111,15 @@ lock_lo_thd(void *d) while (flag != 1) {} patina_mutex_unlock(mid); - if (first == 0) - first = 1; - else - perfdata_add(&perf, end - start); + if (i != COLD_INDEX) { perfdata_add(&perf, end - start); } debug("l4,"); } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); while (1) ; @@ -98,7 +129,6 @@ void test_lock(void) { int i; - int first = 0; sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; @@ -106,24 +136,21 @@ test_lock(void) /* Uncontended lock taking/releasing */ perfdata_init(&perf, "Uncontended lock - take+release", result, ITERATION); - for (i = 0; i < ITERATION + 1; i++) { + for (i = 0; i < ITERATION + COLD_OFFSET; i++) { + cache_flush(); start = time_now(); patina_mutex_lock(mid); patina_mutex_unlock(mid); end = time_now(); - if (first == 0) - first = 1; - else - perfdata_add(&perf, end - start); + if (i != COLD_INDEX) { perfdata_add(&perf, end - start); } } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); perfdata_init(&perf, "Contended lock - take+release", result, ITERATION); diff --git a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c index 23c7030f60..2452f14ca5 100644 --- a/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c +++ b/src/components/implementation/tests/patina_sem_bench/patina_sem_bench.c @@ -63,9 +63,8 @@ void sem_lo_thd(void *d) { int i; - int first = 0; - for (i = 0; i < ITERATION + 1; i++) { + for (i = 0; i < ITERATION; i++) { debug("l1"); sched_thd_wakeup(sem_hi); @@ -78,19 +77,15 @@ sem_lo_thd(void *d) patina_sem_give(sid); - if (first == 0) - first = 1; - else - perfdata_add(&perf, end - start); + perfdata_add(&perf, end - start); debug("l4"); } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); while (1) ; @@ -100,7 +95,6 @@ void test_sem(void) { int i; - int first = 0; cycles_t start, end; sched_param_t sps[] = {SCHED_PARAM_CONS(SCHEDP_PRIO, 4), SCHED_PARAM_CONS(SCHEDP_PRIO, 6)}; @@ -109,24 +103,20 @@ test_sem(void) /* Uncontended semaphore taking/releasing */ perfdata_init(&perf, "Uncontended semaphore - take+give", result, ITERATION); - for (i = 0; i < ITERATION + 1; i++) { + for (i = 0; i < ITERATION; i++) { start = time_now(); patina_sem_take(sid); patina_sem_give(sid); end = time_now(); - if (first == 0) - first = 1; - else - perfdata_add(&perf, end - start); + perfdata_add(&perf, end - start); } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); perfdata_init(&perf, "Contended semaphore - take+give", result, ITERATION); diff --git a/src/components/implementation/tests/patina_timer_bench/patina_timer_bench.c b/src/components/implementation/tests/patina_timer_bench/patina_timer_bench.c index 8d475cc300..65948b5e3f 100644 --- a/src/components/implementation/tests/patina_timer_bench/patina_timer_bench.c +++ b/src/components/implementation/tests/patina_timer_bench/patina_timer_bench.c @@ -10,6 +10,20 @@ #include #include +#define COLD_CACHE +#ifdef COLD_CACHE +#define cache_flush() __cache_flush() +#define COLD_OFFSET 1 +#define COLD_INDEX 0 +#else +#define cache_flush() +#define COLD_OFFSET 0 +#define COLD_INDEX -1 +#endif + +#define CACHE_SIZE 512 * 1024 +#define CACHE_LINE_SIZE 32 + #undef TMR_TRACE_DEBUG #ifdef TMR_TRACE_DEBUG #define debug(format, ...) printc(format, ##__VA_ARGS__) @@ -18,8 +32,14 @@ #endif /* High-priority thread interrupts the low-priority thread by timer ticks */ +#ifdef COLD_OFFSET +#define ITERATION 10 * 10 +#define TMR_PERIODIC_TIME 1000 * 1000 +#else #define ITERATION 10 * 1000 #define TMR_PERIODIC_TIME 10 * 1000 +#endif + #define DROP_THRESHOLD 0x1000000U #define PRINT_ALL @@ -35,6 +55,20 @@ cycles_t result[ITERATION] = { 0, }; +volatile char pool[CACHE_SIZE * 4] = { + 0, +}; + +void +__cache_flush() +{ + int agg = 1; + for (int i = 0; i < CACHE_SIZE * 4; i += CACHE_LINE_SIZE) { + pool[i] += agg; + agg = pool[i]; + } +} + /*** * The high priority thread sets up a periodic timer while the low priority thread keeps looping and updating * the timing value variable. The variable is a 32-bit one so that it can be updated atomically. We always @@ -47,7 +81,6 @@ tmr_hi_thd(void *d) patina_time_t t; patina_timer_t tid; patina_event_t evt; - int first = 0; printc("Call into timer manager to make a timer.\n"); tid = patina_timer_create(); @@ -67,27 +100,24 @@ tmr_hi_thd(void *d) /* Event loop */ i = 0; - while (i < ITERATION + 1) { + while (i < ITERATION + COLD_OFFSET) { + cache_flush(); patina_event_wait(&evt, NULL, 0); end = (cycles_32_t)time_now(); if ((end - start) > DROP_THRESHOLD) continue; - if (first == 0) - first = 1; - else - perfdata_add(&perf, end - start); + if (i != COLD_INDEX) { perfdata_add(&perf, end - start); } debug("%lld.\n", end - start); i++; } - perfdata_calc(&perf); #ifdef PRINT_ALL - perfdata_all(&perf); -#else - perfdata_print(&perf); + perfdata_raw(&perf); #endif + perfdata_calc(&perf); + perfdata_print(&perf); while (1) ; diff --git a/src/components/implementation/tests/test.c b/src/components/implementation/tests/test.c new file mode 100644 index 0000000000..33b130abcc --- /dev/null +++ b/src/components/implementation/tests/test.c @@ -0,0 +1,8 @@ +#include + +int main() +{ + void *p = 0; + printf("%p %p\n", p, p + 1); + return 0; +} diff --git a/src/components/implementation/tests/unit_pingpong/Makefile b/src/components/implementation/tests/unit_pingpong/Makefile index 6a48f05d9d..403512929a 100644 --- a/src/components/implementation/tests/unit_pingpong/Makefile +++ b/src/components/implementation/tests/unit_pingpong/Makefile @@ -9,7 +9,7 @@ INTERFACE_EXPORTS = INTERFACE_DEPENDENCIES = init pong # The library dependencies this component is reliant on for # compilation/linking (this is a list of directory names in lib/) -LIBRARY_DEPENDENCIES = kernel ps +LIBRARY_DEPENDENCIES = kernel ps ubench # Note: Both the interface and library dependencies should be # *minimal*. That is to say that removing a dependency should cause # the build to fail. The build system does not validate this diff --git a/src/components/lib/ubench/perfdata.h b/src/components/lib/ubench/perfdata.h index b60bcbb11e..4c1d633c37 100644 --- a/src/components/lib/ubench/perfdata.h +++ b/src/components/lib/ubench/perfdata.h @@ -229,7 +229,7 @@ perfdata_99ptile(struct perfdata *pd) static void perfdata_print(struct perfdata *pd) { - printc("PD:%s -sz:%d,SD:%llu,Mean:%llu,99%%:%llu, Max: %llu\n", + printc("#PD:%s -sz:%d,SD:%llu,Mean:%llu,99%%:%llu, Max: %llu\n", pd->name, pd->sz, pd->sd, pd->avg, pd->ptiles[PTILE_99], pd->max); } @@ -240,12 +240,12 @@ perfdata_all(struct perfdata *pd) perfdata_print(pd); - printc(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); + printc("#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"); printc("#Latency\n"); for (i = 0 ; i < pd->sz ; i++) printc("V: %llu\n", pd->values[i]); - printc("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); + printc("#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); } static void