Skip to content

Commit

Permalink
Merge branch 'check-instr' into 'master'
Browse files Browse the repository at this point in the history
Add configurable switch for instrumentation

See merge request nos-v/nos-v!63
  • Loading branch information
kevinsala committed May 22, 2023
2 parents 05fcc6b + d5a33b2 commit d24ca3f
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 64 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pkgconfig_DATA = nos-v.pc

libnosv_la_SOURCES = \
src/bootstrap.c \
src/instr.c \
src/config/config.c \
src/config/toml.c \
src/hardware/cpus.c \
Expand Down
7 changes: 6 additions & 1 deletion nosv.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of nOS-V and is licensed under the terms contained in the COPYING file
#
# Copyright (C) 2021-2022 Barcelona Supercomputing Center (BSC)
# Copyright (C) 2021-2023 Barcelona Supercomputing Center (BSC)

# Default nOS-V configuration file.
# Note that every process in the same nOS-V instance should load an identical configuration file,
Expand Down Expand Up @@ -124,3 +124,8 @@
enabled = false
# Whether to print verbose information if monitoring is enabled
verbose = false

# Instrumentation. Only applies if nOS-V was configured with --with-ovni
[instrumentation]
# Select the instrumentation to be used. Current options are "none" or "ovni".
version = "none"
6 changes: 5 additions & 1 deletion src/config/config.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Nanos6 and nOS-V and is licensed under the terms contained in the COPYING file.
Copyright (C) 2020-2022 Barcelona Supercomputing Center (BSC)
Copyright (C) 2020-2023 Barcelona Supercomputing Center (BSC)
*/

#include <assert.h>
Expand Down Expand Up @@ -84,6 +84,8 @@ static inline void config_init(rt_config_t *config)

config->monitoring_enabled = 0;
config->monitoring_verbose = 0;

config->instrumentation_version = strdup(INSTR_DEFAULT_VERSION);
}

#define sanity_check(cond, explanation) \
Expand Down Expand Up @@ -130,6 +132,8 @@ static inline int config_check(rt_config_t *config)

sanity_check_str(config->hwcounters_backend, "Currently available hardware counter backends: papi, none", "none", "papi");

sanity_check_str(config->instrumentation_version, "Currently available instrumentations: ovni, none", "ovni", "none");

return ret;
}

Expand Down
5 changes: 4 additions & 1 deletion src/include/config/config.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Nanos6 and nOS-V and is licensed under the terms contained in the COPYING file.
Copyright (C) 2020-2022 Barcelona Supercomputing Center (BSC)
Copyright (C) 2020-2023 Barcelona Supercomputing Center (BSC)
*/

#ifndef CONFIG_H
Expand Down Expand Up @@ -77,6 +77,9 @@ typedef struct rt_config {
// Monitoring
int monitoring_enabled;
int monitoring_verbose;

// Instrumentation
const char *instrumentation_version;
} rt_config_t;

__internal extern rt_config_t nosv_config;
Expand Down
3 changes: 2 additions & 1 deletion src/include/config/configspec.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Nanos6 and nOS-V and is licensed under the terms contained in the COPYING file.
Copyright (C) 2020-2022 Barcelona Supercomputing Center (BSC)
Copyright (C) 2020-2023 Barcelona Supercomputing Center (BSC)
*/

#ifndef CONFIG_PARSE_H
Expand Down Expand Up @@ -83,6 +83,7 @@ static config_spec_t config_spec_list[] = {
DECLARE_CONFIG(TYPE_BOOL, "turbo.enabled", turbo_enabled),
DECLARE_CONFIG(TYPE_BOOL, "monitoring.enabled", monitoring_enabled),
DECLARE_CONFIG(TYPE_BOOL, "monitoring.verbose", monitoring_verbose),
DECLARE_CONFIG(TYPE_STR, "instrumentation.version", instrumentation_version),
};

#endif // CONFIG_PARSE_H
3 changes: 3 additions & 0 deletions src/include/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,7 @@
// The enabled HWCounter backend, "none" by default
#define HWCOUNTERS_BACKEND "none"

// Enabled instrumentation. None by default
#define INSTR_DEFAULT_VERSION "none"

#endif // DEFAULTS_H
113 changes: 68 additions & 45 deletions src/include/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,69 +22,80 @@

#include "common.h"
#include "compat.h"
#include "config/config.h"
#include "hardware/pids.h"
#include "hardware/threads.h"
#include "nosv-internal.h"

