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; +}