diff --git a/src/emu/CMakeLists.txt b/src/emu/CMakeLists.txt index ec7aff7..f081dd2 100644 --- a/src/emu/CMakeLists.txt +++ b/src/emu/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Barcelona Supercomputing Center (BSC) +# Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC) # SPDX-License-Identifier: GPL-3.0-or-later include_directories( @@ -42,6 +42,7 @@ add_library(emu STATIC track.c thread.c extend.c + value.c ovni/event.c ovni/setup.c nanos6/setup.c diff --git a/src/emu/chan.c b/src/emu/chan.c index b2a787e..fccfe7c 100644 --- a/src/emu/chan.c +++ b/src/emu/chan.c @@ -71,9 +71,8 @@ check_duplicates(struct chan *chan, struct value *v) return 0; if (value_is_equal(&chan->last_value, v)) { - char buf[128]; err("%s: same value as last_value %s", - chan->name, value_str(chan->last_value, buf)); + chan->name, value_str(chan->last_value)); return -1; } @@ -98,10 +97,7 @@ chan_set(struct chan *chan, struct value value) return -1; } -#ifdef ENABLE_DEBUG - char buf[128]; - dbg("%s: sets value to %s", chan->name, value_str(value, buf)); -#endif + dbg("%s: sets value to %s", chan->name, value_str(value)); chan->data.value = value; if (set_dirty(chan) != 0) { diff --git a/src/emu/mux.c b/src/emu/mux.c index 474978f..e6a374c 100644 --- a/src/emu/mux.c +++ b/src/emu/mux.c @@ -77,7 +77,7 @@ cb_select(struct chan *sel_chan, void *ptr) char buf[128]; UNUSED(buf); dbg("select channel got value %s\n", - value_str(sel_value, buf)); + value_str(sel_value)); struct mux_input *input = NULL; if (select_input(mux, sel_value, &input) != 0) { @@ -90,7 +90,7 @@ cb_select(struct chan *sel_chan, void *ptr) input->selected = 1; mux->selected = input->index; dbg("mux selects input key=%s chan=%s\n", - value_str(sel_value, buf), input->chan->name); + value_str(sel_value), input->chan->name); } /* Set to null by default */ @@ -123,9 +123,8 @@ cb_input(struct chan *in_chan, void *ptr) return -1; } - char buf[128]; dbg("setting output chan %s to value %s", - input->output->name, value_str(out_value, buf)); + input->output->name, value_str(out_value)); if (chan_set(input->output, out_value) != 0) { err("chan_set() failed"); diff --git a/src/emu/pv/prv.c b/src/emu/pv/prv.c index a5e5ad7..c7fa205 100644 --- a/src/emu/pv/prv.c +++ b/src/emu/pv/prv.c @@ -88,7 +88,6 @@ emit(struct prv *prv, struct prv_chan *rchan) { struct value value; struct chan *chan = rchan->chan; - char buf[128]; if (chan_read(chan, &value) != 0) { err("chan_read %s failed\n", chan->name); return -1; @@ -106,7 +105,7 @@ emit(struct prv *prv, struct prv_chan *rchan) return 0; err("error duplicated value %s for channel %s\n", - value_str(value, buf), chan->name); + value_str(value), chan->name); return -1; } @@ -125,7 +124,7 @@ emit(struct prv *prv, struct prv_chan *rchan) if (~rchan->flags & PRV_ZERO && val == 0) { err("forbidden value 0 in %s: %s\n", chan->name, - value_str(value, buf)); + value_str(value)); return -1; } break; @@ -134,13 +133,13 @@ emit(struct prv *prv, struct prv_chan *rchan) break; default: err("chan_read %s only int64 and null supported: %s\n", - chan->name, value_str(value, buf)); + chan->name, value_str(value)); return -1; } write_line(prv, rchan->row_base1, rchan->type, val); - dbg("written %s for chan %s", value_str(value, buf), chan->name); + dbg("written %s for chan %s", value_str(value), chan->name); return 0; diff --git a/src/emu/value.c b/src/emu/value.c new file mode 100644 index 0000000..a382a7c --- /dev/null +++ b/src/emu/value.c @@ -0,0 +1,7 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include "value.h" + +char value_buffers[VALUE_NBUF][VALUE_BUFSIZE]; +size_t value_nextbuf = 0; diff --git a/src/emu/value.h b/src/emu/value.h index 330c4de..5ec8395 100644 --- a/src/emu/value.h +++ b/src/emu/value.h @@ -9,6 +9,12 @@ #include #include "common.h" +#define VALUE_NBUF 32 +#define VALUE_BUFSIZE 128 + +extern char value_buffers[VALUE_NBUF][VALUE_BUFSIZE]; +extern size_t value_nextbuf; + enum value_type { VALUE_NULL = 0, VALUE_INT64, @@ -51,22 +57,33 @@ value_is_null(struct value a) } static inline char * -value_str(struct value a, char *buf) +value_str(struct value a) { + char *buf = value_buffers[value_nextbuf]; + int ret = 0; + size_t n = VALUE_BUFSIZE; + switch (a.type) { case VALUE_NULL: - sprintf(buf, "{NULL}"); + ret = snprintf(buf, n, "{NULL}"); break; case VALUE_INT64: - sprintf(buf, "{int64_t %ld}", a.i); + ret = snprintf(buf, n, "{int64_t %ld}", a.i); break; case VALUE_DOUBLE: - sprintf(buf, "{double %e}", a.d); + ret = snprintf(buf, n, "{double %e}", a.d); break; default: die("value_str: unexpected value type\n"); } + if (ret >= (int) n) + die("value string too long"); + + value_nextbuf++; + if (value_nextbuf > VALUE_NBUF) + value_nextbuf = 0; + return buf; } diff --git a/test/unit/mux.c b/test/unit/mux.c index 5891535..46f7ff9 100644 --- a/test/unit/mux.c +++ b/test/unit/mux.c @@ -14,11 +14,9 @@ check_output(struct mux *mux, struct value expected) die("chan_read() failed for output channel\n"); if (!value_is_equal(&out_value, &expected)) { - char buf1[128]; - char buf2[128]; die("unexpected value found %s in output (expected %s)\n", - value_str(out_value, buf1), - value_str(expected, buf2)); + value_str(out_value), + value_str(expected)); } err("----- output ok -----\n"); diff --git a/test/unit/value.c b/test/unit/value.c index c6738c7..bdff9f9 100644 --- a/test/unit/value.c +++ b/test/unit/value.c @@ -4,8 +4,9 @@ #include "emu/value.h" #include "common.h" -int -main(void) +/* Ensure there are no holes in the value structure */ +static void +test_holes(void) { struct value a, b; @@ -21,6 +22,16 @@ main(void) die("values are not the same\n"); err("OK\n"); +} + +/* Ensure value_null results in values being equal */ +static void +test_null_init(void) +{ + struct value a, b; + + memset(&a, 66, sizeof(struct value)); + memset(&b, 0, sizeof(struct value)); a = value_null(); b = value_null(); @@ -28,5 +39,42 @@ main(void) if (!value_is_equal(&a, &b)) die("null not equal"); + err("OK\n"); +} + +/* Test that we can printf at least 8 values without overwritting the + * value_str() buffer */ +static void +test_multiple_str(void) +{ + if (VALUE_NBUF < 8) + die("VALUE_NBUF too small"); + + char *str[VALUE_NBUF]; + for (int i = 0; i < VALUE_NBUF; i++) { + struct value v = value_int64(i); + str[i] = value_str(v); + } + + for (int i = 0; i < VALUE_NBUF; i++) { + char expected[128]; + sprintf(expected, "{int64_t %d}", i); + if (strcmp(expected, str[i]) != 0) { + die("mismatch in bufer i=%d: expected %s, got %s", + i, expected, str[i]); + } + } + + err("OK"); +} + + +int +main(void) +{ + test_holes(); + test_null_init(); + test_multiple_str(); + return 0; }