#ifdef ENABLE_INSTRUMENTATION
#define INSTR_0ARG(name, mcv) \
static inline void name(void) \
{ \
struct ovni_ev ev = {0}; \
__internal extern int instr_ovni_enabled;

#define CHECK_INSTR_ENABLED \
if (!instr_ovni_enabled) \
return;

#define INSTR_0ARG(name, mcv) \
static inline void name(void) \
{ \
CHECK_INSTR_ENABLED \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_ev_emit(&ev); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_ev_emit(&ev); \
}

#define INSTR_1ARG(name, mcv, ta, a) \
static inline void name(ta a) \
{ \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \
ovni_ev_emit(&ev); \
#define INSTR_1ARG(name, mcv, ta, a) \
static inline void name(ta a) \
{ \
CHECK_INSTR_ENABLED \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_ev_emit(&ev); \
}

#define INSTR_2ARG(name, mcv, ta, a, tb, b) \
static inline void name(ta a, tb b) \
{ \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *)&b, sizeof(b)); \
ovni_ev_emit(&ev); \
#define INSTR_2ARG(name, mcv, ta, a, tb, b) \
static inline void name(ta a, tb b) \
{ \
CHECK_INSTR_ENABLED \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
ovni_ev_emit(&ev); \
}

#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \
static inline void name(ta a, tb b, tc c) \
{ \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *)&b, sizeof(b)); \
ovni_payload_add(&ev, (uint8_t *)&c, sizeof(c)); \
ovni_ev_emit(&ev); \
#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \
static inline void name(ta a, tb b, tc c) \
{ \
CHECK_INSTR_ENABLED \
struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \
ovni_ev_emit(&ev); \
}
#else // ENABLE_INSTRUMENTATION
#define INSTR_0ARG(name, mcv) \
#define INSTR_0ARG(name, mcv) \
static inline void name(void) \
{ \
}

#define INSTR_1ARG(name, mcv, ta, a) \
#define INSTR_1ARG(name, mcv, ta, a) \
static inline void name(ta a) \
{ \
}

#define INSTR_2ARG(name, mcv, ta, a, tb, b) \
#define INSTR_2ARG(name, mcv, ta, a, tb, b) \
static inline void name(ta a, tb b) \
{ \
}

