From 93ab5a58330e0658077daf84f8ba4bf50beba014 Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Date: Thu, 13 Jun 2024 15:46:55 +0200 Subject: [PATCH] Add ovni_mark_* API to store custom states In order to allow easy debugging of some programs and runtimes, it is often neccessary to add extra information in the timeline views. The modification of the emulator to accomodate those temporal events is time consuming and requires knowlegde of the emulator internals. To improve the situation, a new set of functions are added to libovni which allow users to define their own views. Up to 100 types of events can be declared, where each type can have an unlimited number ov values with an optional label attached. --- include/ovni.h.in | 6 +++ src/emu/emu_prv.h | 6 ++- src/emu/ovni/event.c | 3 ++ src/emu/ovni/setup.c | 5 ++- src/rt/ovni.c | 86 ++++++++++++++++++++++++++++++++++++ test/emu/ovni/CMakeLists.txt | 1 + test/emu/ovni/libovni-mark.c | 40 +++++++++++++++++ 7 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 test/emu/ovni/libovni-mark.c diff --git a/include/ovni.h.in b/include/ovni.h.in index aa0343f..237f63c 100644 --- a/include/ovni.h.in +++ b/include/ovni.h.in @@ -142,6 +142,12 @@ const char *ovni_attr_get_str(const char *key); char *ovni_attr_get_json(const char *key); void ovni_attr_flush(void); +/* Mark */ +void ovni_mark_type(int32_t type, const char *title); +void ovni_mark_label(int32_t type, int64_t value, const char *label); +void ovni_mark_push(int32_t type, int64_t value); +void ovni_mark_pop(int32_t type, int64_t value); + #ifdef __cplusplus } #endif diff --git a/src/emu/emu_prv.h b/src/emu/emu_prv.h index 44a5a9f..06383a8 100644 --- a/src/emu/emu_prv.h +++ b/src/emu/emu_prv.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC) +/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: GPL-3.0-or-later */ #ifndef EMU_PRV_H @@ -33,7 +33,9 @@ enum emu_prv_types { PRV_NANOS6_BREAKDOWN = 41, PRV_KERNEL_CS = 45, PRV_OPENMP_SUBSYSTEM = 50, - PRV_RESERVED = 100, + PRV_OVNI_MARK = 100, + /* User marks [100, 200) */ + PRV_RESERVED = 200, }; #endif /* EMU_PRV_H */ diff --git a/src/emu/ovni/event.c b/src/emu/ovni/event.c index b49e7a5..338f48e 100644 --- a/src/emu/ovni/event.c +++ b/src/emu/ovni/event.c @@ -477,6 +477,9 @@ model_ovni_event(struct emu *emu) case 'U': /* Ignore sorting events */ return 0; + case 'M': + /* TODO: Ignore mark events for now */ + return 0; default: err("unknown ovni event category %c", emu->ev->c); diff --git a/src/emu/ovni/setup.c b/src/emu/ovni/setup.c index 3a8ea48..84be469 100644 --- a/src/emu/ovni/setup.c +++ b/src/emu/ovni/setup.c @@ -37,12 +37,15 @@ static struct ev_decl model_evlist[] = { PAIR_B("OF[", "OF]", "flushing events to disk") PAIR_E("OU[", "OU]", "unordered event region") + { "OM[(i64 value, i32 type)", "push mark with value %{value} from type %{type}" }, + { "OM](i64 value, i32 type)", "pop mark with value %{value} from type %{type}" }, + { NULL, NULL }, }; struct model_spec model_ovni = { .name = model_name, - .version = "1.0.0", + .version = "1.1.0", .evlist = model_evlist, .model = model_id, .create = model_ovni_create, diff --git a/src/rt/ovni.c b/src/rt/ovni.c index aa910d4..3c6d7ec 100644 --- a/src/rt/ovni.c +++ b/src/rt/ovni.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -1061,3 +1062,88 @@ ovni_attr_flush(void) thread_metadata_store(); } + +/* Mark */ + +/** creates a new mark type. */ +void +ovni_mark_type(int32_t type, const char *title) +{ + if (type < 0 || type >= 100) + die("type must be in [0,100) range"); + + if (!title || title[0] == '\0') + die("bad title"); + + JSON_Object *meta = get_thread_metadata(); + + char key[128]; + if (snprintf(key, 128, "ovni.mark.%"PRId32, type) >= 128) + die("type key too long"); + + JSON_Value *val = json_object_dotget_value(meta, key); + if (val != NULL) + die("type %"PRId32" already defined", type); + + if (snprintf(key, 128, "ovni.mark.%"PRId32".title", type) >= 128) + die("title key too long"); + + if (json_object_dotset_string(meta, key, title) != 0) + die("json_object_dotset_string() failed", type); +} + +/** creates a new mark type. */ +void +ovni_mark_label(int32_t type, int64_t value, const char *label) +{ + if (type < 0 || type >= 100) + die("type must be in [0,100) range"); + + if (value <= 0) + die("value must be >0"); + + if (!label || label[0] == '\0') + die("bad label"); + + JSON_Object *meta = get_thread_metadata(); + + char key[128]; + if (snprintf(key, 128, "ovni.mark.%"PRId32, type) >= 128) + die("type key too long"); + + JSON_Value *valtype = json_object_dotget_value(meta, key); + if (valtype == NULL) + die("type %"PRId32" not defined", type); + + if (snprintf(key, 128, "ovni.mark.%"PRId32".labels.%"PRId64, type, value) >= 128) + die("value key too long"); + + JSON_Value *val = json_object_dotget_value(meta, key); + if (val != NULL) + die("label '%s' already defined", label); + + if (json_object_dotset_string(meta, key, label) != 0) + die("json_object_dotset_string() failed", type); +} + +void +ovni_mark_push(int32_t type, int64_t value) +{ + struct ovni_ev ev = {0}; + ovni_ev_set_clock(&ev, ovni_clock_now()); + ovni_ev_set_mcv(&ev, "OM["); + ovni_payload_add(&ev, (uint8_t *) &value, sizeof(value)); + ovni_payload_add(&ev, (uint8_t *) &type, sizeof(type)); + ovni_ev_add(&ev); +} + +void +ovni_mark_pop(int32_t type, int64_t value) +{ + struct ovni_ev ev = {0}; + ovni_ev_set_clock(&ev, ovni_clock_now()); + ovni_ev_set_mcv(&ev, "OM]"); + ovni_payload_add(&ev, (uint8_t *) &value, sizeof(value)); + ovni_payload_add(&ev, (uint8_t *) &type, sizeof(type)); + ovni_ev_add(&ev); +} diff --git a/test/emu/ovni/CMakeLists.txt b/test/emu/ovni/CMakeLists.txt index 1bb7718..7b4f19f 100644 --- a/test/emu/ovni/CMakeLists.txt +++ b/test/emu/ovni/CMakeLists.txt @@ -29,3 +29,4 @@ test_emu(dummy.c NAME "ovniver" DRIVER "ovniver.driver.sh") test_emu(dummy.c NAME "match-doc-events" DRIVER "match-doc-events.sh") test_emu(dummy.c NAME "match-doc-version" DRIVER "match-doc-version.sh") test_emu(libovni-attr.c) +test_emu(libovni-mark.c) diff --git a/test/emu/ovni/libovni-mark.c b/test/emu/ovni/libovni-mark.c new file mode 100644 index 0000000..25a167c --- /dev/null +++ b/test/emu/ovni/libovni-mark.c @@ -0,0 +1,40 @@ +/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include "instr.h" +#include "ovni.h" + +enum { + MARK_COLORS = 1, + COL_RED = 1, + COL_BLUE = 2, + COL_GREEN = 3, +}; + +/* Check ovni_mark_* API. */ +int +main(void) +{ + instr_start(0, 1); + + ovni_mark_type(MARK_COLORS, "Colors"); + + if(!ovni_attr_has("ovni.mark.1.title")) + die("missing mark title"); + + ovni_mark_label(MARK_COLORS, 1, "Red"); + ovni_mark_label(MARK_COLORS, 2, "Blue"); + ovni_mark_label(MARK_COLORS, 3, "Green"); + + sleep_us(10); ovni_mark_push(MARK_COLORS, COL_RED); + sleep_us(10); ovni_mark_push(MARK_COLORS, COL_BLUE); + sleep_us(10); ovni_mark_push(MARK_COLORS, COL_GREEN); + sleep_us(10); ovni_mark_pop(MARK_COLORS, COL_GREEN); + sleep_us(10); ovni_mark_pop(MARK_COLORS, COL_BLUE); + sleep_us(10); ovni_mark_pop(MARK_COLORS, COL_RED); + + instr_end(); + + return 0; +}