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.
This commit is contained in:
parent
247ea7e7c3
commit
93ab5a5833
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
40
test/emu/ovni/libovni-mark.c
Normal file
40
test/emu/ovni/libovni-mark.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user