#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \
#define INSTR_3ARG(name, mcv, ta, a, tb, b, tc, c) \
static inline void name(ta a, tb b, tc c) \
{ \
}
Expand Down Expand Up @@ -135,6 +146,7 @@ INSTR_1ARG(instr_task_end, "VTe", uint32_t, task_id)
// A jumbo event is needed to encode a large label
static inline void instr_type_create(uint32_t typeid, const char *label)
{
CHECK_INSTR_ENABLED
size_t bufsize, label_len, size_left;
uint8_t buf[1024], *p;

Expand Down Expand Up @@ -203,11 +215,13 @@ INSTR_0ARG(instr_thread_warm, "OHw")

static inline void instr_cpu_id(int index, int phyid)
{
CHECK_INSTR_ENABLED
ovni_add_cpu(index, phyid);
}

static inline void instr_thread_end(void)
{
CHECK_INSTR_ENABLED
struct ovni_ev ev = {0};

ovni_ev_set_clock(&ev, ovni_clock_now());
Expand All @@ -220,6 +234,7 @@ static inline void instr_thread_end(void)

static inline void instr_proc_init(const char *suffix)
{
CHECK_INSTR_ENABLED
char hostname[HOST_NAME_MAX + 1];
int appid;
char *appid_str;
Expand Down Expand Up @@ -252,22 +267,26 @@ static inline void instr_proc_init(const char *suffix)

static inline void instr_proc_fini(void)
{
CHECK_INSTR_ENABLED
ovni_proc_fini();
}

static inline void instr_gen_bursts(void)
{
CHECK_INSTR_ENABLED
for (int i = 0; i < 100; i++)
instr_burst();
}

static inline void instr_thread_init(void)
{
CHECK_INSTR_ENABLED
ovni_thread_init(gettid());
}

static inline void instr_thread_attach(void)
{
CHECK_INSTR_ENABLED
struct ovni_ev ev = {0};

if (!ovni_thread_isready())
Expand All @@ -280,6 +299,7 @@ static inline void instr_thread_attach(void)

static inline void instr_thread_detach(void)
{
CHECK_INSTR_ENABLED
struct ovni_ev ev = {0};

ovni_ev_set_clock(&ev, ovni_clock_now());
Expand Down Expand Up @@ -345,13 +365,14 @@ struct kinstr;

#ifdef ENABLE_INSTRUMENTATION
static int perf_event_open(struct perf_event_attr *attr, pid_t pid,
int cpu, int group_fd, unsigned long flags)
int cpu, int group_fd, unsigned long flags)
{
return (int) syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, flags);
}

static inline void instr_kernel_init(struct kinstr **ki_ptr)
{
CHECK_INSTR_ENABLED
struct perf_event_attr attr;
struct kinstr *ki;
long pagesize;
Expand Down Expand Up @@ -403,7 +424,7 @@ static inline void instr_kernel_init(struct kinstr **ki_ptr)
// Map the buffer: must be 1+2^n pages
ki->bufsize = pagesize + ki->ringsize;
ki->buf = mmap(NULL, ki->bufsize,
PROT_READ | PROT_WRITE, MAP_SHARED, ki->fd, 0);
PROT_READ | PROT_WRITE, MAP_SHARED, ki->fd, 0);

if (ki->buf == MAP_FAILED) {
nosv_warn("cannot enable kernel events, mmap failed");
Expand All @@ -421,12 +442,12 @@ static inline void instr_kernel_init(struct kinstr **ki_ptr)
}

struct sample_id {
//u32 pid, tid; } /* if PERF_SAMPLE_TID set */
uint64_t time; /* if PERF_SAMPLE_TIME set */
//u64 id; } /* if PERF_SAMPLE_ID set */
//u64 stream_id;} /* if PERF_SAMPLE_STREAM_ID set */
//u32 cpu, res; } /* if PERF_SAMPLE_CPU set */
//u64 id; } /* if PERF_SAMPLE_IDENTIFIER set */
// u32 pid, tid; } /* if PERF_SAMPLE_TID set */
uint64_t time; /* if PERF_SAMPLE_TIME set */
// u64 id; } /* if PERF_SAMPLE_ID set */
// u64 stream_id;} /* if PERF_SAMPLE_STREAM_ID set */
// u32 cpu, res; } /* if PERF_SAMPLE_CPU set */
// u64 id; } /* if PERF_SAMPLE_IDENTIFIER set */
};

struct perf_ev {
Expand All @@ -453,6 +474,7 @@ static inline void emit_perf_event(struct perf_ev *ev)

static inline void instr_kernel_flush(struct kinstr *ki)
{
CHECK_INSTR_ENABLED
struct ovni_ev ev0 = {0}, ev1 = {0};
struct perf_ev *ev;
uint8_t *p;
Expand Down Expand Up @@ -484,6 +506,7 @@ static inline void instr_kernel_flush(struct kinstr *ki)

static inline void instr_kernel_free(struct kinstr *ki)
{
CHECK_INSTR_ENABLED
sfree(ki, sizeof(*ki), -1);
}

Expand Down
9 changes: 9 additions & 0 deletions src/instr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
This file is part of nOS-V and is licensed under the terms contained in the COPYING file.
Copyright (C) 2023 Barcelona Supercomputing Center (BSC)
*/

#include "instr.h"

int instr_ovni_enabled = 0;
8 changes: 8 additions & 0 deletions src/memory/sharedmemory.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ static inline void calculate_shared_memory_permissions(void)

static inline void initialize_instrumentation(void)
{
if (strcmp(nosv_config.instrumentation_version, "ovni") == 0) {
#ifdef ENABLE_INSTRUMENTATION
instr_ovni_enabled = 1;
#else
nosv_warn("ovni instrumentation requested, but nOS-V was built without ovni support");
#endif
}

instr_proc_init(st_config.smem_name);
instr_thread_init();
instr_thread_execute(-1, -1, 0);
Expand Down
15 changes: 0 additions & 15 deletions tests/basic/attach-external.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
#include <pthread.h>
#include <sched.h>

#ifdef ENABLE_INSTRUMENTATION
// Load instrumentation definitions from nosv header for now
#include "instr.h"
#endif

static nosv_task_type_t type;
static test_t test;

Expand All @@ -23,22 +18,12 @@ static void *start_routine(void *arg)
{
nosv_task_t task;

#ifdef ENABLE_INSTRUMENTATION
// The thread must be instrumented *outside* nosv, before it
// calls any external nosv function which may emit events.
instr_thread_init();
instr_thread_execute(-1, -1, 0);
#endif
nosv_attach(&task, type, 0, NULL, NOSV_ATTACH_NONE);
test_ok(&test, "External thread can attach");

nosv_detach(NOSV_DETACH_NONE);
test_ok(&test, "External thread can detach");

#ifdef ENABLE_INSTRUMENTATION
// The thread end also flushes the events to disk.
instr_thread_end();
#endif
return NULL;
}

Expand Down

0 comments on commit d24ca3f

Please sign in to comment.