Follow K&R coding style using clang-format

This commit is contained in:
Rodrigo Arias 2022-09-29 15:34:44 +02:00
parent baefb2b01c
commit 177429fabc
49 changed files with 6229 additions and 5685 deletions

31
.clang-format Normal file
View File

@ -0,0 +1,31 @@
Language: Cpp
BasedOnStyle: LLVM
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: None
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakConstructorInitializers: AfterColon
BraceWrapping:
AfterControlStatement: false
AfterFunction: true
AfterStruct: false
AfterUnion: false
BeforeElse: false
ColumnLimit: 0
ContinuationIndentWidth: 8
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentWidth: 8
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2
SortIncludes: true
SpaceAfterCStyleCast: true
SpacesBeforeTrailingComments: 0
TabWidth: 8
UseTab: Always
...

167
chan.c
View File

@ -27,10 +27,10 @@ chan_init(struct ovni_chan *chan, enum chan_track track, int row, int type, FILE
static void static void
mark_dirty(struct ovni_chan *chan, enum chan_dirty dirty) mark_dirty(struct ovni_chan *chan, enum chan_dirty dirty)
{ {
if(chan->dirty != CHAN_CLEAN) if (chan->dirty != CHAN_CLEAN)
die("mark_dirty: chan %d already dirty\n", chan->id); die("mark_dirty: chan %d already dirty\n", chan->id);
if(dirty == CHAN_CLEAN) if (dirty == CHAN_CLEAN)
die("mark_dirty: cannot use CHAN_CLEAN\n"); die("mark_dirty: cannot use CHAN_CLEAN\n");
dbg("adding dirty chan %d to list\n", chan->id); dbg("adding dirty chan %d to list\n", chan->id);
@ -40,15 +40,15 @@ mark_dirty(struct ovni_chan *chan, enum chan_dirty dirty)
void void
chan_th_init(struct ovni_ethread *th, chan_th_init(struct ovni_ethread *th,
struct ovni_chan **update_list, struct ovni_chan **update_list,
enum chan id, enum chan id,
enum chan_track track, enum chan_track track,
int init_st, int init_st,
int enabled, int enabled,
int dirty, int dirty,
int row, int row,
FILE *prv, FILE *prv,
int64_t *clock) int64_t *clock)
{ {
struct ovni_chan *chan; struct ovni_chan *chan;
int prvth; int prvth;
@ -63,21 +63,21 @@ chan_th_init(struct ovni_ethread *th,
chan->update_list = update_list; chan->update_list = update_list;
chan->enabled = enabled; chan->enabled = enabled;
chan->stack[chan->n++] = init_st; chan->stack[chan->n++] = init_st;
if(dirty) if (dirty)
mark_dirty(chan, CHAN_DIRTY_ACTIVE); mark_dirty(chan, CHAN_DIRTY_ACTIVE);
} }
void void
chan_cpu_init(struct ovni_cpu *cpu, chan_cpu_init(struct ovni_cpu *cpu,
struct ovni_chan **update_list, struct ovni_chan **update_list,
enum chan id, enum chan id,
enum chan_track track, enum chan_track track,
int init_st, int init_st,
int enabled, int enabled,
int dirty, int dirty,
int row, int row,
FILE *prv, FILE *prv,
int64_t *clock) int64_t *clock)
{ {
struct ovni_chan *chan; struct ovni_chan *chan;
int prvcpu; int prvcpu;
@ -92,7 +92,7 @@ chan_cpu_init(struct ovni_cpu *cpu,
chan->update_list = update_list; chan->update_list = update_list;
chan->enabled = enabled; chan->enabled = enabled;
chan->stack[chan->n++] = init_st; chan->stack[chan->n++] = init_st;
if(dirty) if (dirty)
mark_dirty(chan, CHAN_DIRTY_ACTIVE); mark_dirty(chan, CHAN_DIRTY_ACTIVE);
} }
@ -102,9 +102,8 @@ chan_dump_update_list(struct ovni_chan *chan)
struct ovni_chan *c; struct ovni_chan *c;
dbg("update list for chan %d at %p:\n", dbg("update list for chan %d at %p:\n",
chan->id, (void *) chan); chan->id, (void *) chan);
for(c = *chan->update_list; c; c = c->next) for (c = *chan->update_list; c; c = c->next) {
{
dbg(" chan %d at %p\n", c->id, (void *) c); dbg(" chan %d at %p\n", c->id, (void *) c);
} }
} }
@ -116,8 +115,7 @@ chan_enable(struct ovni_chan *chan, int enabled)
dbg("chan_enable chan=%d enabled=%d\n", chan->id, enabled); dbg("chan_enable chan=%d enabled=%d\n", chan->id, enabled);
if(chan->enabled == enabled) if (chan->enabled == enabled) {
{
err("chan_enable: chan already in enabled=%d\n", enabled); err("chan_enable: chan already in enabled=%d\n", enabled);
abort(); abort();
} }
@ -126,14 +124,11 @@ chan_enable(struct ovni_chan *chan, int enabled)
chan->t = *chan->clock; chan->t = *chan->clock;
/* Only append if not dirty */ /* Only append if not dirty */
if(!chan->dirty) if (!chan->dirty) {
{
mark_dirty(chan, CHAN_DIRTY_ACTIVE); mark_dirty(chan, CHAN_DIRTY_ACTIVE);
} } else {
else
{
dbg("already dirty chan %d: skip update list\n", dbg("already dirty chan %d: skip update list\n",
chan->id); chan->id);
chan_dump_update_list(chan); chan_dump_update_list(chan);
} }
} }
@ -157,40 +152,36 @@ chan_set(struct ovni_chan *chan, int st)
dbg("chan_set chan %d st=%d\n", chan->id, st); dbg("chan_set chan %d st=%d\n", chan->id, st);
if(!chan->enabled) if (!chan->enabled)
die("chan_set: chan %d not enabled\n", chan->id); die("chan_set: chan %d not enabled\n", chan->id);
/* Only chan_set can set the 0 state */ /* Only chan_set can set the 0 state */
if(st < 0) if (st < 0)
die("chan_set: cannot set a negative state %d\n", st); die("chan_set: cannot set a negative state %d\n", st);
/* Don't enforce this check if we are dirty because the channel was /* Don't enforce this check if we are dirty because the channel was
* just enabled; it may collide with a new state 0 set via chan_set() * just enabled; it may collide with a new state 0 set via chan_set()
* used by the tracking channels */ * used by the tracking channels */
if(chan->dirty != CHAN_DIRTY_ACTIVE if (chan->dirty != CHAN_DIRTY_ACTIVE
&& chan->lastst >= 0 && chan->lastst >= 0
&& chan->lastst == st) && chan->lastst == st) {
{
err("chan_set id=%d cannot emit the state %d twice\n", err("chan_set id=%d cannot emit the state %d twice\n",
chan->id, st); chan->id, st);
abort(); abort();
} }
if(chan->n == 0) if (chan->n == 0)
chan->n = 1; chan->n = 1;
chan->stack[chan->n - 1] = st; chan->stack[chan->n - 1] = st;
chan->t = *chan->clock; chan->t = *chan->clock;
/* Only append if not dirty */ /* Only append if not dirty */
if(!chan->dirty) if (!chan->dirty) {
{
mark_dirty(chan, CHAN_DIRTY_VALUE); mark_dirty(chan, CHAN_DIRTY_VALUE);
} } else {
else
{
dbg("already dirty chan %d: skip update list\n", dbg("already dirty chan %d: skip update list\n",
chan->id); chan->id);
chan_dump_update_list(chan); chan_dump_update_list(chan);
} }
} }
@ -200,28 +191,25 @@ chan_push(struct ovni_chan *chan, int st)
{ {
dbg("chan_push chan %d st=%d\n", chan->id, st); dbg("chan_push chan %d st=%d\n", chan->id, st);
if(!chan->enabled) if (!chan->enabled)
die("chan_push: chan %d not enabled\n", chan->id); die("chan_push: chan %d not enabled\n", chan->id);
if(st <= 0) if (st <= 0) {
{
err("chan_push: cannot push a non-positive state %d\n", st); err("chan_push: cannot push a non-positive state %d\n", st);
abort(); abort();
} }
/* Cannot be dirty */ /* Cannot be dirty */
if(chan->dirty != CHAN_CLEAN) if (chan->dirty != CHAN_CLEAN)
die("chan_push: chan %d not clean", chan->id); die("chan_push: chan %d not clean", chan->id);
if(chan->lastst >= 0 && chan->lastst == st) if (chan->lastst >= 0 && chan->lastst == st) {
{
err("chan_push id=%d cannot emit the state %d twice\n", err("chan_push id=%d cannot emit the state %d twice\n",
chan->id, st); chan->id, st);
abort(); abort();
} }
if(chan->n >= MAX_CHAN_STACK) if (chan->n >= MAX_CHAN_STACK) {
{
err("chan_push: channel stack full\n"); err("chan_push: channel stack full\n");
abort(); abort();
} }
@ -239,25 +227,23 @@ chan_pop(struct ovni_chan *chan, int expected_st)
dbg("chan_pop chan %d expected_st=%d\n", chan->id, expected_st); dbg("chan_pop chan %d expected_st=%d\n", chan->id, expected_st);
if(!chan->enabled) if (!chan->enabled)
die("chan_pop: chan %d not enabled\n", chan->id); die("chan_pop: chan %d not enabled\n", chan->id);
/* Cannot be dirty */ /* Cannot be dirty */
if(chan->dirty != CHAN_CLEAN) if (chan->dirty != CHAN_CLEAN)
die("chan_pop: chan %d not clean", chan->id); die("chan_pop: chan %d not clean", chan->id);
if(chan->n <= 0) if (chan->n <= 0) {
{
err("chan_pop: channel empty\n"); err("chan_pop: channel empty\n");
abort(); abort();
} }
st = chan->stack[chan->n - 1]; st = chan->stack[chan->n - 1];
if(expected_st >= 0 && st != expected_st) if (expected_st >= 0 && st != expected_st) {
{
err("chan_pop: unexpected channel state %d (expected %d)\n", err("chan_pop: unexpected channel state %d (expected %d)\n",
st, expected_st); st, expected_st);
abort(); abort();
} }
@ -267,16 +253,14 @@ chan_pop(struct ovni_chan *chan, int expected_st)
st = chan_get_st(chan); st = chan_get_st(chan);
/* A st == 0 can be obtained when returning to the initial state */ /* A st == 0 can be obtained when returning to the initial state */
if(st < 0) if (st < 0) {
{
err("chan_pop: obtained negative state %d from the stack\n", st); err("chan_pop: obtained negative state %d from the stack\n", st);
abort(); abort();
} }
if(chan->lastst >= 0 && chan->lastst == st) if (chan->lastst >= 0 && chan->lastst == st) {
{
err("chan_pop id=%d cannot emit the state %d twice\n", err("chan_pop id=%d cannot emit the state %d twice\n",
chan->id, st); chan->id, st);
abort(); abort();
} }
@ -292,19 +276,19 @@ chan_ev(struct ovni_chan *chan, int ev)
{ {
dbg("chan_ev chan %d ev=%d\n", chan->id, ev); dbg("chan_ev chan %d ev=%d\n", chan->id, ev);
if(!chan->enabled) if (!chan->enabled)
die("chan_ev: chan %d not enabled\n", chan->id); die("chan_ev: chan %d not enabled\n", chan->id);
/* Cannot be dirty */ /* Cannot be dirty */
if(chan->dirty != CHAN_CLEAN) if (chan->dirty != CHAN_CLEAN)
die("chan_ev: chan %d is dirty\n", chan->id); die("chan_ev: chan %d is dirty\n", chan->id);
if(ev <= 0) if (ev <= 0)
die("chan_ev: cannot emit non-positive state %d\n", ev); die("chan_ev: cannot emit non-positive state %d\n", ev);
if(chan->lastst >= 0 && chan->lastst == ev) if (chan->lastst >= 0 && chan->lastst == ev)
die("chan_ev id=%d cannot emit the state %d twice\n", die("chan_ev id=%d cannot emit the state %d twice\n",
chan->id, ev); chan->id, ev);
chan->ev = ev; chan->ev = ev;
chan->t = *chan->clock; chan->t = *chan->clock;
@ -315,38 +299,36 @@ chan_ev(struct ovni_chan *chan, int ev)
int int
chan_get_st(struct ovni_chan *chan) chan_get_st(struct ovni_chan *chan)
{ {
if(chan->enabled == 0) if (chan->enabled == 0)
return chan->badst; return chan->badst;
if(chan->n == 0) if (chan->n == 0)
return 0; return 0;
if(chan->n < 0) if (chan->n < 0)
die("chan_get_st: chan %d has negative n\n", chan->id); die("chan_get_st: chan %d has negative n\n", chan->id);
return chan->stack[chan->n-1]; return chan->stack[chan->n - 1];
} }
static void static void
emit(struct ovni_chan *chan, int64_t t, int state) emit(struct ovni_chan *chan, int64_t t, int state)
{ {
if(chan->dirty == CHAN_CLEAN) if (chan->dirty == CHAN_CLEAN)
die("emit: chan %d is not dirty\n", chan->id); die("emit: chan %d is not dirty\n", chan->id);
/* A channel can only emit the same state as lastst if is dirty because /* A channel can only emit the same state as lastst if is dirty because
* it has been enabled or disabled. Otherwise is a bug (ie. you have two * it has been enabled or disabled. Otherwise is a bug (ie. you have two
* consecutive ovni events?) */ * consecutive ovni events?) */
if(chan->lastst != -1 if (chan->lastst != -1
&& chan->dirty == CHAN_DIRTY_VALUE && chan->dirty == CHAN_DIRTY_VALUE
&& chan->lastst == state) && chan->lastst == state) {
{
/* TODO: Print the raw clock of the offending event */ /* TODO: Print the raw clock of the offending event */
die("emit: chan %d cannot emit the same state %d twice\n", die("emit: chan %d cannot emit the same state %d twice\n",
chan->id, state); chan->id, state);
} }
if(chan->lastst != state) if (chan->lastst != state) {
{
prv_ev(chan->prv, chan->row, t, chan->type, state); prv_ev(chan->prv, chan->row, t, chan->type, state);
chan->lastst = state; chan->lastst = state;
@ -358,16 +340,16 @@ emit_ev(struct ovni_chan *chan)
{ {
int new, last; int new, last;
if(!chan->enabled) if (!chan->enabled)
die("emit_ev: chan %d is not enabled\n", chan->id); die("emit_ev: chan %d is not enabled\n", chan->id);
if(chan->ev == -1) if (chan->ev == -1)
die("emit_ev: chan %d cannot emit -1 ev\n", chan->id); die("emit_ev: chan %d cannot emit -1 ev\n", chan->id);
new = chan->ev; new = chan->ev;
last = chan_get_st(chan); last = chan_get_st(chan);
emit(chan, chan->t-1, new); emit(chan, chan->t - 1, new);
emit(chan, chan->t, last); emit(chan, chan->t, last);
chan->ev = -1; chan->ev = -1;
@ -387,16 +369,15 @@ emit_st(struct ovni_chan *chan)
void void
chan_emit(struct ovni_chan *chan) chan_emit(struct ovni_chan *chan)
{ {
if(likely(chan->dirty == 0)) if (likely(chan->dirty == 0))
return; return;
dbg("chan_emit chan %d\n", chan->id); dbg("chan_emit chan %d\n", chan->id);
/* Emit badst if disabled */ /* Emit badst if disabled */
if(chan->enabled == 0) if (chan->enabled == 0) {
{
/* No punctual events allowed when disabled */ /* No punctual events allowed when disabled */
if(chan->ev != -1) if (chan->ev != -1)
die("chan_emit: no punctual event allowed when disabled\n"); die("chan_emit: no punctual event allowed when disabled\n");
emit_st(chan); emit_st(chan);
@ -404,7 +385,7 @@ chan_emit(struct ovni_chan *chan)
} }
/* Otherwise, emit punctual event if any or the state */ /* Otherwise, emit punctual event if any or the state */
if(chan->ev != -1) if (chan->ev != -1)
emit_ev(chan); emit_ev(chan);
else else
emit_st(chan); emit_st(chan);

36
chan.h
View File

@ -8,27 +8,27 @@
void void
chan_th_init(struct ovni_ethread *th, chan_th_init(struct ovni_ethread *th,
struct ovni_chan **update_list, struct ovni_chan **update_list,
enum chan id, enum chan id,
enum chan_track track, enum chan_track track,
int init_st, int init_st,
int enabled, int enabled,
int dirty, int dirty,
int row, int row,
FILE *prv, FILE *prv,
int64_t *clock); int64_t *clock);
void void
chan_cpu_init(struct ovni_cpu *cpu, chan_cpu_init(struct ovni_cpu *cpu,
struct ovni_chan **update_list, struct ovni_chan **update_list,
enum chan id, enum chan id,
enum chan_track track, enum chan_track track,
int row, int row,
int init_st, int init_st,
int enabled, int enabled,
int dirty, int dirty,
FILE *prv, FILE *prv,
int64_t *clock); int64_t *clock);
void void
chan_enable(struct ovni_chan *chan, int enabled); chan_enable(struct ovni_chan *chan, int enabled);

View File

@ -11,11 +11,12 @@
/* Define gettid for older glibc versions (below 2.30) */ /* Define gettid for older glibc versions (below 2.30) */
#if defined(__GLIBC__) #if defined(__GLIBC__)
#if !__GLIBC_PREREQ(2, 30) #if !__GLIBC_PREREQ(2, 30)
static inline pid_t gettid(void) static inline pid_t
gettid(void)
{ {
return (pid_t)syscall(SYS_gettid); return (pid_t) syscall(SYS_gettid);
} }
#endif /* !__GLIBC_PREREQ(2, 30) */ #endif /* !__GLIBC_PREREQ(2, 30) */
#endif /* defined(__GLIBC__) */ #endif /* defined(__GLIBC__) */
#endif // COMPAT_H #endif// COMPAT_H

91
dump.c
View File

@ -3,26 +3,26 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdio.h> #include <dirent.h>
#include <errno.h>
#include <linux/limits.h>
#include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <linux/limits.h>
#include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdatomic.h>
#include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include "emu.h"
#include "ovni.h" #include "ovni.h"
#include "trace.h" #include "trace.h"
#include "emu.h"
int filter_tid = -1; int filter_tid = -1;
char *tracedir; char *tracedir;
//static void // static void
//hexdump(uint8_t *buf, size_t size) // hexdump(uint8_t *buf, size_t size)
//{ //{
// size_t i, j; // size_t i, j;
// //
@ -36,7 +36,7 @@ char *tracedir;
// } // }
// fprintf(stderr, "\n"); // fprintf(stderr, "\n");
// } // }
//} // }
static void static void
emit(struct ovni_stream *stream, struct ovni_ev *ev) emit(struct ovni_stream *stream, struct ovni_ev *ev)
@ -44,25 +44,24 @@ emit(struct ovni_stream *stream, struct ovni_ev *ev)
uint64_t clock; uint64_t clock;
int i, payloadsize; int i, payloadsize;
//printf("sizeof(*ev) = %d\n", sizeof(*ev)); // printf("sizeof(*ev) = %d\n", sizeof(*ev));
//hexdump((uint8_t *) ev, sizeof(*ev)); // hexdump((uint8_t *) ev, sizeof(*ev));
clock = ovni_ev_get_clock(ev); clock = ovni_ev_get_clock(ev);
printf("%s.%d.%d %ld %c%c%c", printf("%s.%d.%d %ld %c%c%c",
stream->loom->hostname, stream->loom->hostname,
stream->proc->pid, stream->proc->pid,
stream->thread->tid, stream->thread->tid,
clock, clock,
ev->header.model, ev->header.model,
ev->header.category, ev->header.category,
ev->header.value); ev->header.value);
payloadsize = ovni_payload_size(ev); payloadsize = ovni_payload_size(ev);
if(payloadsize > 0) if (payloadsize > 0) {
{
printf(" "); printf(" ");
for(i=0; i<payloadsize; i++) for (i = 0; i < payloadsize; i++)
printf(":%02x", ev->payload.u8[i]); printf(":%02x", ev->payload.u8[i]);
} }
printf("\n"); printf("\n");
@ -81,50 +80,45 @@ dump_events(struct ovni_trace *trace)
struct ovni_stream *stream; struct ovni_stream *stream;
/* Load events */ /* Load events */
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
/* It can be inactive if it has been disabled by the /* It can be inactive if it has been disabled by the
* thread TID filter */ * thread TID filter */
if(stream->active) if (stream->active)
ovni_load_next_event(stream); ovni_load_next_event(stream);
} }
lastclock = 0; lastclock = 0;
while(1) while (1) {
{
f = -1; f = -1;
minclock = 0; minclock = 0;
/* Select next event based on the clock */ /* Select next event based on the clock */
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
if(!stream->active) if (!stream->active)
continue; continue;
ev = stream->cur_ev; ev = stream->cur_ev;
if(f < 0 || ovni_ev_get_clock(ev) < minclock) if (f < 0 || ovni_ev_get_clock(ev) < minclock) {
{
f = i; f = i;
minclock = ovni_ev_get_clock(ev); minclock = ovni_ev_get_clock(ev);
} }
} }
//fprintf(stderr, "f=%d minclock=%u\n", f, minclock); // fprintf(stderr, "f=%d minclock=%u\n", f, minclock);
if(f < 0) if (f < 0)
break; break;
stream = &trace->stream[f]; stream = &trace->stream[f];
if(lastclock > ovni_ev_get_clock(stream->cur_ev)) if (lastclock > ovni_ev_get_clock(stream->cur_ev)) {
{
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n", fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
lastclock, ovni_ev_get_clock(stream->cur_ev)); lastclock, ovni_ev_get_clock(stream->cur_ev));
} }
/* Emit current event */ /* Emit current event */
@ -138,7 +132,6 @@ dump_events(struct ovni_trace *trace)
/* Unset the index */ /* Unset the index */
f = -1; f = -1;
minclock = 0; minclock = 0;
} }
} }
@ -166,10 +159,8 @@ parse_args(int argc, char *argv[])
{ {
int opt; int opt;
while((opt = getopt(argc, argv, "t:")) != -1) while ((opt = getopt(argc, argv, "t:")) != -1) {
{ switch (opt) {
switch(opt)
{
case 't': case 't':
filter_tid = atoi(optarg); filter_tid = atoi(optarg);
break; break;
@ -178,8 +169,7 @@ parse_args(int argc, char *argv[])
} }
} }
if(optind >= argc) if (optind >= argc) {
{
err("missing tracedir\n"); err("missing tracedir\n");
usage(argc, argv); usage(argc, argv);
} }
@ -187,25 +177,24 @@ parse_args(int argc, char *argv[])
tracedir = argv[optind]; tracedir = argv[optind];
} }
int main(int argc, char *argv[]) int
main(int argc, char *argv[])
{ {
parse_args(argc, argv); parse_args(argc, argv);
struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace)); struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace));
if(ovni_load_trace(trace, tracedir)) if (ovni_load_trace(trace, tracedir))
return 1; return 1;
if(ovni_load_streams(trace)) if (ovni_load_streams(trace))
return 1; return 1;
if(filter_tid != -1) if (filter_tid != -1) {
{ for (size_t i = 0; i < trace->nstreams; i++) {
for(size_t i=0; i<trace->nstreams; i++)
{
struct ovni_stream *stream; struct ovni_stream *stream;
stream = &trace->stream[i]; stream = &trace->stream[i];
if(stream->tid != filter_tid) if (stream->tid != filter_tid)
stream->active = 0; stream->active = 0;
} }
} }

467
emu.c
View File

@ -3,25 +3,25 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
#include <dirent.h>
#include <errno.h>
#include <linux/limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <linux/limits.h>
#include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdatomic.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include "ovni.h"
#include "trace.h"
#include "emu.h"
#include "prv.h"
#include "pcf.h"
#include "chan.h" #include "chan.h"
#include "emu.h"
#include "ovni.h"
#include "pcf.h"
#include "prv.h"
#include "trace.h"
#include "utlist.h" #include "utlist.h"
/* Obtains the corrected clock of the given event */ /* Obtains the corrected clock of the given event */
@ -39,22 +39,21 @@ print_ev(struct ovni_stream *stream, struct ovni_ev *ev)
UNUSED(delta); UNUSED(delta);
//dbg("sizeof(*ev) = %d\n", sizeof(*ev)); // dbg("sizeof(*ev) = %d\n", sizeof(*ev));
//hexdump((uint8_t *) ev, sizeof(*ev)); // hexdump((uint8_t *) ev, sizeof(*ev));
clock = evclock(stream, ev); clock = evclock(stream, ev);
delta = clock - stream->lastclock; delta = clock - stream->lastclock;
dbg(">>> %s.%d.%d %c %c %c % 20ld % 15ld ", dbg(">>> %s.%d.%d %c %c %c % 20ld % 15ld ",
stream->loom->hostname, stream->loom->hostname,
stream->proc->pid, stream->proc->pid,
stream->thread->tid, stream->thread->tid,
ev->header.model, ev->header.category, ev->header.value, clock, delta); ev->header.model, ev->header.category, ev->header.value, clock, delta);
payloadsize = ovni_payload_size(ev); payloadsize = ovni_payload_size(ev);
for(i=0; i<payloadsize; i++) for (i = 0; i < payloadsize; i++) {
{
dbg("%d ", ev->payload.u8[i]); dbg("%d ", ev->payload.u8[i]);
} }
dbg("\n"); dbg("\n");
@ -73,8 +72,7 @@ cpu_update_tracking_chan(struct ovni_chan *cpu_chan, struct ovni_ethread *th)
int th_enabled, cpu_enabled, st; int th_enabled, cpu_enabled, st;
struct ovni_chan *th_chan; struct ovni_chan *th_chan;
switch (cpu_chan->track) switch (cpu_chan->track) {
{
case CHAN_TRACK_TH_RUNNING: case CHAN_TRACK_TH_RUNNING:
cpu_enabled = th->is_running; cpu_enabled = th->is_running;
break; break;
@ -91,44 +89,36 @@ cpu_update_tracking_chan(struct ovni_chan *cpu_chan, struct ovni_ethread *th)
th_enabled = chan_is_enabled(th_chan); th_enabled = chan_is_enabled(th_chan);
/* Enable the cpu channel if needed */ /* Enable the cpu channel if needed */
if(cpu_enabled && !chan_is_enabled(cpu_chan)) if (cpu_enabled && !chan_is_enabled(cpu_chan))
chan_enable(cpu_chan, cpu_enabled); chan_enable(cpu_chan, cpu_enabled);
/* Copy the state from the thread channel if needed */ /* Copy the state from the thread channel if needed */
if(th_enabled && cpu_enabled) if (th_enabled && cpu_enabled) {
{
/* Both enabled: simply follow the same value */ /* Both enabled: simply follow the same value */
st = chan_get_st(th_chan); st = chan_get_st(th_chan);
if(chan_get_st(cpu_chan) != st) if (chan_get_st(cpu_chan) != st)
chan_set(cpu_chan, st); chan_set(cpu_chan, st);
} } else if (th_enabled && !cpu_enabled) {
else if(th_enabled && !cpu_enabled)
{
/* Only thread enabled: disable CPU */ /* Only thread enabled: disable CPU */
if(chan_is_enabled(cpu_chan)) if (chan_is_enabled(cpu_chan))
chan_disable(cpu_chan); chan_disable(cpu_chan);
} } else if (!th_enabled && cpu_enabled) {
else if(!th_enabled && cpu_enabled)
{
/* Only CPU enabled: is this possible? Set to bad */ /* Only CPU enabled: is this possible? Set to bad */
chan_set(cpu_chan, ST_BAD); chan_set(cpu_chan, ST_BAD);
err("warning: cpu %s chan %d enabled but tracked thread %d chan disabled\n", err("warning: cpu %s chan %d enabled but tracked thread %d chan disabled\n",
cpu_chan->cpu->name, cpu_chan->cpu->name,
cpu_chan->id, cpu_chan->id,
th->tid); th->tid);
} } else {
else
{
/* Both disabled: disable CPU channel if needed */ /* Both disabled: disable CPU channel if needed */
if(chan_is_enabled(cpu_chan)) if (chan_is_enabled(cpu_chan))
chan_disable(cpu_chan); chan_disable(cpu_chan);
} }
dbg("cpu %s chan %d enabled=%d state=%d\n", dbg("cpu %s chan %d enabled=%d state=%d\n",
cpu_chan->cpu->name, cpu_chan->id, cpu_chan->cpu->name, cpu_chan->id,
chan_is_enabled(cpu_chan), chan_is_enabled(cpu_chan),
chan_get_st(cpu_chan)); chan_get_st(cpu_chan));
} }
void void
@ -139,8 +129,7 @@ emu_cpu_update_chan(struct ovni_cpu *cpu, struct ovni_chan *cpu_chan)
/* Determine the source of tracking */ /* Determine the source of tracking */
switch (cpu_chan->track) switch (cpu_chan->track) {
{
case CHAN_TRACK_TH_RUNNING: case CHAN_TRACK_TH_RUNNING:
count = cpu->nrunning_threads; count = cpu->nrunning_threads;
th = cpu->th_running; th = cpu->th_running;
@ -156,32 +145,27 @@ emu_cpu_update_chan(struct ovni_cpu *cpu, struct ovni_chan *cpu_chan)
} }
/* Based on how many threads, determine the state */ /* Based on how many threads, determine the state */
if(count == 0) if (count == 0) {
{
/* The channel can be already disabled (migration of paused /* The channel can be already disabled (migration of paused
* thread) so only disable it if needed. */ * thread) so only disable it if needed. */
if(chan_is_enabled(cpu_chan)) if (chan_is_enabled(cpu_chan))
chan_disable(cpu_chan); chan_disable(cpu_chan);
} } else if (count == 1) {
else if(count == 1) if (th == NULL)
{
if(th == NULL)
die("emu_cpu_update_chan: tracking thread is NULL\n"); die("emu_cpu_update_chan: tracking thread is NULL\n");
/* A unique thread found: copy the state */ /* A unique thread found: copy the state */
dbg("cpu_update_chan: unique thread %d found, updating chan %d\n", dbg("cpu_update_chan: unique thread %d found, updating chan %d\n",
th->tid, cpu_chan->id); th->tid, cpu_chan->id);
cpu_update_tracking_chan(cpu_chan, th); cpu_update_tracking_chan(cpu_chan, th);
} } else {
else
{
/* More than one thread: enable the channel and set it to a /* More than one thread: enable the channel and set it to a
* error value */ * error value */
if(!chan_is_enabled(cpu_chan)) if (!chan_is_enabled(cpu_chan))
chan_enable(cpu_chan, 1); chan_enable(cpu_chan, 1);
if(chan_get_st(cpu_chan) != ST_TOO_MANY_TH) if (chan_get_st(cpu_chan) != ST_TOO_MANY_TH)
chan_set(cpu_chan, ST_TOO_MANY_TH); chan_set(cpu_chan, ST_TOO_MANY_TH);
} }
} }
@ -197,13 +181,13 @@ propagate_channels(struct ovni_emu *emu)
DL_FOREACH_SAFE(emu->th_chan, th_chan, tmp) DL_FOREACH_SAFE(emu->th_chan, th_chan, tmp)
{ {
if(th_chan->thread == NULL) if (th_chan->thread == NULL)
die("propagate_channels: channel thread is NULL\n"); die("propagate_channels: channel thread is NULL\n");
thread = th_chan->thread; thread = th_chan->thread;
/* No CPU in the thread */ /* No CPU in the thread */
if(thread->cpu == NULL) if (thread->cpu == NULL)
continue; continue;
cpu = thread->cpu; cpu = thread->cpu;
@ -211,7 +195,7 @@ propagate_channels(struct ovni_emu *emu)
cpu_chan = &cpu->chan[th_chan->id]; cpu_chan = &cpu->chan[th_chan->id];
dbg("propagate thread %d chan %d in cpu %s\n", dbg("propagate thread %d chan %d in cpu %s\n",
thread->tid, th_chan->id, cpu->name); thread->tid, th_chan->id, cpu->name);
emu_cpu_update_chan(cpu, cpu_chan); emu_cpu_update_chan(cpu, cpu_chan);
} }
@ -266,15 +250,28 @@ hook_end(struct ovni_emu *emu)
static void static void
hook_pre(struct ovni_emu *emu) hook_pre(struct ovni_emu *emu)
{ {
switch(emu->cur_ev->header.model) switch (emu->cur_ev->header.model) {
{ case 'O':
case 'O': hook_pre_ovni(emu); break; hook_pre_ovni(emu);
case 'V': hook_pre_nosv(emu); break; break;
case 'T': hook_pre_tampi(emu); break; case 'V':
case 'M': hook_pre_openmp(emu); break; hook_pre_nosv(emu);
case 'D': hook_pre_nodes(emu); break; break;
case 'K': hook_pre_kernel(emu); break; case 'T':
case '6': hook_pre_nanos6(emu); break; hook_pre_tampi(emu);
break;
case 'M':
hook_pre_openmp(emu);
break;
case 'D':
hook_pre_nodes(emu);
break;
case 'K':
hook_pre_kernel(emu);
break;
case '6':
hook_pre_nanos6(emu);
break;
default: default:
break; break;
} }
@ -283,11 +280,10 @@ hook_pre(struct ovni_emu *emu)
static void static void
hook_post(struct ovni_emu *emu) hook_post(struct ovni_emu *emu)
{ {
switch(emu->cur_ev->header.model) switch (emu->cur_ev->header.model) {
{
default: default:
//dbg("unknown model %c\n", emu->cur_ev->model); // dbg("unknown model %c\n", emu->cur_ev->model);
break; break;
} }
} }
@ -310,16 +306,17 @@ set_current(struct ovni_emu *emu, struct ovni_stream *stream)
* *
* Invert the comparison function to get a min-heap instead * Invert the comparison function to get a min-heap instead
*/ */
static inline int stream_cmp(heap_node_t *a, heap_node_t *b) static inline int
stream_cmp(heap_node_t *a, heap_node_t *b)
{ {
struct ovni_stream *sa, *sb; struct ovni_stream *sa, *sb;
sa = heap_elem(a, struct ovni_stream, hh); sa = heap_elem(a, struct ovni_stream, hh);
sb = heap_elem(b, struct ovni_stream, hh); sb = heap_elem(b, struct ovni_stream, hh);
if(sb->lastclock < sa->lastclock) if (sb->lastclock < sa->lastclock)
return -1; return -1;
else if(sb->lastclock > sa->lastclock) else if (sb->lastclock > sa->lastclock)
return +1; return +1;
else else
return 0; return 0;
@ -330,7 +327,7 @@ get_time(void)
{ {
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + (double)ts.tv_nsec * 1.0e-9; return (double) ts.tv_sec + (double) ts.tv_nsec * 1.0e-9;
} }
static void static void
@ -346,8 +343,7 @@ print_progress(struct ovni_emu *emu)
written = cpu_written + th_written; written = cpu_written + th_written;
progress = ((double) emu->global_offset) / progress = ((double) emu->global_offset) / ((double) emu->global_size);
((double) emu->global_size);
time_now = get_time(); time_now = get_time();
time_elapsed = time_now - emu->start_emulation_time; time_elapsed = time_now - emu->start_emulation_time;
@ -361,12 +357,12 @@ print_progress(struct ovni_emu *emu)
sec = (int) ((time_left / 60.0 - min) * 60); sec = (int) ((time_left / 60.0 - min) * 60);
err("%.1f%% done at %.0f Kev/s, out %.1f GB CPU / %.1f GB TH at %.1f MB/s (%d min %d s left)\n", err("%.1f%% done at %.0f Kev/s, out %.1f GB CPU / %.1f GB TH at %.1f MB/s (%d min %d s left)\n",
100.0 * progress, 100.0 * progress,
speed_in / 1024.0, speed_in / 1024.0,
cpu_written / (1024.0 * 1024.0 * 1024.0), cpu_written / (1024.0 * 1024.0 * 1024.0),
th_written / (1024.0 * 1024.0 * 1024.0), th_written / (1024.0 * 1024.0 * 1024.0),
speed_out / (1024.0 * 1024), speed_out / (1024.0 * 1024),
min, sec); min, sec);
} }
/* Loads the next event and sets the lastclock in the stream. /* Loads the next event and sets the lastclock in the stream.
@ -374,7 +370,7 @@ print_progress(struct ovni_emu *emu)
static int static int
emu_step_stream(struct ovni_emu *emu, struct ovni_stream *stream) emu_step_stream(struct ovni_emu *emu, struct ovni_stream *stream)
{ {
if(ovni_load_next_event(stream) < 0) if (ovni_load_next_event(stream) < 0)
return -1; return -1;
stream->lastclock = evclock(stream, stream->cur_ev); stream->lastclock = evclock(stream, stream->cur_ev);
@ -396,19 +392,19 @@ next_event(struct ovni_emu *emu)
node = heap_pop_max(&emu->sorted_stream, stream_cmp); node = heap_pop_max(&emu->sorted_stream, stream_cmp);
/* No more streams */ /* No more streams */
if(node == NULL) if (node == NULL)
return -1; return -1;
stream = heap_elem(node, struct ovni_stream, hh); stream = heap_elem(node, struct ovni_stream, hh);
if(stream == NULL) if (stream == NULL)
die("next_event: heap_elem returned NULL\n"); die("next_event: heap_elem returned NULL\n");
set_current(emu, stream); set_current(emu, stream);
emu->global_offset += ovni_ev_size(stream->cur_ev); emu->global_offset += ovni_ev_size(stream->cur_ev);
//err("stream %d clock at %ld\n", stream->tid, stream->lastclock); // err("stream %d clock at %ld\n", stream->tid, stream->lastclock);
/* This can happen if two events are not ordered in the stream, but the /* This can happen if two events are not ordered in the stream, but the
* emulator picks other events in the middle. Example: * emulator picks other events in the middle. Example:
@ -423,19 +419,17 @@ next_event(struct ovni_emu *emu)
* 12 * 12
* ... * ...
* */ * */
if(emu->lastclock > stream->lastclock) if (emu->lastclock > stream->lastclock) {
{
err("warning: backwards jump in time %lu -> %lu for tid %d\n", err("warning: backwards jump in time %lu -> %lu for tid %d\n",
emu->lastclock, stream->lastclock, stream->tid); emu->lastclock, stream->lastclock, stream->tid);
if(emu->enable_linter) if (emu->enable_linter)
abort(); abort();
} }
emu->lastclock = stream->lastclock; emu->lastclock = stream->lastclock;
if(!done_first) if (!done_first) {
{
done_first = 1; done_first = 1;
emu->firstclock = emu->lastclock; emu->firstclock = emu->lastclock;
} }
@ -459,16 +453,14 @@ emu_load_first_events(struct ovni_emu *emu)
/* Load initial streams and events */ /* Load initial streams and events */
trace = &emu->trace; trace = &emu->trace;
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
emu->global_size += stream->size; emu->global_size += stream->size;
if(emu_step_stream(emu, stream) < 0) if (emu_step_stream(emu, stream) < 0) {
{
err("warning: empty stream for tid %d\n", stream->tid); err("warning: empty stream for tid %d\n", stream->tid);
if(emu->enable_linter) if (emu->enable_linter)
abort(); abort();
continue; continue;
@ -494,8 +486,7 @@ emulate(struct ovni_emu *emu)
emit_channels(emu); emit_channels(emu);
/* Then process all events */ /* Then process all events */
for(i=0; next_event(emu) == 0; i++) for (i = 0; next_event(emu) == 0; i++) {
{
print_cur_ev(emu); print_cur_ev(emu);
hook_pre(emu); hook_pre(emu);
@ -505,8 +496,7 @@ emulate(struct ovni_emu *emu)
hook_post(emu); hook_post(emu);
if(i >= 50000) if (i >= 50000) {
{
print_progress(emu); print_progress(emu);
i = 0; i = 0;
} }
@ -527,10 +517,9 @@ emu_get_thread(struct ovni_eproc *proc, int tid)
size_t i; size_t i;
struct ovni_ethread *thread; struct ovni_ethread *thread;
for(i=0; i<proc->nthreads; i++) for (i = 0; i < proc->nthreads; i++) {
{
thread = &proc->thread[i]; thread = &proc->thread[i];
if(thread->tid == tid) if (thread->tid == tid)
return thread; return thread;
} }
@ -544,13 +533,13 @@ add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid)
cpu = &loom->cpu[i]; cpu = &loom->cpu[i];
if(i < 0 || i >= (int) loom->ncpus) if (i < 0 || i >= (int) loom->ncpus)
die("CPU with index %d in loom %s is out of bounds\n", die("CPU with index %d in loom %s is out of bounds\n",
i, loom->hostname); i, loom->hostname);
if(cpu->state != CPU_ST_UNKNOWN) if (cpu->state != CPU_ST_UNKNOWN)
die("new cpu %d in unexpected state in loom %s\n", die("new cpu %d in unexpected state in loom %s\n",
i, loom->hostname); i, loom->hostname);
cpu->state = CPU_ST_READY; cpu->state = CPU_ST_READY;
cpu->i = i; cpu->i = i;
@ -563,43 +552,42 @@ add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid)
static int static int
proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom, proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom,
struct ovni_eproc *proc, struct ovni_eproc *proc,
struct ovni_eproc *metadata_proc) struct ovni_eproc *metadata_proc)
{ {
JSON_Object *meta = json_value_get_object(proc->meta); JSON_Object *meta = json_value_get_object(proc->meta);
if(meta == NULL) if (meta == NULL)
die("json_value_get_object() failed\n"); die("json_value_get_object() failed\n");
JSON_Array *cpuarray = json_object_get_array(meta, "cpus"); JSON_Array *cpuarray = json_object_get_array(meta, "cpus");
/* This process doesn't have the cpu list */ /* This process doesn't have the cpu list */
if(cpuarray == NULL) if (cpuarray == NULL)
return -1; return -1;
if(metadata_proc) if (metadata_proc)
die("duplicated metadata for proc %d and %d in loom %s\n", die("duplicated metadata for proc %d and %d in loom %s\n",
metadata_proc->pid, proc->pid, metadata_proc->pid, proc->pid,
loom->hostname); loom->hostname);
if(loom->ncpus != 0) if (loom->ncpus != 0)
die("loom %s already has CPUs\n", loom->hostname); die("loom %s already has CPUs\n", loom->hostname);
loom->ncpus = json_array_get_count(cpuarray); loom->ncpus = json_array_get_count(cpuarray);
if(loom->ncpus == 0) if (loom->ncpus == 0)
die("loom %s proc %d has metadata but no CPUs\n", die("loom %s proc %d has metadata but no CPUs\n",
loom->hostname, proc->pid); loom->hostname, proc->pid);
loom->cpu = calloc(loom->ncpus, sizeof(struct ovni_cpu)); loom->cpu = calloc(loom->ncpus, sizeof(struct ovni_cpu));
if(loom->cpu == NULL) if (loom->cpu == NULL)
die("calloc failed: %s\n", strerror(errno)); die("calloc failed: %s\n", strerror(errno));
for(size_t i = 0; i < loom->ncpus; i++) for (size_t i = 0; i < loom->ncpus; i++) {
{
JSON_Object *cpu = json_array_get_object(cpuarray, i); JSON_Object *cpu = json_array_get_object(cpuarray, i);
if(cpu == NULL) if (cpu == NULL)
die("proc_load_cpus: json_array_get_object() failed\n"); die("proc_load_cpus: json_array_get_object() failed\n");
int index = (int) json_object_get_number(cpu, "index"); int index = (int) json_object_get_number(cpu, "index");
@ -612,9 +600,9 @@ proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom,
/* Init the vcpu as well */ /* Init the vcpu as well */
struct ovni_cpu *vcpu = &loom->vcpu; struct ovni_cpu *vcpu = &loom->vcpu;
if(vcpu->state != CPU_ST_UNKNOWN) if (vcpu->state != CPU_ST_UNKNOWN)
die("unexpected virtual CPU state in loom %s\n", die("unexpected virtual CPU state in loom %s\n",
loom->hostname); loom->hostname);
vcpu->state = CPU_ST_READY; vcpu->state = CPU_ST_READY;
vcpu->i = -1; vcpu->i = -1;
@ -638,33 +626,31 @@ load_metadata(struct ovni_emu *emu)
trace = &emu->trace; trace = &emu->trace;
for(i=0; i<trace->nlooms; i++) for (i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
loom->offset_ncpus = emu->total_ncpus; loom->offset_ncpus = emu->total_ncpus;
struct ovni_eproc *metadata_proc = NULL; struct ovni_eproc *metadata_proc = NULL;
for(j=0; j<loom->nprocs; j++) for (j = 0; j < loom->nprocs; j++) {
{
proc = &loom->proc[j]; proc = &loom->proc[j];
if(proc_load_cpus(emu, loom, proc, metadata_proc) < 0) if (proc_load_cpus(emu, loom, proc, metadata_proc) < 0)
continue; continue;
if(metadata_proc) if (metadata_proc)
die("duplicated metadata found in pid %d and %d\n", die("duplicated metadata found in pid %d and %d\n",
metadata_proc->pid, metadata_proc->pid,
proc->pid); proc->pid);
metadata_proc = proc; metadata_proc = proc;
} }
/* One of the process must have the list of CPUs */ /* One of the process must have the list of CPUs */
if(metadata_proc == NULL) if (metadata_proc == NULL)
die("no metadata found in loom %s\n", loom->hostname); die("no metadata found in loom %s\n", loom->hostname);
if(loom->ncpus == 0) if (loom->ncpus == 0)
die("no CPUs found in loom %s\n", loom->hostname); die("no CPUs found in loom %s\n", loom->hostname);
} }
} }
@ -679,14 +665,12 @@ destroy_metadata(struct ovni_emu *emu)
trace = &emu->trace; trace = &emu->trace;
for(i=0; i<trace->nlooms; i++) for (i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
for(j=0; j<loom->nprocs; j++) for (j = 0; j < loom->nprocs; j++) {
{
proc = &loom->proc[j]; proc = &loom->proc[j];
if(proc->meta == NULL) if (proc->meta == NULL)
die("cannot destroy metadata: is NULL\n"); die("cannot destroy metadata: is NULL\n");
json_value_free(proc->meta); json_value_free(proc->meta);
@ -707,10 +691,9 @@ open_prvs(struct ovni_emu *emu, char *tracedir)
emu->prv_thread = fopen(path, "w"); emu->prv_thread = fopen(path, "w");
if(emu->prv_thread == NULL) if (emu->prv_thread == NULL) {
{
err("error opening thread PRV file %s: %s\n", path, err("error opening thread PRV file %s: %s\n", path,
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -718,10 +701,9 @@ open_prvs(struct ovni_emu *emu, char *tracedir)
emu->prv_cpu = fopen(path, "w"); emu->prv_cpu = fopen(path, "w");
if(emu->prv_cpu == NULL) if (emu->prv_cpu == NULL) {
{
err("error opening cpu PRV file %s: %s\n", path, err("error opening cpu PRV file %s: %s\n", path,
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -788,10 +770,8 @@ parse_args(struct ovni_emu *emu, int argc, char *argv[])
{ {
int opt; int opt;
while((opt = getopt(argc, argv, "c:l")) != -1) while ((opt = getopt(argc, argv, "c:l")) != -1) {
{ switch (opt) {
switch(opt)
{
case 'c': case 'c':
emu->clock_offset_file = optarg; emu->clock_offset_file = optarg;
break; break;
@ -803,8 +783,7 @@ parse_args(struct ovni_emu *emu, int argc, char *argv[])
} }
} }
if(optind >= argc) if (optind >= argc) {
{
err("missing tracedir\n"); err("missing tracedir\n");
usage(argc, argv); usage(argc, argv);
} }
@ -817,22 +796,21 @@ set_clock_offsets(struct ovni_emu *emu, const char *host, size_t offset)
{ {
size_t matches = 0; size_t matches = 0;
for(size_t i = 0; i < emu->trace.nlooms; i++) for (size_t i = 0; i < emu->trace.nlooms; i++) {
{
struct ovni_loom *loom = &emu->trace.loom[i]; struct ovni_loom *loom = &emu->trace.loom[i];
/* Match the hostname exactly */ /* Match the hostname exactly */
if(strcmp(loom->hostname, host) != 0) if (strcmp(loom->hostname, host) != 0)
continue; continue;
if(loom->clock_offset != 0) if (loom->clock_offset != 0)
die("loom %s already has a clock offset\n", loom->dname); die("loom %s already has a clock offset\n", loom->dname);
loom->clock_offset = offset; loom->clock_offset = offset;
matches++; matches++;
} }
if(matches == 0) if (matches == 0)
die("no loom has hostname %s\n", host); die("no loom has hostname %s\n", host);
} }
@ -849,53 +827,44 @@ load_clock_offsets(struct ovni_emu *emu)
struct ovni_trace *trace; struct ovni_trace *trace;
struct ovni_stream *stream; struct ovni_stream *stream;
if(emu->clock_offset_file != NULL) if (emu->clock_offset_file != NULL) {
{
f = fopen(emu->clock_offset_file, "r"); f = fopen(emu->clock_offset_file, "r");
/* If provided by the user, it must exist */ /* If provided by the user, it must exist */
if(f == NULL) if (f == NULL) {
{
err("error opening clock offset file %s: %s\n", err("error opening clock offset file %s: %s\n",
emu->clock_offset_file, emu->clock_offset_file,
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} } else {
else
{
char path[PATH_MAX]; char path[PATH_MAX];
if(snprintf(path, PATH_MAX, "%s/clock-offsets.txt", if (snprintf(path, PATH_MAX, "%s/clock-offsets.txt",
emu->tracedir) >= PATH_MAX) emu->tracedir)
{ >= PATH_MAX) {
die("clock offset path too long\n"); die("clock offset path too long\n");
} }
f = fopen(path, "r"); f = fopen(path, "r");
if(f == NULL) if (f == NULL) {
{
/* May not exist, but is fine */ /* May not exist, but is fine */
return; return;
} }
} }
/* Ignore header line */ /* Ignore header line */
if(fgets(buf, 1024, f) == NULL) if (fgets(buf, 1024, f) == NULL) {
{
perror("fgets failed"); perror("fgets failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while(1) while (1) {
{
errno = 0; errno = 0;
ret = fscanf(f, "%d %s %lf %lf %lf", &rank, host, &offset, &mean, &std); ret = fscanf(f, "%d %s %lf %lf %lf", &rank, host, &offset, &mean, &std);
if(ret == EOF) if (ret == EOF) {
{ if (errno != 0) {
if(errno != 0)
{
perror("fscanf failed"); perror("fscanf failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -903,10 +872,9 @@ load_clock_offsets(struct ovni_emu *emu)
break; break;
} }
if(ret != 5) if (ret != 5) {
{
err("fscanf read %d instead of 5 fields in %s\n", err("fscanf read %d instead of 5 fields in %s\n",
ret, emu->clock_offset_file); ret, emu->clock_offset_file);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -917,8 +885,7 @@ load_clock_offsets(struct ovni_emu *emu)
trace = &emu->trace; trace = &emu->trace;
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
loom = stream->loom; loom = stream->loom;
stream->clock_offset = loom->clock_offset; stream->clock_offset = loom->clock_offset;
@ -941,8 +908,7 @@ write_row_cpu(struct ovni_emu *emu)
f = fopen(path, "w"); f = fopen(path, "w");
if(f == NULL) if (f == NULL) {
{
perror("cannot open row file"); perror("cannot open row file");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -953,8 +919,7 @@ write_row_cpu(struct ovni_emu *emu)
fprintf(f, "LEVEL THREAD SIZE %ld\n", emu->total_ncpus); fprintf(f, "LEVEL THREAD SIZE %ld\n", emu->total_ncpus);
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
fprintf(f, "%s\n", cpu->name); fprintf(f, "%s\n", cpu->name);
} }
@ -974,8 +939,7 @@ write_row_thread(struct ovni_emu *emu)
f = fopen(path, "w"); f = fopen(path, "w");
if(f == NULL) if (f == NULL) {
{
perror("cannot open row file"); perror("cannot open row file");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -986,8 +950,7 @@ write_row_thread(struct ovni_emu *emu)
fprintf(f, "LEVEL THREAD SIZE %ld\n", emu->total_nthreads); fprintf(f, "LEVEL THREAD SIZE %ld\n", emu->total_nthreads);
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
fprintf(f, "THREAD %d.%d\n", th->proc->appid, th->tid); fprintf(f, "THREAD %d.%d\n", th->proc->appid, th->tid);
} }
@ -1009,15 +972,12 @@ init_threads(struct ovni_emu *emu)
trace = &emu->trace; trace = &emu->trace;
for(i=0; i<trace->nlooms; i++) for (i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
for(j=0; j<loom->nprocs; j++) for (j = 0; j < loom->nprocs; j++) {
{
proc = &loom->proc[j]; proc = &loom->proc[j];
emu->total_nprocs++; emu->total_nprocs++;
for(k=0; k<proc->nthreads; k++) for (k = 0; k < proc->nthreads; k++) {
{
thread = &proc->thread[k]; thread = &proc->thread[k];
emu->total_nthreads++; emu->total_nthreads++;
} }
@ -1025,22 +985,18 @@ init_threads(struct ovni_emu *emu)
} }
emu->global_thread = calloc(emu->total_nthreads, emu->global_thread = calloc(emu->total_nthreads,
sizeof(*emu->global_thread)); sizeof(*emu->global_thread));
if(emu->global_thread == NULL) if (emu->global_thread == NULL) {
{
perror("calloc failed"); perror("calloc failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for(gi=0, i=0; i<trace->nlooms; i++) for (gi = 0, i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
for(j=0; j<loom->nprocs; j++) for (j = 0; j < loom->nprocs; j++) {
{
proc = &loom->proc[j]; proc = &loom->proc[j];
for(k=0; k<proc->nthreads; k++) for (k = 0; k < proc->nthreads; k++) {
{
thread = &proc->thread[k]; thread = &proc->thread[k];
emu->global_thread[gi++] = thread; emu->global_thread[gi++] = thread;
@ -1060,25 +1016,22 @@ init_cpus(struct ovni_emu *emu)
trace = &emu->trace; trace = &emu->trace;
emu->global_cpu = calloc(emu->total_ncpus, emu->global_cpu = calloc(emu->total_ncpus,
sizeof(*emu->global_cpu)); sizeof(*emu->global_cpu));
if(emu->global_cpu == NULL) if (emu->global_cpu == NULL) {
{
perror("calloc"); perror("calloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for(i=0; i<trace->nlooms; i++) for (i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
for(j=0; j<loom->ncpus; j++) for (j = 0; j < loom->ncpus; j++) {
{
cpu = &loom->cpu[j]; cpu = &loom->cpu[j];
emu->global_cpu[cpu->gindex] = cpu; emu->global_cpu[cpu->gindex] = cpu;
if(snprintf(cpu->name, MAX_CPU_NAME, "CPU %ld.%ld", if (snprintf(cpu->name, MAX_CPU_NAME, "CPU %ld.%ld",
i, j) >= MAX_CPU_NAME) i, j)
{ >= MAX_CPU_NAME) {
err("error cpu %ld.%ld name too long\n", i, j); err("error cpu %ld.%ld name too long\n", i, j);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -1086,9 +1039,9 @@ init_cpus(struct ovni_emu *emu)
} }
emu->global_cpu[loom->vcpu.gindex] = &loom->vcpu; emu->global_cpu[loom->vcpu.gindex] = &loom->vcpu;
if(snprintf(loom->vcpu.name, MAX_CPU_NAME, "CPU %ld.*", if (snprintf(loom->vcpu.name, MAX_CPU_NAME, "CPU %ld.*",
i) >= MAX_CPU_NAME) i)
{ >= MAX_CPU_NAME) {
err("error cpu %ld.* name too long\n", i); err("error cpu %ld.* name too long\n", i);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -1104,11 +1057,10 @@ create_pcf_cpus(struct ovni_emu *emu)
int prvtype = chan_to_prvtype[CHAN_OVNI_CPU]; int prvtype = chan_to_prvtype[CHAN_OVNI_CPU];
struct pcf_type *type = pcf_find_type(pcf, prvtype); struct pcf_type *type = pcf_find_type(pcf, prvtype);
if(type == NULL) if (type == NULL)
die("cannot find PCF type for CHAN_OVNI_CPU\n"); die("cannot find PCF type for CHAN_OVNI_CPU\n");
for(size_t i=0; i<emu->total_ncpus; i++) for (size_t i = 0; i < emu->total_ncpus; i++) {
{
int value = i + 1; int value = i + 1;
char *label = emu->global_cpu[i]->name; char *label = emu->global_cpu[i]->name;
@ -1123,14 +1075,12 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[])
parse_args(emu, argc, argv); parse_args(emu, argc, argv);
if(ovni_load_trace(&emu->trace, emu->tracedir)) if (ovni_load_trace(&emu->trace, emu->tracedir)) {
{
err("error loading ovni trace\n"); err("error loading ovni trace\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(ovni_load_streams(&emu->trace)) if (ovni_load_streams(&emu->trace)) {
{
err("error loading streams\n"); err("error loading streams\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -1151,8 +1101,8 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[])
emu->global_offset = 0; emu->global_offset = 0;
err("loaded %ld cpus and %ld threads\n", err("loaded %ld cpus and %ld threads\n",
emu->total_ncpus, emu->total_ncpus,
emu->total_nthreads); emu->total_nthreads);
} }
static void static void
@ -1181,41 +1131,41 @@ emu_destroy(struct ovni_emu *emu)
} }
void void
edie(struct ovni_emu *emu, const char* fmt, ...) edie(struct ovni_emu *emu, const char *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
fprintf(stderr, "fatal: "); fprintf(stderr, "fatal: ");
vfprintf(stderr, fmt, args); vfprintf(stderr, fmt, args);
va_end(args); va_end(args);
fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n", fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n",
emu->cur_ev->header.model, emu->cur_ev->header.model,
emu->cur_ev->header.category, emu->cur_ev->header.category,
emu->cur_ev->header.value, emu->cur_ev->header.value,
emu->cur_ev->header.clock, emu->cur_ev->header.clock,
emu->cur_thread->tid); emu->cur_thread->tid);
abort(); abort();
} }
void void
eerr(struct ovni_emu *emu, const char* fmt, ...) eerr(struct ovni_emu *emu, const char *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
fprintf(stderr, "fatal: "); fprintf(stderr, "fatal: ");
vfprintf(stderr, fmt, args); vfprintf(stderr, fmt, args);
va_end(args); va_end(args);
fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n", fprintf(stderr, "fatal: while evaluating the event %c%c%c with clock=%ld in thread=%d\n",
emu->cur_ev->header.model, emu->cur_ev->header.model,
emu->cur_ev->header.category, emu->cur_ev->header.category,
emu->cur_ev->header.value, emu->cur_ev->header.value,
emu->cur_ev->header.clock, emu->cur_ev->header.clock,
emu->cur_thread->tid); emu->cur_thread->tid);
} }
int int
@ -1225,8 +1175,7 @@ main(int argc, char *argv[])
emu = malloc(sizeof(struct ovni_emu)); emu = malloc(sizeof(struct ovni_emu));
if(emu == NULL) if (emu == NULL) {
{
perror("malloc"); perror("malloc");
return 1; return 1;
} }

34
emu.h
View File

@ -7,11 +7,11 @@
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
#include "ovni.h"
#include "uthash.h"
#include "parson.h"
#include "heap.h" #include "heap.h"
#include "ovni.h"
#include "parson.h"
#include "pcf.h" #include "pcf.h"
#include "uthash.h"
/* Emulated thread runtime status */ /* Emulated thread runtime status */
enum ethread_state { enum ethread_state {
@ -136,8 +136,8 @@ struct ovni_ethread;
struct ovni_eproc; struct ovni_eproc;
struct task_type { struct task_type {
uint32_t id; /* Per-process task identifier */ uint32_t id; /* Per-process task identifier */
uint32_t gid; /* Global identifier computed from the label */ uint32_t gid; /* Global identifier computed from the label */
char label[MAX_PCF_LABEL]; char label[MAX_PCF_LABEL];
UT_hash_handle hh; UT_hash_handle hh;
}; };
@ -158,17 +158,17 @@ struct task {
}; };
struct task_info { struct task_info {
/* Both hash maps of all known tasks and types */ /* Both hash maps of all known tasks and types */
struct task_type *types; struct task_type *types;
struct task *tasks; struct task *tasks;
}; };
struct task_stack { struct task_stack {
union { union {
struct task *top; /* Synctactic sugar */ struct task *top; /* Synctactic sugar */
struct task *tasks; struct task *tasks;
}; };
struct ovni_ethread *thread; struct ovni_ethread *thread;
}; };
#define MAX_CHAN_STACK 512 #define MAX_CHAN_STACK 512
@ -383,7 +383,7 @@ struct ovni_eproc {
/* TODO: Use dynamic allocation */ /* TODO: Use dynamic allocation */
struct task_info nosv_task_info; struct task_info nosv_task_info;
struct task_info nanos6_task_info; struct task_info nanos6_task_info;
}; };
@ -445,7 +445,7 @@ struct ovni_loom {
size_t nprocs; size_t nprocs;
char hostname[OVNI_MAX_HOSTNAME]; char hostname[OVNI_MAX_HOSTNAME];
char dname[PATH_MAX]; /* Loom directory name */ char dname[PATH_MAX]; /* Loom directory name */
char path[PATH_MAX]; /* Relative to cwd */ char path[PATH_MAX]; /* Relative to cwd */
size_t max_ncpus; size_t max_ncpus;
size_t max_phyid; size_t max_phyid;
@ -546,8 +546,8 @@ struct ovni_emu {
/* Emulator function declaration */ /* Emulator function declaration */
void edie(struct ovni_emu *emu, const char* fmt, ...); void edie(struct ovni_emu *emu, const char *fmt, ...);
void eerr(struct ovni_emu *emu, const char* fmt, ...); void eerr(struct ovni_emu *emu, const char *fmt, ...);
void hook_init_ovni(struct ovni_emu *emu); void hook_init_ovni(struct ovni_emu *emu);
void hook_pre_ovni(struct ovni_emu *emu); void hook_pre_ovni(struct ovni_emu *emu);

View File

@ -3,11 +3,11 @@
#include "uthash.h" #include "uthash.h"
#include "ovni.h"
#include "trace.h"
#include "emu.h"
#include "prv.h"
#include "chan.h" #include "chan.h"
#include "emu.h"
#include "ovni.h"
#include "prv.h"
#include "trace.h"
/* --------------------------- init ------------------------------- */ /* --------------------------- init ------------------------------- */
@ -27,8 +27,7 @@ hook_init_kernel(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the channels in all threads */ /* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
@ -37,8 +36,7 @@ hook_init_kernel(struct ovni_emu *emu)
} }
/* Init the channels in all cpus */ /* Init the channels in all cpus */
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
@ -58,8 +56,7 @@ context_switch(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan = &th->chan[CHAN_KERNEL_CS]; chan = &th->chan[CHAN_KERNEL_CS];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case 'O': case 'O':
chan_push(chan, ST_KERNEL_CSOUT); chan_push(chan, ST_KERNEL_CSOUT);
break; break;
@ -68,24 +65,23 @@ context_switch(struct ovni_emu *emu)
break; break;
default: default:
edie(emu, "unexpected value '%c' (expecting 'O' or 'I')\n", edie(emu, "unexpected value '%c' (expecting 'O' or 'I')\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
} }
} }
void void
hook_pre_kernel(struct ovni_emu *emu) hook_pre_kernel(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.model != 'K') if (emu->cur_ev->header.model != 'K')
edie(emu, "hook_pre_kernel: unexpected event with model %c\n", edie(emu, "hook_pre_kernel: unexpected event with model %c\n",
emu->cur_ev->header.model); emu->cur_ev->header.model);
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{
case 'C': case 'C':
context_switch(emu); context_switch(emu);
break; break;
default: default:
edie(emu, "hook_pre_kernel: unexpected event with category %c\n", edie(emu, "hook_pre_kernel: unexpected event with category %c\n",
emu->cur_ev->header.category); emu->cur_ev->header.category);
} }
} }

View File

@ -4,11 +4,11 @@
#include "uthash.h" #include "uthash.h"
#include "utlist.h" #include "utlist.h"
#include "ovni.h" #include "chan.h"
#include "emu.h" #include "emu.h"
#include "emu_task.h" #include "emu_task.h"
#include "ovni.h"
#include "prv.h" #include "prv.h"
#include "chan.h"
void void
hook_init_nanos6(struct ovni_emu *emu) hook_init_nanos6(struct ovni_emu *emu)
@ -25,37 +25,34 @@ hook_init_nanos6(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the channels in all threads */ /* Init the channels in all threads */
for(size_t i=0; i<emu->total_nthreads; i++) for (size_t i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
chan_th_init(th, uth, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_ACTIVE, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_ACTIVE, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NANOS6_THREAD, CHAN_TRACK_NONE, 0, 1, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NANOS6_THREAD, CHAN_TRACK_NONE, 0, 1, 1, row, prv_th, clock);
} }
/* Init the Nanos6 channels in all cpus */ /* Init the Nanos6 channels in all cpus */
for(size_t i=0; i<emu->total_ncpus; i++) for (size_t i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_THREAD, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NANOS6_THREAD, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
} }
/* Init task stack */ /* Init task stack */
for(size_t i=0; i<emu->total_nthreads; i++) for (size_t i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
th->nanos6_task_stack.thread = th; th->nanos6_task_stack.thread = th;
} }
@ -72,7 +69,7 @@ chan_task_stopped(struct ovni_emu *emu)
chan_set(&th->chan[CHAN_NANOS6_TASKID], 0); chan_set(&th->chan[CHAN_NANOS6_TASKID], 0);
chan_set(&th->chan[CHAN_NANOS6_TYPE], 0); chan_set(&th->chan[CHAN_NANOS6_TYPE], 0);
if(emu->cur_loom->rank_enabled) if (emu->cur_loom->rank_enabled)
chan_set(&th->chan[CHAN_NANOS6_RANK], 0); chan_set(&th->chan[CHAN_NANOS6_RANK], 0);
} }
@ -85,41 +82,41 @@ chan_task_running(struct ovni_emu *emu, struct task *task)
th = emu->cur_thread; th = emu->cur_thread;
proc = emu->cur_proc; proc = emu->cur_proc;
if(task->id == 0) if (task->id == 0)
edie(emu, "task id cannot be 0\n"); edie(emu, "task id cannot be 0\n");
if(task->type->gid == 0) if (task->type->gid == 0)
edie(emu, "task type gid cannot be 0\n"); edie(emu, "task type gid cannot be 0\n");
if(proc->appid <= 0) if (proc->appid <= 0)
edie(emu, "app id must be positive\n"); edie(emu, "app id must be positive\n");
chan_set(&th->chan[CHAN_NANOS6_TASKID], task->id); chan_set(&th->chan[CHAN_NANOS6_TASKID], task->id);
chan_set(&th->chan[CHAN_NANOS6_TYPE], task->type->gid); chan_set(&th->chan[CHAN_NANOS6_TYPE], task->type->gid);
if(emu->cur_loom->rank_enabled) if (emu->cur_loom->rank_enabled)
chan_set(&th->chan[CHAN_NANOS6_RANK], proc->rank + 1); chan_set(&th->chan[CHAN_NANOS6_RANK], proc->rank + 1);
} }
static void static void
chan_task_switch(struct ovni_emu *emu, chan_task_switch(struct ovni_emu *emu,
struct task *prev, struct task *next) struct task *prev, struct task *next)
{ {
struct ovni_ethread *th = emu->cur_thread; struct ovni_ethread *th = emu->cur_thread;
if(!prev || !next) if (!prev || !next)
edie(emu, "cannot switch to or from a NULL task\n"); edie(emu, "cannot switch to or from a NULL task\n");
if(prev == next) if (prev == next)
edie(emu, "cannot switch to the same task\n"); edie(emu, "cannot switch to the same task\n");
if(next->id == 0) if (next->id == 0)
edie(emu, "next task id cannot be 0\n"); edie(emu, "next task id cannot be 0\n");
if(next->type->gid == 0) if (next->type->gid == 0)
edie(emu, "next task type id cannot be 0\n"); edie(emu, "next task type id cannot be 0\n");
if(prev->thread != next->thread) if (prev->thread != next->thread)
edie(emu, "cannot switch to a task of another thread\n"); edie(emu, "cannot switch to a task of another thread\n");
/* No need to change the rank as we will switch to tasks from /* No need to change the rank as we will switch to tasks from
@ -130,14 +127,14 @@ chan_task_switch(struct ovni_emu *emu,
* the same type event, to mark the end of the current task. For * the same type event, to mark the end of the current task. For
* now we only emit a new type if we switch to a type with a * now we only emit a new type if we switch to a type with a
* different gid. */ * different gid. */
if(prev->type->gid != next->type->gid) if (prev->type->gid != next->type->gid)
chan_set(&th->chan[CHAN_NANOS6_TYPE], next->type->gid); chan_set(&th->chan[CHAN_NANOS6_TYPE], next->type->gid);
} }
static void static void
update_task_state(struct ovni_emu *emu) update_task_state(struct ovni_emu *emu)
{ {
if(ovni_payload_size(emu->cur_ev) < 4) if (ovni_payload_size(emu->cur_ev) < 4)
edie(emu, "missing task id in payload\n"); edie(emu, "missing task id in payload\n");
uint32_t task_id = emu->cur_ev->payload.u32[0]; uint32_t task_id = emu->cur_ev->payload.u32[0];
@ -150,17 +147,24 @@ update_task_state(struct ovni_emu *emu)
struct task *task = task_find(info->tasks, task_id); struct task *task = task_find(info->tasks, task_id);
if(task == NULL) if (task == NULL)
edie(emu, "cannot find task with id %u\n", task_id); edie(emu, "cannot find task with id %u\n", task_id);
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'x':
case 'x': task_execute(emu, stack, task); break; task_execute(emu, stack, task);
case 'e': task_end(emu, stack, task); break; break;
case 'p': task_pause(emu, stack, task); break; case 'e':
case 'r': task_resume(emu, stack, task); break; task_end(emu, stack, task);
break;
case 'p':
task_pause(emu, stack, task);
break;
case 'r':
task_resume(emu, stack, task);
break;
default: default:
edie(emu, "unexpected Nanos6 task event\n"); edie(emu, "unexpected Nanos6 task event\n");
} }
} }
@ -170,13 +174,13 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now)
char tr = emu->cur_ev->header.value; char tr = emu->cur_ev->header.value;
/* Ensure we don't clobber the value */ /* Ensure we don't clobber the value */
if(tr == 'X' || tr == 'E') if (tr == 'X' || tr == 'E')
edie(emu, "unexpected event value %c\n", tr); edie(emu, "unexpected event value %c\n", tr);
/* Modify the event value to detect nested transitions */ /* Modify the event value to detect nested transitions */
if(tr == 'x' && was_running) if (tr == 'x' && was_running)
tr = 'X'; /* Execute a new nested task */ tr = 'X'; /* Execute a new nested task */
else if(tr == 'e' && runs_now) else if (tr == 'e' && runs_now)
tr = 'E'; /* End a nested task */ tr = 'E'; /* End a nested task */
return tr; return tr;
@ -184,10 +188,9 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now)
static void static void
update_task_channels(struct ovni_emu *emu, update_task_channels(struct ovni_emu *emu,
char tr, struct task *prev, struct task *next) char tr, struct task *prev, struct task *next)
{ {
switch(tr) switch (tr) {
{
case 'x': case 'x':
case 'r': case 'r':
chan_task_running(emu, next); chan_task_running(emu, next);
@ -208,23 +211,22 @@ update_task_channels(struct ovni_emu *emu,
static void static void
enforce_task_rules(struct ovni_emu *emu, enforce_task_rules(struct ovni_emu *emu,
char tr, struct task *prev, struct task *next) char tr, struct task *prev, struct task *next)
{ {
UNUSED(prev); UNUSED(prev);
/* If a task has just entered the running state, it must show /* If a task has just entered the running state, it must show
* the running task body subsystem */ * the running task body subsystem */
if(tr == 'x' || tr == 'X') if (tr == 'x' || tr == 'X') {
{ if (next->state != TASK_ST_RUNNING)
if(next->state != TASK_ST_RUNNING)
edie(emu, "a Nanos6 task starts running but not in the running state\n"); edie(emu, "a Nanos6 task starts running but not in the running state\n");
struct ovni_ethread *th = emu->cur_thread; struct ovni_ethread *th = emu->cur_thread;
struct ovni_chan *sschan = &th->chan[CHAN_NANOS6_SUBSYSTEM]; struct ovni_chan *sschan = &th->chan[CHAN_NANOS6_SUBSYSTEM];
int st = chan_get_st(sschan); int st = chan_get_st(sschan);
if(st != 0 && st != ST_NANOS6_TASK_BODY) if (st != 0 && st != ST_NANOS6_TASK_BODY)
edie(emu, "a Nanos6 task starts running but not in the \"running body\" subsystem state\n"); edie(emu, "a Nanos6 task starts running but not in the \"running body\" subsystem state\n");
} }
} }
@ -255,7 +257,7 @@ update_task(struct ovni_emu *emu)
static void static void
create_task(struct ovni_emu *emu) create_task(struct ovni_emu *emu)
{ {
if(ovni_payload_size(emu->cur_ev) != 8) if (ovni_payload_size(emu->cur_ev) != 8)
edie(emu, "cannot create task: unexpected payload size\n"); edie(emu, "cannot create task: unexpected payload size\n");
uint32_t task_id = emu->cur_ev->payload.u32[0]; uint32_t task_id = emu->cur_ev->payload.u32[0];
@ -269,8 +271,7 @@ create_task(struct ovni_emu *emu)
static void static void
pre_task(struct ovni_emu *emu) pre_task(struct ovni_emu *emu)
{ {
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case 'c': case 'c':
create_task(emu); create_task(emu);
break; break;
@ -290,10 +291,10 @@ pre_type(struct ovni_emu *emu)
{ {
uint8_t value = emu->cur_ev->header.value; uint8_t value = emu->cur_ev->header.value;
if(value != 'c') if (value != 'c')
edie(emu, "unexpected event value %c\n", value); edie(emu, "unexpected event value %c\n", value);
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0) if ((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
edie(emu, "expecting a jumbo event\n"); edie(emu, "expecting a jumbo event\n");
uint8_t *data = &emu->cur_ev->payload.jumbo.data[0]; uint8_t *data = &emu->cur_ev->payload.jumbo.data[0];
@ -316,12 +317,19 @@ pre_deps(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'r':
case 'r': chan_push(chan_th, ST_NANOS6_DEP_REG); break; chan_push(chan_th, ST_NANOS6_DEP_REG);
case 'R': chan_pop (chan_th, ST_NANOS6_DEP_REG); break; break;
case 'u': chan_push(chan_th, ST_NANOS6_DEP_UNREG); break; case 'R':
case 'U': chan_pop (chan_th, ST_NANOS6_DEP_UNREG); break; chan_pop(chan_th, ST_NANOS6_DEP_REG);
break;
case 'u':
chan_push(chan_th, ST_NANOS6_DEP_UNREG);
break;
case 'U':
chan_pop(chan_th, ST_NANOS6_DEP_UNREG);
break;
default: default:
edie(emu, "unknown Nanos6 dependency event\n"); edie(emu, "unknown Nanos6 dependency event\n");
} }
@ -336,16 +344,31 @@ pre_blocking(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'b':
case 'b': chan_push(chan_th, ST_NANOS6_BLK_BLOCKING); break; chan_push(chan_th, ST_NANOS6_BLK_BLOCKING);
case 'B': chan_pop (chan_th, ST_NANOS6_BLK_BLOCKING); break; break;
case 'u': chan_push(chan_th, ST_NANOS6_BLK_UNBLOCKING); break; case 'B':
case 'U': chan_pop (chan_th, ST_NANOS6_BLK_UNBLOCKING); break; chan_pop(chan_th, ST_NANOS6_BLK_BLOCKING);
case 'w': chan_push(chan_th, ST_NANOS6_BLK_TASKWAIT); break; break;
case 'W': chan_pop (chan_th, ST_NANOS6_BLK_TASKWAIT); break; case 'u':
case 'f': chan_push(chan_th, ST_NANOS6_BLK_WAITFOR); break; chan_push(chan_th, ST_NANOS6_BLK_UNBLOCKING);
case 'F': chan_pop (chan_th, ST_NANOS6_BLK_WAITFOR); break; break;
case 'U':
chan_pop(chan_th, ST_NANOS6_BLK_UNBLOCKING);
break;
case 'w':
chan_push(chan_th, ST_NANOS6_BLK_TASKWAIT);
break;
case 'W':
chan_pop(chan_th, ST_NANOS6_BLK_TASKWAIT);
break;
case 'f':
chan_push(chan_th, ST_NANOS6_BLK_WAITFOR);
break;
case 'F':
chan_pop(chan_th, ST_NANOS6_BLK_WAITFOR);
break;
default: default:
edie(emu, "unknown Nanos6 blocking event\n"); edie(emu, "unknown Nanos6 blocking event\n");
} }
@ -360,21 +383,46 @@ pre_worker(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case '[':
case '[': chan_push(chan_th, ST_NANOS6_WORKER_LOOP); break; chan_push(chan_th, ST_NANOS6_WORKER_LOOP);
case ']': chan_pop (chan_th, ST_NANOS6_WORKER_LOOP); break; break;
case 't': chan_push(chan_th, ST_NANOS6_HANDLING_TASK); break; case ']':
case 'T': chan_pop (chan_th, ST_NANOS6_HANDLING_TASK); break; chan_pop(chan_th, ST_NANOS6_WORKER_LOOP);
case 'w': chan_push(chan_th, ST_NANOS6_SWITCH_TO); break; break;
case 'W': chan_pop (chan_th, ST_NANOS6_SWITCH_TO); break; case 't':
case 'm': chan_push(chan_th, ST_NANOS6_MIGRATE); break; chan_push(chan_th, ST_NANOS6_HANDLING_TASK);
case 'M': chan_pop (chan_th, ST_NANOS6_MIGRATE); break; break;
case 's': chan_push(chan_th, ST_NANOS6_SUSPEND); break; case 'T':
case 'S': chan_pop (chan_th, ST_NANOS6_SUSPEND); break; chan_pop(chan_th, ST_NANOS6_HANDLING_TASK);
case 'r': chan_push(chan_th, ST_NANOS6_RESUME); break; break;
case 'R': chan_pop (chan_th, ST_NANOS6_RESUME); break; case 'w':
case '*': chan_ev (chan_th, EV_NANOS6_SIGNAL); break; chan_push(chan_th, ST_NANOS6_SWITCH_TO);
break;
case 'W':
chan_pop(chan_th, ST_NANOS6_SWITCH_TO);
break;
case 'm':
chan_push(chan_th, ST_NANOS6_MIGRATE);
break;
case 'M':
chan_pop(chan_th, ST_NANOS6_MIGRATE);
break;
case 's':
chan_push(chan_th, ST_NANOS6_SUSPEND);
break;
case 'S':
chan_pop(chan_th, ST_NANOS6_SUSPEND);
break;
case 'r':
chan_push(chan_th, ST_NANOS6_RESUME);
break;
case 'R':
chan_pop(chan_th, ST_NANOS6_RESUME);
break;
case '*':
chan_ev(chan_th, EV_NANOS6_SIGNAL);
break;
default: default:
edie(emu, "unknown Nanos6 worker event\n"); edie(emu, "unknown Nanos6 worker event\n");
} }
@ -389,12 +437,19 @@ pre_memory(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'a':
case 'a': chan_push(chan_th, ST_NANOS6_ALLOCATING); break; chan_push(chan_th, ST_NANOS6_ALLOCATING);
case 'A': chan_pop (chan_th, ST_NANOS6_ALLOCATING); break; break;
case 'f': chan_push(chan_th, ST_NANOS6_FREEING); break; case 'A':
case 'F': chan_pop (chan_th, ST_NANOS6_FREEING); break; chan_pop(chan_th, ST_NANOS6_ALLOCATING);
break;
case 'f':
chan_push(chan_th, ST_NANOS6_FREEING);
break;
case 'F':
chan_pop(chan_th, ST_NANOS6_FREEING);
break;
default: default:
edie(emu, "unknown Nanos6 memory event\n"); edie(emu, "unknown Nanos6 memory event\n");
} }
@ -409,17 +464,34 @@ pre_sched(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM]; chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case '[':
case '[': chan_push(chan_th, ST_NANOS6_SCHED_SERVING); break; chan_push(chan_th, ST_NANOS6_SCHED_SERVING);
case ']': chan_pop (chan_th, ST_NANOS6_SCHED_SERVING); break; break;
case 'a': chan_push(chan_th, ST_NANOS6_SCHED_ADDING); break; case ']':
case 'A': chan_pop (chan_th, ST_NANOS6_SCHED_ADDING); break; chan_pop(chan_th, ST_NANOS6_SCHED_SERVING);
case 'p': chan_push(chan_th, ST_NANOS6_SCHED_PROCESSING); break; break;
case 'P': chan_pop (chan_th, ST_NANOS6_SCHED_PROCESSING); break; case 'a':
case '@': chan_ev (chan_th, EV_NANOS6_SCHED_SELF); break; chan_push(chan_th, ST_NANOS6_SCHED_ADDING);
case 'r': chan_ev (chan_th, EV_NANOS6_SCHED_RECV); break; break;
case 's': chan_ev (chan_th, EV_NANOS6_SCHED_SEND); break; case 'A':
chan_pop(chan_th, ST_NANOS6_SCHED_ADDING);
break;
case 'p':
chan_push(chan_th, ST_NANOS6_SCHED_PROCESSING);
break;
case 'P':
chan_pop(chan_th, ST_NANOS6_SCHED_PROCESSING);
break;
case '@':
chan_ev(chan_th, EV_NANOS6_SCHED_SELF);
break;
case 'r':
chan_ev(chan_th, EV_NANOS6_SCHED_RECV);
break;
case 's':
chan_ev(chan_th, EV_NANOS6_SCHED_SEND);
break;
default: default:
edie(emu, "unknown Nanos6 scheduler event\n"); edie(emu, "unknown Nanos6 scheduler event\n");
} }
@ -434,16 +506,31 @@ pre_thread(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NANOS6_THREAD]; chan_th = &th->chan[CHAN_NANOS6_THREAD];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'e':
case 'e': chan_push(chan_th, ST_NANOS6_TH_EXTERNAL); break; chan_push(chan_th, ST_NANOS6_TH_EXTERNAL);
case 'E': chan_pop (chan_th, ST_NANOS6_TH_EXTERNAL); break; break;
case 'w': chan_push(chan_th, ST_NANOS6_TH_WORKER); break; case 'E':
case 'W': chan_pop (chan_th, ST_NANOS6_TH_WORKER); break; chan_pop(chan_th, ST_NANOS6_TH_EXTERNAL);
case 'l': chan_push(chan_th, ST_NANOS6_TH_LEADER); break; break;
case 'L': chan_pop (chan_th, ST_NANOS6_TH_LEADER); break; case 'w':
case 'm': chan_push(chan_th, ST_NANOS6_TH_MAIN); break; chan_push(chan_th, ST_NANOS6_TH_WORKER);
case 'M': chan_pop (chan_th, ST_NANOS6_TH_MAIN); break; break;
case 'W':
chan_pop(chan_th, ST_NANOS6_TH_WORKER);
break;
case 'l':
chan_push(chan_th, ST_NANOS6_TH_LEADER);
break;
case 'L':
chan_pop(chan_th, ST_NANOS6_TH_LEADER);
break;
case 'm':
chan_push(chan_th, ST_NANOS6_TH_MAIN);
break;
case 'M':
chan_pop(chan_th, ST_NANOS6_TH_MAIN);
break;
default: default:
edie(emu, "unknown Nanos6 thread type event\n"); edie(emu, "unknown Nanos6 thread type event\n");
} }
@ -460,13 +547,16 @@ pre_ss(struct ovni_emu *emu, int st)
dbg("pre_ss chan id %d st=%d\n", chan_th->id, st); dbg("pre_ss chan id %d st=%d\n", chan_th->id, st);
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case '[':
case '[': chan_push(chan_th, st); break; chan_push(chan_th, st);
case ']': chan_pop(chan_th, st); break; break;
case ']':
chan_pop(chan_th, st);
break;
default: default:
edie(emu, "unexpected value '%c' (expecting '[' or ']')\n", edie(emu, "unexpected value '%c' (expecting '[' or ']')\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
} }
} }
@ -476,16 +566,15 @@ check_affinity(struct ovni_emu *emu)
struct ovni_ethread *th = emu->cur_thread; struct ovni_ethread *th = emu->cur_thread;
struct ovni_cpu *cpu = th->cpu; struct ovni_cpu *cpu = th->cpu;
if(!cpu || cpu->virtual) if (!cpu || cpu->virtual)
return; return;
if(cpu->nrunning_threads > 1) if (cpu->nrunning_threads > 1) {
{
eerr(emu, "cpu %s has more than one thread running\n", cpu->name); eerr(emu, "cpu %s has more than one thread running\n", cpu->name);
/* Only abort in linter mode so we can still see the /* Only abort in linter mode so we can still see the
* trace to find out what was happening */ * trace to find out what was happening */
if(emu->enable_linter) if (emu->enable_linter)
abort(); abort();
} }
} }
@ -493,30 +582,55 @@ check_affinity(struct ovni_emu *emu)
void void
hook_pre_nanos6(struct ovni_emu *emu) hook_pre_nanos6(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.model != '6') if (emu->cur_ev->header.model != '6')
edie(emu, "hook_pre_nanos6: unexpected event with model %c\n", edie(emu, "hook_pre_nanos6: unexpected event with model %c\n",
emu->cur_ev->header.model); emu->cur_ev->header.model);
if(!emu->cur_thread->is_active) { if (!emu->cur_thread->is_active) {
edie(emu, "hook_pre_nanos6: current thread %d not active\n", edie(emu, "hook_pre_nanos6: current thread %d not active\n",
emu->cur_thread->tid); emu->cur_thread->tid);
} }
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{ case 'T':
case 'T': pre_task(emu); break; pre_task(emu);
case 'C': pre_ss(emu, ST_NANOS6_TASK_CREATING); break; break;
case 'Y': pre_type(emu); break; case 'C':
case 'S': pre_sched(emu); break; pre_ss(emu, ST_NANOS6_TASK_CREATING);
case 'U': pre_ss(emu, ST_NANOS6_TASK_SUBMIT); break; break;
case 'F': pre_ss(emu, ST_NANOS6_TASK_SPAWNING); break; case 'Y':
case 'O': pre_ss(emu, ST_NANOS6_TASK_FOR); break; pre_type(emu);
case 't': pre_ss(emu, ST_NANOS6_TASK_BODY); break; break;
case 'H': pre_thread(emu); break; case 'S':
case 'D': pre_deps(emu); break; pre_sched(emu);
case 'B': pre_blocking(emu); break; break;
case 'W': pre_worker(emu); break; case 'U':
case 'M': pre_memory(emu); break; pre_ss(emu, ST_NANOS6_TASK_SUBMIT);
break;
case 'F':
pre_ss(emu, ST_NANOS6_TASK_SPAWNING);
break;
case 'O':
pre_ss(emu, ST_NANOS6_TASK_FOR);
break;
case 't':
pre_ss(emu, ST_NANOS6_TASK_BODY);
break;
case 'H':
pre_thread(emu);
break;
case 'D':
pre_deps(emu);
break;
case 'B':
pre_blocking(emu);
break;
case 'W':
pre_worker(emu);
break;
case 'M':
pre_memory(emu);
break;
default: default:
edie(emu, "unknown Nanos6 event category\n"); edie(emu, "unknown Nanos6 event category\n");
} }
@ -528,27 +642,23 @@ static void
end_lint(struct ovni_emu *emu) end_lint(struct ovni_emu *emu)
{ {
/* Ensure we run out of subsystem states */ /* Ensure we run out of subsystem states */
for(size_t i = 0; i < emu->total_nthreads; i++) for (size_t i = 0; i < emu->total_nthreads; i++) {
{
struct ovni_ethread *th = emu->global_thread[i]; struct ovni_ethread *th = emu->global_thread[i];
struct ovni_chan *ch = &th->chan[CHAN_NANOS6_SUBSYSTEM]; struct ovni_chan *ch = &th->chan[CHAN_NANOS6_SUBSYSTEM];
if(ch->n != 1) if (ch->n != 1) {
{
int top = ch->stack[ch->n - 1]; int top = ch->stack[ch->n - 1];
struct pcf_value_label *pv; struct pcf_value_label *pv;
char *name = "(unknown)"; char *name = "(unknown)";
for(pv = &nanos6_ss_values[0]; pv->label; pv++) for (pv = &nanos6_ss_values[0]; pv->label; pv++) {
{ if (pv->value == top) {
if(pv->value == top)
{
name = pv->label; name = pv->label;
break; break;
} }
} }
die("thread %d ended with %d extra stacked nanos6 subsystems, top=\"%s\"\n", die("thread %d ended with %d extra stacked nanos6 subsystems, top=\"%s\"\n",
th->tid, ch->n - 1, name); th->tid, ch->n - 1, name);
} }
} }
} }
@ -557,17 +667,14 @@ void
hook_end_nanos6(struct ovni_emu *emu) hook_end_nanos6(struct ovni_emu *emu)
{ {
/* Emit types for all channel types and processes */ /* Emit types for all channel types and processes */
for(enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) for (enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) {
{
struct pcf_file *pcf = &emu->pcf[ct]; struct pcf_file *pcf = &emu->pcf[ct];
int typeid = chan_to_prvtype[CHAN_NANOS6_TYPE]; int typeid = chan_to_prvtype[CHAN_NANOS6_TYPE];
struct pcf_type *pcftype = pcf_find_type(pcf, typeid); struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
for(size_t i = 0; i < emu->trace.nlooms; i++) for (size_t i = 0; i < emu->trace.nlooms; i++) {
{
struct ovni_loom *loom = &emu->trace.loom[i]; struct ovni_loom *loom = &emu->trace.loom[i];
for(size_t j = 0; j < loom->nprocs; j++) for (size_t j = 0; j < loom->nprocs; j++) {
{
struct ovni_eproc *proc = &loom->proc[j]; struct ovni_eproc *proc = &loom->proc[j];
task_create_pcf_types(pcftype, proc->nanos6_task_info.types); task_create_pcf_types(pcftype, proc->nanos6_task_info.types);
} }
@ -575,6 +682,6 @@ hook_end_nanos6(struct ovni_emu *emu)
} }
/* When running in linter mode perform additional checks */ /* When running in linter mode perform additional checks */
if(emu->enable_linter) if (emu->enable_linter)
end_lint(emu); end_lint(emu);
} }

View File

@ -3,10 +3,10 @@
#include "uthash.h" #include "uthash.h"
#include "ovni.h"
#include "emu.h"
#include "prv.h"
#include "chan.h" #include "chan.h"
#include "emu.h"
#include "ovni.h"
#include "prv.h"
/* --------------------------- init ------------------------------- */ /* --------------------------- init ------------------------------- */
@ -26,8 +26,7 @@ hook_init_nodes(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the channels in all threads */ /* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
@ -36,8 +35,7 @@ hook_init_nodes(struct ovni_emu *emu)
} }
/* Init the channels in all cpus */ /* Init the channels in all cpus */
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
@ -57,8 +55,7 @@ pre_subsystem(struct ovni_emu *emu, int st)
th = emu->cur_thread; th = emu->cur_thread;
chan = &th->chan[CHAN_NODES_SUBSYSTEM]; chan = &th->chan[CHAN_NODES_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case '[': case '[':
chan_push(chan, st); chan_push(chan, st);
break; break;
@ -67,31 +64,46 @@ pre_subsystem(struct ovni_emu *emu, int st)
break; break;
default: default:
edie(emu, "unexpected value '%c' (expecting '[' or ']')\n", edie(emu, "unexpected value '%c' (expecting '[' or ']')\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
} }
} }
void void
hook_pre_nodes(struct ovni_emu *emu) hook_pre_nodes(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.model != 'D') if (emu->cur_ev->header.model != 'D')
edie(emu, "hook_pre_nodes: unexpected event with model %c\n", edie(emu, "hook_pre_nodes: unexpected event with model %c\n",
emu->cur_ev->header.model); emu->cur_ev->header.model);
if(!emu->cur_thread->is_running) if (!emu->cur_thread->is_running)
edie(emu, "hook_pre_nodes: current thread %d not running\n", edie(emu, "hook_pre_nodes: current thread %d not running\n",
emu->cur_thread->tid); emu->cur_thread->tid);
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{ case 'R':
case 'R': pre_subsystem(emu, ST_NODES_REGISTER); break; pre_subsystem(emu, ST_NODES_REGISTER);
case 'U': pre_subsystem(emu, ST_NODES_UNREGISTER); break; break;
case 'W': pre_subsystem(emu, ST_NODES_IF0_WAIT); break; case 'U':
case 'I': pre_subsystem(emu, ST_NODES_IF0_INLINE); break; pre_subsystem(emu, ST_NODES_UNREGISTER);
case 'T': pre_subsystem(emu, ST_NODES_TASKWAIT); break; break;
case 'C': pre_subsystem(emu, ST_NODES_CREATE); break; case 'W':
case 'S': pre_subsystem(emu, ST_NODES_SUBMIT); break; pre_subsystem(emu, ST_NODES_IF0_WAIT);
case 'P': pre_subsystem(emu, ST_NODES_SPAWN); break; break;
case 'I':
pre_subsystem(emu, ST_NODES_IF0_INLINE);
break;
case 'T':
pre_subsystem(emu, ST_NODES_TASKWAIT);
break;
case 'C':
pre_subsystem(emu, ST_NODES_CREATE);
break;
case 'S':
pre_subsystem(emu, ST_NODES_SUBMIT);
break;
case 'P':
pre_subsystem(emu, ST_NODES_SPAWN);
break;
default: default:
break; break;
} }

View File

@ -4,11 +4,11 @@
#include "uthash.h" #include "uthash.h"
#include "utlist.h" #include "utlist.h"
#include "ovni.h" #include "chan.h"
#include "emu.h" #include "emu.h"
#include "emu_task.h" #include "emu_task.h"
#include "ovni.h"
#include "prv.h" #include "prv.h"
#include "chan.h"
/* --------------------------- init ------------------------------- */ /* --------------------------- init ------------------------------- */
@ -28,17 +28,16 @@ hook_init_nosv(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the channels in all threads */ /* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
chan_th_init(th, uth, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
/* We allow threads to emit subsystem events in cooling and /* We allow threads to emit subsystem events in cooling and
* warming states as well, as they may be allocating memory. * warming states as well, as they may be allocating memory.
@ -48,22 +47,20 @@ hook_init_nosv(struct ovni_emu *emu)
} }
/* Init the nosv channels in all cpus */ /* Init the nosv channels in all cpus */
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
chan_cpu_init(cpu, ucpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
} }
/* Init task stack */ /* Init task stack */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
th->nosv_task_stack.thread = th; th->nosv_task_stack.thread = th;
} }
@ -80,7 +77,7 @@ chan_task_stopped(struct ovni_emu *emu)
chan_set(&th->chan[CHAN_NOSV_TYPE], 0); chan_set(&th->chan[CHAN_NOSV_TYPE], 0);
chan_set(&th->chan[CHAN_NOSV_APPID], 0); chan_set(&th->chan[CHAN_NOSV_APPID], 0);
if(emu->cur_loom->rank_enabled) if (emu->cur_loom->rank_enabled)
chan_set(&th->chan[CHAN_NOSV_RANK], 0); chan_set(&th->chan[CHAN_NOSV_RANK], 0);
/* XXX: Do we need this transition? */ /* XXX: Do we need this transition? */
@ -96,20 +93,20 @@ chan_task_running(struct ovni_emu *emu, struct task *task)
th = emu->cur_thread; th = emu->cur_thread;
proc = emu->cur_proc; proc = emu->cur_proc;
if(task->id == 0) if (task->id == 0)
edie(emu, "task id cannot be 0\n"); edie(emu, "task id cannot be 0\n");
if(task->type->gid == 0) if (task->type->gid == 0)
edie(emu, "task type gid cannot be 0\n"); edie(emu, "task type gid cannot be 0\n");
if(proc->appid <= 0) if (proc->appid <= 0)
edie(emu, "app id must be positive\n"); edie(emu, "app id must be positive\n");
chan_set(&th->chan[CHAN_NOSV_TASKID], task->id); chan_set(&th->chan[CHAN_NOSV_TASKID], task->id);
chan_set(&th->chan[CHAN_NOSV_TYPE], task->type->gid); chan_set(&th->chan[CHAN_NOSV_TYPE], task->type->gid);
chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid); chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid);
if(emu->cur_loom->rank_enabled) if (emu->cur_loom->rank_enabled)
chan_set(&th->chan[CHAN_NOSV_RANK], proc->rank + 1); chan_set(&th->chan[CHAN_NOSV_RANK], proc->rank + 1);
chan_push(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_NOSV_TASK_RUNNING); chan_push(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_NOSV_TASK_RUNNING);
@ -117,23 +114,23 @@ chan_task_running(struct ovni_emu *emu, struct task *task)
static void static void
chan_task_switch(struct ovni_emu *emu, chan_task_switch(struct ovni_emu *emu,
struct task *prev, struct task *next) struct task *prev, struct task *next)
{ {
struct ovni_ethread *th = emu->cur_thread; struct ovni_ethread *th = emu->cur_thread;
if(!prev || !next) if (!prev || !next)
edie(emu, "cannot switch to or from a NULL task\n"); edie(emu, "cannot switch to or from a NULL task\n");
if(prev == next) if (prev == next)
edie(emu, "cannot switch to the same task\n"); edie(emu, "cannot switch to the same task\n");
if(next->id == 0) if (next->id == 0)
edie(emu, "next task id cannot be 0\n"); edie(emu, "next task id cannot be 0\n");
if(next->type->gid == 0) if (next->type->gid == 0)
edie(emu, "next task type id cannot be 0\n"); edie(emu, "next task type id cannot be 0\n");
if(prev->thread != next->thread) if (prev->thread != next->thread)
edie(emu, "cannot switch to a task of another thread\n"); edie(emu, "cannot switch to a task of another thread\n");
/* No need to change the rank or app ID, as we can only switch /* No need to change the rank or app ID, as we can only switch
@ -144,14 +141,14 @@ chan_task_switch(struct ovni_emu *emu,
* the same type event, to mark the end of the current task. For * the same type event, to mark the end of the current task. For
* now we only emit a new type if we switch to a type with a * now we only emit a new type if we switch to a type with a
* different gid. */ * different gid. */
if(prev->type->gid != next->type->gid) if (prev->type->gid != next->type->gid)
chan_set(&th->chan[CHAN_NOSV_TYPE], next->type->gid); chan_set(&th->chan[CHAN_NOSV_TYPE], next->type->gid);
} }
static void static void
update_task_state(struct ovni_emu *emu) update_task_state(struct ovni_emu *emu)
{ {
if(ovni_payload_size(emu->cur_ev) < 4) if (ovni_payload_size(emu->cur_ev) < 4)
edie(emu, "missing task id in payload\n"); edie(emu, "missing task id in payload\n");
uint32_t task_id = emu->cur_ev->payload.u32[0]; uint32_t task_id = emu->cur_ev->payload.u32[0];
@ -164,18 +161,25 @@ update_task_state(struct ovni_emu *emu)
struct task *task = task_find(info->tasks, task_id); struct task *task = task_find(info->tasks, task_id);
if(task == NULL) if (task == NULL)
edie(emu, "cannot find task with id %u\n", task_id); edie(emu, "cannot find task with id %u\n", task_id);
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'x':
case 'x': task_execute(emu, stack, task); break; task_execute(emu, stack, task);
case 'e': task_end(emu, stack, task); break; break;
case 'p': task_pause(emu, stack, task); break; case 'e':
case 'r': task_resume(emu, stack, task); break; task_end(emu, stack, task);
break;
case 'p':
task_pause(emu, stack, task);
break;
case 'r':
task_resume(emu, stack, task);
break;
default: default:
edie(emu, "unexpected Nanos6 task event value %c\n", edie(emu, "unexpected Nanos6 task event value %c\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
} }
} }
@ -185,13 +189,13 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now)
char tr = emu->cur_ev->header.value; char tr = emu->cur_ev->header.value;
/* Ensure we don't clobber the value */ /* Ensure we don't clobber the value */
if(tr == 'X' || tr == 'E') if (tr == 'X' || tr == 'E')
edie(emu, "unexpected event value %c\n", tr); edie(emu, "unexpected event value %c\n", tr);
/* Modify the event value to detect nested transitions */ /* Modify the event value to detect nested transitions */
if(tr == 'x' && was_running) if (tr == 'x' && was_running)
tr = 'X'; /* Execute a new nested task */ tr = 'X'; /* Execute a new nested task */
else if(tr == 'e' && runs_now) else if (tr == 'e' && runs_now)
tr = 'E'; /* End a nested task */ tr = 'E'; /* End a nested task */
return tr; return tr;
@ -199,17 +203,28 @@ expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now)
static void static void
update_task_channels(struct ovni_emu *emu, update_task_channels(struct ovni_emu *emu,
char tr, struct task *prev, struct task *next) char tr, struct task *prev, struct task *next)
{ {
switch(tr) switch (tr) {
{ case 'x':
case 'x': chan_task_running(emu, next); break; chan_task_running(emu, next);
case 'r': chan_task_running(emu, next); break; break;
case 'e': chan_task_stopped(emu); break; case 'r':
case 'p': chan_task_stopped(emu); break; chan_task_running(emu, next);
break;
case 'e':
chan_task_stopped(emu);
break;
case 'p':
chan_task_stopped(emu);
break;
/* Additional nested transitions */ /* Additional nested transitions */
case 'X': chan_task_switch(emu, prev, next); break; case 'X':
case 'E': chan_task_switch(emu, prev, next); break; chan_task_switch(emu, prev, next);
break;
case 'E':
chan_task_switch(emu, prev, next);
break;
default: default:
edie(emu, "unexpected transition value %c\n", tr); edie(emu, "unexpected transition value %c\n", tr);
} }
@ -239,7 +254,7 @@ update_task(struct ovni_emu *emu)
static void static void
create_task(struct ovni_emu *emu) create_task(struct ovni_emu *emu)
{ {
if(ovni_payload_size(emu->cur_ev) != 8) if (ovni_payload_size(emu->cur_ev) != 8)
edie(emu, "cannot create task: unexpected payload size\n"); edie(emu, "cannot create task: unexpected payload size\n");
uint32_t task_id = emu->cur_ev->payload.u32[0]; uint32_t task_id = emu->cur_ev->payload.u32[0];
@ -253,8 +268,7 @@ create_task(struct ovni_emu *emu)
static void static void
pre_task(struct ovni_emu *emu) pre_task(struct ovni_emu *emu)
{ {
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case 'c': case 'c':
create_task(emu); create_task(emu);
break; break;
@ -266,18 +280,18 @@ pre_task(struct ovni_emu *emu)
break; break;
default: default:
edie(emu, "unexpected task event value %c\n", edie(emu, "unexpected task event value %c\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
} }
} }
static void static void
pre_type(struct ovni_emu *emu) pre_type(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.value != 'c') if (emu->cur_ev->header.value != 'c')
edie(emu, "unexpected event value %c\n", edie(emu, "unexpected event value %c\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0) if ((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
edie(emu, "expecting a jumbo event\n"); edie(emu, "expecting a jumbo event\n");
uint8_t *data = &emu->cur_ev->payload.jumbo.data[0]; uint8_t *data = &emu->cur_ev->payload.jumbo.data[0];
@ -300,8 +314,7 @@ pre_sched(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case 'h': case 'h':
chan_push(chan_th, ST_NOSV_SCHED_HUNGRY); chan_push(chan_th, ST_NOSV_SCHED_HUNGRY);
break; break;
@ -337,19 +350,39 @@ pre_api(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 's':
case 's': chan_push(chan_th, ST_NOSV_API_SUBMIT); break; chan_push(chan_th, ST_NOSV_API_SUBMIT);
case 'S': chan_pop (chan_th, ST_NOSV_API_SUBMIT); break; break;
case 'p': chan_push(chan_th, ST_NOSV_API_PAUSE); break; case 'S':
case 'P': chan_pop (chan_th, ST_NOSV_API_PAUSE); break; chan_pop(chan_th, ST_NOSV_API_SUBMIT);
case 'y': chan_push(chan_th, ST_NOSV_API_YIELD); break; break;
case 'Y': chan_pop (chan_th, ST_NOSV_API_YIELD); break; case 'p':
case 'w': chan_push(chan_th, ST_NOSV_API_WAITFOR); break; chan_push(chan_th, ST_NOSV_API_PAUSE);
case 'W': chan_pop (chan_th, ST_NOSV_API_WAITFOR); break; break;
case 'c': chan_push(chan_th, ST_NOSV_API_SCHEDPOINT); break; case 'P':
case 'C': chan_pop (chan_th, ST_NOSV_API_SCHEDPOINT); break; chan_pop(chan_th, ST_NOSV_API_PAUSE);
default: break; break;
case 'y':
chan_push(chan_th, ST_NOSV_API_YIELD);
break;
case 'Y':
chan_pop(chan_th, ST_NOSV_API_YIELD);
break;
case 'w':
chan_push(chan_th, ST_NOSV_API_WAITFOR);
break;
case 'W':
chan_pop(chan_th, ST_NOSV_API_WAITFOR);
break;
case 'c':
chan_push(chan_th, ST_NOSV_API_SCHEDPOINT);
break;
case 'C':
chan_pop(chan_th, ST_NOSV_API_SCHEDPOINT);
break;
default:
break;
} }
} }
@ -362,13 +395,21 @@ pre_mem(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'a':
case 'a': chan_push(chan_th, ST_NOSV_MEM_ALLOCATING); break; chan_push(chan_th, ST_NOSV_MEM_ALLOCATING);
case 'A': chan_pop (chan_th, ST_NOSV_MEM_ALLOCATING); break; break;
case 'f': chan_push(chan_th, ST_NOSV_MEM_FREEING); break; case 'A':
case 'F': chan_pop (chan_th, ST_NOSV_MEM_FREEING); break; chan_pop(chan_th, ST_NOSV_MEM_ALLOCATING);
default: break; break;
case 'f':
chan_push(chan_th, ST_NOSV_MEM_FREEING);
break;
case 'F':
chan_pop(chan_th, ST_NOSV_MEM_FREEING);
break;
default:
break;
} }
} }
@ -381,15 +422,27 @@ pre_thread_type(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 'a':
case 'a': chan_push(chan_th, ST_NOSV_ATTACH); break; chan_push(chan_th, ST_NOSV_ATTACH);
case 'A': chan_pop (chan_th, ST_NOSV_ATTACH); break; break;
case 'w': chan_push(chan_th, ST_NOSV_WORKER); break; case 'A':
case 'W': chan_pop (chan_th, ST_NOSV_WORKER); break; chan_pop(chan_th, ST_NOSV_ATTACH);
case 'd': chan_push(chan_th, ST_NOSV_DELEGATE); break; break;
case 'D': chan_pop (chan_th, ST_NOSV_DELEGATE); break; case 'w':
default: break; chan_push(chan_th, ST_NOSV_WORKER);
break;
case 'W':
chan_pop(chan_th, ST_NOSV_WORKER);
break;
case 'd':
chan_push(chan_th, ST_NOSV_DELEGATE);
break;
case 'D':
chan_pop(chan_th, ST_NOSV_DELEGATE);
break;
default:
break;
} }
} }
@ -404,8 +457,7 @@ pre_ss(struct ovni_emu *emu, int st)
dbg("pre_ss chan id %d st=%d\n", chan_th->id, st); dbg("pre_ss chan id %d st=%d\n", chan_th->id, st);
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case '[': case '[':
chan_push(chan_th, st); chan_push(chan_th, st);
break; break;
@ -414,7 +466,7 @@ pre_ss(struct ovni_emu *emu, int st)
break; break;
default: default:
err("unexpected value '%c' (expecting '[' or ']')\n", err("unexpected value '%c' (expecting '[' or ']')\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
abort(); abort();
} }
} }
@ -425,44 +477,56 @@ check_affinity(struct ovni_emu *emu)
struct ovni_ethread *th = emu->cur_thread; struct ovni_ethread *th = emu->cur_thread;
struct ovni_cpu *cpu = th->cpu; struct ovni_cpu *cpu = th->cpu;
if(!cpu || cpu->virtual) if (!cpu || cpu->virtual)
return; return;
if(th->state != TH_ST_RUNNING) if (th->state != TH_ST_RUNNING)
return; return;
if(cpu->nrunning_threads > 1) if (cpu->nrunning_threads > 1) {
{
edie(emu, "cpu %s has more than one thread running\n", edie(emu, "cpu %s has more than one thread running\n",
cpu->name); cpu->name);
} }
} }
void void
hook_pre_nosv(struct ovni_emu *emu) hook_pre_nosv(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.model != 'V') if (emu->cur_ev->header.model != 'V')
edie(emu, "hook_pre_nosv: unexpected event with model %c\n", edie(emu, "hook_pre_nosv: unexpected event with model %c\n",
emu->cur_ev->header.model); emu->cur_ev->header.model);
if(!emu->cur_thread->is_active) if (!emu->cur_thread->is_active)
edie(emu, "hook_pre_nosv: current thread %d not active\n", edie(emu, "hook_pre_nosv: current thread %d not active\n",
emu->cur_thread->tid); emu->cur_thread->tid);
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{ case 'T':
case 'T': pre_task(emu); break; pre_task(emu);
case 'Y': pre_type(emu); break; break;
case 'S': pre_sched(emu); break; case 'Y':
case 'U': pre_ss(emu, ST_NOSV_SCHED_SUBMITTING); break; pre_type(emu);
case 'M': pre_mem(emu); break; break;
case 'H': pre_thread_type(emu); break; case 'S':
case 'A': pre_api(emu); break; pre_sched(emu);
break;
case 'U':
pre_ss(emu, ST_NOSV_SCHED_SUBMITTING);
break;
case 'M':
pre_mem(emu);
break;
case 'H':
pre_thread_type(emu);
break;
case 'A':
pre_api(emu);
break;
default: default:
break; break;
} }
if(emu->enable_linter) if (emu->enable_linter)
check_affinity(emu); check_affinity(emu);
} }
@ -470,17 +534,14 @@ void
hook_end_nosv(struct ovni_emu *emu) hook_end_nosv(struct ovni_emu *emu)
{ {
/* Emit types for all channel types and processes */ /* Emit types for all channel types and processes */
for(enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) for (enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) {
{
struct pcf_file *pcf = &emu->pcf[ct]; struct pcf_file *pcf = &emu->pcf[ct];
int typeid = chan_to_prvtype[CHAN_NOSV_TYPE]; int typeid = chan_to_prvtype[CHAN_NOSV_TYPE];
struct pcf_type *pcftype = pcf_find_type(pcf, typeid); struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
for(size_t i = 0; i < emu->trace.nlooms; i++) for (size_t i = 0; i < emu->trace.nlooms; i++) {
{
struct ovni_loom *loom = &emu->trace.loom[i]; struct ovni_loom *loom = &emu->trace.loom[i];
for(size_t j = 0; j < loom->nprocs; j++) for (size_t j = 0; j < loom->nprocs; j++) {
{
struct ovni_eproc *proc = &loom->proc[j]; struct ovni_eproc *proc = &loom->proc[j];
task_create_pcf_types(pcftype, proc->nosv_task_info.types); task_create_pcf_types(pcftype, proc->nosv_task_info.types);
} }

View File

@ -3,10 +3,10 @@
#include "uthash.h" #include "uthash.h"
#include "ovni.h"
#include "emu.h"
#include "prv.h"
#include "chan.h" #include "chan.h"
#include "emu.h"
#include "ovni.h"
#include "prv.h"
/* --------------------------- init ------------------------------- */ /* --------------------------- init ------------------------------- */
@ -26,8 +26,7 @@ hook_init_openmp(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the channels in all threads */ /* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
@ -36,8 +35,7 @@ hook_init_openmp(struct ovni_emu *emu)
} }
/* Init the channels in all cpus */ /* Init the channels in all cpus */
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
@ -57,8 +55,7 @@ pre_mode(struct ovni_emu *emu, int st)
th = emu->cur_thread; th = emu->cur_thread;
chan = &th->chan[CHAN_OPENMP_MODE]; chan = &th->chan[CHAN_OPENMP_MODE];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case '[': case '[':
chan_push(chan, st); chan_push(chan, st);
break; break;
@ -67,7 +64,7 @@ pre_mode(struct ovni_emu *emu, int st)
break; break;
default: default:
err("unexpected value '%c' (expecting '[' or ']')\n", err("unexpected value '%c' (expecting '[' or ']')\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
abort(); abort();
} }
} }
@ -75,18 +72,21 @@ pre_mode(struct ovni_emu *emu, int st)
void void
hook_pre_openmp(struct ovni_emu *emu) hook_pre_openmp(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.model != 'M') if (emu->cur_ev->header.model != 'M')
die("hook_pre_openmp: unexpected event with model %c\n", die("hook_pre_openmp: unexpected event with model %c\n",
emu->cur_ev->header.model); emu->cur_ev->header.model);
if(!emu->cur_thread->is_active) if (!emu->cur_thread->is_active)
die("hook_pre_openmp: current thread %d not active\n", die("hook_pre_openmp: current thread %d not active\n",
emu->cur_thread->tid); emu->cur_thread->tid);
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{ case 'T':
case 'T': pre_mode(emu, ST_OPENMP_TASK); break; pre_mode(emu, ST_OPENMP_TASK);
case 'P': pre_mode(emu, ST_OPENMP_PARALLEL); break; break;
case 'P':
pre_mode(emu, ST_OPENMP_PARALLEL);
break;
default: default:
break; break;
} }

View File

@ -1,10 +1,10 @@
/* Copyright (c) 2021 Barcelona Supercomputing Center (BSC) /* Copyright (c) 2021 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
#include "ovni.h"
#include "emu.h"
#include "prv.h"
#include "chan.h" #include "chan.h"
#include "emu.h"
#include "ovni.h"
#include "prv.h"
#include "utlist.h" #include "utlist.h"
/* The emulator ovni module provides the execution model by tracking the thread /* The emulator ovni module provides the execution model by tracking the thread
@ -28,30 +28,28 @@ hook_init_ovni(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the ovni channels in all threads */ /* Init the ovni channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
chan_th_init(th, uth, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, th->tid, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, th->tid, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, th->proc->pid, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, th->proc->pid, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_OVNI_CPU, CHAN_TRACK_NONE, -1, 0, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_OVNI_CPU, CHAN_TRACK_NONE, -1, 0, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_OVNI_STATE, CHAN_TRACK_NONE, TH_ST_UNKNOWN, 1, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_OVNI_STATE, CHAN_TRACK_NONE, TH_ST_UNKNOWN, 1, 1, row, prv_th, clock);
chan_th_init(th, uth, CHAN_OVNI_FLUSH, CHAN_TRACK_NONE, ST_NULL, 1, 1, row, prv_th, clock); chan_th_init(th, uth, CHAN_OVNI_FLUSH, CHAN_TRACK_NONE, ST_NULL, 1, 1, row, prv_th, clock);
} }
/* Init the ovni channels in all cpus */ /* Init the ovni channels in all cpus */
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
chan_cpu_init(cpu, ucpu, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_OVNI_TID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_OVNI_PID, CHAN_TRACK_TH_RUNNING, 0, 1, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_OVNI_NRTHREADS, CHAN_TRACK_NONE, 0, 1, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_OVNI_NRTHREADS, CHAN_TRACK_NONE, 0, 1, 1, row, prv_cpu, clock);
chan_cpu_init(cpu, ucpu, CHAN_OVNI_FLUSH, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock); chan_cpu_init(cpu, ucpu, CHAN_OVNI_FLUSH, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
} }
} }
@ -63,11 +61,10 @@ chan_tracking_update(struct ovni_chan *chan, struct ovni_ethread *th)
{ {
int enabled; int enabled;
if(th == NULL) if (th == NULL)
die("chan_tracking_update: thread is NULL"); die("chan_tracking_update: thread is NULL");
switch (chan->track) switch (chan->track) {
{
case CHAN_TRACK_TH_RUNNING: case CHAN_TRACK_TH_RUNNING:
enabled = th->is_running; enabled = th->is_running;
break; break;
@ -81,11 +78,11 @@ chan_tracking_update(struct ovni_chan *chan, struct ovni_ethread *th)
} }
/* The channel is already in the proper state */ /* The channel is already in the proper state */
if(chan_is_enabled(chan) == enabled) if (chan_is_enabled(chan) == enabled)
return; return;
dbg("thread %d changes state to %d: chan %d enabled=%d\n", dbg("thread %d changes state to %d: chan %d enabled=%d\n",
th->tid, th->state, chan->id, enabled); th->tid, th->state, chan->id, enabled);
chan_enable(chan, enabled); chan_enable(chan, enabled);
} }
@ -97,25 +94,27 @@ thread_set_state(struct ovni_ethread *th, enum ethread_state state)
int i; int i;
/* The state must be updated when a cpu is set */ /* The state must be updated when a cpu is set */
if(th->cpu == NULL) if (th->cpu == NULL)
die("thread_set_state: thread %d doesn't have a CPU\n", die("thread_set_state: thread %d doesn't have a CPU\n",
th->tid); th->tid);
dbg("thread_set_state: setting thread %d state %d\n", dbg("thread_set_state: setting thread %d state %d\n",
th->tid, state); th->tid, state);
th->state = state; th->state = state;
th->is_running = (state == TH_ST_RUNNING) ? 1 : 0; th->is_running = (state == TH_ST_RUNNING) ? 1 : 0;
th->is_active = (state == TH_ST_RUNNING th->is_active = (state == TH_ST_RUNNING
|| state == TH_ST_COOLING || state == TH_ST_COOLING
|| state == TH_ST_WARMING) ? 1 : 0; || state == TH_ST_WARMING)
? 1
: 0;
chan_set(&th->chan[CHAN_OVNI_STATE], th->state); chan_set(&th->chan[CHAN_OVNI_STATE], th->state);
/* Enable or disable the thread channels that track the thread state */ /* Enable or disable the thread channels that track the thread state */
for(i=0; i<CHAN_MAX; i++) for (i = 0; i < CHAN_MAX; i++)
chan_tracking_update(&th->chan[i], th); chan_tracking_update(&th->chan[i], th);
dbg("thread_set_state: done\n"); dbg("thread_set_state: done\n");
@ -129,15 +128,12 @@ cpu_update_th_stats(struct ovni_cpu *cpu)
DL_FOREACH(cpu->thread, th) DL_FOREACH(cpu->thread, th)
{ {
if(th->state == TH_ST_RUNNING) if (th->state == TH_ST_RUNNING) {
{
th_running = th; th_running = th;
running++; running++;
th_active = th; th_active = th;
active++; active++;
} } else if (th->state == TH_ST_COOLING || th->state == TH_ST_WARMING) {
else if(th->state == TH_ST_COOLING || th->state == TH_ST_WARMING)
{
th_active = th; th_active = th;
active++; active++;
} }
@ -161,11 +157,11 @@ update_cpu(struct ovni_cpu *cpu)
/* From the CPU channels we only need to manually update the number of /* From the CPU channels we only need to manually update the number of
* threads running in the CPU */ * threads running in the CPU */
if(chan_get_st(&cpu->chan[CHAN_OVNI_NRTHREADS]) != (int) cpu->nrunning_threads) if (chan_get_st(&cpu->chan[CHAN_OVNI_NRTHREADS]) != (int) cpu->nrunning_threads)
chan_set(&cpu->chan[CHAN_OVNI_NRTHREADS], (int) cpu->nrunning_threads); chan_set(&cpu->chan[CHAN_OVNI_NRTHREADS], (int) cpu->nrunning_threads);
/* Update all tracking channels */ /* Update all tracking channels */
for(i=0; i<CHAN_MAX; i++) for (i = 0; i < CHAN_MAX; i++)
emu_cpu_update_chan(cpu, &cpu->chan[i]); emu_cpu_update_chan(cpu, &cpu->chan[i]);
dbg("updating cpu %s complete!\n", cpu->name); dbg("updating cpu %s complete!\n", cpu->name);
@ -174,10 +170,10 @@ update_cpu(struct ovni_cpu *cpu)
struct ovni_cpu * struct ovni_cpu *
emu_get_cpu(struct ovni_loom *loom, int cpuid) emu_get_cpu(struct ovni_loom *loom, int cpuid)
{ {
if(cpuid >= (int) loom->ncpus) if (cpuid >= (int) loom->ncpus)
die("emu_get_cpu: CPU index out of bounds\n"); die("emu_get_cpu: CPU index out of bounds\n");
if(cpuid < 0) if (cpuid < 0)
return &loom->vcpu; return &loom->vcpu;
return &loom->cpu[cpuid]; return &loom->cpu[cpuid];
@ -190,7 +186,7 @@ emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
DL_FOREACH(cpu->thread, p) DL_FOREACH(cpu->thread, p)
{ {
if(p == thread) if (p == thread)
return p; return p;
} }
@ -202,10 +198,9 @@ static void
cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread) cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
{ {
/* Found, abort */ /* Found, abort */
if(emu_cpu_find_thread(cpu, thread) != NULL) if (emu_cpu_find_thread(cpu, thread) != NULL) {
{
err("The thread %d is already assigned to %s\n", err("The thread %d is already assigned to %s\n",
thread->tid, cpu->name); thread->tid, cpu->name);
abort(); abort();
} }
@ -223,10 +218,9 @@ cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
p = emu_cpu_find_thread(cpu, thread); p = emu_cpu_find_thread(cpu, thread);
/* Not found, abort */ /* Not found, abort */
if(p == NULL) if (p == NULL) {
{
err("cannot remove missing thread %d from cpu %s\n", err("cannot remove missing thread %d from cpu %s\n",
thread->tid, cpu->name); thread->tid, cpu->name);
abort(); abort();
} }
@ -238,10 +232,9 @@ cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
static void static void
cpu_migrate_thread(struct ovni_cpu *cpu, cpu_migrate_thread(struct ovni_cpu *cpu,
struct ovni_ethread *thread, struct ovni_ethread *thread,
struct ovni_cpu *newcpu) struct ovni_cpu *newcpu)
{ {
cpu_remove_thread(cpu, thread); cpu_remove_thread(cpu, thread);
cpu_add_thread(newcpu, thread); cpu_add_thread(newcpu, thread);
} }
@ -251,12 +244,12 @@ cpu_migrate_thread(struct ovni_cpu *cpu,
static void static void
thread_set_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu) thread_set_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu)
{ {
if(th->cpu != NULL) if (th->cpu != NULL)
die("thread_set_cpu: thread %d already has a CPU\n", die("thread_set_cpu: thread %d already has a CPU\n",
th->tid); th->tid);
dbg("thread_set_cpu: setting thread %d cpu to %s\n", dbg("thread_set_cpu: setting thread %d cpu to %s\n",
th->tid, cpu->name); th->tid, cpu->name);
th->cpu = cpu; th->cpu = cpu;
chan_enable(&th->chan[CHAN_OVNI_CPU], 1); chan_enable(&th->chan[CHAN_OVNI_CPU], 1);
@ -268,9 +261,9 @@ thread_set_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu)
static void static void
thread_unset_cpu(struct ovni_ethread *th) thread_unset_cpu(struct ovni_ethread *th)
{ {
if(th->cpu == NULL) if (th->cpu == NULL)
die("thread_unset_cpu: thread %d doesn't have a CPU\n", die("thread_unset_cpu: thread %d doesn't have a CPU\n",
th->tid); th->tid);
th->cpu = NULL; th->cpu = NULL;
@ -282,9 +275,9 @@ thread_unset_cpu(struct ovni_ethread *th)
static void static void
thread_migrate_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu) thread_migrate_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu)
{ {
if(th->cpu == NULL) if (th->cpu == NULL)
die("thread_migrate_cpu: thread %d doesn't have a CPU\n", die("thread_migrate_cpu: thread %d doesn't have a CPU\n",
th->tid); th->tid);
th->cpu = cpu; th->cpu = cpu;
chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1); chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1);
@ -297,9 +290,9 @@ pre_thread_execute(struct ovni_emu *emu, struct ovni_ethread *th)
int cpuid; int cpuid;
/* The thread cannot be already running */ /* The thread cannot be already running */
if(th->state == TH_ST_RUNNING) if (th->state == TH_ST_RUNNING)
edie(emu, "pre_thread_execute: thread %d already running\n", edie(emu, "pre_thread_execute: thread %d already running\n",
th->tid); th->tid);
cpuid = emu->cur_ev->payload.i32[0]; cpuid = emu->cur_ev->payload.i32[0];
@ -320,13 +313,13 @@ pre_thread_execute(struct ovni_emu *emu, struct ovni_ethread *th)
static void static void
pre_thread_end(struct ovni_ethread *th) pre_thread_end(struct ovni_ethread *th)
{ {
if(th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING) if (th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING)
die("pre_thread_end: thread %d not running or cooling\n", die("pre_thread_end: thread %d not running or cooling\n",
th->tid); th->tid);
if(th->cpu == NULL) if (th->cpu == NULL)
die("pre_thread_end: thread %d doesn't have a CPU\n", die("pre_thread_end: thread %d doesn't have a CPU\n",
th->tid); th->tid);
/* First update the thread state */ /* First update the thread state */
thread_set_state(th, TH_ST_DEAD); thread_set_state(th, TH_ST_DEAD);
@ -340,13 +333,13 @@ pre_thread_end(struct ovni_ethread *th)
static void static void
pre_thread_pause(struct ovni_ethread *th) pre_thread_pause(struct ovni_ethread *th)
{ {
if(th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING) if (th->state != TH_ST_RUNNING && th->state != TH_ST_COOLING)
die("pre_thread_pause: thread %d not running or cooling\n", die("pre_thread_pause: thread %d not running or cooling\n",
th->tid); th->tid);
if(th->cpu == NULL) if (th->cpu == NULL)
die("pre_thread_pause: thread %d doesn't have a CPU\n", die("pre_thread_pause: thread %d doesn't have a CPU\n",
th->tid); th->tid);
thread_set_state(th, TH_ST_PAUSED); thread_set_state(th, TH_ST_PAUSED);
update_cpu(th->cpu); update_cpu(th->cpu);
@ -355,13 +348,13 @@ pre_thread_pause(struct ovni_ethread *th)
static void static void
pre_thread_resume(struct ovni_ethread *th) pre_thread_resume(struct ovni_ethread *th)
{ {
if(th->state != TH_ST_PAUSED && th->state != TH_ST_WARMING) if (th->state != TH_ST_PAUSED && th->state != TH_ST_WARMING)
die("pre_thread_resume: thread %d not paused or warming\n", die("pre_thread_resume: thread %d not paused or warming\n",
th->tid); th->tid);
if(th->cpu == NULL) if (th->cpu == NULL)
die("pre_thread_resume: thread %d doesn't have a CPU\n", die("pre_thread_resume: thread %d doesn't have a CPU\n",
th->tid); th->tid);
thread_set_state(th, TH_ST_RUNNING); thread_set_state(th, TH_ST_RUNNING);
update_cpu(th->cpu); update_cpu(th->cpu);
@ -370,13 +363,13 @@ pre_thread_resume(struct ovni_ethread *th)
static void static void
pre_thread_cool(struct ovni_ethread *th) pre_thread_cool(struct ovni_ethread *th)
{ {
if(th->state != TH_ST_RUNNING) if (th->state != TH_ST_RUNNING)
die("pre_thread_cool: thread %d not running\n", die("pre_thread_cool: thread %d not running\n",
th->tid); th->tid);
if(th->cpu == NULL) if (th->cpu == NULL)
die("pre_thread_cool: thread %d doesn't have a CPU\n", die("pre_thread_cool: thread %d doesn't have a CPU\n",
th->tid); th->tid);
thread_set_state(th, TH_ST_COOLING); thread_set_state(th, TH_ST_COOLING);
update_cpu(th->cpu); update_cpu(th->cpu);
@ -385,13 +378,13 @@ pre_thread_cool(struct ovni_ethread *th)
static void static void
pre_thread_warm(struct ovni_ethread *th) pre_thread_warm(struct ovni_ethread *th)
{ {
if(th->state != TH_ST_PAUSED) if (th->state != TH_ST_PAUSED)
die("pre_thread_warm: thread %d not paused\n", die("pre_thread_warm: thread %d not paused\n",
th->tid); th->tid);
if(th->cpu == NULL) if (th->cpu == NULL)
die("pre_thread_warm: thread %d doesn't have a CPU\n", die("pre_thread_warm: thread %d doesn't have a CPU\n",
th->tid); th->tid);
thread_set_state(th, TH_ST_WARMING); thread_set_state(th, TH_ST_WARMING);
update_cpu(th->cpu); update_cpu(th->cpu);
@ -403,31 +396,42 @@ pre_thread(struct ovni_emu *emu)
struct ovni_ev *ev; struct ovni_ev *ev;
struct ovni_ethread *th; struct ovni_ethread *th;
//emu_emit(emu); // emu_emit(emu);
th = emu->cur_thread; th = emu->cur_thread;
ev = emu->cur_ev; ev = emu->cur_ev;
switch(ev->header.value) switch (ev->header.value) {
{
case 'C': /* create */ case 'C': /* create */
dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n", dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n",
th->tid, th->tid,
ev->payload.u32[0], ev->payload.u32[0],
ev->payload.u32[1], ev->payload.u32[1],
ev->payload.u32[2]); ev->payload.u32[2]);
break; break;
case 'x': pre_thread_execute(emu, th); break; case 'x':
case 'e': pre_thread_end(th); break; pre_thread_execute(emu, th);
case 'p': pre_thread_pause(th); break; break;
case 'r': pre_thread_resume(th); break; case 'e':
case 'c': pre_thread_cool(th); break; pre_thread_end(th);
case 'w': pre_thread_warm(th); break; break;
case 'p':
pre_thread_pause(th);
break;
case 'r':
pre_thread_resume(th);
break;
case 'c':
pre_thread_cool(th);
break;
case 'w':
pre_thread_warm(th);
break;
default: default:
err("unknown thread event value %c\n", err("unknown thread event value %c\n",
ev->header.value); ev->header.value);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@ -441,25 +445,25 @@ pre_affinity_set(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
cpuid = emu->cur_ev->payload.i32[0]; cpuid = emu->cur_ev->payload.i32[0];
if(th->cpu == NULL) if (th->cpu == NULL)
edie(emu, "pre_affinity_set: thread %d doesn't have a CPU\n", edie(emu, "pre_affinity_set: thread %d doesn't have a CPU\n",
th->tid); th->tid);
if(!th->is_active) if (!th->is_active)
edie(emu, "pre_affinity_set: thread %d is not active\n", edie(emu, "pre_affinity_set: thread %d is not active\n",
th->tid); th->tid);
/* Migrate current cpu to the one at cpuid */ /* Migrate current cpu to the one at cpuid */
newcpu = emu_get_cpu(emu->cur_loom, cpuid); newcpu = emu_get_cpu(emu->cur_loom, cpuid);
/* The CPU is already properly set, return */ /* The CPU is already properly set, return */
if(th->cpu == newcpu) if (th->cpu == newcpu)
return; return;
cpu_migrate_thread(th->cpu, th, newcpu); cpu_migrate_thread(th->cpu, th, newcpu);
thread_migrate_cpu(th, newcpu); thread_migrate_cpu(th, newcpu);
//dbg("cpu %d now runs %d\n", cpuid, th->tid); // dbg("cpu %d now runs %d\n", cpuid, th->tid);
} }
static void static void
@ -477,47 +481,44 @@ pre_affinity_remote(struct ovni_emu *emu)
remote_th = emu_get_thread(emu->cur_proc, tid); remote_th = emu_get_thread(emu->cur_proc, tid);
if(remote_th == NULL) if (remote_th == NULL) {
{
/* Search the thread in other processes of the loom if /* Search the thread in other processes of the loom if
* not found in the current one */ * not found in the current one */
loom = emu->cur_loom; loom = emu->cur_loom;
for(i=0; i<loom->nprocs; i++) for (i = 0; i < loom->nprocs; i++) {
{
proc = &loom->proc[i]; proc = &loom->proc[i];
/* Skip the current process */ /* Skip the current process */
if(proc == emu->cur_proc) if (proc == emu->cur_proc)
continue; continue;
remote_th = emu_get_thread(proc, tid); remote_th = emu_get_thread(proc, tid);
if(remote_th) if (remote_th)
break; break;
} }
if(remote_th == NULL) if (remote_th == NULL) {
{
err("thread tid %d not found: cannot set affinity remotely\n", err("thread tid %d not found: cannot set affinity remotely\n",
tid); tid);
abort(); abort();
} }
} }
/* The remote_th cannot be in states dead or unknown */ /* The remote_th cannot be in states dead or unknown */
if(remote_th->state == TH_ST_DEAD) if (remote_th->state == TH_ST_DEAD)
edie(emu, "pre_affinity_remote: remote thread %d in state DEAD\n", edie(emu, "pre_affinity_remote: remote thread %d in state DEAD\n",
remote_th->tid); remote_th->tid);
if(remote_th->state == TH_ST_UNKNOWN) if (remote_th->state == TH_ST_UNKNOWN)
edie(emu, "pre_affinity_remote: remote thread %d in state UNKNOWN\n", edie(emu, "pre_affinity_remote: remote thread %d in state UNKNOWN\n",
remote_th->tid); remote_th->tid);
/* It must have an assigned CPU */ /* It must have an assigned CPU */
if(remote_th->cpu == NULL) if (remote_th->cpu == NULL)
edie(emu, "pre_affinity_remote: remote thread %d has no CPU\n", edie(emu, "pre_affinity_remote: remote thread %d has no CPU\n",
remote_th->tid); remote_th->tid);
/* Migrate current cpu to the one at cpuid */ /* Migrate current cpu to the one at cpuid */
newcpu = emu_get_cpu(emu->cur_loom, cpuid); newcpu = emu_get_cpu(emu->cur_loom, cpuid);
@ -525,21 +526,24 @@ pre_affinity_remote(struct ovni_emu *emu)
cpu_migrate_thread(remote_th->cpu, remote_th, newcpu); cpu_migrate_thread(remote_th->cpu, remote_th, newcpu);
thread_migrate_cpu(remote_th, newcpu); thread_migrate_cpu(remote_th, newcpu);
//dbg("remote_th %d switches to cpu %d by remote petition\n", tid, // dbg("remote_th %d switches to cpu %d by remote petition\n", tid,
// cpuid); // cpuid);
} }
static void static void
pre_affinity(struct ovni_emu *emu) pre_affinity(struct ovni_emu *emu)
{ {
//emu_emit(emu); // emu_emit(emu);
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{ case 's':
case 's': pre_affinity_set(emu); break; pre_affinity_set(emu);
case 'r': pre_affinity_remote(emu); break; break;
case 'r':
pre_affinity_remote(emu);
break;
default: default:
dbg("unknown affinity event value %c\n", dbg("unknown affinity event value %c\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
break; break;
} }
} }
@ -554,17 +558,14 @@ pre_burst(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
if(th->nbursts >= MAX_BURSTS) if (th->nbursts >= MAX_BURSTS) {
{
err("too many bursts: ignored\n"); err("too many bursts: ignored\n");
return; return;
} }
th->burst_time[th->nbursts] = emu->delta_time; th->burst_time[th->nbursts] = emu->delta_time;
if(th->nbursts > 0) if (th->nbursts > 0) {
{ dt = th->burst_time[th->nbursts] - th->burst_time[th->nbursts - 1];
dt = th->burst_time[th->nbursts] -
th->burst_time[th->nbursts - 1];
dbg("burst delta time %ld ns\n", dt); dbg("burst delta time %ld ns\n", dt);
} }
@ -581,8 +582,7 @@ pre_flush(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_OVNI_FLUSH]; chan_th = &th->chan[CHAN_OVNI_FLUSH];
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case '[': case '[':
chan_push(chan_th, ST_OVNI_FLUSHING); chan_push(chan_th, ST_OVNI_FLUSHING);
break; break;
@ -591,7 +591,7 @@ pre_flush(struct ovni_emu *emu)
break; break;
default: default:
err("unexpected value '%c' (expecting '[' or ']')\n", err("unexpected value '%c' (expecting '[' or ']')\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
abort(); abort();
} }
} }
@ -599,20 +599,27 @@ pre_flush(struct ovni_emu *emu)
void void
hook_pre_ovni(struct ovni_emu *emu) hook_pre_ovni(struct ovni_emu *emu)
{ {
//emu_emit(emu); // emu_emit(emu);
if(emu->cur_ev->header.model != 'O') if (emu->cur_ev->header.model != 'O')
return; return;
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{ case 'H':
case 'H': pre_thread(emu); break; pre_thread(emu);
case 'A': pre_affinity(emu); break; break;
case 'B': pre_burst(emu); break; case 'A':
case 'F': pre_flush(emu); break; pre_affinity(emu);
break;
case 'B':
pre_burst(emu);
break;
case 'F':
pre_flush(emu);
break;
default: default:
dbg("unknown ovni event category %c\n", dbg("unknown ovni event category %c\n",
emu->cur_ev->header.category); emu->cur_ev->header.category);
break; break;
} }
} }

View File

@ -3,10 +3,10 @@
#include "uthash.h" #include "uthash.h"
#include "ovni.h"
#include "emu.h"
#include "prv.h"
#include "chan.h" #include "chan.h"
#include "emu.h"
#include "ovni.h"
#include "prv.h"
/* --------------------------- init ------------------------------- */ /* --------------------------- init ------------------------------- */
@ -26,8 +26,7 @@ hook_init_tampi(struct ovni_emu *emu)
prv_cpu = emu->prv_cpu; prv_cpu = emu->prv_cpu;
/* Init the channels in all threads */ /* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for (i = 0; i < emu->total_nthreads; i++) {
{
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
uth = &emu->th_chan; uth = &emu->th_chan;
@ -36,8 +35,7 @@ hook_init_tampi(struct ovni_emu *emu)
} }
/* Init the channels in all cpus */ /* Init the channels in all cpus */
for(i=0; i<emu->total_ncpus; i++) for (i = 0; i < emu->total_ncpus; i++) {
{
cpu = emu->global_cpu[i]; cpu = emu->global_cpu[i];
row = cpu->gindex + 1; row = cpu->gindex + 1;
ucpu = &emu->cpu_chan; ucpu = &emu->cpu_chan;
@ -55,8 +53,7 @@ pre_tampi_mode(struct ovni_emu *emu, int state)
th = emu->cur_thread; th = emu->cur_thread;
switch(emu->cur_ev->header.value) switch (emu->cur_ev->header.value) {
{
case '[': case '[':
chan_push(&th->chan[CHAN_TAMPI_MODE], state); chan_push(&th->chan[CHAN_TAMPI_MODE], state);
break; break;
@ -65,25 +62,36 @@ pre_tampi_mode(struct ovni_emu *emu, int state)
break; break;
default: default:
edie(emu, "unexpected event value %c for tampi mode\n", edie(emu, "unexpected event value %c for tampi mode\n",
emu->cur_ev->header.value); emu->cur_ev->header.value);
} }
} }
void void
hook_pre_tampi(struct ovni_emu *emu) hook_pre_tampi(struct ovni_emu *emu)
{ {
if(emu->cur_ev->header.model != 'T') if (emu->cur_ev->header.model != 'T')
edie(emu, "hook_pre_tampi: unexpected event with model %c\n", edie(emu, "hook_pre_tampi: unexpected event with model %c\n",
emu->cur_ev->header.model); emu->cur_ev->header.model);
switch(emu->cur_ev->header.category) switch (emu->cur_ev->header.category) {
{ case 'S':
case 'S': pre_tampi_mode(emu, ST_TAMPI_SEND); break; pre_tampi_mode(emu, ST_TAMPI_SEND);
case 'R': pre_tampi_mode(emu, ST_TAMPI_RECV); break; break;
case 's': pre_tampi_mode(emu, ST_TAMPI_ISEND); break; case 'R':
case 'r': pre_tampi_mode(emu, ST_TAMPI_IRECV); break; pre_tampi_mode(emu, ST_TAMPI_RECV);
case 'V': pre_tampi_mode(emu, ST_TAMPI_WAIT); break; break;
case 'W': pre_tampi_mode(emu, ST_TAMPI_WAITALL); break; case 's':
pre_tampi_mode(emu, ST_TAMPI_ISEND);
break;
case 'r':
pre_tampi_mode(emu, ST_TAMPI_IRECV);
break;
case 'V':
pre_tampi_mode(emu, ST_TAMPI_WAIT);
break;
case 'W':
pre_tampi_mode(emu, ST_TAMPI_WAITALL);
break;
default: default:
break; break;
} }

View File

@ -4,11 +4,11 @@
#include "uthash.h" #include "uthash.h"
#include "utlist.h" #include "utlist.h"
#include "ovni.h" #include "chan.h"
#include "emu.h" #include "emu.h"
#include "emu_task.h" #include "emu_task.h"
#include "ovni.h"
#include "prv.h" #include "prv.h"
#include "chan.h"
struct task * struct task *
task_find(struct task *tasks, uint32_t task_id) task_find(struct task *tasks, uint32_t task_id)
@ -30,21 +30,21 @@ task_type_find(struct task_type *types, uint32_t type_id)
void void
task_create(struct ovni_emu *emu, struct task_info *info, task_create(struct ovni_emu *emu, struct task_info *info,
uint32_t type_id, uint32_t task_id) uint32_t type_id, uint32_t task_id)
{ {
/* Ensure the task id is new */ /* Ensure the task id is new */
if(task_find(info->tasks, task_id) != NULL) if (task_find(info->tasks, task_id) != NULL)
edie(emu, "cannot create task: task_id %u already exists\n", edie(emu, "cannot create task: task_id %u already exists\n",
task_id); task_id);
/* Ensure the type exists */ /* Ensure the type exists */
struct task_type *type = task_type_find(info->types, type_id); struct task_type *type = task_type_find(info->types, type_id);
if(type == NULL) if (type == NULL)
edie(emu, "cannot create task: unknown type id %u\n", type_id); edie(emu, "cannot create task: unknown type id %u\n", type_id);
struct task *task = calloc(1, sizeof(struct task)); struct task *task = calloc(1, sizeof(struct task));
if(task == NULL) if (task == NULL)
die("calloc failed\n"); die("calloc failed\n");
task->id = task_id; task->id = task_id;
@ -60,24 +60,24 @@ task_create(struct ovni_emu *emu, struct task_info *info,
void void
task_execute(struct ovni_emu *emu, task_execute(struct ovni_emu *emu,
struct task_stack *stack, struct task *task) struct task_stack *stack, struct task *task)
{ {
if(task == NULL) if (task == NULL)
edie(emu, "cannot execute: task is NULL\n"); edie(emu, "cannot execute: task is NULL\n");
if(task->state != TASK_ST_CREATED) if (task->state != TASK_ST_CREATED)
edie(emu, "cannot execute task %u: state is not created\n", task->id); edie(emu, "cannot execute task %u: state is not created\n", task->id);
if(task->thread != NULL) if (task->thread != NULL)
edie(emu, "task already has a thread assigned\n"); edie(emu, "task already has a thread assigned\n");
if(stack->thread->state != TH_ST_RUNNING) if (stack->thread->state != TH_ST_RUNNING)
edie(emu, "thread state is not running\n"); edie(emu, "thread state is not running\n");
if(stack->top == task) if (stack->top == task)
edie(emu, "thread already has assigned task %u\n", task->id); edie(emu, "thread already has assigned task %u\n", task->id);
if(stack->top && stack->top->state != TASK_ST_RUNNING) if (stack->top && stack->top->state != TASK_ST_RUNNING)
edie(emu, "cannot execute a nested task from a non-running task\n"); edie(emu, "cannot execute a nested task from a non-running task\n");
task->state = TASK_ST_RUNNING; task->state = TASK_ST_RUNNING;
@ -90,24 +90,24 @@ task_execute(struct ovni_emu *emu,
void void
task_pause(struct ovni_emu *emu, task_pause(struct ovni_emu *emu,
struct task_stack *stack, struct task *task) struct task_stack *stack, struct task *task)
{ {
if(task == NULL) if (task == NULL)
edie(emu, "cannot pause: task is NULL\n"); edie(emu, "cannot pause: task is NULL\n");
if(task->state != TASK_ST_RUNNING) if (task->state != TASK_ST_RUNNING)
edie(emu, "cannot pause: task state is not running\n"); edie(emu, "cannot pause: task state is not running\n");
if(task->thread == NULL) if (task->thread == NULL)
edie(emu, "cannot pause: task has no thread assigned\n"); edie(emu, "cannot pause: task has no thread assigned\n");
if(stack->thread->state != TH_ST_RUNNING) if (stack->thread->state != TH_ST_RUNNING)
edie(emu, "cannot pause: thread state is not running\n"); edie(emu, "cannot pause: thread state is not running\n");
if(stack->top != task) if (stack->top != task)
edie(emu, "thread has assigned a different task\n"); edie(emu, "thread has assigned a different task\n");
if(stack->thread != task->thread) if (stack->thread != task->thread)
edie(emu, "task is assigned to a different thread\n"); edie(emu, "task is assigned to a different thread\n");
task->state = TASK_ST_PAUSED; task->state = TASK_ST_PAUSED;
@ -117,24 +117,24 @@ task_pause(struct ovni_emu *emu,
void void
task_resume(struct ovni_emu *emu, task_resume(struct ovni_emu *emu,
struct task_stack *stack, struct task *task) struct task_stack *stack, struct task *task)
{ {
if(task == NULL) if (task == NULL)
edie(emu, "cannot resume: task is NULL\n"); edie(emu, "cannot resume: task is NULL\n");
if(task->state != TASK_ST_PAUSED) if (task->state != TASK_ST_PAUSED)
edie(emu, "task state is not paused\n"); edie(emu, "task state is not paused\n");
if(task->thread == NULL) if (task->thread == NULL)
edie(emu, "cannot resume: task has no thread assigned\n"); edie(emu, "cannot resume: task has no thread assigned\n");
if(stack->thread->state != TH_ST_RUNNING) if (stack->thread->state != TH_ST_RUNNING)
edie(emu, "thread is not running\n"); edie(emu, "thread is not running\n");
if(stack->top != task) if (stack->top != task)
edie(emu, "thread has assigned a different task\n"); edie(emu, "thread has assigned a different task\n");
if(stack->thread != task->thread) if (stack->thread != task->thread)
edie(emu, "task is assigned to a different thread\n"); edie(emu, "task is assigned to a different thread\n");
task->state = TASK_ST_RUNNING; task->state = TASK_ST_RUNNING;
@ -144,24 +144,24 @@ task_resume(struct ovni_emu *emu,
void void
task_end(struct ovni_emu *emu, task_end(struct ovni_emu *emu,
struct task_stack *stack, struct task *task) struct task_stack *stack, struct task *task)
{ {
if(task == NULL) if (task == NULL)
edie(emu, "cannot end: task is NULL\n"); edie(emu, "cannot end: task is NULL\n");
if(task->state != TASK_ST_RUNNING) if (task->state != TASK_ST_RUNNING)
edie(emu, "task state is not running\n"); edie(emu, "task state is not running\n");
if(task->thread == NULL) if (task->thread == NULL)
edie(emu, "cannot end: task has no thread assigned\n"); edie(emu, "cannot end: task has no thread assigned\n");
if(stack->thread->state != TH_ST_RUNNING) if (stack->thread->state != TH_ST_RUNNING)
edie(emu, "cannot end task: thread is not running\n"); edie(emu, "cannot end task: thread is not running\n");
if(stack->top != task) if (stack->top != task)
edie(emu, "thread has assigned a different task\n"); edie(emu, "thread has assigned a different task\n");
if(stack->thread != task->thread) if (stack->thread != task->thread)
edie(emu, "task is assigned to a different thread\n"); edie(emu, "task is assigned to a different thread\n");
task->state = TASK_ST_DEAD; task->state = TASK_ST_DEAD;
@ -187,7 +187,7 @@ get_task_type_gid(const char *label)
/* Avoid bad colors for "Unlabeled0" */ /* Avoid bad colors for "Unlabeled0" */
gid += 123; gid += 123;
if(gid == 0) if (gid == 0)
gid++; gid++;
return gid; return gid;
@ -200,29 +200,29 @@ task_type_create(struct task_info *info, uint32_t type_id, const char *label)
/* Ensure the type id is new */ /* Ensure the type id is new */
HASH_FIND_INT(info->types, &type_id, type); HASH_FIND_INT(info->types, &type_id, type);
if(type != NULL) if (type != NULL)
die("a task type with id %u already exists\n", type_id); die("a task type with id %u already exists\n", type_id);
type = calloc(1, sizeof(*type)); type = calloc(1, sizeof(*type));
if(type == NULL) if (type == NULL)
die("calloc failed"); die("calloc failed");
type->id = type_id; type->id = type_id;
if(type->id == 0) if (type->id == 0)
die("invalid task type id %d\n", type->id); die("invalid task type id %d\n", type->id);
type->gid = get_task_type_gid(label); type->gid = get_task_type_gid(label);
int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label); int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label);
if(n >= MAX_PCF_LABEL) if (n >= MAX_PCF_LABEL)
die("task type label too long: %s\n", label); die("task type label too long: %s\n", label);
/* Add the new task type to the hash table */ /* Add the new task type to the hash table */
HASH_ADD_INT(info->types, id, type); HASH_ADD_INT(info->types, id, type);
dbg("new task type created id=%d label=%s\n", type->id, dbg("new task type created id=%d label=%s\n", type->id,
type->label); type->label);
} }
void void
@ -230,14 +230,12 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types)
{ {
/* Emit types for all task types */ /* Emit types for all task types */
struct task_type *tt; struct task_type *tt;
for(tt = types; tt != NULL; tt = tt->hh.next) for (tt = types; tt != NULL; tt = tt->hh.next) {
{
struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid); struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid);
if(pcfvalue != NULL) if (pcfvalue != NULL) {
{
/* Ensure the label is the same, so we know that /* Ensure the label is the same, so we know that
* no collision occurred */ * no collision occurred */
if(strcmp(pcfvalue->label, tt->label) != 0) if (strcmp(pcfvalue->label, tt->label) != 0)
die("collision occurred in task type labels\n"); die("collision occurred in task type labels\n");
else else
continue; continue;
@ -251,7 +249,7 @@ struct task *
task_get_running(struct task_stack *stack) task_get_running(struct task_stack *stack)
{ {
struct task *task = stack->top; struct task *task = stack->top;
if(task && task->state == TASK_ST_RUNNING) if (task && task->state == TASK_ST_RUNNING)
return task; return task;
return NULL; return NULL;

26
heap.h
View File

@ -7,8 +7,8 @@
#ifndef HEAP_H #ifndef HEAP_H
#define HEAP_H #define HEAP_H
#include <stddef.h>
#include "common.h" #include "common.h"
#include <stddef.h>
typedef struct heap_node { typedef struct heap_node {
struct heap_node *parent; struct heap_node *parent;
@ -24,15 +24,19 @@ typedef struct head_head {
#define heap_elem(head, type, name) \ #define heap_elem(head, type, name) \
((type *) (((char *) head) - offsetof(type, name))) ((type *) (((char *) head) - offsetof(type, name)))
#define heap_swap(a, b) \ #define heap_swap(a, b) \
do { heap_node_t *aux = (a); (a) = (b); (b) = aux; } while(0) do { \
heap_node_t *aux = (a); \
(a) = (b); \
(b) = aux; \
} while (0)
/* heap_node_compare_t - comparison function. /* heap_node_compare_t - comparison function.
* The comparison function cmp(a, b) shall return an integer: * The comparison function cmp(a, b) shall return an integer:
* > 0 if a > b * > 0 if a > b
* < 0 if a < b * < 0 if a < b
* = 0 if a == b * = 0 if a == b
* *
* Invert the comparison function to get a min-heap instead */ * Invert the comparison function to get a min-heap instead */
typedef int (*heap_node_compare_t)(heap_node_t *a, heap_node_t *b); typedef int (*heap_node_compare_t)(heap_node_t *a, heap_node_t *b);
@ -116,7 +120,7 @@ heap_get_move(size_t *node /*out*/)
// Round to previous po2 // Round to previous po2
size_t base = (1ULL) << (sizeof(size_t) * 8 size_t base = (1ULL) << (sizeof(size_t) * 8
- __builtin_clzll(aux_node) - 1); - __builtin_clzll(aux_node) - 1);
aux_node -= base / 2; aux_node -= base / 2;
@ -157,7 +161,7 @@ heap_pop_max(heap_head_t *head, heap_node_compare_t cmp)
size_t size = head->size; size_t size = head->size;
heap_node_t *change = heap_get(head, size); heap_node_t *change = heap_get(head, size);
if(change == NULL) if (change == NULL)
die("heap_pop_max: heap_get() failed\n"); die("heap_pop_max: heap_get() failed\n");
head->size--; head->size--;
@ -189,10 +193,10 @@ heap_pop_max(heap_head_t *head, heap_node_compare_t cmp)
else else
change->parent->left = NULL; change->parent->left = NULL;
if(change->left) if (change->left)
die("heap_pop_max: change->left not NULL\n"); die("heap_pop_max: change->left not NULL\n");
if(change->right) if (change->right)
die("heap_pop_max: change->right not NULL\n"); die("heap_pop_max: change->right not NULL\n");
change->left = max->left; change->left = max->left;
@ -230,11 +234,11 @@ heap_insert(heap_head_t *head, heap_node_t *node, heap_node_compare_t cmp)
// Right child // Right child
if (head->size % 2) { if (head->size % 2) {
if(parent->right) if (parent->right)
die("heap_insert: parent->right already set\n"); die("heap_insert: parent->right already set\n");
parent->right = node; parent->right = node;
} else { } else {
if(parent->left) if (parent->left)
die("heap_insert: parent->left already set\n"); die("heap_insert: parent->left already set\n");
parent->left = node; parent->left = node;
} }
@ -286,4 +290,4 @@ heap_insert(heap_head_t *head, heap_node_t *node, heap_node_compare_t cmp)
head->root = node; head->root = node;
} }
#endif // HEAP_H #endif// HEAP_H

202
ovni.c
View File

@ -6,7 +6,6 @@
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <fcntl.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -14,10 +13,10 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "ovni.h"
#include "common.h" #include "common.h"
#include "parson.h"
#include "compat.h" #include "compat.h"
#include "ovni.h"
#include "parson.h"
/* Data per process */ /* Data per process */
struct ovni_rproc rproc = {0}; struct ovni_rproc rproc = {0};
@ -31,15 +30,15 @@ create_trace_stream(void)
char path[PATH_MAX]; char path[PATH_MAX];
int written = snprintf(path, PATH_MAX, "%s/thread.%d", int written = snprintf(path, PATH_MAX, "%s/thread.%d",
rproc.procdir, rthread.tid); rproc.procdir, rthread.tid);
if(written >= PATH_MAX) if (written >= PATH_MAX)
die("thread trace path too long: %s/thread.%d\n", die("thread trace path too long: %s/thread.%d\n",
rproc.procdir, rthread.tid); rproc.procdir, rthread.tid);
rthread.streamfd = open(path, O_WRONLY | O_CREAT, 0644); rthread.streamfd = open(path, O_WRONLY | O_CREAT, 0644);
if(rthread.streamfd == -1) if (rthread.streamfd == -1)
die("open %s failed: %s\n", path, strerror(errno)); die("open %s failed: %s\n", path, strerror(errno));
} }
@ -48,7 +47,7 @@ proc_metadata_init(struct ovni_rproc *proc)
{ {
proc->meta = json_value_init_object(); proc->meta = json_value_init_object();
if(proc->meta == NULL) if (proc->meta == NULL)
die("failed to create metadata JSON object\n"); die("failed to create metadata JSON object\n");
} }
@ -57,35 +56,35 @@ proc_metadata_store(JSON_Value *meta, const char *procdir)
{ {
char path[PATH_MAX]; char path[PATH_MAX];
if(meta == NULL) if (meta == NULL)
die("process metadata not initialized\n"); die("process metadata not initialized\n");
if(snprintf(path, PATH_MAX, "%s/metadata.json", procdir) >= PATH_MAX) if (snprintf(path, PATH_MAX, "%s/metadata.json", procdir) >= PATH_MAX)
die("metadata path too long: %s/metadata.json\n", die("metadata path too long: %s/metadata.json\n",
procdir); procdir);
if(json_serialize_to_file_pretty(meta, path) != JSONSuccess) if (json_serialize_to_file_pretty(meta, path) != JSONSuccess)
die("failed to write process metadata\n"); die("failed to write process metadata\n");
} }
void void
ovni_add_cpu(int index, int phyid) ovni_add_cpu(int index, int phyid)
{ {
if(index < 0) if (index < 0)
die("ovni_add_cpu: cannot use negative index %d\n", index); die("ovni_add_cpu: cannot use negative index %d\n", index);
if(phyid < 0) if (phyid < 0)
die("ovni_add_cpu: cannot use negative CPU id %d\n", phyid); die("ovni_add_cpu: cannot use negative CPU id %d\n", phyid);
if(!rproc.ready) if (!rproc.ready)
die("ovni_add_cpu: process not yet initialized\n"); die("ovni_add_cpu: process not yet initialized\n");
if(rproc.meta == NULL) if (rproc.meta == NULL)
die("ovni_add_cpu: metadata not initialized\n"); die("ovni_add_cpu: metadata not initialized\n");
JSON_Object *meta = json_value_get_object(rproc.meta); JSON_Object *meta = json_value_get_object(rproc.meta);
if(meta == NULL) if (meta == NULL)
die("ovni_add_cpu: json_value_get_object() failed\n"); die("ovni_add_cpu: json_value_get_object() failed\n");
int first_time = 0; int first_time = 0;
@ -93,43 +92,41 @@ ovni_add_cpu(int index, int phyid)
/* Find the CPU array and create it if needed */ /* Find the CPU array and create it if needed */
JSON_Array *cpuarray = json_object_dotget_array(meta, "cpus"); JSON_Array *cpuarray = json_object_dotget_array(meta, "cpus");
if(cpuarray == NULL) if (cpuarray == NULL) {
{
JSON_Value *value = json_value_init_array(); JSON_Value *value = json_value_init_array();
if(value == NULL) if (value == NULL)
die("ovni_add_cpu: json_value_init_array() failed\n"); die("ovni_add_cpu: json_value_init_array() failed\n");
cpuarray = json_array(value); cpuarray = json_array(value);
if(cpuarray == NULL) if (cpuarray == NULL)
die("ovni_add_cpu: json_array() failed\n"); die("ovni_add_cpu: json_array() failed\n");
first_time = 1; first_time = 1;
} }
JSON_Value *valcpu = json_value_init_object(); JSON_Value *valcpu = json_value_init_object();
if(valcpu == NULL) if (valcpu == NULL)
die("ovni_add_cpu: json_value_init_object() failed\n"); die("ovni_add_cpu: json_value_init_object() failed\n");
JSON_Object *cpu = json_object(valcpu); JSON_Object *cpu = json_object(valcpu);
if(cpu == NULL) if (cpu == NULL)
die("ovni_add_cpu: json_object() failed\n"); die("ovni_add_cpu: json_object() failed\n");
if(json_object_set_number(cpu, "index", index) != 0) if (json_object_set_number(cpu, "index", index) != 0)
die("ovni_add_cpu: json_object_set_number() failed\n"); die("ovni_add_cpu: json_object_set_number() failed\n");
if(json_object_set_number(cpu, "phyid", phyid) != 0) if (json_object_set_number(cpu, "phyid", phyid) != 0)
die("ovni_add_cpu: json_object_set_number() failed\n"); die("ovni_add_cpu: json_object_set_number() failed\n");
if(json_array_append_value(cpuarray, valcpu) != 0) if (json_array_append_value(cpuarray, valcpu) != 0)
die("ovni_add_cpu: json_array_append_value() failed\n"); die("ovni_add_cpu: json_array_append_value() failed\n");
if(first_time) if (first_time) {
{
JSON_Value *value = json_array_get_wrapping_value(cpuarray); JSON_Value *value = json_array_get_wrapping_value(cpuarray);
if(value == NULL) if (value == NULL)
die("ovni_add_cpu: json_array_get_wrapping_value() failed\n"); die("ovni_add_cpu: json_array_get_wrapping_value() failed\n");
if(json_object_set_value(meta, "cpus", value) != 0) if (json_object_set_value(meta, "cpus", value) != 0)
die("ovni_add_cpu: json_object_set_value failed\n"); die("ovni_add_cpu: json_object_set_value failed\n");
} }
} }
@ -139,10 +136,10 @@ proc_set_app(int appid)
{ {
JSON_Object *meta = json_value_get_object(rproc.meta); JSON_Object *meta = json_value_get_object(rproc.meta);
if(meta == NULL) if (meta == NULL)
die("json_value_get_object failed\n"); die("json_value_get_object failed\n");
if(json_object_set_number(meta, "app_id", appid) != 0) if (json_object_set_number(meta, "app_id", appid) != 0)
die("json_object_set_number for app_id failed\n"); die("json_object_set_number for app_id failed\n");
} }
@ -151,13 +148,13 @@ proc_set_version(void)
{ {
JSON_Object *meta = json_value_get_object(rproc.meta); JSON_Object *meta = json_value_get_object(rproc.meta);
if(meta == NULL) if (meta == NULL)
die("json_value_get_object failed\n"); die("json_value_get_object failed\n");
if(json_object_set_number(meta, "version", OVNI_METADATA_VERSION) != 0) if (json_object_set_number(meta, "version", OVNI_METADATA_VERSION) != 0)
die("json_object_set_number for version failed\n"); die("json_object_set_number for version failed\n");
if(json_object_set_string(meta, "model_version", OVNI_MODEL_VERSION) != 0) if (json_object_set_string(meta, "model_version", OVNI_MODEL_VERSION) != 0)
die("json_object_set_string for model_version failed\n"); die("json_object_set_string for model_version failed\n");
} }
@ -165,18 +162,18 @@ proc_set_version(void)
void void
ovni_proc_set_rank(int rank, int nranks) ovni_proc_set_rank(int rank, int nranks)
{ {
if(!rproc.ready) if (!rproc.ready)
die("ovni_proc_set_rank: process not yet initialized\n"); die("ovni_proc_set_rank: process not yet initialized\n");
JSON_Object *meta = json_value_get_object(rproc.meta); JSON_Object *meta = json_value_get_object(rproc.meta);
if(meta == NULL) if (meta == NULL)
die("json_value_get_object failed\n"); die("json_value_get_object failed\n");
if(json_object_set_number(meta, "rank", rank) != 0) if (json_object_set_number(meta, "rank", rank) != 0)
die("json_object_set_number for rank failed\n"); die("json_object_set_number for rank failed\n");
if(json_object_set_number(meta, "nranks", nranks) != 0) if (json_object_set_number(meta, "nranks", nranks) != 0)
die("json_object_set_number for nranks failed\n"); die("json_object_set_number for nranks failed\n");
} }
@ -197,7 +194,7 @@ mkdir_proc(char *path, const char *tracedir, const char *loom, int pid)
snprintf(path, PATH_MAX, "%s/loom.%s/proc.%d", tracedir, loom, pid); snprintf(path, PATH_MAX, "%s/loom.%s/proc.%d", tracedir, loom, pid);
/* But this one shall not fail */ /* But this one shall not fail */
if(mkdir(path, 0755)) if (mkdir(path, 0755))
die("mkdir %s failed: %s\n", path, strerror(errno)); die("mkdir %s failed: %s\n", path, strerror(errno));
} }
@ -206,14 +203,11 @@ create_proc_dir(const char *loom, int pid)
{ {
char *tmpdir = getenv("OVNI_TMPDIR"); char *tmpdir = getenv("OVNI_TMPDIR");
if(tmpdir != NULL) if (tmpdir != NULL) {
{
rproc.move_to_final = 1; rproc.move_to_final = 1;
mkdir_proc(rproc.procdir, tmpdir, loom, pid); mkdir_proc(rproc.procdir, tmpdir, loom, pid);
mkdir_proc(rproc.procdir_final, OVNI_TRACEDIR, loom, pid); mkdir_proc(rproc.procdir_final, OVNI_TRACEDIR, loom, pid);
} } else {
else
{
rproc.move_to_final = 0; rproc.move_to_final = 0;
mkdir_proc(rproc.procdir, OVNI_TRACEDIR, loom, pid); mkdir_proc(rproc.procdir, OVNI_TRACEDIR, loom, pid);
} }
@ -222,12 +216,12 @@ create_proc_dir(const char *loom, int pid)
void void
ovni_proc_init(int app, const char *loom, int pid) ovni_proc_init(int app, const char *loom, int pid)
{ {
if(rproc.ready) if (rproc.ready)
die("ovni_proc_init: pid %d already initialized\n", pid); die("ovni_proc_init: pid %d already initialized\n", pid);
memset(&rproc, 0, sizeof(rproc)); memset(&rproc, 0, sizeof(rproc));
if(strlen(loom) >= OVNI_MAX_HOSTNAME) if (strlen(loom) >= OVNI_MAX_HOSTNAME)
die("ovni_proc_init: loom name too long: %s\n", loom); die("ovni_proc_init: loom name too long: %s\n", loom);
strcpy(rproc.loom, loom); strcpy(rproc.loom, loom);
@ -253,28 +247,25 @@ move_thread_to_final(const char *src, const char *dst)
FILE *infile = fopen(src, "r"); FILE *infile = fopen(src, "r");
if(infile == NULL) if (infile == NULL) {
{
err("fopen(%s) failed: %s\n", src, strerror(errno)); err("fopen(%s) failed: %s\n", src, strerror(errno));
return -1; return -1;
} }
FILE *outfile = fopen(dst, "w"); FILE *outfile = fopen(dst, "w");
if(outfile == NULL) if (outfile == NULL) {
{
err("fopen(%s) failed: %s\n", src, strerror(errno)); err("fopen(%s) failed: %s\n", src, strerror(errno));
return -1; return -1;
} }
while((bytes = fread(buffer, 1, sizeof(buffer), infile)) > 0) while ((bytes = fread(buffer, 1, sizeof(buffer), infile)) > 0)
fwrite(buffer, 1, bytes, outfile); fwrite(buffer, 1, bytes, outfile);
fclose(outfile); fclose(outfile);
fclose(infile); fclose(infile);
if(remove(src) != 0) if (remove(src) != 0) {
{
err("remove(%s) failed: %s\n", src, strerror(errno)); err("remove(%s) failed: %s\n", src, strerror(errno));
return -1; return -1;
} }
@ -291,71 +282,65 @@ move_procdir_to_final(const char *procdir, const char *procdir_final)
char thread_final[PATH_MAX]; char thread_final[PATH_MAX];
int err = 0; int err = 0;
if((dir = opendir(procdir)) == NULL) if ((dir = opendir(procdir)) == NULL) {
{
err("opendir %s failed: %s\n", procdir, strerror(errno)); err("opendir %s failed: %s\n", procdir, strerror(errno));
return; return;
} }
const char *prefix = "thread."; const char *prefix = "thread.";
while((dirent = readdir(dir)) != NULL) while ((dirent = readdir(dir)) != NULL) {
{
/* It should only contain thread.* directories, skip others */ /* It should only contain thread.* directories, skip others */
if(strncmp(dirent->d_name, prefix, strlen(prefix)) != 0) if (strncmp(dirent->d_name, prefix, strlen(prefix)) != 0)
continue; continue;
if(snprintf(thread, PATH_MAX, "%s/%s", procdir, if (snprintf(thread, PATH_MAX, "%s/%s", procdir,
dirent->d_name) >= PATH_MAX) dirent->d_name)
{ >= PATH_MAX) {
err("snprintf: path too large: %s/%s\n", procdir, err("snprintf: path too large: %s/%s\n", procdir,
dirent->d_name); dirent->d_name);
err = 1; err = 1;
continue; continue;
} }
if(snprintf(thread_final, PATH_MAX, "%s/%s", procdir_final, if (snprintf(thread_final, PATH_MAX, "%s/%s", procdir_final,
dirent->d_name) >= PATH_MAX) dirent->d_name)
{ >= PATH_MAX) {
err("snprintf: path too large: %s/%s\n", procdir_final, err("snprintf: path too large: %s/%s\n", procdir_final,
dirent->d_name); dirent->d_name);
err = 1; err = 1;
continue; continue;
} }
if(move_thread_to_final(thread, thread_final) != 0) if (move_thread_to_final(thread, thread_final) != 0)
err = 1; err = 1;
} }
closedir(dir); closedir(dir);
if(rmdir(procdir) != 0) if (rmdir(procdir) != 0) {
{
err("rmdir(%s) failed: %s\n", procdir, strerror(errno)); err("rmdir(%s) failed: %s\n", procdir, strerror(errno));
err = 1; err = 1;
} }
/* Warn the user, but we cannot do much at this point */ /* Warn the user, but we cannot do much at this point */
if(err) if (err)
err("errors occurred when moving the trace to %s\n", procdir_final); err("errors occurred when moving the trace to %s\n", procdir_final);
} }
void void
ovni_proc_fini(void) ovni_proc_fini(void)
{ {
if(!rproc.ready) if (!rproc.ready)
die("ovni_proc_fini: process not initialized\n"); die("ovni_proc_fini: process not initialized\n");
/* Mark the process no longer ready */ /* Mark the process no longer ready */
rproc.ready = 0; rproc.ready = 0;
if(rproc.move_to_final) if (rproc.move_to_final) {
{
proc_metadata_store(rproc.meta, rproc.procdir_final); proc_metadata_store(rproc.meta, rproc.procdir_final);
move_procdir_to_final(rproc.procdir, rproc.procdir_final); move_procdir_to_final(rproc.procdir, rproc.procdir_final);
} } else {
else
{
proc_metadata_store(rproc.meta, rproc.procdir); proc_metadata_store(rproc.meta, rproc.procdir);
} }
} }
@ -363,16 +348,15 @@ ovni_proc_fini(void)
static void static void
write_evbuf(uint8_t *buf, size_t size) write_evbuf(uint8_t *buf, size_t size)
{ {
do do {
{
ssize_t written = write(rthread.streamfd, buf, size); ssize_t written = write(rthread.streamfd, buf, size);
if(written < 0) if (written < 0)
die("failed to write buffer to disk: %s\n", strerror(errno)); die("failed to write buffer to disk: %s\n", strerror(errno));
size -= written; size -= written;
buf += written; buf += written;
} while(size > 0); } while (size > 0);
} }
static void static void
@ -399,16 +383,15 @@ write_stream_header(void)
void void
ovni_thread_init(pid_t tid) ovni_thread_init(pid_t tid)
{ {
if(rthread.ready) if (rthread.ready) {
{
err("warning: thread %d already initialized, ignored\n", tid); err("warning: thread %d already initialized, ignored\n", tid);
return; return;
} }
if(tid == 0) if (tid == 0)
die("ovni_thread_init: cannot use tid=%d\n", tid); die("ovni_thread_init: cannot use tid=%d\n", tid);
if(!rproc.ready) if (!rproc.ready)
die("ovni_thread_init: process not yet initialized\n"); die("ovni_thread_init: process not yet initialized\n");
memset(&rthread, 0, sizeof(rthread)); memset(&rthread, 0, sizeof(rthread));
@ -417,7 +400,7 @@ ovni_thread_init(pid_t tid)
rthread.evlen = 0; rthread.evlen = 0;
rthread.evbuf = malloc(OVNI_MAX_EV_BUF); rthread.evbuf = malloc(OVNI_MAX_EV_BUF);
if(rthread.evbuf == NULL) if (rthread.evbuf == NULL)
die("ovni_thread_init: malloc failed: %s", strerror(errno)); die("ovni_thread_init: malloc failed: %s", strerror(errno));
create_trace_stream(); create_trace_stream();
@ -429,7 +412,7 @@ ovni_thread_init(pid_t tid)
void void
ovni_thread_free(void) ovni_thread_free(void)
{ {
if(!rthread.ready) if (!rthread.ready)
die("ovni_thread_free: thread not initialized\n"); die("ovni_thread_free: thread not initialized\n");
free(rthread.evbuf); free(rthread.evbuf);
@ -442,13 +425,14 @@ ovni_thread_isready(void)
} }
#ifdef USE_TSC #ifdef USE_TSC
static inline static inline uint64_t
uint64_t clock_tsc_now(void) clock_tsc_now(void)
{ {
uint32_t lo, hi; uint32_t lo, hi;
/* RDTSC copies contents of 64-bit TSC into EDX:EAX */ /* RDTSC copies contents of 64-bit TSC into EDX:EAX */
__asm__ volatile("rdtsc" : "=a" (lo), "=d" (hi)); __asm__ volatile("rdtsc"
: "=a"(lo), "=d"(hi));
return (uint64_t) hi << 32 | lo; return (uint64_t) hi << 32 | lo;
} }
#endif #endif
@ -459,7 +443,7 @@ clock_monotonic_now(void)
uint64_t ns = 1000ULL * 1000ULL * 1000ULL; uint64_t ns = 1000ULL * 1000ULL * 1000ULL;
struct timespec tp; struct timespec tp;
if(clock_gettime(rproc.clockid, &tp)) if (clock_gettime(rproc.clockid, &tp))
die("clock_gettime() failed: %s\n", strerror(errno)); die("clock_gettime() failed: %s\n", strerror(errno));
return tp.tv_sec * ns + tp.tv_nsec; return tp.tv_sec * ns + tp.tv_nsec;
@ -506,12 +490,12 @@ ovni_payload_size(const struct ovni_ev *ev)
{ {
int size; int size;
if(ev->header.flags & OVNI_EV_JUMBO) if (ev->header.flags & OVNI_EV_JUMBO)
return get_jumbo_payload_size(ev); return get_jumbo_payload_size(ev);
size = ev->header.flags & 0x0f; size = ev->header.flags & 0x0f;
if(size == 0) if (size == 0)
return 0; return 0;
/* The minimum size is 2 bytes, so we can encode a length of 16 /* The minimum size is 2 bytes, so we can encode a length of 16
@ -524,22 +508,22 @@ ovni_payload_size(const struct ovni_ev *ev)
void void
ovni_payload_add(struct ovni_ev *ev, const uint8_t *buf, int size) ovni_payload_add(struct ovni_ev *ev, const uint8_t *buf, int size)
{ {
if(ev->header.flags & OVNI_EV_JUMBO) if (ev->header.flags & OVNI_EV_JUMBO)
die("ovni_payload_add: event is marked as jumbo\n"); die("ovni_payload_add: event is marked as jumbo\n");
if(size < 2) if (size < 2)
die("ovni_payload_add: payload size %d too small\n", size); die("ovni_payload_add: payload size %d too small\n", size);
size_t payload_size = ovni_payload_size(ev); size_t payload_size = ovni_payload_size(ev);
/* Ensure we have room */ /* Ensure we have room */
if(payload_size + size > sizeof(ev->payload)) if (payload_size + size > sizeof(ev->payload))
die("ovni_payload_add: no space left for %d bytes\n", size); die("ovni_payload_add: no space left for %d bytes\n", size);
memcpy(&ev->payload.u8[payload_size], buf, size); memcpy(&ev->payload.u8[payload_size], buf, size);
payload_size += size; payload_size += size;
ev->header.flags = (ev->header.flags & 0xf0) | ((payload_size-1) & 0x0f); ev->header.flags = (ev->header.flags & 0xf0) | ((payload_size - 1) & 0x0f);
} }
int int
@ -554,12 +538,12 @@ ovni_ev_add(struct ovni_ev *ev);
void void
ovni_flush(void) ovni_flush(void)
{ {
struct ovni_ev pre={0}, post={0}; struct ovni_ev pre = {0}, post = {0};
if(!rthread.ready) if (!rthread.ready)
die("ovni_flush: thread is not initialized\n"); die("ovni_flush: thread is not initialized\n");
if(!rproc.ready) if (!rproc.ready)
die("ovni_flush: process is not initialized\n"); die("ovni_flush: process is not initialized\n");
ovni_ev_set_clock(&pre, ovni_clock_now()); ovni_ev_set_clock(&pre, ovni_clock_now());
@ -578,7 +562,7 @@ ovni_flush(void)
static void static void
add_flush_events(uint64_t t0, uint64_t t1) add_flush_events(uint64_t t0, uint64_t t1)
{ {
struct ovni_ev pre={0}, post={0}; struct ovni_ev pre = {0}, post = {0};
pre.header.clock = t0; pre.header.clock = t0;
ovni_ev_set_mcv(&pre, "OF["); ovni_ev_set_mcv(&pre, "OF[");
@ -597,7 +581,7 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize)
int flushed = 0; int flushed = 0;
uint64_t t0, t1; uint64_t t0, t1;
if(ovni_payload_size(ev) != 0) if (ovni_payload_size(ev) != 0)
die("ovni_ev_add_jumbo: the event payload must be empty\n"); die("ovni_ev_add_jumbo: the event payload must be empty\n");
ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize)); ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize));
@ -605,12 +589,11 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize)
size_t totalsize = evsize + bufsize; size_t totalsize = evsize + bufsize;
if(totalsize >= OVNI_MAX_EV_BUF) if (totalsize >= OVNI_MAX_EV_BUF)
die("ovni_ev_add_jumbo: event too large\n"); die("ovni_ev_add_jumbo: event too large\n");
/* Check if the event fits or flush first otherwise */ /* Check if the event fits or flush first otherwise */
if(rthread.evlen + totalsize >= OVNI_MAX_EV_BUF) if (rthread.evlen + totalsize >= OVNI_MAX_EV_BUF) {
{
/* Measure the flush times */ /* Measure the flush times */
t0 = ovni_clock_now(); t0 = ovni_clock_now();
flush_evbuf(); flush_evbuf();
@ -627,8 +610,7 @@ ovni_ev_add_jumbo(struct ovni_ev *ev, const uint8_t *buf, uint32_t bufsize)
memcpy(&rthread.evbuf[rthread.evlen], buf, bufsize); memcpy(&rthread.evbuf[rthread.evlen], buf, bufsize);
rthread.evlen += bufsize; rthread.evlen += bufsize;
if(flushed) if (flushed) {
{
/* Emit the flush events *after* the user event */ /* Emit the flush events *after* the user event */
add_flush_events(t0, t1); add_flush_events(t0, t1);
} }
@ -643,8 +625,7 @@ ovni_ev_add(struct ovni_ev *ev)
int size = ovni_ev_size(ev); int size = ovni_ev_size(ev);
/* Check if the event fits or flush first otherwise */ /* Check if the event fits or flush first otherwise */
if(rthread.evlen + size >= OVNI_MAX_EV_BUF) if (rthread.evlen + size >= OVNI_MAX_EV_BUF) {
{
/* Measure the flush times */ /* Measure the flush times */
t0 = ovni_clock_now(); t0 = ovni_clock_now();
flush_evbuf(); flush_evbuf();
@ -655,8 +636,7 @@ ovni_ev_add(struct ovni_ev *ev)
memcpy(&rthread.evbuf[rthread.evlen], ev, size); memcpy(&rthread.evbuf[rthread.evlen], ev, size);
rthread.evlen += size; rthread.evlen += size;
if(flushed) if (flushed) {
{
/* Emit the flush events *after* the user event */ /* Emit the flush events *after* the user event */
add_flush_events(t0, t1); add_flush_events(t0, t1);
} }

9
ovni.h
View File

@ -8,16 +8,16 @@
extern "C" { extern "C" {
#endif #endif
#include <stdio.h> #include <limits.h>
#include <linux/limits.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <linux/limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <limits.h>
/* Hardcode the JSON_Value to avoid a dependency with janson */ /* Hardcode the JSON_Value to avoid a dependency with janson */
typedef struct json_value_t JSON_Value; typedef struct json_value_t JSON_Value;
#define OVNI_METADATA_VERSION 1 #define OVNI_METADATA_VERSION 1
@ -43,7 +43,6 @@ struct __attribute__((__packed__)) ovni_jumbo_payload {
}; };
union __attribute__((__packed__)) ovni_ev_payload { union __attribute__((__packed__)) ovni_ev_payload {
int8_t i8[16]; int8_t i8[16];
int16_t i16[8]; int16_t i16[8];
int32_t i32[4]; int32_t i32[4];

View File

@ -1,15 +1,15 @@
/* Copyright (c) 2021 Barcelona Supercomputing Center (BSC) /* Copyright (c) 2021 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
#include <stdio.h> #include <dirent.h>
#include <errno.h>
#include <linux/limits.h>
#include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <linux/limits.h>
#include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdatomic.h>
#include <dirent.h>
#include "ovni.h" #include "ovni.h"
#include "trace.h" #include "trace.h"
@ -20,19 +20,19 @@ emit(struct ovni_ev *ev, int row)
static uint64_t firstclock = 0; static uint64_t firstclock = 0;
int64_t delta; int64_t delta;
if(firstclock == 0) if (firstclock == 0)
firstclock = ovni_ev_get_clock(ev); firstclock = ovni_ev_get_clock(ev);
delta = ovni_ev_get_clock(ev) - firstclock; delta = ovni_ev_get_clock(ev) - firstclock;
//#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1) //#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1)
//2:0:1:1:7:1540663:6400010:1 // 2:0:1:1:7:1540663:6400010:1
//2:0:1:1:7:1540663:6400015:1 // 2:0:1:1:7:1540663:6400015:1
//2:0:1:1:7:1540663:6400017:0 // 2:0:1:1:7:1540663:6400017:0
//2:0:1:1:7:1542091:6400010:1 // 2:0:1:1:7:1542091:6400010:1
//2:0:1:1:7:1542091:6400015:1 // 2:0:1:1:7:1542091:6400015:1
//2:0:1:1:7:1542091:6400025:1 // 2:0:1:1:7:1542091:6400025:1
//2:0:1:1:7:1542091:6400017:0 // 2:0:1:1:7:1542091:6400017:0
printf("2:0:1:1:%d:%ld:%d:%d\n", row, delta, ev->header.category, ev->header.value); printf("2:0:1:1:%d:%ld:%d:%d\n", row, delta, ev->header.category, ev->header.value);
} }
@ -47,44 +47,39 @@ dump_events(struct ovni_trace *trace)
struct ovni_stream *stream; struct ovni_stream *stream;
/* Load events */ /* Load events */
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
ovni_load_next_event(stream); ovni_load_next_event(stream);
} }
lastclock = 0; lastclock = 0;
while(1) while (1) {
{
f = -1; f = -1;
minclock = 0; minclock = 0;
/* Select next event based on the clock */ /* Select next event based on the clock */
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
if(!stream->active) if (!stream->active)
continue; continue;
ev = stream->cur_ev; ev = stream->cur_ev;
if(f < 0 || ovni_ev_get_clock(ev) < minclock) if (f < 0 || ovni_ev_get_clock(ev) < minclock) {
{
f = i; f = i;
minclock = ovni_ev_get_clock(ev); minclock = ovni_ev_get_clock(ev);
} }
} }
//fprintf(stderr, "f=%d minclock=%u\n", f, minclock); // fprintf(stderr, "f=%d minclock=%u\n", f, minclock);
if(f < 0) if (f < 0)
break; break;
stream = &trace->stream[f]; stream = &trace->stream[f];
if(lastclock >= ovni_ev_get_clock(stream->cur_ev)) if (lastclock >= ovni_ev_get_clock(stream->cur_ev)) {
{
fprintf(stderr, "warning: backwards jump in time\n"); fprintf(stderr, "warning: backwards jump in time\n");
} }
@ -100,37 +95,35 @@ dump_events(struct ovni_trace *trace)
/* Unset the index */ /* Unset the index */
f = -1; f = -1;
minclock = 0; minclock = 0;
} }
} }
int main(int argc, char *argv[]) int
main(int argc, char *argv[])
{ {
char *tracedir; char *tracedir;
struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace)); struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace));
if(trace == NULL) if (trace == NULL) {
{
perror("calloc"); perror("calloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(argc != 2) if (argc != 2) {
{
fprintf(stderr, "missing tracedir\n"); fprintf(stderr, "missing tracedir\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tracedir = argv[1]; tracedir = argv[1];
if(ovni_load_trace(trace, tracedir)) if (ovni_load_trace(trace, tracedir))
return 1; return 1;
if(ovni_load_streams(trace)) if (ovni_load_streams(trace))
return 1; return 1;
printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%ld:1)\n", printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%ld:1)\n",
trace->nstreams); trace->nstreams);
dump_events(trace); dump_events(trace);

View File

@ -60,18 +60,15 @@ static double
get_time(clockid_t clock, int use_ns) get_time(clockid_t clock, int use_ns)
{ {
struct timespec tv; struct timespec tv;
if(clock_gettime(clock, &tv) != 0) if (clock_gettime(clock, &tv) != 0) {
{
perror("clock_gettime failed"); perror("clock_gettime failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(use_ns) if (use_ns)
return (double)(tv.tv_sec) * 1.0e9 + return (double) (tv.tv_sec) * 1.0e9 + (double) tv.tv_nsec;
(double)tv.tv_nsec;
return (double)(tv.tv_sec) + return (double) (tv.tv_sec) + (double) tv.tv_nsec * 1.0e-9;
(double)tv.tv_nsec * 1.0e-9;
} }
static int static int
@ -82,9 +79,9 @@ cmp_double(const void *pa, const void *pb)
a = *(const double *) pa; a = *(const double *) pa;
b = *(const double *) pb; b = *(const double *) pb;
if(a < b) if (a < b)
return -1; return -1;
else if(a > b) else if (a > b)
return 1; return 1;
else else
return 0; return 0;
@ -96,7 +93,7 @@ usage(void)
fprintf(stderr, "%s: clock synchronization utility\n", progname); fprintf(stderr, "%s: clock synchronization utility\n", progname);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [-o outfile] [-d ndrift_samples] [-v] [-n nsamples] [-w drift_delay]\n", fprintf(stderr, "Usage: %s [-o outfile] [-d ndrift_samples] [-v] [-n nsamples] [-w drift_delay]\n",
progname); progname);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -105,13 +102,10 @@ try_mkdir(const char *path, mode_t mode)
{ {
struct stat st; struct stat st;
if(stat(path, &st) != 0) if (stat(path, &st) != 0) {
{
/* Directory does not exist */ /* Directory does not exist */
return mkdir(path, mode); return mkdir(path, mode);
} } else if (!S_ISDIR(st.st_mode)) {
else if(!S_ISDIR(st.st_mode))
{
errno = ENOTDIR; errno = ENOTDIR;
return -1; return -1;
} }
@ -183,8 +177,7 @@ parse_options(struct options *options, int argc, char *argv[])
} }
} }
if (optind < argc) if (optind < argc) {
{
fprintf(stderr, "error: unexpected extra arguments\n"); fprintf(stderr, "error: unexpected extra arguments\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -200,8 +193,7 @@ get_clock_samples(struct offset *offset, int nsamples)
offset->nsamples = nsamples; offset->nsamples = nsamples;
for(i=0; i<nsamples; i++) for (i = 0; i < nsamples; i++) {
{
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
offset->clock_sample[i] = get_time(CLOCK_MONOTONIC, 1); offset->clock_sample[i] = get_time(CLOCK_MONOTONIC, 1);
} }
@ -218,13 +210,12 @@ fill_offset(struct offset *offset, int nsamples)
MPI_Comm_rank(MPI_COMM_WORLD, &offset->rank); MPI_Comm_rank(MPI_COMM_WORLD, &offset->rank);
/* Fill the host name */ /* Fill the host name */
if(gethostname(offset->hostname, OVNI_MAX_HOSTNAME) != 0) if (gethostname(offset->hostname, OVNI_MAX_HOSTNAME) != 0) {
{
perror("gethostname"); perror("gethostname");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
//printf("rank=%d hostname=%s\n", offset->rank, offset->hostname); // printf("rank=%d hostname=%s\n", offset->rank, offset->hostname);
/* Warm up iterations */ /* Warm up iterations */
warmup_nsamples = nsamples >= 20 ? 20 : nsamples; warmup_nsamples = nsamples >= 20 ? 20 : nsamples;
@ -241,21 +232,18 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v
delta = malloc(sizeof(double) * nsamples); delta = malloc(sizeof(double) * nsamples);
if(delta == NULL) if (delta == NULL) {
{
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for(i=0; i<nsamples; i++) for (i = 0; i < nsamples; i++) {
{
delta[i] = ref->clock_sample[i] - cur->clock_sample[i]; delta[i] = ref->clock_sample[i] - cur->clock_sample[i];
if(verbose) if (verbose) {
{
printf("rank=%d sample=%d delta=%f ref=%f cur=%f\n", printf("rank=%d sample=%d delta=%f ref=%f cur=%f\n",
cur->rank, i, delta[i], cur->rank, i, delta[i],
ref->clock_sample[i], ref->clock_sample[i],
cur->clock_sample[i]); cur->clock_sample[i]);
} }
} }
@ -263,14 +251,13 @@ offset_compute_delta(struct offset *ref, struct offset *cur, int nsamples, int v
cur->delta_median = delta[nsamples / 2]; cur->delta_median = delta[nsamples / 2];
for(cur->delta_mean=0, i=0; i<nsamples; i++) for (cur->delta_mean = 0, i = 0; i < nsamples; i++)
cur->delta_mean += delta[i]; cur->delta_mean += delta[i];
cur->delta_mean /= nsamples; cur->delta_mean /= nsamples;
for(cur->delta_var=0, i=0; i<nsamples; i++) for (cur->delta_var = 0, i = 0; i < nsamples; i++)
cur->delta_var += (delta[i] - cur->delta_mean) * cur->delta_var += (delta[i] - cur->delta_mean) * (delta[i] - cur->delta_mean);
(delta[i] - cur->delta_mean);
cur->delta_var /= (double) (nsamples - 1); cur->delta_var /= (double) (nsamples - 1);
cur->delta_std = sqrt(cur->delta_var); cur->delta_std = sqrt(cur->delta_var);
@ -307,12 +294,10 @@ build_offset_table(int nsamples, int rank, int verbose)
void *sendbuf; void *sendbuf;
/* The rank 0 must build the table */ /* The rank 0 must build the table */
if(rank == 0) if (rank == 0) {
{
table = malloc(sizeof(*table)); table = malloc(sizeof(*table));
if(table == NULL) if (table == NULL) {
{
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -321,33 +306,27 @@ build_offset_table(int nsamples, int rank, int verbose)
table->_offset = calloc(table->nprocs, offset_size(nsamples)); table->_offset = calloc(table->nprocs, offset_size(nsamples));
if(table->_offset == NULL) if (table->_offset == NULL) {
{
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
table->offset = malloc(sizeof(struct offset *) * table->offset = malloc(sizeof(struct offset *) * table->nprocs);
table->nprocs);
if(table->offset == NULL) if (table->offset == NULL) {
{
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for(i=0; i<table->nprocs; i++) for (i = 0; i < table->nprocs; i++)
table->offset[i] = table_get_offset(table, i, nsamples); table->offset[i] = table_get_offset(table, i, nsamples);
offset = table->offset[0]; offset = table->offset[0];
} } else {
else
{
/* Otherwise just allocate one offset */ /* Otherwise just allocate one offset */
offset = calloc(1, offset_size(nsamples)); offset = calloc(1, offset_size(nsamples));
if(offset == NULL) if (offset == NULL) {
{
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -362,21 +341,19 @@ build_offset_table(int nsamples, int rank, int verbose)
/* Then collect all the offsets into the rank 0 */ /* Then collect all the offsets into the rank 0 */
MPI_Gather(sendbuf, offset_size(nsamples), MPI_CHAR, MPI_Gather(sendbuf, offset_size(nsamples), MPI_CHAR,
offset, offset_size(nsamples), MPI_CHAR, offset, offset_size(nsamples), MPI_CHAR,
0, MPI_COMM_WORLD); 0, MPI_COMM_WORLD);
/* Finish the offsets by computing the deltas on rank 0 */ /* Finish the offsets by computing the deltas on rank 0 */
if(rank == 0) if (rank == 0) {
{ for (i = 0; i < table->nprocs; i++) {
for(i=0; i<table->nprocs; i++)
{
offset_compute_delta(offset, table->offset[i], offset_compute_delta(offset, table->offset[i],
nsamples, verbose); nsamples, verbose);
} }
} }
/* Cleanup for non-zero ranks */ /* Cleanup for non-zero ranks */
if(rank != 0) if (rank != 0)
free(offset); free(offset);
return table; return table;
@ -386,13 +363,12 @@ static void
print_drift_header(FILE *out, struct offset_table *table) print_drift_header(FILE *out, struct offset_table *table)
{ {
int i; int i;
//char buf[64]; // char buf[64];
fprintf(out, "%-20s", "wallclock"); fprintf(out, "%-20s", "wallclock");
for(i=0; i<table->nprocs; i++) for (i = 0; i < table->nprocs; i++) {
{ // sprintf(buf, "rank%d", i);
//sprintf(buf, "rank%d", i);
fprintf(out, " %-20s", table->offset[i]->hostname); fprintf(out, " %-20s", table->offset[i]->hostname);
} }
@ -406,7 +382,7 @@ print_drift_row(FILE *out, struct offset_table *table)
fprintf(out, "%-20f", table->offset[0]->wall_t1); fprintf(out, "%-20f", table->offset[0]->wall_t1);
for(i=0; i<table->nprocs; i++) for (i = 0; i < table->nprocs; i++)
fprintf(out, " %-20ld", table->offset[i]->offset); fprintf(out, " %-20ld", table->offset[i]->offset);
fprintf(out, "\n"); fprintf(out, "\n");
@ -419,14 +395,13 @@ print_table_detailed(FILE *out, struct offset_table *table)
struct offset *offset; struct offset *offset;
fprintf(out, "%-10s %-20s %-20s %-20s %-20s\n", fprintf(out, "%-10s %-20s %-20s %-20s %-20s\n",
"rank", "hostname", "offset_median", "offset_mean", "offset_std"); "rank", "hostname", "offset_median", "offset_mean", "offset_std");
for(i=0; i<table->nprocs; i++) for (i = 0; i < table->nprocs; i++) {
{
offset = table->offset[i]; offset = table->offset[i];
fprintf(out, "%-10d %-20s %-20ld %-20f %-20f\n", fprintf(out, "%-10d %-20s %-20ld %-20f %-20f\n",
i, offset->hostname, offset->offset, i, offset->hostname, offset->offset,
offset->delta_mean, offset->delta_std); offset->delta_mean, offset->delta_std);
} }
} }
@ -440,39 +415,31 @@ do_work(struct options *options, int rank)
drift_mode = options->ndrift_samples > 1 ? 1 : 0; drift_mode = options->ndrift_samples > 1 ? 1 : 0;
if(rank == 0) if (rank == 0) {
{ if (mkpath(options->outpath, 0755) != 0) {
if(mkpath(options->outpath, 0755) != 0)
{
fprintf(stderr, "mkpath(%s) failed: %s\n", fprintf(stderr, "mkpath(%s) failed: %s\n",
options->outpath, strerror(errno)); options->outpath, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
out = fopen(options->outpath, "w"); out = fopen(options->outpath, "w");
if(out == NULL) if (out == NULL) {
{
fprintf(stderr, "fopen(%s) failed: %s\n", fprintf(stderr, "fopen(%s) failed: %s\n",
options->outpath, strerror(errno)); options->outpath, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
for(i=0; i<options->ndrift_samples; i++) for (i = 0; i < options->ndrift_samples; i++) {
{
table = build_offset_table(options->nsamples, rank, options->verbose); table = build_offset_table(options->nsamples, rank, options->verbose);
if(rank == 0) if (rank == 0) {
{ if (drift_mode) {
if(drift_mode) if (i == 0)
{
if(i == 0)
print_drift_header(out, table); print_drift_header(out, table);
print_drift_row(out, table); print_drift_row(out, table);
} } else {
else
{
print_table_detailed(out, table); print_table_detailed(out, table);
} }
@ -481,11 +448,11 @@ do_work(struct options *options, int rank)
free(table); free(table);
} }
if(drift_mode) if (drift_mode)
sleep(options->drift_wait); sleep(options->drift_wait);
} }
if(rank == 0) if (rank == 0)
fclose(out); fclose(out);
} }

4218
parson.c

File diff suppressed because it is too large Load Diff

161
parson.h
View File

@ -27,36 +27,35 @@
#define parson_parson_h #define parson_parson_h
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <stddef.h> /* size_t */ #include <stddef.h> /* size_t */
/* Types and enums */ /* Types and enums */
typedef struct json_object_t JSON_Object; typedef struct json_object_t JSON_Object;
typedef struct json_array_t JSON_Array; typedef struct json_array_t JSON_Array;
typedef struct json_value_t JSON_Value; typedef struct json_value_t JSON_Value;
enum json_value_type { enum json_value_type {
JSONError = -1, JSONError = -1,
JSONNull = 1, JSONNull = 1,
JSONString = 2, JSONString = 2,
JSONNumber = 3, JSONNumber = 3,
JSONObject = 4, JSONObject = 4,
JSONArray = 5, JSONArray = 5,
JSONBoolean = 6 JSONBoolean = 6
}; };
typedef int JSON_Value_Type; typedef int JSON_Value_Type;
enum json_result_t { enum json_result_t {
JSONSuccess = 0, JSONSuccess = 0,
JSONFailure = -1 JSONFailure = -1
}; };
typedef int JSON_Status; typedef int JSON_Status;
typedef void * (*JSON_Malloc_Function)(size_t); typedef void *(*JSON_Malloc_Function)(size_t);
typedef void (*JSON_Free_Function)(void *); typedef void (*JSON_Free_Function)(void *);
/* Call only once, before calling any other function from parson API. If not called, malloc and free /* Call only once, before calling any other function from parson API. If not called, malloc and free
from stdlib will be used for all allocations */ from stdlib will be used for all allocations */
@ -67,35 +66,35 @@ void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Fu
void json_set_escape_slashes(int escape_slashes); void json_set_escape_slashes(int escape_slashes);
/* Parses first JSON value in a file, returns NULL in case of error */ /* Parses first JSON value in a file, returns NULL in case of error */
JSON_Value * json_parse_file(const char *filename); JSON_Value *json_parse_file(const char *filename);
/* Parses first JSON value in a file and ignores comments (/ * * / and //), /* Parses first JSON value in a file and ignores comments (/ * * / and //),
returns NULL in case of error */ returns NULL in case of error */
JSON_Value * json_parse_file_with_comments(const char *filename); JSON_Value *json_parse_file_with_comments(const char *filename);
/* Parses first JSON value in a string, returns NULL in case of error */ /* Parses first JSON value in a string, returns NULL in case of error */
JSON_Value * json_parse_string(const char *string); JSON_Value *json_parse_string(const char *string);
/* Parses first JSON value in a string and ignores comments (/ * * / and //), /* Parses first JSON value in a string and ignores comments (/ * * / and //),
returns NULL in case of error */ returns NULL in case of error */
JSON_Value * json_parse_string_with_comments(const char *string); JSON_Value *json_parse_string_with_comments(const char *string);
/* Serialization */ /* Serialization */
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
char * json_serialize_to_string(const JSON_Value *value); char *json_serialize_to_string(const JSON_Value *value);
/* Pretty serialization */ /* Pretty serialization */
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
char * json_serialize_to_string_pretty(const JSON_Value *value); char *json_serialize_to_string_pretty(const JSON_Value *value);
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
/* Comparing */ /* Comparing */
int json_value_equals(const JSON_Value *a, const JSON_Value *b); int json_value_equals(const JSON_Value *a, const JSON_Value *b);
/* Validation /* Validation
This is *NOT* JSON Schema. It validates json by checking if object have identically This is *NOT* JSON Schema. It validates json by checking if object have identically
@ -112,45 +111,45 @@ JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
/* /*
* JSON Object * JSON Object
*/ */
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); JSON_Value *json_object_get_value(const JSON_Object *object, const char *name);
const char * json_object_get_string (const JSON_Object *object, const char *name); const char *json_object_get_string(const JSON_Object *object, const char *name);
size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); JSON_Object *json_object_get_object(const JSON_Object *object, const char *name);
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); JSON_Array *json_object_get_array(const JSON_Object *object, const char *name);
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ double json_object_get_number(const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* dotget functions enable addressing values with dot notation in nested objects, /* dotget functions enable addressing values with dot notation in nested objects,
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
Because valid names in JSON can contain dots, some values may be inaccessible Because valid names in JSON can contain dots, some values may be inaccessible
this way. */ this way. */
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); JSON_Value *json_object_dotget_value(const JSON_Object *object, const char *name);
const char * json_object_dotget_string (const JSON_Object *object, const char *name); const char *json_object_dotget_string(const JSON_Object *object, const char *name);
size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); JSON_Object *json_object_dotget_object(const JSON_Object *object, const char *name);
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); JSON_Array *json_object_dotget_array(const JSON_Object *object, const char *name);
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ double json_object_dotget_number(const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* Functions to get available names */ /* Functions to get available names */
size_t json_object_get_count (const JSON_Object *object); size_t json_object_get_count(const JSON_Object *object);
const char * json_object_get_name (const JSON_Object *object, size_t index); const char *json_object_get_name(const JSON_Object *object, size_t index);
JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index); JSON_Value *json_object_get_value_at(const JSON_Object *object, size_t index);
JSON_Value * json_object_get_wrapping_value(const JSON_Object *object); JSON_Value *json_object_get_wrapping_value(const JSON_Object *object);
/* Functions to check if object has a value with a specific name. Returned value is 1 if object has /* Functions to check if object has a value with a specific name. Returned value is 1 if object has
* a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
int json_object_has_value (const JSON_Object *object, const char *name); int json_object_has_value(const JSON_Object *object, const char *name);
int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
int json_object_dothas_value (const JSON_Object *object, const char *name); int json_object_dothas_value(const JSON_Object *object, const char *name);
int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
/* Creates new name-value pair or frees and replaces old value with a new one. /* Creates new name-value pair or frees and replaces old value with a new one.
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */ JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_set_null(JSON_Object *object, const char *name); JSON_Status json_object_set_null(JSON_Object *object, const char *name);
@ -176,15 +175,15 @@ JSON_Status json_object_clear(JSON_Object *object);
/* /*
*JSON Array *JSON Array
*/ */
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); JSON_Value *json_array_get_value(const JSON_Array *array, size_t index);
const char * json_array_get_string (const JSON_Array *array, size_t index); const char *json_array_get_string(const JSON_Array *array, size_t index);
size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */ size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); JSON_Object *json_array_get_object(const JSON_Array *array, size_t index);
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); JSON_Array *json_array_get_array(const JSON_Array *array, size_t index);
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ double json_array_get_number(const JSON_Array *array, size_t index); /* returns 0 on fail */
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
size_t json_array_get_count (const JSON_Array *array); size_t json_array_get_count(const JSON_Array *array);
JSON_Value * json_array_get_wrapping_value(const JSON_Array *array); JSON_Value *json_array_get_wrapping_value(const JSON_Array *array);
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist. /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
* Order of values in array may change during execution. */ * Order of values in array may change during execution. */
@ -194,7 +193,7 @@ JSON_Status json_array_remove(JSON_Array *array, size_t i);
* Does nothing and returns JSONFailure if index doesn't exist. * Does nothing and returns JSONFailure if index doesn't exist.
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char *string);
JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */ JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
@ -215,33 +214,33 @@ JSON_Status json_array_append_null(JSON_Array *array);
/* /*
*JSON Value *JSON Value
*/ */
JSON_Value * json_value_init_object (void); JSON_Value *json_value_init_object(void);
JSON_Value * json_value_init_array (void); JSON_Value *json_value_init_array(void);
JSON_Value * json_value_init_string (const char *string); /* copies passed string */ JSON_Value *json_value_init_string(const char *string); /* copies passed string */
JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */ JSON_Value *json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */
JSON_Value * json_value_init_number (double number); JSON_Value *json_value_init_number(double number);
JSON_Value * json_value_init_boolean(int boolean); JSON_Value *json_value_init_boolean(int boolean);
JSON_Value * json_value_init_null (void); JSON_Value *json_value_init_null(void);
JSON_Value * json_value_deep_copy (const JSON_Value *value); JSON_Value *json_value_deep_copy(const JSON_Value *value);
void json_value_free (JSON_Value *value); void json_value_free(JSON_Value *value);
JSON_Value_Type json_value_get_type (const JSON_Value *value); JSON_Value_Type json_value_get_type(const JSON_Value *value);
JSON_Object * json_value_get_object (const JSON_Value *value); JSON_Object *json_value_get_object(const JSON_Value *value);
JSON_Array * json_value_get_array (const JSON_Value *value); JSON_Array *json_value_get_array(const JSON_Value *value);
const char * json_value_get_string (const JSON_Value *value); const char *json_value_get_string(const JSON_Value *value);
size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */ size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */
double json_value_get_number (const JSON_Value *value); double json_value_get_number(const JSON_Value *value);
int json_value_get_boolean(const JSON_Value *value); int json_value_get_boolean(const JSON_Value *value);
JSON_Value * json_value_get_parent (const JSON_Value *value); JSON_Value *json_value_get_parent(const JSON_Value *value);
/* Same as above, but shorter */ /* Same as above, but shorter */
JSON_Value_Type json_type (const JSON_Value *value); JSON_Value_Type json_type(const JSON_Value *value);
JSON_Object * json_object (const JSON_Value *value); JSON_Object *json_object(const JSON_Value *value);
JSON_Array * json_array (const JSON_Value *value); JSON_Array *json_array(const JSON_Value *value);
const char * json_string (const JSON_Value *value); const char *json_string(const JSON_Value *value);
size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */ size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */
double json_number (const JSON_Value *value); double json_number(const JSON_Value *value);
int json_boolean(const JSON_Value *value); int json_boolean(const JSON_Value *value);
#ifdef __cplusplus #ifdef __cplusplus
} }

441
pcf.c
View File

@ -2,12 +2,12 @@
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
#include "pcf.h" #include "pcf.h"
#include "prv.h"
#include "emu.h" #include "emu.h"
#include "prv.h"
#include <stdio.h>
#include <stdint.h>
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <stdio.h>
const char *pcf_def_header = const char *pcf_def_header =
"DEFAULT_OPTIONS\n" "DEFAULT_OPTIONS\n"
@ -25,44 +25,43 @@ const char *pcf_def_header =
"\n" "\n"
"THREAD_FUNC State As Is\n"; "THREAD_FUNC State As Is\n";
#define RGB(r, g, b) (r<<16 | g<<8 | b) #define RGB(r, g, b) (r << 16 | g << 8 | b)
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0])) #define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
/* Define colors for the trace */ /* Define colors for the trace */
#define DEEPBLUE RGB( 0, 0, 255) #define DEEPBLUE RGB(0, 0, 255)
#define LIGHTGREY RGB(217, 217, 217) #define LIGHTGREY RGB(217, 217, 217)
#define RED RGB(230, 25, 75) #define RED RGB(230, 25, 75)
#define GREEN RGB(60, 180, 75) #define GREEN RGB(60, 180, 75)
#define YELLOW RGB(255, 225, 25) #define YELLOW RGB(255, 225, 25)
#define ORANGE RGB(245, 130, 48) #define ORANGE RGB(245, 130, 48)
#define PURPLE RGB(145, 30, 180) #define PURPLE RGB(145, 30, 180)
#define CYAN RGB( 70, 240, 240) #define CYAN RGB(70, 240, 240)
#define MAGENTA RGB(240, 50, 230) #define MAGENTA RGB(240, 50, 230)
#define LIME RGB(210, 245, 60) #define LIME RGB(210, 245, 60)
#define PINK RGB(250, 190, 212) #define PINK RGB(250, 190, 212)
#define TEAL RGB( 0, 128, 128) #define TEAL RGB(0, 128, 128)
#define LAVENDER RGB(220, 190, 255) #define LAVENDER RGB(220, 190, 255)
#define BROWN RGB(170, 110, 40) #define BROWN RGB(170, 110, 40)
#define BEIGE RGB(255, 250, 200) #define BEIGE RGB(255, 250, 200)
#define MAROON RGB(128, 0, 0) #define MAROON RGB(128, 0, 0)
#define MINT RGB(170, 255, 195) #define MINT RGB(170, 255, 195)
#define OLIVE RGB(128, 128, 0) #define OLIVE RGB(128, 128, 0)
#define APRICOT RGB(255, 215, 180) #define APRICOT RGB(255, 215, 180)
#define NAVY RGB( 0, 0, 128) #define NAVY RGB(0, 0, 128)
#define BLUE RGB( 0, 130, 200) #define BLUE RGB(0, 130, 200)
#define GREY RGB(128, 128, 128) #define GREY RGB(128, 128, 128)
#define BLACK RGB( 0, 0, 0) #define BLACK RGB(0, 0, 0)
const uint32_t pcf_def_palette[] = { const uint32_t pcf_def_palette[] = {
BLACK, /* (never shown anyways) */ BLACK, /* (never shown anyways) */
BLUE, /* runtime */ BLUE, /* runtime */
LIGHTGREY, /* busy wait */ LIGHTGREY, /* busy wait */
RED, /* task */ RED, /* task */
GREEN, GREEN,
YELLOW, ORANGE, PURPLE, CYAN, MAGENTA, LIME, PINK, YELLOW, ORANGE, PURPLE, CYAN, MAGENTA, LIME, PINK,
TEAL, GREY, LAVENDER, BROWN, BEIGE, MAROON, MINT, TEAL, GREY, LAVENDER, BROWN, BEIGE, MAROON, MINT,
OLIVE, APRICOT, NAVY, DEEPBLUE OLIVE, APRICOT, NAVY, DEEPBLUE};
};
const uint32_t *pcf_palette = pcf_def_palette; const uint32_t *pcf_palette = pcf_def_palette;
const int pcf_palette_len = ARRAY_LEN(pcf_def_palette); const int pcf_palette_len = ARRAY_LEN(pcf_def_palette);
@ -70,197 +69,201 @@ const int pcf_palette_len = ARRAY_LEN(pcf_def_palette);
/* ------------------ Value labels --------------------- */ /* ------------------ Value labels --------------------- */
struct pcf_value_label default_values[] = { struct pcf_value_label default_values[] = {
{ ST_TOO_MANY_TH, "Unknown: Multiple threads running" }, {ST_TOO_MANY_TH, "Unknown: Multiple threads running"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label ovni_state_values[] = { struct pcf_value_label ovni_state_values[] = {
{ TH_ST_UNKNOWN, "Unknown" }, {TH_ST_UNKNOWN, "Unknown"},
{ TH_ST_RUNNING, "Running" }, {TH_ST_RUNNING, "Running"},
{ TH_ST_PAUSED, "Paused" }, {TH_ST_PAUSED, "Paused"},
{ TH_ST_DEAD, "Dead" }, {TH_ST_DEAD, "Dead"},
{ TH_ST_COOLING, "Cooling" }, {TH_ST_COOLING, "Cooling"},
{ TH_ST_WARMING, "Warming" }, {TH_ST_WARMING, "Warming"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label ovni_flush_values[] = { struct pcf_value_label ovni_flush_values[] = {
{ 0, "None" }, {0, "None"},
{ ST_OVNI_FLUSHING, "Flushing" }, {ST_OVNI_FLUSHING, "Flushing"},
{ ST_TOO_MANY_TH, "Unknown flushing state: Multiple threads running" }, {ST_TOO_MANY_TH, "Unknown flushing state: Multiple threads running"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label nosv_ss_values[] = { struct pcf_value_label nosv_ss_values[] = {
/* Errors */ /* Errors */
{ ST_BAD, "Unknown: bad happened (report bug)" }, {ST_BAD, "Unknown: bad happened (report bug)"},
{ ST_TOO_MANY_TH, "Unknown: multiple threads running" }, {ST_TOO_MANY_TH, "Unknown: multiple threads running"},
/* Good values */ /* Good values */
{ ST_NULL, "No subsystem" }, {ST_NULL, "No subsystem"},
{ ST_NOSV_SCHED_HUNGRY, "Scheduler: Hungry" }, {ST_NOSV_SCHED_HUNGRY, "Scheduler: Hungry"},
{ ST_NOSV_SCHED_SERVING, "Scheduler: Serving" }, {ST_NOSV_SCHED_SERVING, "Scheduler: Serving"},
{ ST_NOSV_SCHED_SUBMITTING, "Scheduler: Submitting" }, {ST_NOSV_SCHED_SUBMITTING, "Scheduler: Submitting"},
{ ST_NOSV_MEM_ALLOCATING, "Memory: Allocating" }, {ST_NOSV_MEM_ALLOCATING, "Memory: Allocating"},
{ ST_NOSV_MEM_FREEING, "Memory: Freeing" }, {ST_NOSV_MEM_FREEING, "Memory: Freeing"},
{ ST_NOSV_TASK_RUNNING, "Task: Running" }, {ST_NOSV_TASK_RUNNING, "Task: Running"},
{ ST_NOSV_API_SUBMIT, "API: Submit" }, {ST_NOSV_API_SUBMIT, "API: Submit"},
{ ST_NOSV_API_PAUSE, "API: Pause" }, {ST_NOSV_API_PAUSE, "API: Pause"},
{ ST_NOSV_API_YIELD, "API: Yield" }, {ST_NOSV_API_YIELD, "API: Yield"},
{ ST_NOSV_API_WAITFOR, "API: Waitfor" }, {ST_NOSV_API_WAITFOR, "API: Waitfor"},
{ ST_NOSV_API_SCHEDPOINT, "API: Scheduling point" }, {ST_NOSV_API_SCHEDPOINT, "API: Scheduling point"},
{ ST_NOSV_ATTACH, "Thread: Attached" }, {ST_NOSV_ATTACH, "Thread: Attached"},
{ ST_NOSV_WORKER, "Thread: Worker" }, {ST_NOSV_WORKER, "Thread: Worker"},
{ ST_NOSV_DELEGATE, "Thread: Delegate" }, {ST_NOSV_DELEGATE, "Thread: Delegate"},
{ EV_NOSV_SCHED_SEND, "EV Scheduler: Send task" }, {EV_NOSV_SCHED_SEND, "EV Scheduler: Send task"},
{ EV_NOSV_SCHED_RECV, "EV Scheduler: Recv task" }, {EV_NOSV_SCHED_RECV, "EV Scheduler: Recv task"},
{ EV_NOSV_SCHED_SELF, "EV Scheduler: Self-assign task" }, {EV_NOSV_SCHED_SELF, "EV Scheduler: Self-assign task"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label tampi_mode_values[] = { struct pcf_value_label tampi_mode_values[] = {
{ ST_NULL, "NULL" }, {ST_NULL, "NULL"},
{ ST_TOO_MANY_TH, "TAMPI: Unknown, multiple threads running" }, {ST_TOO_MANY_TH, "TAMPI: Unknown, multiple threads running"},
{ ST_TAMPI_SEND, "TAMPI: Send" }, {ST_TAMPI_SEND, "TAMPI: Send"},
{ ST_TAMPI_RECV, "TAMPI: Recv" }, {ST_TAMPI_RECV, "TAMPI: Recv"},
{ ST_TAMPI_ISEND, "TAMPI: Isend" }, {ST_TAMPI_ISEND, "TAMPI: Isend"},
{ ST_TAMPI_IRECV, "TAMPI: Irecv" }, {ST_TAMPI_IRECV, "TAMPI: Irecv"},
{ ST_TAMPI_WAIT, "TAMPI: Wait" }, {ST_TAMPI_WAIT, "TAMPI: Wait"},
{ ST_TAMPI_WAITALL, "TAMPI: Waitall" }, {ST_TAMPI_WAITALL, "TAMPI: Waitall"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label openmp_mode_values[] = { struct pcf_value_label openmp_mode_values[] = {
{ ST_NULL, "NULL" }, {ST_NULL, "NULL"},
{ ST_TOO_MANY_TH, "OpenMP: Unknown, multiple threads running" }, {ST_TOO_MANY_TH, "OpenMP: Unknown, multiple threads running"},
{ ST_OPENMP_TASK, "OpenMP: Task" }, {ST_OPENMP_TASK, "OpenMP: Task"},
{ ST_OPENMP_PARALLEL, "OpenMP: Parallel" }, {ST_OPENMP_PARALLEL, "OpenMP: Parallel"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label nodes_mode_values[] = { struct pcf_value_label nodes_mode_values[] = {
{ ST_NULL, "NULL" }, {ST_NULL, "NULL"},
{ ST_TOO_MANY_TH, "NODES: Multiple threads running" }, {ST_TOO_MANY_TH, "NODES: Multiple threads running"},
{ ST_NODES_REGISTER, "Dependencies: Registering task accesses" }, {ST_NODES_REGISTER, "Dependencies: Registering task accesses"},
{ ST_NODES_UNREGISTER, "Dependencies: Unregistering task accesses" }, {ST_NODES_UNREGISTER, "Dependencies: Unregistering task accesses"},
{ ST_NODES_IF0_WAIT, "If0: Waiting for an If0 task" }, {ST_NODES_IF0_WAIT, "If0: Waiting for an If0 task"},
{ ST_NODES_IF0_INLINE, "If0: Executing an If0 task inline" }, {ST_NODES_IF0_INLINE, "If0: Executing an If0 task inline"},
{ ST_NODES_TASKWAIT, "Taskwait: Taskwait" }, {ST_NODES_TASKWAIT, "Taskwait: Taskwait"},
{ ST_NODES_CREATE, "Add Task: Creating a task" }, {ST_NODES_CREATE, "Add Task: Creating a task"},
{ ST_NODES_SUBMIT, "Add Task: Submitting a task" }, {ST_NODES_SUBMIT, "Add Task: Submitting a task"},
{ ST_NODES_SPAWN, "Spawn Function: Spawning a function" }, {ST_NODES_SPAWN, "Spawn Function: Spawning a function"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label kernel_cs_values[] = { struct pcf_value_label kernel_cs_values[] = {
{ ST_NULL, "NULL" }, {ST_NULL, "NULL"},
{ ST_TOO_MANY_TH, "Unknown: multiple threads running" }, {ST_TOO_MANY_TH, "Unknown: multiple threads running"},
{ ST_KERNEL_CSOUT, "Context switch: Out of the CPU" }, {ST_KERNEL_CSOUT, "Context switch: Out of the CPU"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label nanos6_ss_values[] = { struct pcf_value_label nanos6_ss_values[] = {
{ ST_NULL, "No subsystem" }, {ST_NULL, "No subsystem"},
{ ST_TOO_MANY_TH, "Unknown: multiple threads running" }, {ST_TOO_MANY_TH, "Unknown: multiple threads running"},
{ ST_NANOS6_TASK_BODY, "Task: Running body" }, {ST_NANOS6_TASK_BODY, "Task: Running body"},
{ ST_NANOS6_TASK_CREATING, "Task: Creating" }, {ST_NANOS6_TASK_CREATING, "Task: Creating"},
{ ST_NANOS6_TASK_SUBMIT, "Task: Submitting" }, {ST_NANOS6_TASK_SUBMIT, "Task: Submitting"},
{ ST_NANOS6_TASK_SPAWNING, "Task: Spawning function" }, {ST_NANOS6_TASK_SPAWNING, "Task: Spawning function"},
{ ST_NANOS6_TASK_FOR, "Task: Running task for" }, {ST_NANOS6_TASK_FOR, "Task: Running task for"},
{ ST_NANOS6_SCHED_SERVING, "Scheduler: Serving tasks" }, {ST_NANOS6_SCHED_SERVING, "Scheduler: Serving tasks"},
{ ST_NANOS6_SCHED_ADDING, "Scheduler: Adding ready tasks" }, {ST_NANOS6_SCHED_ADDING, "Scheduler: Adding ready tasks"},
{ ST_NANOS6_SCHED_PROCESSING, "Scheduler: Processing ready tasks" }, {ST_NANOS6_SCHED_PROCESSING, "Scheduler: Processing ready tasks"},
{ ST_NANOS6_DEP_REG, "Dependency: Registering" }, {ST_NANOS6_DEP_REG, "Dependency: Registering"},
{ ST_NANOS6_DEP_UNREG, "Dependency: Unregistering" }, {ST_NANOS6_DEP_UNREG, "Dependency: Unregistering"},
{ ST_NANOS6_BLK_TASKWAIT, "Blocking: Taskwait" }, {ST_NANOS6_BLK_TASKWAIT, "Blocking: Taskwait"},
{ ST_NANOS6_BLK_BLOCKING, "Blocking: Blocking current task" }, {ST_NANOS6_BLK_BLOCKING, "Blocking: Blocking current task"},
{ ST_NANOS6_BLK_UNBLOCKING, "Blocking: Unblocking remote task" }, {ST_NANOS6_BLK_UNBLOCKING, "Blocking: Unblocking remote task"},
{ ST_NANOS6_BLK_WAITFOR, "Blocking: Wait for deadline" }, {ST_NANOS6_BLK_WAITFOR, "Blocking: Wait for deadline"},
{ ST_NANOS6_HANDLING_TASK, "Worker: Handling task" }, {ST_NANOS6_HANDLING_TASK, "Worker: Handling task"},
{ ST_NANOS6_WORKER_LOOP, "Worker: Looking for work" }, {ST_NANOS6_WORKER_LOOP, "Worker: Looking for work"},
{ ST_NANOS6_SWITCH_TO, "Worker: Switching to another thread" }, {ST_NANOS6_SWITCH_TO, "Worker: Switching to another thread"},
{ ST_NANOS6_MIGRATE, "Worker: Migrating CPU" }, {ST_NANOS6_MIGRATE, "Worker: Migrating CPU"},
{ ST_NANOS6_SUSPEND, "Worker: Suspending thread" }, {ST_NANOS6_SUSPEND, "Worker: Suspending thread"},
{ ST_NANOS6_RESUME, "Worker: Resuming another thread" }, {ST_NANOS6_RESUME, "Worker: Resuming another thread"},
{ ST_NANOS6_ALLOCATING, "Memory: Allocating" }, {ST_NANOS6_ALLOCATING, "Memory: Allocating"},
{ ST_NANOS6_FREEING, "Memory: Freeing" }, {ST_NANOS6_FREEING, "Memory: Freeing"},
{ EV_NANOS6_SCHED_SEND, "EV Scheduler: Send task" }, {EV_NANOS6_SCHED_SEND, "EV Scheduler: Send task"},
{ EV_NANOS6_SCHED_RECV, "EV Scheduler: Recv task" }, {EV_NANOS6_SCHED_RECV, "EV Scheduler: Recv task"},
{ EV_NANOS6_SCHED_SELF, "EV Scheduler: Self-assign task" }, {EV_NANOS6_SCHED_SELF, "EV Scheduler: Self-assign task"},
{ EV_NANOS6_CPU_IDLE, "EV CPU: Becomes idle" }, {EV_NANOS6_CPU_IDLE, "EV CPU: Becomes idle"},
{ EV_NANOS6_CPU_ACTIVE, "EV CPU: Becomes active" }, {EV_NANOS6_CPU_ACTIVE, "EV CPU: Becomes active"},
{ EV_NANOS6_SIGNAL, "EV Worker: Wakening another thread" }, {EV_NANOS6_SIGNAL, "EV Worker: Wakening another thread"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label nanos6_thread_type[] = { struct pcf_value_label nanos6_thread_type[] = {
{ ST_NULL, "No type" }, {ST_NULL, "No type"},
{ ST_TOO_MANY_TH, "Unknown: multiple threads running" }, {ST_TOO_MANY_TH, "Unknown: multiple threads running"},
{ ST_NANOS6_TH_EXTERNAL, "External" }, {ST_NANOS6_TH_EXTERNAL, "External"},
{ ST_NANOS6_TH_WORKER, "Worker" }, {ST_NANOS6_TH_WORKER, "Worker"},
{ ST_NANOS6_TH_LEADER, "Leader" }, {ST_NANOS6_TH_LEADER, "Leader"},
{ ST_NANOS6_TH_MAIN, "Main" }, {ST_NANOS6_TH_MAIN, "Main"},
{ -1, NULL }, {-1, NULL},
}; };
struct pcf_value_label (*pcf_chan_value_labels[CHAN_MAX])[] = { struct pcf_value_label (*pcf_chan_value_labels[CHAN_MAX])[] = {
[CHAN_OVNI_PID] = &default_values, [CHAN_OVNI_PID] = &default_values,
[CHAN_OVNI_TID] = &default_values, [CHAN_OVNI_TID] = &default_values,
[CHAN_OVNI_NRTHREADS] = &default_values, [CHAN_OVNI_NRTHREADS] = &default_values,
[CHAN_OVNI_STATE] = &ovni_state_values, [CHAN_OVNI_STATE] = &ovni_state_values,
[CHAN_OVNI_APPID] = &default_values, [CHAN_OVNI_APPID] = &default_values,
[CHAN_OVNI_CPU] = &default_values, [CHAN_OVNI_CPU] = &default_values,
[CHAN_OVNI_FLUSH] = &ovni_flush_values, [CHAN_OVNI_FLUSH] = &ovni_flush_values,
[CHAN_NOSV_TASKID] = &default_values, [CHAN_NOSV_TASKID] = &default_values,
[CHAN_NOSV_TYPE] = &default_values, [CHAN_NOSV_TYPE] = &default_values,
[CHAN_NOSV_APPID] = &default_values, [CHAN_NOSV_APPID] = &default_values,
[CHAN_NOSV_SUBSYSTEM] = &nosv_ss_values, [CHAN_NOSV_SUBSYSTEM] = &nosv_ss_values,
[CHAN_NOSV_RANK] = &default_values, [CHAN_NOSV_RANK] = &default_values,
[CHAN_TAMPI_MODE] = &tampi_mode_values, [CHAN_TAMPI_MODE] = &tampi_mode_values,
[CHAN_OPENMP_MODE] = &openmp_mode_values, [CHAN_OPENMP_MODE] = &openmp_mode_values,
[CHAN_NODES_SUBSYSTEM] = &nodes_mode_values, [CHAN_NODES_SUBSYSTEM] = &nodes_mode_values,
[CHAN_NANOS6_TASKID] = &default_values, [CHAN_NANOS6_TASKID] = &default_values,
[CHAN_NANOS6_TYPE] = &default_values, [CHAN_NANOS6_TYPE] = &default_values,
[CHAN_NANOS6_SUBSYSTEM] = &nanos6_ss_values, [CHAN_NANOS6_SUBSYSTEM] = &nanos6_ss_values,
[CHAN_NANOS6_RANK] = &default_values, [CHAN_NANOS6_RANK] = &default_values,
[CHAN_NANOS6_THREAD] = &nanos6_thread_type, [CHAN_NANOS6_THREAD] = &nanos6_thread_type,
[CHAN_KERNEL_CS] = &kernel_cs_values, [CHAN_KERNEL_CS] = &kernel_cs_values,
}; };
/* ------------------ Type labels --------------------- */ /* ------------------ Type labels --------------------- */
char *pcf_chan_name[CHAN_MAX] = { char *pcf_chan_name[CHAN_MAX] = {
[CHAN_OVNI_PID] = "PID", [CHAN_OVNI_PID] = "PID",
[CHAN_OVNI_TID] = "TID", [CHAN_OVNI_TID] = "TID",
[CHAN_OVNI_NRTHREADS] = "Number of RUNNING threads", [CHAN_OVNI_NRTHREADS] = "Number of RUNNING threads",
[CHAN_OVNI_STATE] = "Execution state", [CHAN_OVNI_STATE] = "Execution state",
[CHAN_OVNI_APPID] = "AppID", [CHAN_OVNI_APPID] = "AppID",
[CHAN_OVNI_CPU] = "CPU affinity", [CHAN_OVNI_CPU] = "CPU affinity",
[CHAN_OVNI_FLUSH] = "Flushing state", [CHAN_OVNI_FLUSH] = "Flushing state",
[CHAN_NOSV_TASKID] = "nOS-V TaskID", [CHAN_NOSV_TASKID] = "nOS-V TaskID",
[CHAN_NOSV_TYPE] = "nOS-V task type", [CHAN_NOSV_TYPE] = "nOS-V task type",
[CHAN_NOSV_APPID] = "nOS-V task AppID", [CHAN_NOSV_APPID] = "nOS-V task AppID",
[CHAN_NOSV_SUBSYSTEM] = "nOS-V subsystem", [CHAN_NOSV_SUBSYSTEM] = "nOS-V subsystem",
[CHAN_NOSV_RANK] = "nOS-V task MPI rank", [CHAN_NOSV_RANK] = "nOS-V task MPI rank",
[CHAN_TAMPI_MODE] = "TAMPI mode", [CHAN_TAMPI_MODE] = "TAMPI mode",
[CHAN_OPENMP_MODE] = "OpenMP mode", [CHAN_OPENMP_MODE] = "OpenMP mode",
[CHAN_NODES_SUBSYSTEM] = "NODES subsystem", [CHAN_NODES_SUBSYSTEM] = "NODES subsystem",
[CHAN_NANOS6_TASKID] = "Nanos6 task ID", [CHAN_NANOS6_TASKID] = "Nanos6 task ID",
[CHAN_NANOS6_TYPE] = "Nanos6 task type", [CHAN_NANOS6_TYPE] = "Nanos6 task type",
[CHAN_NANOS6_SUBSYSTEM] = "Nanos6 subsystem", [CHAN_NANOS6_SUBSYSTEM] = "Nanos6 subsystem",
[CHAN_NANOS6_RANK] = "Nanos6 task MPI rank", [CHAN_NANOS6_RANK] = "Nanos6 task MPI rank",
[CHAN_NANOS6_THREAD] = "Nanos6 thread type", [CHAN_NANOS6_THREAD] = "Nanos6 thread type",
[CHAN_KERNEL_CS] = "Context switches", [CHAN_KERNEL_CS] = "Context switches",
}; };
enum pcf_suffix { NONE = 0, CUR_TH, RUN_TH, ACT_TH, SUFFIX_MAX }; enum pcf_suffix { NONE = 0,
CUR_TH,
RUN_TH,
ACT_TH,
SUFFIX_MAX };
char *pcf_suffix_name[SUFFIX_MAX] = { char *pcf_suffix_name[SUFFIX_MAX] = {
[NONE] = "", [NONE] = "",
@ -270,32 +273,32 @@ char *pcf_suffix_name[SUFFIX_MAX] = {
}; };
int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = { int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = {
/* Thread CPU */ /* Thread CPU */
[CHAN_OVNI_PID] = { CUR_TH, CUR_TH }, [CHAN_OVNI_PID] = {CUR_TH, CUR_TH},
[CHAN_OVNI_TID] = { CUR_TH, CUR_TH }, [CHAN_OVNI_TID] = {CUR_TH, CUR_TH},
[CHAN_OVNI_NRTHREADS] = { NONE, NONE }, [CHAN_OVNI_NRTHREADS] = {NONE, NONE},
[CHAN_OVNI_STATE] = { CUR_TH, NONE }, [CHAN_OVNI_STATE] = {CUR_TH, NONE},
[CHAN_OVNI_APPID] = { NONE, RUN_TH }, [CHAN_OVNI_APPID] = {NONE, RUN_TH},
[CHAN_OVNI_CPU] = { CUR_TH, NONE }, [CHAN_OVNI_CPU] = {CUR_TH, NONE},
[CHAN_OVNI_FLUSH] = { CUR_TH, RUN_TH }, [CHAN_OVNI_FLUSH] = {CUR_TH, RUN_TH},
[CHAN_NOSV_TASKID] = { RUN_TH, RUN_TH }, [CHAN_NOSV_TASKID] = {RUN_TH, RUN_TH},
[CHAN_NOSV_TYPE] = { RUN_TH, RUN_TH }, [CHAN_NOSV_TYPE] = {RUN_TH, RUN_TH},
[CHAN_NOSV_APPID] = { RUN_TH, RUN_TH }, [CHAN_NOSV_APPID] = {RUN_TH, RUN_TH},
[CHAN_NOSV_SUBSYSTEM] = { ACT_TH, RUN_TH }, [CHAN_NOSV_SUBSYSTEM] = {ACT_TH, RUN_TH},
[CHAN_NOSV_RANK] = { RUN_TH, RUN_TH }, [CHAN_NOSV_RANK] = {RUN_TH, RUN_TH},
[CHAN_TAMPI_MODE] = { RUN_TH, RUN_TH }, [CHAN_TAMPI_MODE] = {RUN_TH, RUN_TH},
[CHAN_OPENMP_MODE] = { RUN_TH, RUN_TH }, [CHAN_OPENMP_MODE] = {RUN_TH, RUN_TH},
[CHAN_NODES_SUBSYSTEM] = { RUN_TH, RUN_TH }, [CHAN_NODES_SUBSYSTEM] = {RUN_TH, RUN_TH},
[CHAN_NANOS6_TASKID] = { RUN_TH, RUN_TH }, [CHAN_NANOS6_TASKID] = {RUN_TH, RUN_TH},
[CHAN_NANOS6_TYPE] = { RUN_TH, RUN_TH }, [CHAN_NANOS6_TYPE] = {RUN_TH, RUN_TH},
[CHAN_NANOS6_SUBSYSTEM] = { ACT_TH, RUN_TH }, [CHAN_NANOS6_SUBSYSTEM] = {ACT_TH, RUN_TH},
[CHAN_NANOS6_RANK] = { RUN_TH, RUN_TH }, [CHAN_NANOS6_RANK] = {RUN_TH, RUN_TH},
[CHAN_NANOS6_THREAD] = { ACT_TH, NONE }, [CHAN_NANOS6_THREAD] = {ACT_TH, NONE},
[CHAN_KERNEL_CS] = { RUN_TH, ACT_TH }, [CHAN_KERNEL_CS] = {RUN_TH, ACT_TH},
}; };
/* ----------------------------------------------- */ /* ----------------------------------------------- */
@ -303,9 +306,9 @@ int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = {
static void static void
decompose_rgb(uint32_t col, uint8_t *r, uint8_t *g, uint8_t *b) decompose_rgb(uint32_t col, uint8_t *r, uint8_t *g, uint8_t *b)
{ {
*r = (col>>16) & 0xff; *r = (col >> 16) & 0xff;
*g = (col>>8) & 0xff; *g = (col >> 8) & 0xff;
*b = (col>>0) & 0xff; *b = (col >> 0) & 0xff;
} }
static void static void
@ -323,8 +326,7 @@ write_colors(FILE *f, const uint32_t *palette, int n)
fprintf(f, "\n\n"); fprintf(f, "\n\n");
fprintf(f, "STATES_COLOR\n"); fprintf(f, "STATES_COLOR\n");
for(i=0; i<n; i++) for (i = 0; i < n; i++) {
{
decompose_rgb(palette[i], &r, &g, &b); decompose_rgb(palette[i], &r, &g, &b);
fprintf(f, "%-3d {%3d, %3d, %3d}\n", i, r, g, b); fprintf(f, "%-3d {%3d, %3d, %3d}\n", i, r, g, b);
} }
@ -338,7 +340,7 @@ write_type(FILE *f, struct pcf_type *type)
fprintf(f, "0 %-10d %s\n", type->id, type->label); fprintf(f, "0 %-10d %s\n", type->id, type->label);
fprintf(f, "VALUES\n"); fprintf(f, "VALUES\n");
for(struct pcf_value *v = type->values; v != NULL; v = v->hh.next) for (struct pcf_value *v = type->values; v != NULL; v = v->hh.next)
fprintf(f, "%-4d %s\n", v->value, v->label); fprintf(f, "%-4d %s\n", v->value, v->label);
} }
@ -347,19 +349,19 @@ write_types(struct pcf_file *pcf)
{ {
struct pcf_type *t; struct pcf_type *t;
for(t = pcf->types; t != NULL; t = t->hh.next) for (t = pcf->types; t != NULL; t = t->hh.next)
write_type(pcf->f, t); write_type(pcf->f, t);
} }
static void static void
create_values(struct pcf_type *t, enum chan c) create_values(struct pcf_type *t, enum chan c)
{ {
struct pcf_value_label (*q)[] = pcf_chan_value_labels[c]; struct pcf_value_label(*q)[] = pcf_chan_value_labels[c];
if(q == NULL) if (q == NULL)
return; return;
for(struct pcf_value_label *p = *q; p->label != NULL; p++) for (struct pcf_value_label *p = *q; p->label != NULL; p++)
pcf_add_value(t, p->value, p->label); pcf_add_value(t, p->value, p->label);
} }
@ -370,7 +372,7 @@ create_type(struct pcf_file *pcf, enum chan c)
enum chan_type ct = pcf->chantype; enum chan_type ct = pcf->chantype;
int prv_type = chan_to_prvtype[c]; int prv_type = chan_to_prvtype[c];
if(prv_type == -1) if (prv_type == -1)
return; return;
/* Compute the label by joining the two parts */ /* Compute the label by joining the two parts */
@ -379,9 +381,9 @@ create_type(struct pcf_file *pcf, enum chan c)
char *suffix = pcf_suffix_name[isuffix]; char *suffix = pcf_suffix_name[isuffix];
int ret = snprintf(label, MAX_PCF_LABEL, "%s %s", int ret = snprintf(label, MAX_PCF_LABEL, "%s %s",
prefix, suffix); prefix, suffix);
if(ret >= MAX_PCF_LABEL) if (ret >= MAX_PCF_LABEL)
die("computed type label too long\n"); die("computed type label too long\n");
struct pcf_type *t = pcf_add_type(pcf, prv_type, label); struct pcf_type *t = pcf_add_type(pcf, prv_type, label);
@ -398,14 +400,13 @@ pcf_open(struct pcf_file *pcf, char *path, int chantype)
pcf->f = fopen(path, "w"); pcf->f = fopen(path, "w");
pcf->chantype = chantype; pcf->chantype = chantype;
if(pcf->f == NULL) if (pcf->f == NULL) {
{
die("cannot open PCF file '%s': %s\n", die("cannot open PCF file '%s': %s\n",
path, strerror(errno)); path, strerror(errno));
} }
/* Create default types and values */ /* Create default types and values */
for(enum chan c = 0; c < CHAN_MAX; c++) for (enum chan c = 0; c < CHAN_MAX; c++)
create_type(pcf, c); create_type(pcf, c);
} }
@ -431,11 +432,11 @@ pcf_add_type(struct pcf_file *pcf, int type_id, const char *label)
pcftype = pcf_find_type(pcf, type_id); pcftype = pcf_find_type(pcf, type_id);
if(pcftype != NULL) if (pcftype != NULL)
die("PCF type %d already defined\n", type_id); die("PCF type %d already defined\n", type_id);
pcftype = calloc(1, sizeof(struct pcf_type)); pcftype = calloc(1, sizeof(struct pcf_type));
if(pcftype == NULL) if (pcftype == NULL)
die("calloc failed: %s\n", strerror(errno)); die("calloc failed: %s\n", strerror(errno));
pcftype->id = type_id; pcftype->id = type_id;
@ -443,7 +444,7 @@ pcf_add_type(struct pcf_file *pcf, int type_id, const char *label)
pcftype->nvalues = 0; pcftype->nvalues = 0;
int len = snprintf(pcftype->label, MAX_PCF_LABEL, "%s", label); int len = snprintf(pcftype->label, MAX_PCF_LABEL, "%s", label);
if(len >= MAX_PCF_LABEL) if (len >= MAX_PCF_LABEL)
die("PCF type label too long\n"); die("PCF type label too long\n");
HASH_ADD_INT(pcf->types, id, pcftype); HASH_ADD_INT(pcf->types, id, pcftype);
@ -471,17 +472,17 @@ pcf_add_value(struct pcf_type *type, int value, const char *label)
{ {
struct pcf_value *pcfvalue = pcf_find_value(type, value); struct pcf_value *pcfvalue = pcf_find_value(type, value);
if(pcfvalue != NULL) if (pcfvalue != NULL)
die("PCF value %d already in type %d\n", value, type->id); die("PCF value %d already in type %d\n", value, type->id);
pcfvalue = calloc(1, sizeof(struct pcf_value)); pcfvalue = calloc(1, sizeof(struct pcf_value));
if(pcfvalue == NULL) if (pcfvalue == NULL)
die("calloc failed: %s\n", strerror(errno)); die("calloc failed: %s\n", strerror(errno));
pcfvalue->value = value; pcfvalue->value = value;
int len = snprintf(pcfvalue->label, MAX_PCF_LABEL, "%s", label); int len = snprintf(pcfvalue->label, MAX_PCF_LABEL, "%s", label);
if(len >= MAX_PCF_LABEL) if (len >= MAX_PCF_LABEL)
die("PCF value label too long\n"); die("PCF value label too long\n");
HASH_ADD_INT(type->values, value, pcfvalue); HASH_ADD_INT(type->values, value, pcfvalue);

6
pcf.h
View File

@ -4,8 +4,8 @@
#ifndef OVNI_PCF_H #ifndef OVNI_PCF_H
#define OVNI_PCF_H #define OVNI_PCF_H
#include <stdio.h>
#include "uthash.h" #include "uthash.h"
#include <stdio.h>
#define MAX_PCF_LABEL 512 #define MAX_PCF_LABEL 512
@ -53,10 +53,10 @@ void pcf_close(struct pcf_file *pcf);
struct pcf_type *pcf_find_type(struct pcf_file *pcf, int type_id); struct pcf_type *pcf_find_type(struct pcf_file *pcf, int type_id);
struct pcf_type *pcf_add_type(struct pcf_file *pcf, int type_id, struct pcf_type *pcf_add_type(struct pcf_file *pcf, int type_id,
const char *label); const char *label);
struct pcf_value *pcf_add_value(struct pcf_type *type, int value, struct pcf_value *pcf_add_value(struct pcf_type *type, int value,
const char *label); const char *label);
struct pcf_value *pcf_find_value(struct pcf_type *type, int value); struct pcf_value *pcf_find_value(struct pcf_type *type, int value);

8
prv.c
View File

@ -3,8 +3,8 @@
#include <stdio.h> #include <stdio.h>
#include "ovni.h"
#include "emu.h" #include "emu.h"
#include "ovni.h"
#include "prv.h" #include "prv.h"
void void
@ -41,16 +41,16 @@ prv_ev_cpu(struct ovni_emu *emu, int row, int type, int val)
void void
prv_ev_autocpu_raw(struct ovni_emu *emu, int64_t time, int type, int val) prv_ev_autocpu_raw(struct ovni_emu *emu, int64_t time, int type, int val)
{ {
if(emu->cur_thread == NULL) if (emu->cur_thread == NULL)
die("prv_ev_autocpu_raw: current thread is NULL\n"); die("prv_ev_autocpu_raw: current thread is NULL\n");
struct ovni_cpu *cpu = emu->cur_thread->cpu; struct ovni_cpu *cpu = emu->cur_thread->cpu;
if(cpu == NULL) if (cpu == NULL)
die("prv_ev_autocpu_raw: current thread CPU is NULL\n"); die("prv_ev_autocpu_raw: current thread CPU is NULL\n");
/* FIXME: Use the global index of the CPUs */ /* FIXME: Use the global index of the CPUs */
if(cpu->i < 0) if (cpu->i < 0)
die("prv_ev_autocpu_raw: CPU index is negative\n"); die("prv_ev_autocpu_raw: CPU index is negative\n");
/* Begin at 1 */ /* Begin at 1 */

4
prv.h
View File

@ -4,9 +4,9 @@
#ifndef OVNI_PRV_H #ifndef OVNI_PRV_H
#define OVNI_PRV_H #define OVNI_PRV_H
#include <stdint.h>
#include "ovni.h"
#include "emu.h" #include "emu.h"
#include "ovni.h"
#include <stdint.h>
void void
prv_ev(FILE *f, int row, int64_t time, int type, int val); prv_ev(FILE *f, int row, int64_t time, int type, int val);

160
sort.c
View File

@ -27,9 +27,9 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "emu.h"
#include "ovni.h" #include "ovni.h"
#include "trace.h" #include "trace.h"
#include "emu.h"
struct ring { struct ring {
ssize_t head; ssize_t head;
@ -54,7 +54,8 @@ struct sortplan {
int fd; int fd;
}; };
enum operation_mode { SORT, CHECK }; enum operation_mode { SORT,
CHECK };
static char *tracedir = NULL; static char *tracedir = NULL;
static enum operation_mode operation_mode = SORT; static enum operation_mode operation_mode = SORT;
@ -72,13 +73,13 @@ ring_add(struct ring *r, struct ovni_ev *ev)
r->ev[r->tail] = ev; r->ev[r->tail] = ev;
r->tail++; r->tail++;
if(r->tail >= r->size) if (r->tail >= r->size)
r->tail = 0; r->tail = 0;
if(r->head == r->tail) if (r->head == r->tail)
r->head = r->tail + 1; r->head = r->tail + 1;
if(r->head >= r->size) if (r->head >= r->size)
r->head = 0; r->head = 0;
} }
@ -92,12 +93,10 @@ find_destination(struct ring *r, uint64_t clock)
start = r->tail - 1 >= 0 ? r->tail - 1 : r->size - 1; start = r->tail - 1 >= 0 ? r->tail - 1 : r->size - 1;
end = r->head - 1 >= 0 ? r->head - 1 : r->size - 1; end = r->head - 1 >= 0 ? r->head - 1 : r->size - 1;
for(i=start; i != end; i = i-1 < 0 ? r->size - 1: i-1) for (i = start; i != end; i = i - 1 < 0 ? r->size - 1 : i - 1) {
{ if (r->ev[i]->header.clock < clock) {
if(r->ev[i]->header.clock < clock)
{
dbg("found suitable position %ld events backwards\n", dbg("found suitable position %ld events backwards\n",
nback); nback);
return i; return i;
} }
nback++; nback++;
@ -111,17 +110,13 @@ find_destination(struct ring *r, uint64_t clock)
static int static int
starts_unsorted_region(struct ovni_ev *ev) starts_unsorted_region(struct ovni_ev *ev)
{ {
return ev->header.model == 'O' && return ev->header.model == 'O' && ev->header.category == 'U' && ev->header.value == '[';
ev->header.category == 'U' &&
ev->header.value == '[';
} }
static int static int
ends_unsorted_region(struct ovni_ev *ev) ends_unsorted_region(struct ovni_ev *ev)
{ {
return ev->header.model == 'O' && return ev->header.model == 'O' && ev->header.category == 'U' && ev->header.value == ']';
ev->header.category == 'U' &&
ev->header.value == ']';
} }
#if 0 #if 0
@ -168,7 +163,7 @@ hexdump(uint8_t *buf, size_t size)
static void static void
sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize, sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize,
uint8_t *srcbad, uint8_t *srcnext) uint8_t *srcbad, uint8_t *srcnext)
{ {
uint8_t *p, *q; uint8_t *p, *q;
int64_t evsize, injected = 0; int64_t evsize, injected = 0;
@ -179,31 +174,27 @@ sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize,
p = src; p = src;
q = srcbad; q = srcbad;
while(1) while (1) {
{
ep = (struct ovni_ev *) p; ep = (struct ovni_ev *) p;
eq = (struct ovni_ev *) q; eq = (struct ovni_ev *) q;
if(p < srcbad && ep->header.clock < eq->header.clock) if (p < srcbad && ep->header.clock < eq->header.clock) {
{
ev = ep; ev = ep;
evsize = ovni_ev_size(ev); evsize = ovni_ev_size(ev);
p += evsize; p += evsize;
} } else {
else
{
ev = eq; ev = eq;
evsize = ovni_ev_size(ev); evsize = ovni_ev_size(ev);
q += evsize; q += evsize;
} }
if((uint8_t *) ev == srcnext) if ((uint8_t *) ev == srcnext)
break; break;
if((uint8_t *) ev > srcnext) if ((uint8_t *) ev > srcnext)
die("exceeded srcnext while sorting\n"); die("exceeded srcnext while sorting\n");
if(bufsize < evsize) if (bufsize < evsize)
die("no space left in the sort buffer\n"); die("no space left in the sort buffer\n");
memcpy(buf, ev, evsize); memcpy(buf, ev, evsize);
@ -218,11 +209,11 @@ sort_buf(uint8_t *src, uint8_t *buf, int64_t bufsize,
static void static void
write_stream(int fd, void *base, void *dst, const void *src, size_t size) write_stream(int fd, void *base, void *dst, const void *src, size_t size)
{ {
while(size > 0) { while (size > 0) {
off_t offset = (off_t) ((int64_t) dst - (int64_t) base); off_t offset = (off_t) ((int64_t) dst - (int64_t) base);
ssize_t written = pwrite(fd, src, size, offset); ssize_t written = pwrite(fd, src, size, offset);
if(written < 0) if (written < 0)
die("pwrite failed: %s\n", strerror(errno)); die("pwrite failed: %s\n", strerror(errno));
size -= written; size -= written;
@ -243,10 +234,9 @@ execute_sort_plan(struct sortplan *sp)
dbg("attempt to sort: start clock %ld\n", sp->bad0->header.clock); dbg("attempt to sort: start clock %ld\n", sp->bad0->header.clock);
/* Cannot sort in one pass; just fail for now */ /* Cannot sort in one pass; just fail for now */
if((i0 = find_destination(sp->r, sp->bad0->header.clock)) < 0) if ((i0 = find_destination(sp->r, sp->bad0->header.clock)) < 0) {
{
err("cannot find destination for region starting at clock %ld\n", err("cannot find destination for region starting at clock %ld\n",
sp->bad0->header.clock); sp->bad0->header.clock);
return -1; return -1;
} }
@ -257,15 +247,15 @@ execute_sort_plan(struct sortplan *sp)
/* Allocate a working buffer */ /* Allocate a working buffer */
bufsize = ((int64_t) sp->next) - ((int64_t) first); bufsize = ((int64_t) sp->next) - ((int64_t) first);
if(bufsize <= 0) if (bufsize <= 0)
die("bufsize is non-positive\n"); die("bufsize is non-positive\n");
buf = malloc(bufsize); buf = malloc(bufsize);
if(!buf) if (!buf)
die("malloc failed: %s\n", strerror(errno)); die("malloc failed: %s\n", strerror(errno));
sort_buf((uint8_t *) first, buf, bufsize, sort_buf((uint8_t *) first, buf, bufsize,
(uint8_t *) sp->bad0, (uint8_t *) sp->next); (uint8_t *) sp->bad0, (uint8_t *) sp->next);
/* Copy the sorted events back into the stream buffer */ /* Copy the sorted events back into the stream buffer */
memcpy(first, buf, bufsize); memcpy(first, buf, bufsize);
@ -282,13 +272,13 @@ stream_winsort(struct ovni_stream *stream, struct ring *r)
{ {
struct ovni_ev *ev; struct ovni_ev *ev;
struct sortplan sp = {0}; struct sortplan sp = {0};
//uint64_t lastclock = 0; // uint64_t lastclock = 0;
char st = 'S'; char st = 'S';
char *fn = stream->thread->tracefile; char *fn = stream->thread->tracefile;
int fd = open(fn, O_WRONLY); int fd = open(fn, O_WRONLY);
if(fd < 0) if (fd < 0)
die("open %s failed: %s\n", fn, strerror(errno)); die("open %s failed: %s\n", fn, strerror(errno));
ring_reset(r); ring_reset(r);
@ -299,41 +289,30 @@ stream_winsort(struct ovni_stream *stream, struct ring *r)
size_t empty_regions = 0; size_t empty_regions = 0;
size_t updated = 0; size_t updated = 0;
while(stream->active) while (stream->active) {
{
ovni_load_next_event(stream); ovni_load_next_event(stream);
ev = stream->cur_ev; ev = stream->cur_ev;
if(st == 'S' && starts_unsorted_region(ev)) if (st == 'S' && starts_unsorted_region(ev)) {
{
st = 'U'; st = 'U';
} } else if (st == 'U') {
else if(st == 'U')
{
/* Ensure that we have at least one unsorted /* Ensure that we have at least one unsorted
* event inside the section */ * event inside the section */
if(ends_unsorted_region(ev)) if (ends_unsorted_region(ev)) {
{
empty_regions++; empty_regions++;
st = 'S'; st = 'S';
} } else {
else
{
st = 'X'; st = 'X';
sp.bad0 = ev; sp.bad0 = ev;
} }
} } else if (st == 'X') {
else if(st == 'X') if (ends_unsorted_region(ev)) {
{
if(ends_unsorted_region(ev))
{
updated = 1; updated = 1;
sp.next = ev; sp.next = ev;
dbg("executing sort plan for stream tid=%d\n", stream->tid); dbg("executing sort plan for stream tid=%d\n", stream->tid);
if(execute_sort_plan(&sp) < 0) if (execute_sort_plan(&sp) < 0) {
{
err("sort failed for stream tid=%d\n", err("sort failed for stream tid=%d\n",
stream->tid); stream->tid);
return -1; return -1;
} }
@ -348,14 +327,14 @@ stream_winsort(struct ovni_stream *stream, struct ring *r)
ring_add(r, ev); ring_add(r, ev);
} }
if(empty_regions > 0) if (empty_regions > 0)
err("warning: stream %d contains %ld empty sort regions\n", err("warning: stream %d contains %ld empty sort regions\n",
stream->tid, empty_regions); stream->tid, empty_regions);
if(updated && fdatasync(fd) < 0) if (updated && fdatasync(fd) < 0)
die("fdatasync %s failed: %s\n", fn, strerror(errno)); die("fdatasync %s failed: %s\n", fn, strerror(errno));
if(close(fd) < 0) if (close(fd) < 0)
die("close %s failed: %s\n", fn, strerror(errno)); die("close %s failed: %s\n", fn, strerror(errno));
return 0; return 0;
@ -370,16 +349,14 @@ stream_check(struct ovni_stream *stream)
uint64_t last_clock = ev->header.clock; uint64_t last_clock = ev->header.clock;
int ret = 0; int ret = 0;
while(stream->active) while (stream->active) {
{
ovni_load_next_event(stream); ovni_load_next_event(stream);
ev = stream->cur_ev; ev = stream->cur_ev;
uint64_t cur_clock = ovni_ev_get_clock(ev); uint64_t cur_clock = ovni_ev_get_clock(ev);
if(cur_clock < last_clock) if (cur_clock < last_clock) {
{
err("backwards jump in time %ld -> %ld for stream tid=%d\n", err("backwards jump in time %ld -> %ld for stream tid=%d\n",
last_clock, cur_clock, stream->tid); last_clock, cur_clock, stream->tid);
ret = -1; ret = -1;
} }
@ -400,27 +377,21 @@ process_trace(struct ovni_trace *trace)
ring.size = max_look_back; ring.size = max_look_back;
ring.ev = malloc(ring.size * sizeof(struct ovni_ev *)); ring.ev = malloc(ring.size * sizeof(struct ovni_ev *));
if(ring.ev == NULL) if (ring.ev == NULL)
die("malloc failed: %s\n", strerror(errno)); die("malloc failed: %s\n", strerror(errno));
for(i=0; i<trace->nstreams; i++) for (i = 0; i < trace->nstreams; i++) {
{
stream = &trace->stream[i]; stream = &trace->stream[i];
if(operation_mode == SORT) if (operation_mode == SORT) {
{
dbg("sorting stream tid=%d\n", stream->tid); dbg("sorting stream tid=%d\n", stream->tid);
if(stream_winsort(stream, &ring) != 0) if (stream_winsort(stream, &ring) != 0) {
{
err("sort stream tid=%d failed\n", stream->tid); err("sort stream tid=%d failed\n", stream->tid);
/* When sorting, return at the first /* When sorting, return at the first
* attempt */ * attempt */
return -1; return -1;
} }
} } else {
else if (stream_check(stream) != 0) {
{
if(stream_check(stream) != 0)
{
err("stream tid=%d is not sorted\n", stream->tid); err("stream tid=%d is not sorted\n", stream->tid);
/* When checking, report all errors and /* When checking, report all errors and
* then fail */ * then fail */
@ -431,14 +402,10 @@ process_trace(struct ovni_trace *trace)
free(ring.ev); free(ring.ev);
if(operation_mode == CHECK) if (operation_mode == CHECK) {
{ if (ret == 0) {
if(ret == 0)
{
err("all streams sorted\n"); err("all streams sorted\n");
} } else {
else
{
err("streams NOT sorted\n"); err("streams NOT sorted\n");
} }
} }
@ -458,7 +425,7 @@ usage(int argc, char *argv[])
err("tracedir, so they are suitable for the emulator ovniemu.\n"); err("tracedir, so they are suitable for the emulator ovniemu.\n");
err("Only the events enclosed by OU[ OU] are sorted. At most a\n"); err("Only the events enclosed by OU[ OU] are sorted. At most a\n");
err("total of %ld events are looked back to insert the unsorted\n", err("total of %ld events are looked back to insert the unsorted\n",
max_look_back); max_look_back);
err("events, so the sort procedure can fail with an error.\n"); err("events, so the sort procedure can fail with an error.\n");
err("\n"); err("\n");
err("Options:\n"); err("Options:\n");
@ -476,10 +443,8 @@ parse_args(int argc, char *argv[])
{ {
int opt; int opt;
while((opt = getopt(argc, argv, "c")) != -1) while ((opt = getopt(argc, argv, "c")) != -1) {
{ switch (opt) {
switch(opt)
{
case 'c': case 'c':
operation_mode = CHECK; operation_mode = CHECK;
break; break;
@ -488,8 +453,7 @@ parse_args(int argc, char *argv[])
} }
} }
if(optind >= argc) if (optind >= argc) {
{
err("missing tracedir\n"); err("missing tracedir\n");
usage(argc, argv); usage(argc, argv);
} }
@ -497,7 +461,8 @@ parse_args(int argc, char *argv[])
tracedir = argv[optind]; tracedir = argv[optind];
} }
int main(int argc, char *argv[]) int
main(int argc, char *argv[])
{ {
int ret = 0; int ret = 0;
struct ovni_trace *trace; struct ovni_trace *trace;
@ -506,19 +471,18 @@ int main(int argc, char *argv[])
trace = calloc(1, sizeof(struct ovni_trace)); trace = calloc(1, sizeof(struct ovni_trace));
if(trace == NULL) if (trace == NULL) {
{
perror("calloc"); perror("calloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if(ovni_load_trace(trace, tracedir)) if (ovni_load_trace(trace, tracedir))
return 1; return 1;
if(ovni_load_streams(trace)) if (ovni_load_streams(trace))
return 1; return 1;
if(process_trace(trace)) if (process_trace(trace))
ret = 1; ret = 1;
ovni_free_streams(trace); ovni_free_streams(trace);

View File

@ -18,46 +18,46 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#define INSTR_0ARG(name, mcv) \ #define INSTR_0ARG(name, mcv) \
static inline void name(void) \ static inline void name(void) \
{ \ { \
struct ovni_ev ev = {0}; \ struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \ ovni_ev_set_mcv(&ev, mcv); \
ovni_ev_emit(&ev); \ ovni_ev_emit(&ev); \
} }
#define INSTR_1ARG(name, mcv, ta, a) \ #define INSTR_1ARG(name, mcv, ta, a) \
static inline void name(ta a) \ static inline void name(ta a) \
{ \ { \
struct ovni_ev ev = {0}; \ struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \ ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_ev_emit(&ev); \ ovni_ev_emit(&ev); \
} }
#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) \ static inline void name(ta a, tb b) \
{ \ { \
struct ovni_ev ev = {0}; \ struct ovni_ev ev = {0}; \
ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_ev_set_mcv(&ev, mcv); \ ovni_ev_set_mcv(&ev, mcv); \
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \ ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
ovni_ev_emit(&ev); \ ovni_ev_emit(&ev); \
} }
#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) \ static inline void name(ta a, tb b, tc c) \
{ \ { \
struct ovni_ev ev = {0}; \ struct ovni_ev ev = {0}; \
ovni_ev_set_mcv(&ev, mcv); \ ovni_ev_set_mcv(&ev, mcv); \
ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \ ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \ ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \
ovni_ev_emit(&ev); \ ovni_ev_emit(&ev); \
} }
INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag) INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag)
@ -81,7 +81,7 @@ instr_start(int rank, int nranks)
char hostname[OVNI_MAX_HOSTNAME]; char hostname[OVNI_MAX_HOSTNAME];
char rankname[OVNI_MAX_HOSTNAME + 64]; char rankname[OVNI_MAX_HOSTNAME + 64];
if(gethostname(hostname, HOST_NAME_MAX) != 0) if (gethostname(hostname, HOST_NAME_MAX) != 0)
die("gethostname failed"); die("gethostname failed");
sprintf(rankname, "%s.%d", hostname, rank); sprintf(rankname, "%s.%d", hostname, rank);
@ -91,13 +91,13 @@ instr_start(int rank, int nranks)
ovni_thread_init(gettid()); ovni_thread_init(gettid());
/* All ranks inform CPUs */ /* All ranks inform CPUs */
for(int i=0; i < nranks; i++) for (int i = 0; i < nranks; i++)
ovni_add_cpu(i, i); ovni_add_cpu(i, i);
int curcpu = rank; int curcpu = rank;
dbg("thread %d has cpu %d (ncpus=%d)\n", dbg("thread %d has cpu %d (ncpus=%d)\n",
gettid(), curcpu, nranks); gettid(), curcpu, nranks);
instr_thread_execute(curcpu, -1, 0); instr_thread_execute(curcpu, -1, 0);
} }

View File

@ -34,72 +34,72 @@ INSTR_1ARG(instr_nanos6_task_pause, "6Tp", int32_t, id)
INSTR_1ARG(instr_nanos6_task_resume, "6Tr", int32_t, id) INSTR_1ARG(instr_nanos6_task_resume, "6Tr", int32_t, id)
INSTR_1ARG(instr_nanos6_task_end, "6Te", int32_t, id) INSTR_1ARG(instr_nanos6_task_end, "6Te", int32_t, id)
INSTR_0ARG(instr_nanos6_task_create_begin, "6C[") INSTR_0ARG(instr_nanos6_task_create_begin, "6C[")
INSTR_0ARG(instr_nanos6_task_create_end, "6C]") INSTR_0ARG(instr_nanos6_task_create_end, "6C]")
INSTR_0ARG(instr_nanos6_sched_server_enter, "6S[") INSTR_0ARG(instr_nanos6_sched_server_enter, "6S[")
INSTR_0ARG(instr_nanos6_sched_server_exit, "6S]") INSTR_0ARG(instr_nanos6_sched_server_exit, "6S]")
INSTR_0ARG(instr_nanos6_add_ready_enter, "6Sa") INSTR_0ARG(instr_nanos6_add_ready_enter, "6Sa")
INSTR_0ARG(instr_nanos6_add_ready_exit, "6SA") INSTR_0ARG(instr_nanos6_add_ready_exit, "6SA")
INSTR_0ARG(instr_nanos6_process_ready_enter, "6Sp") INSTR_0ARG(instr_nanos6_process_ready_enter, "6Sp")
INSTR_0ARG(instr_nanos6_process_ready_exit, "6SP") INSTR_0ARG(instr_nanos6_process_ready_exit, "6SP")
INSTR_0ARG(instr_nanos6_sched_receive, "6Sr") INSTR_0ARG(instr_nanos6_sched_receive, "6Sr")
INSTR_0ARG(instr_nanos6_sched_assign, "6Ss") INSTR_0ARG(instr_nanos6_sched_assign, "6Ss")
INSTR_0ARG(instr_nanos6_sched_self_assign, "6S@") INSTR_0ARG(instr_nanos6_sched_self_assign, "6S@")
INSTR_0ARG(instr_nanos6_worker_loop_enter, "6W[") INSTR_0ARG(instr_nanos6_worker_loop_enter, "6W[")
INSTR_0ARG(instr_nanos6_worker_loop_exit, "6W]") INSTR_0ARG(instr_nanos6_worker_loop_exit, "6W]")
INSTR_0ARG(instr_nanos6_handle_task_enter, "6Wt") INSTR_0ARG(instr_nanos6_handle_task_enter, "6Wt")
INSTR_0ARG(instr_nanos6_handle_task_exit, "6WT") INSTR_0ARG(instr_nanos6_handle_task_exit, "6WT")
INSTR_0ARG(instr_nanos6_switch_to_enter, "6Ww") INSTR_0ARG(instr_nanos6_switch_to_enter, "6Ww")
INSTR_0ARG(instr_nanos6_switch_to_exit, "6WW") INSTR_0ARG(instr_nanos6_switch_to_exit, "6WW")
INSTR_0ARG(instr_nanos6_migrate_enter, "6Wm") INSTR_0ARG(instr_nanos6_migrate_enter, "6Wm")
INSTR_0ARG(instr_nanos6_migrate_exit, "6WM") INSTR_0ARG(instr_nanos6_migrate_exit, "6WM")
INSTR_0ARG(instr_nanos6_suspend_enter, "6Ws") INSTR_0ARG(instr_nanos6_suspend_enter, "6Ws")
INSTR_0ARG(instr_nanos6_suspend_exit, "6WS") INSTR_0ARG(instr_nanos6_suspend_exit, "6WS")
INSTR_0ARG(instr_nanos6_resume_enter, "6Wr") INSTR_0ARG(instr_nanos6_resume_enter, "6Wr")
INSTR_0ARG(instr_nanos6_resume_exit, "6WR") INSTR_0ARG(instr_nanos6_resume_exit, "6WR")
INSTR_0ARG(instr_nanos6_signal, "6W*") INSTR_0ARG(instr_nanos6_signal, "6W*")
INSTR_0ARG(instr_nanos6_submit_task_enter, "6U[") INSTR_0ARG(instr_nanos6_submit_task_enter, "6U[")
INSTR_0ARG(instr_nanos6_submit_task_exit, "6U]") INSTR_0ARG(instr_nanos6_submit_task_exit, "6U]")
INSTR_0ARG(instr_nanos6_spawn_function_enter, "6F[") INSTR_0ARG(instr_nanos6_spawn_function_enter, "6F[")
INSTR_0ARG(instr_nanos6_spawn_function_exit, "6F]") INSTR_0ARG(instr_nanos6_spawn_function_exit, "6F]")
INSTR_0ARG(instr_nanos6_taskfor_start, "6O[") INSTR_0ARG(instr_nanos6_taskfor_start, "6O[")
INSTR_0ARG(instr_nanos6_taskfor_stop, "6O]") INSTR_0ARG(instr_nanos6_taskfor_stop, "6O]")
INSTR_0ARG(instr_nanos6_task_body_enter, "6t[") INSTR_0ARG(instr_nanos6_task_body_enter, "6t[")
INSTR_0ARG(instr_nanos6_task_body_exit, "6t]") INSTR_0ARG(instr_nanos6_task_body_exit, "6t]")
INSTR_0ARG(instr_nanos6_register_enter, "6Dr") INSTR_0ARG(instr_nanos6_register_enter, "6Dr")
INSTR_0ARG(instr_nanos6_register_exit, "6DR") INSTR_0ARG(instr_nanos6_register_exit, "6DR")
INSTR_0ARG(instr_nanos6_unregister_enter, "6Du") INSTR_0ARG(instr_nanos6_unregister_enter, "6Du")
INSTR_0ARG(instr_nanos6_unregister_exit, "6DU") INSTR_0ARG(instr_nanos6_unregister_exit, "6DU")
INSTR_0ARG(instr_nanos6_block_enter, "6Bb") INSTR_0ARG(instr_nanos6_block_enter, "6Bb")
INSTR_0ARG(instr_nanos6_block_exit, "6BB") INSTR_0ARG(instr_nanos6_block_exit, "6BB")
INSTR_0ARG(instr_nanos6_unblock_enter, "6Bb") INSTR_0ARG(instr_nanos6_unblock_enter, "6Bb")
INSTR_0ARG(instr_nanos6_unblock_exit, "6BB") INSTR_0ARG(instr_nanos6_unblock_exit, "6BB")
INSTR_0ARG(instr_nanos6_taskwait_enter, "6Bw") INSTR_0ARG(instr_nanos6_taskwait_enter, "6Bw")
INSTR_0ARG(instr_nanos6_taskwait_exit, "6BW") INSTR_0ARG(instr_nanos6_taskwait_exit, "6BW")
INSTR_0ARG(instr_nanos6_waitfor_enter, "6Bf") INSTR_0ARG(instr_nanos6_waitfor_enter, "6Bf")
INSTR_0ARG(instr_nanos6_waitfor_exit, "6BF") INSTR_0ARG(instr_nanos6_waitfor_exit, "6BF")
INSTR_0ARG(instr_nanos6_external_set, "6He") INSTR_0ARG(instr_nanos6_external_set, "6He")
INSTR_0ARG(instr_nanos6_external_unset, "6HE") INSTR_0ARG(instr_nanos6_external_unset, "6HE")
INSTR_0ARG(instr_nanos6_worker_set, "6Hw") INSTR_0ARG(instr_nanos6_worker_set, "6Hw")
INSTR_0ARG(instr_nanos6_worker_unset, "6HW") INSTR_0ARG(instr_nanos6_worker_unset, "6HW")
INSTR_0ARG(instr_nanos6_leader_set, "6Hl") INSTR_0ARG(instr_nanos6_leader_set, "6Hl")
INSTR_0ARG(instr_nanos6_leader_unset, "6HL") INSTR_0ARG(instr_nanos6_leader_unset, "6HL")
INSTR_0ARG(instr_nanos6_main_set, "6Hm") INSTR_0ARG(instr_nanos6_main_set, "6Hm")
INSTR_0ARG(instr_nanos6_main_unset, "6HM") INSTR_0ARG(instr_nanos6_main_unset, "6HM")
INSTR_0ARG(instr_nanos6_alloc_enter, "6Ma") INSTR_0ARG(instr_nanos6_alloc_enter, "6Ma")
INSTR_0ARG(instr_nanos6_alloc_exit, "6MA") INSTR_0ARG(instr_nanos6_alloc_exit, "6MA")
INSTR_0ARG(instr_nanos6_free_enter, "6Mf") INSTR_0ARG(instr_nanos6_free_enter, "6Mf")
INSTR_0ARG(instr_nanos6_free_exit, "6MF") INSTR_0ARG(instr_nanos6_free_exit, "6MF")
static inline void static inline void
instr_nanos6_task_create_and_execute(int32_t id, uint32_t typeid) instr_nanos6_task_create_and_execute(int32_t id, uint32_t typeid)

View File

@ -14,16 +14,14 @@ main(void)
instr_nanos6_type_create(typeid); instr_nanos6_type_create(typeid);
/* Create and run the tasks, one nested into another */ /* Create and run the tasks, one nested into another */
for(int i = 0; i < ntasks; i++) for (int i = 0; i < ntasks; i++) {
{
instr_nanos6_handle_task_enter(); instr_nanos6_handle_task_enter();
instr_nanos6_task_create_and_execute(i + 1, typeid); instr_nanos6_task_create_and_execute(i + 1, typeid);
usleep(500); usleep(500);
} }
/* End the tasks in the opposite order */ /* End the tasks in the opposite order */
for(int i = ntasks - 1; i >= 0; i--) for (int i = ntasks - 1; i >= 0; i--) {
{
instr_nanos6_task_end(i + 1); instr_nanos6_task_end(i + 1);
instr_nanos6_task_body_exit(); instr_nanos6_task_body_exit();
instr_nanos6_handle_task_exit(); instr_nanos6_handle_task_exit();

View File

@ -14,11 +14,10 @@ main(void)
int ntasks = 100; int ntasks = 100;
int ntypes = 10; int ntypes = 10;
for(int i = 0; i < ntypes; i++) for (int i = 0; i < ntypes; i++)
instr_nanos6_type_create(i + 1); instr_nanos6_type_create(i + 1);
for(int i = 0; i < ntasks; i++) for (int i = 0; i < ntasks; i++) {
{
instr_nanos6_task_create_and_execute(i + 1, (i % ntypes) + 1); instr_nanos6_task_create_and_execute(i + 1, (i % ntypes) + 1);
usleep(500); usleep(500);
instr_nanos6_task_end(i + 1); instr_nanos6_task_end(i + 1);

View File

@ -22,15 +22,14 @@ main(void)
instr_nosv_type_create(typeid); instr_nosv_type_create(typeid);
/* Create and run the tasks, one nested into another */ /* Create and run the tasks, one nested into another */
for(int i = 0; i < ntasks; i++) for (int i = 0; i < ntasks; i++)
create_and_run(i + 1, typeid, 500); create_and_run(i + 1, typeid, 500);
/* End the tasks in the opposite order */ /* End the tasks in the opposite order */
for(int i = ntasks - 1; i >= 0; i--) for (int i = ntasks - 1; i >= 0; i--)
instr_nosv_task_end(i + 1); instr_nosv_task_end(i + 1);
instr_end(); instr_end();
return 0; return 0;
} }

View File

@ -27,4 +27,3 @@ main(void)
return 0; return 0;
} }

View File

@ -14,11 +14,10 @@ main(void)
int ntasks = 100; int ntasks = 100;
int ntypes = 10; int ntypes = 10;
for(int i=0; i<ntypes; i++) for (int i = 0; i < ntypes; i++)
instr_nosv_type_create(i + 1); instr_nosv_type_create(i + 1);
for(int i=0; i<ntasks; i++) for (int i = 0; i < ntasks; i++) {
{
instr_nosv_task_create(i + 1, (i % ntypes) + 1); instr_nosv_task_create(i + 1, (i % ntypes) + 1);
instr_nosv_task_execute(i + 1); instr_nosv_task_execute(i + 1);
usleep(500); usleep(500);
@ -29,4 +28,3 @@ main(void)
return 0; return 0;
} }

View File

@ -4,25 +4,24 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdint.h> #include <limits.h>
#include <linux/limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <linux/limits.h> #include <unistd.h>
#include <limits.h>
#include "ovni.h"
#include "compat.h" #include "compat.h"
#include "ovni.h"
static inline void static inline void
init(void) init(void)
{ {
char hostname[HOST_NAME_MAX]; char hostname[HOST_NAME_MAX];
if(gethostname(hostname, HOST_NAME_MAX) != 0) if (gethostname(hostname, HOST_NAME_MAX) != 0) {
{
perror("gethostname failed"); perror("gethostname failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -32,7 +31,8 @@ init(void)
ovni_add_cpu(0, 0); ovni_add_cpu(0, 0);
} }
static void emit(uint8_t *buf, size_t size) static void
emit(uint8_t *buf, size_t size)
{ {
struct ovni_ev ev = {0}; struct ovni_ev ev = {0};
ovni_ev_set_mcv(&ev, "O$$"); ovni_ev_set_mcv(&ev, "O$$");
@ -42,13 +42,13 @@ static void emit(uint8_t *buf, size_t size)
#define NRUNS 50 #define NRUNS 50
int main(void) int
main(void)
{ {
size_t payload_size; size_t payload_size;
uint8_t *payload_buf; uint8_t *payload_buf;
if(setenv("OVNI_TMPDIR", "/dev/shm/ovni-flush-overhead", 1) != 0) if (setenv("OVNI_TMPDIR", "/dev/shm/ovni-flush-overhead", 1) != 0) {
{
perror("setenv failed"); perror("setenv failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -59,21 +59,18 @@ int main(void)
payload_size = 1024 * 1024; payload_size = 1024 * 1024;
payload_buf = calloc(1, payload_size); payload_buf = calloc(1, payload_size);
if(!payload_buf) if (!payload_buf) {
{
perror("calloc failed"); perror("calloc failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
double *times = calloc(sizeof(double), NRUNS); double *times = calloc(sizeof(double), NRUNS);
if(times == NULL) if (times == NULL) {
{
perror("calloc failed"); perror("calloc failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for(int i=0; i < NRUNS; i++) for (int i = 0; i < NRUNS; i++) {
{
emit(payload_buf, payload_size); emit(payload_buf, payload_size);
double t0 = (double) ovni_clock_now(); double t0 = (double) ovni_clock_now();
ovni_flush(); ovni_flush();
@ -83,10 +80,10 @@ int main(void)
} }
double mean = 0.0; double mean = 0.0;
for(int i=0; i < NRUNS; i++) for (int i = 0; i < NRUNS; i++)
mean += times[i]; mean += times[i];
mean /= (double) NRUNS; mean /= (double) NRUNS;
fprintf(stderr, "mean %f ms\n", mean); fprintf(stderr, "mean %f ms\n", mean);
/* It should be able to write 1 MiB in less than 1 ms */ /* It should be able to write 1 MiB in less than 1 ms */
@ -94,8 +91,8 @@ int main(void)
fprintf(stderr, "took too much time to flush: %f ms\n", mean); fprintf(stderr, "took too much time to flush: %f ms\n", mean);
fprintf(stderr, "times (in ms):\n"); fprintf(stderr, "times (in ms):\n");
for(int i=0; i < NRUNS; i++) for (int i = 0; i < NRUNS; i++)
fprintf(stderr, " %4d %f\n", i, times[i]); fprintf(stderr, " %4d %f\n", i, times[i]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -4,25 +4,24 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdint.h> #include <limits.h>
#include <linux/limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <linux/limits.h> #include <unistd.h>
#include <limits.h>
#include "ovni.h"
#include "compat.h" #include "compat.h"
#include "ovni.h"
static inline void static inline void
init(void) init(void)
{ {
char hostname[HOST_NAME_MAX]; char hostname[HOST_NAME_MAX];
if(gethostname(hostname, HOST_NAME_MAX) != 0) if (gethostname(hostname, HOST_NAME_MAX) != 0) {
{
perror("gethostname failed"); perror("gethostname failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -32,7 +31,8 @@ init(void)
ovni_add_cpu(0, 0); ovni_add_cpu(0, 0);
} }
static void emit(uint8_t *buf, size_t size) static void
emit(uint8_t *buf, size_t size)
{ {
struct ovni_ev ev = {0}; struct ovni_ev ev = {0};
ovni_ev_set_mcv(&ev, "O$$"); ovni_ev_set_mcv(&ev, "O$$");
@ -40,7 +40,8 @@ static void emit(uint8_t *buf, size_t size)
ovni_ev_jumbo_emit(&ev, buf, size); ovni_ev_jumbo_emit(&ev, buf, size);
} }
int main(void) int
main(void)
{ {
size_t payload_size; size_t payload_size;
uint8_t *payload_buf; uint8_t *payload_buf;
@ -50,8 +51,7 @@ int main(void)
payload_size = (size_t) (0.9 * (double) OVNI_MAX_EV_BUF); payload_size = (size_t) (0.9 * (double) OVNI_MAX_EV_BUF);
payload_buf = calloc(1, payload_size); payload_buf = calloc(1, payload_size);
if(!payload_buf) if (!payload_buf) {
{
perror("calloc failed"); perror("calloc failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -3,8 +3,8 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include "ovni.h"
#include "compat.h" #include "compat.h"
#include "ovni.h"
#include <assert.h> #include <assert.h>
#include <inttypes.h> #include <inttypes.h>
@ -15,27 +15,29 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
static void fail(const char *msg) static void
fail(const char *msg)
{ {
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
abort(); abort();
} }
#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) \ static inline void name(ta a, tb b, tc c) \
{ \ { \
struct ovni_ev ev = {0}; \ struct ovni_ev ev = {0}; \
ovni_ev_set_mcv(&ev, mcv); \ ovni_ev_set_mcv(&ev, mcv); \
ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *)&b, sizeof(b)); \ ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
ovni_payload_add(&ev, (uint8_t *)&c, sizeof(c)); \ ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \
ovni_ev_emit(&ev); \ ovni_ev_emit(&ev); \
} }
INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag) INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag)
static inline void instr_thread_end(void) static inline void
instr_thread_end(void)
{ {
struct ovni_ev ev = {0}; struct ovni_ev ev = {0};
@ -47,36 +49,37 @@ static inline void instr_thread_end(void)
ovni_flush(); ovni_flush();
} }
static inline void instr_start(int rank, int nranks) static inline void
instr_start(int rank, int nranks)
{ {
char hostname[HOST_NAME_MAX]; char hostname[HOST_NAME_MAX];
if(gethostname(hostname, HOST_NAME_MAX) != 0) if (gethostname(hostname, HOST_NAME_MAX) != 0)
fail("gethostname failed"); fail("gethostname failed");
ovni_proc_init(1, hostname, getpid()); ovni_proc_init(1, hostname, getpid());
ovni_proc_set_rank(rank, nranks); ovni_proc_set_rank(rank, nranks);
ovni_thread_init(gettid()); ovni_thread_init(gettid());
/* Only the rank 0 inform about all CPUs */ /* Only the rank 0 inform about all CPUs */
if(rank == 0) if (rank == 0) {
{
/* Fake nranks cpus */ /* Fake nranks cpus */
for(int i=0; i < nranks; i++) for (int i = 0; i < nranks; i++)
ovni_add_cpu(i, i); ovni_add_cpu(i, i);
} }
int curcpu = rank; int curcpu = rank;
fprintf(stderr, "thread %d has cpu %d (ncpus=%d)\n", fprintf(stderr, "thread %d has cpu %d (ncpus=%d)\n",
gettid(), curcpu, nranks); gettid(), curcpu, nranks);
instr_thread_execute(curcpu, -1, 0); instr_thread_execute(curcpu, -1, 0);
} }
static inline void instr_end(void) static inline void
instr_end(void)
{ {
instr_thread_end(); instr_thread_end();
ovni_thread_free(); ovni_thread_free();
@ -132,7 +135,8 @@ task(int32_t id, uint32_t typeid, int us)
ovni_ev_emit(&ev); ovni_ev_emit(&ev);
} }
int main(void) int
main(void)
{ {
int rank = atoi(getenv("OVNI_RANK")); int rank = atoi(getenv("OVNI_RANK"));
int nranks = atoi(getenv("OVNI_NRANKS")); int nranks = atoi(getenv("OVNI_NRANKS"));
@ -143,11 +147,10 @@ int main(void)
type_create(typeid); type_create(typeid);
/* Create some fake nosv tasks */ /* Create some fake nosv tasks */
for(int i=0; i<10; i++) for (int i = 0; i < 10; i++)
task(i + 1, typeid, 5000); task(i + 1, typeid, 5000);
instr_end(); instr_end();
return 0; return 0;
} }

View File

@ -3,8 +3,8 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include "ovni.h"
#include "compat.h" #include "compat.h"
#include "ovni.h"
#include <assert.h> #include <assert.h>
#include <inttypes.h> #include <inttypes.h>
@ -16,27 +16,29 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
static void fail(const char *msg) static void
fail(const char *msg)
{ {
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
abort(); abort();
} }
#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) \ static inline void name(ta a, tb b, tc c) \
{ \ { \
struct ovni_ev ev = {0}; \ struct ovni_ev ev = {0}; \
ovni_ev_set_mcv(&ev, mcv); \ ovni_ev_set_mcv(&ev, mcv); \
ovni_ev_set_clock(&ev, ovni_clock_now()); \ ovni_ev_set_clock(&ev, ovni_clock_now()); \
ovni_payload_add(&ev, (uint8_t *)&a, sizeof(a)); \ ovni_payload_add(&ev, (uint8_t *) &a, sizeof(a)); \
ovni_payload_add(&ev, (uint8_t *)&b, sizeof(b)); \ ovni_payload_add(&ev, (uint8_t *) &b, sizeof(b)); \
ovni_payload_add(&ev, (uint8_t *)&c, sizeof(c)); \ ovni_payload_add(&ev, (uint8_t *) &c, sizeof(c)); \
ovni_ev_emit(&ev); \ ovni_ev_emit(&ev); \
} }
INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag) INSTR_3ARG(instr_thread_execute, "OHx", int32_t, cpu, int32_t, creator_tid, uint64_t, tag)
static inline void instr_thread_end(void) static inline void
instr_thread_end(void)
{ {
struct ovni_ev ev = {0}; struct ovni_ev ev = {0};
@ -48,29 +50,27 @@ static inline void instr_thread_end(void)
ovni_flush(); ovni_flush();
} }
static inline void instr_start(int rank) static inline void
instr_start(int rank)
{ {
cpu_set_t mask; cpu_set_t mask;
char hostname[HOST_NAME_MAX]; char hostname[HOST_NAME_MAX];
int i, j = 0, curcpu = -1; int i, j = 0, curcpu = -1;
int last_phy; int last_phy;
if(gethostname(hostname, HOST_NAME_MAX) != 0) if (gethostname(hostname, HOST_NAME_MAX) != 0)
fail("gethostname failed"); fail("gethostname failed");
if(sched_getaffinity(0, sizeof(mask), &mask) < 0) if (sched_getaffinity(0, sizeof(mask), &mask) < 0)
fail("sched_getaffinity failed"); fail("sched_getaffinity failed");
ovni_proc_init(1, hostname, getpid()); ovni_proc_init(1, hostname, getpid());
ovni_thread_init(gettid()); ovni_thread_init(gettid());
/* Only the rank 0 inform about all CPUs */ /* Only the rank 0 inform about all CPUs */
if(rank == 0) if (rank == 0) {
{ for (i = 0; i < CPU_SETSIZE; i++) {
for(i=0; i < CPU_SETSIZE; i++) if (CPU_ISSET(i, &mask)) {
{
if(CPU_ISSET(i, &mask))
{
last_phy = i; last_phy = i;
if (rank == 0) if (rank == 0)
@ -79,28 +79,30 @@ static inline void instr_start(int rank)
} }
} }
if(CPU_COUNT(&mask) == 1) if (CPU_COUNT(&mask) == 1)
curcpu = last_phy; curcpu = last_phy;
else else
curcpu = -1; curcpu = -1;
fprintf(stderr, "thread %d has cpu %d (ncpus=%d)\n", fprintf(stderr, "thread %d has cpu %d (ncpus=%d)\n",
gettid(), curcpu, CPU_COUNT(&mask)); gettid(), curcpu, CPU_COUNT(&mask));
instr_thread_execute(curcpu, -1, 0); instr_thread_execute(curcpu, -1, 0);
} }
static inline void instr_end(void) static inline void
instr_end(void)
{ {
instr_thread_end(); instr_thread_end();
ovni_thread_free(); ovni_thread_free();
ovni_proc_fini(); ovni_proc_fini();
} }
int main(void) int
main(void)
{ {
int rank = atoi(getenv("OVNI_RANK")); int rank = atoi(getenv("OVNI_RANK"));
//int nranks = atoi(getenv("OVNI_NRANKS")); // int nranks = atoi(getenv("OVNI_NRANKS"));
instr_start(rank); instr_start(rank);
@ -110,4 +112,3 @@ int main(void)
return 0; return 0;
} }

View File

@ -4,9 +4,10 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <unistd.h> #include <unistd.h>
int main(void) int
main(void)
{ {
#pragma oss task if(0) #pragma oss task if (0)
{ {
usleep(1000); usleep(1000);
} }

View File

@ -1,14 +1,15 @@
/* Copyright (c) 2022 Barcelona Supercomputing Center (BSC) /* Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
int main(void) int
main(void)
{ {
#pragma oss task #pragma oss task
{ {
#pragma oss task #pragma oss task
{ {
} }
#pragma oss taskwait #pragma oss taskwait
} }
return 0; return 0;
} }

View File

@ -36,25 +36,26 @@ do_run(void)
memset(handle, 0, ntasks * sizeof(void *)); memset(handle, 0, ntasks * sizeof(void *));
atomic_store(&nhandles, 0); atomic_store(&nhandles, 0);
for(int t = 0; t < ntasks; t++) for (int t = 0; t < ntasks; t++)
do_task(t); do_task(t);
/* Wait for all tasks to fill the handle */ /* Wait for all tasks to fill the handle */
while (atomic_load(&nhandles) < ntasks); while (atomic_load(&nhandles) < ntasks)
;
/* Is ok if we call unblock before the block happens */ /* Is ok if we call unblock before the block happens */
for(int t = 0; t < ntasks; t++) for (int t = 0; t < ntasks; t++) {
{
if (handle[t] == NULL) if (handle[t] == NULL)
abort(); abort();
nanos6_unblock_task(handle[t]); nanos6_unblock_task(handle[t]);
} }
#pragma oss taskwait #pragma oss taskwait
} }
static int get_ncpus(void) static int
get_ncpus(void)
{ {
return (int) nanos6_get_num_cpus(); return (int) nanos6_get_num_cpus();
} }
@ -66,13 +67,12 @@ main(void)
handle = calloc(ntasks, sizeof(void *)); handle = calloc(ntasks, sizeof(void *));
if(handle == NULL) if (handle == NULL) {
{
perror("calloc failed"); perror("calloc failed");
return -1; return -1;
} }
for(int run = 0; run < nruns; run++) for (int run = 0; run < nruns; run++)
do_run(); do_run();
return 0; return 0;

View File

@ -1,17 +1,16 @@
/* Copyright (c) 2022 Barcelona Supercomputing Center (BSC) /* Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
int main(void) int
main(void)
{ {
for(int i = 0; i < 5000; i++) for (int i = 0; i < 5000; i++) {
{ #pragma oss task
#pragma oss task
{ {
for(volatile long j = 0; j < 10000L; j++) for (volatile long j = 0; j < 10000L; j++) {
{
} }
} }
} }
#pragma oss taskwait #pragma oss taskwait
return 0; return 0;
} }

View File

@ -1,9 +1,10 @@
/* Copyright (c) 2022 Barcelona Supercomputing Center (BSC) /* Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
int main(void) int
main(void)
{ {
#pragma oss task #pragma oss task
{ {
} }
return 0; return 0;

View File

@ -4,10 +4,11 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <unistd.h> #include <unistd.h>
int main(void) int
main(void)
{ {
#pragma oss task for #pragma oss task for
for(int i = 0; i < 1024; i++) for (int i = 0; i < 1024; i++)
usleep(1000); usleep(1000);
return 0; return 0;

View File

@ -3,33 +3,35 @@
#define _DEFAULT_SOURCE #define _DEFAULT_SOURCE
#include <unistd.h>
#include <nosv.h> #include <nosv.h>
#include <unistd.h>
#include "common.h" #include "common.h"
int main(void) int
main(void)
{ {
nosv_init(); nosv_init();
nosv_task_type_t type; nosv_task_type_t type;
if(nosv_type_init(&type, NULL, NULL, NULL, "adopted", NULL, if (nosv_type_init(&type, NULL, NULL, NULL, "adopted", NULL,
NULL, NOSV_TYPE_INIT_EXTERNAL) != 0) NULL, NOSV_TYPE_INIT_EXTERNAL)
!= 0)
die("nosv_type_init failed\n"); die("nosv_type_init failed\n");
nosv_task_t task; nosv_task_t task;
if(nosv_attach(&task, type, 0, NULL, 0) != 0) if (nosv_attach(&task, type, 0, NULL, 0) != 0)
die("nosv_attach failed\n"); die("nosv_attach failed\n");
usleep(100); usleep(100);
if(nosv_detach(0) != 0) if (nosv_detach(0) != 0)
die("nosv_detach failed\n"); die("nosv_detach failed\n");
if(nosv_type_destroy(type, 0) != 0) if (nosv_type_destroy(type, 0) != 0)
die("nosv_type_destroy failed\n"); die("nosv_type_destroy failed\n");
if(nosv_shutdown() != 0) if (nosv_shutdown() != 0)
die("nosv_shutdown failed\n"); die("nosv_shutdown failed\n");
return 0; return 0;

290
trace.c
View File

@ -6,20 +6,19 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <unistd.h> #include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <linux/limits.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdatomic.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
static int static int
find_dir_prefix_str(const char *dirname, const char *prefix, const char **str) find_dir_prefix_str(const char *dirname, const char *prefix, const char **str)
@ -29,18 +28,18 @@ find_dir_prefix_str(const char *dirname, const char *prefix, const char **str)
p = dirname; p = dirname;
/* Check the prefix */ /* Check the prefix */
if(strncmp(p, prefix, strlen(prefix)) != 0) if (strncmp(p, prefix, strlen(prefix)) != 0)
return -1; return -1;
p += strlen(prefix); p += strlen(prefix);
/* Find the dot */ /* Find the dot */
if(*p != '.') if (*p != '.')
return -1; return -1;
p++; p++;
if(str) if (str)
*str = p; *str = p;
return 0; return 0;
@ -51,7 +50,7 @@ find_dir_prefix_int(const char *dirname, const char *prefix, int *num)
{ {
const char *p; const char *p;
if(find_dir_prefix_str(dirname, prefix, &p) != 0) if (find_dir_prefix_str(dirname, prefix, &p) != 0)
return -1; return -1;
/* Convert the suffix string to a number */ /* Convert the suffix string to a number */
@ -66,9 +65,8 @@ count_dir_prefix(DIR *dir, const char *prefix)
struct dirent *dirent; struct dirent *dirent;
size_t n = 0; size_t n = 0;
while((dirent = readdir(dir)) != NULL) while ((dirent = readdir(dir)) != NULL) {
{ if (find_dir_prefix_str(dirent->d_name, prefix, NULL) != 0)
if(find_dir_prefix_str(dirent->d_name, prefix, NULL) != 0)
continue; continue;
n++; n++;
@ -88,8 +86,7 @@ load_thread(struct ovni_ethread *thread, struct ovni_eproc *proc, int index, int
thread->state = TH_ST_UNKNOWN; thread->state = TH_ST_UNKNOWN;
thread->proc = proc; thread->proc = proc;
if(strlen(filepath) >= PATH_MAX) if (strlen(filepath) >= PATH_MAX) {
{
err("filepath too large: %s\n", filepath); err("filepath too large: %s\n", filepath);
return -1; return -1;
} }
@ -105,24 +102,21 @@ load_proc_metadata(struct ovni_eproc *proc, int *rank_enabled)
JSON_Object *meta; JSON_Object *meta;
meta = json_value_get_object(proc->meta); meta = json_value_get_object(proc->meta);
if(meta == NULL) if (meta == NULL)
die("load_proc_metadata: json_value_get_object() failed\n"); die("load_proc_metadata: json_value_get_object() failed\n");
JSON_Value *appid_val = json_object_get_value(meta, "app_id"); JSON_Value *appid_val = json_object_get_value(meta, "app_id");
if(appid_val == NULL) if (appid_val == NULL)
die("process %d is missing app_id in metadata\n", proc->pid); die("process %d is missing app_id in metadata\n", proc->pid);
proc->appid = (int) json_number(appid_val); proc->appid = (int) json_number(appid_val);
JSON_Value *rank_val = json_object_get_value(meta, "rank"); JSON_Value *rank_val = json_object_get_value(meta, "rank");
if(rank_val != NULL) if (rank_val != NULL) {
{
proc->rank = (int) json_number(rank_val); proc->rank = (int) json_number(rank_val);
*rank_enabled = 1; *rank_enabled = 1;
} } else {
else
{
proc->rank = -1; proc->rank = -1;
} }
} }
@ -131,40 +125,35 @@ static void
check_metadata_version(struct ovni_eproc *proc) check_metadata_version(struct ovni_eproc *proc)
{ {
JSON_Object *meta = json_value_get_object(proc->meta); JSON_Object *meta = json_value_get_object(proc->meta);
if(meta == NULL) if (meta == NULL)
die("check_metadata_version: json_value_get_object() failed\n"); die("check_metadata_version: json_value_get_object() failed\n");
JSON_Value *version_val = json_object_get_value(meta, "version"); JSON_Value *version_val = json_object_get_value(meta, "version");
if(version_val == NULL) if (version_val == NULL) {
{
die("process %d is missing attribute \"version\" in metadata\n", die("process %d is missing attribute \"version\" in metadata\n",
proc->pid); proc->pid);
} }
int version = (int) json_number(version_val); int version = (int) json_number(version_val);
if(version != OVNI_METADATA_VERSION) if (version != OVNI_METADATA_VERSION) {
{
die("pid %d: metadata version mismatch %d (expected %d)\n", die("pid %d: metadata version mismatch %d (expected %d)\n",
proc->pid, version, proc->pid, version,
OVNI_METADATA_VERSION); OVNI_METADATA_VERSION);
} }
JSON_Value *mversion_val = json_object_get_value(meta, "model_version"); JSON_Value *mversion_val = json_object_get_value(meta, "model_version");
if(mversion_val == NULL) if (mversion_val == NULL) {
{
die("process %d is missing attribute \"model_version\" in metadata\n", die("process %d is missing attribute \"model_version\" in metadata\n",
proc->pid); proc->pid);
} }
const char *mversion = json_string(mversion_val); const char *mversion = json_string(mversion_val);
if(strcmp(mversion, OVNI_MODEL_VERSION) != 0) if (strcmp(mversion, OVNI_MODEL_VERSION) != 0) {
{
die("pid %d: metadata model version mismatch '%s' (expected '%s')\n", die("pid %d: metadata model version mismatch '%s' (expected '%s')\n",
proc->pid, mversion, proc->pid, mversion,
OVNI_MODEL_VERSION); OVNI_MODEL_VERSION);
} }
} }
@ -174,9 +163,9 @@ compare_int(const void *a, const void *b)
int aa = *(const int *) a; int aa = *(const int *) a;
int bb = *(const int *) b; int bb = *(const int *) b;
if(aa < bb) if (aa < bb)
return -1; return -1;
else if(aa > bb) else if (aa > bb)
return +1; return +1;
else else
return 0; return 0;
@ -197,16 +186,13 @@ load_proc(struct ovni_eproc *proc, struct ovni_loom *loom, int index, int pid, c
proc->gindex = total_procs++; proc->gindex = total_procs++;
proc->loom = loom; proc->loom = loom;
if(snprintf(path, PATH_MAX, "%s/%s", procdir, "metadata.json") >= if (snprintf(path, PATH_MAX, "%s/%s", procdir, "metadata.json") >= PATH_MAX) {
PATH_MAX)
{
err("snprintf: path too large: %s\n", procdir); err("snprintf: path too large: %s\n", procdir);
abort(); abort();
} }
proc->meta = json_parse_file_with_comments(path); proc->meta = json_parse_file_with_comments(path);
if(proc->meta == NULL) if (proc->meta == NULL) {
{
err("error loading metadata from %s\n", path); err("error loading metadata from %s\n", path);
return -1; return -1;
} }
@ -216,51 +202,45 @@ load_proc(struct ovni_eproc *proc, struct ovni_loom *loom, int index, int pid, c
/* The appid is populated from the metadata */ /* The appid is populated from the metadata */
load_proc_metadata(proc, &loom->rank_enabled); load_proc_metadata(proc, &loom->rank_enabled);
if((dir = opendir(procdir)) == NULL) if ((dir = opendir(procdir)) == NULL) {
{
fprintf(stderr, "opendir %s failed: %s\n", fprintf(stderr, "opendir %s failed: %s\n",
procdir, strerror(errno)); procdir, strerror(errno));
return -1; return -1;
} }
proc->nthreads = count_dir_prefix(dir, "thread"); proc->nthreads = count_dir_prefix(dir, "thread");
if(proc->nthreads <= 0) if (proc->nthreads <= 0) {
{
err("cannot find any thread for process %d\n", err("cannot find any thread for process %d\n",
proc->pid); proc->pid);
return -1; return -1;
} }
proc->thread = calloc(proc->nthreads, sizeof(struct ovni_ethread)); proc->thread = calloc(proc->nthreads, sizeof(struct ovni_ethread));
if(proc->thread == NULL) if (proc->thread == NULL) {
{
perror("calloc failed"); perror("calloc failed");
return -1; return -1;
} }
int *tids; int *tids;
if((tids = calloc(proc->nthreads, sizeof(int))) == NULL) if ((tids = calloc(proc->nthreads, sizeof(int))) == NULL) {
{
perror("calloc failed\n"); perror("calloc failed\n");
return -1; return -1;
} }
rewinddir(dir); rewinddir(dir);
for(size_t i = 0; i < proc->nthreads; ) for (size_t i = 0; i < proc->nthreads;) {
{
dirent = readdir(dir); dirent = readdir(dir);
if(dirent == NULL) if (dirent == NULL) {
{
err("inconsistent: readdir returned NULL\n"); err("inconsistent: readdir returned NULL\n");
return -1; return -1;
} }
if(find_dir_prefix_int(dirent->d_name, "thread", &tids[i]) != 0) if (find_dir_prefix_int(dirent->d_name, "thread", &tids[i]) != 0)
continue; continue;
i++; i++;
@ -271,20 +251,17 @@ load_proc(struct ovni_eproc *proc, struct ovni_loom *loom, int index, int pid, c
/* Sort threads by ascending TID */ /* Sort threads by ascending TID */
qsort(tids, proc->nthreads, sizeof(int), compare_int); qsort(tids, proc->nthreads, sizeof(int), compare_int);
for(size_t i = 0; i < proc->nthreads; i++) for (size_t i = 0; i < proc->nthreads; i++) {
{
int tid = tids[i]; int tid = tids[i];
if(snprintf(path, PATH_MAX, "%s/thread.%d", procdir, tid) >= if (snprintf(path, PATH_MAX, "%s/thread.%d", procdir, tid) >= PATH_MAX) {
PATH_MAX)
{
err("snprintf: path too large: %s\n", procdir); err("snprintf: path too large: %s\n", procdir);
abort(); abort();
} }
thread = &proc->thread[i]; thread = &proc->thread[i];
if(load_thread(thread, proc, i, tid, path) != 0) if (load_thread(thread, proc, i, tid, path) != 0)
return -1; return -1;
} }
@ -302,27 +279,24 @@ load_loom(struct ovni_loom *loom, char *loomdir)
DIR *dir; DIR *dir;
struct dirent *dirent; struct dirent *dirent;
if((dir = opendir(loomdir)) == NULL) if ((dir = opendir(loomdir)) == NULL) {
{
fprintf(stderr, "opendir %s failed: %s\n", fprintf(stderr, "opendir %s failed: %s\n",
loomdir, strerror(errno)); loomdir, strerror(errno));
return -1; return -1;
} }
loom->rank_enabled = 0; loom->rank_enabled = 0;
loom->nprocs = count_dir_prefix(dir, "proc"); loom->nprocs = count_dir_prefix(dir, "proc");
if(loom->nprocs <= 0) if (loom->nprocs <= 0) {
{
err("cannot find any process directory in loom %s\n", err("cannot find any process directory in loom %s\n",
loom->hostname); loom->hostname);
return -1; return -1;
} }
loom->proc = calloc(loom->nprocs, sizeof(struct ovni_eproc)); loom->proc = calloc(loom->nprocs, sizeof(struct ovni_eproc));
if(loom->proc == NULL) if (loom->proc == NULL) {
{
perror("calloc failed"); perror("calloc failed");
return -1; return -1;
} }
@ -330,28 +304,24 @@ load_loom(struct ovni_loom *loom, char *loomdir)
rewinddir(dir); rewinddir(dir);
i = 0; i = 0;
while((dirent = readdir(dir)) != NULL) while ((dirent = readdir(dir)) != NULL) {
{ if (find_dir_prefix_int(dirent->d_name, "proc", &pid) != 0)
if(find_dir_prefix_int(dirent->d_name, "proc", &pid) != 0)
continue; continue;
sprintf(path, "%s/%s", loomdir, dirent->d_name); sprintf(path, "%s/%s", loomdir, dirent->d_name);
if(i >= loom->nprocs) if (i >= loom->nprocs) {
{
err("more process than expected\n"); err("more process than expected\n");
abort(); abort();
} }
if(load_proc(&loom->proc[i], loom, i, pid, path) != 0) if (load_proc(&loom->proc[i], loom, i, pid, path) != 0)
return -1; return -1;
i++; i++;
} }
if(i != loom->nprocs) if (i != loom->nprocs) {
{
err("unexpected number of processes\n"); err("unexpected number of processes\n");
abort(); abort();
} }
@ -359,15 +329,12 @@ load_loom(struct ovni_loom *loom, char *loomdir)
closedir(dir); closedir(dir);
/* Ensure all process have the rank, if enabled in any */ /* Ensure all process have the rank, if enabled in any */
if(loom->rank_enabled) if (loom->rank_enabled) {
{ for (i = 0; i < loom->nprocs; i++) {
for(i = 0; i < loom->nprocs; i++)
{
struct ovni_eproc *proc = &loom->proc[i]; struct ovni_eproc *proc = &loom->proc[i];
if(proc->rank < 0) if (proc->rank < 0) {
{
die("process %d is missing the rank\n", die("process %d is missing the rank\n",
proc->pid); proc->pid);
} }
} }
} }
@ -388,16 +355,15 @@ loom_to_host(const char *loom_name, char *host, int n)
{ {
int i; int i;
for(i = 0; i < n; i++) for (i = 0; i < n; i++) {
{
/* Copy until dot or end */ /* Copy until dot or end */
if(loom_name[i] != '.' && loom_name[i] != '\0') if (loom_name[i] != '.' && loom_name[i] != '\0')
host[i] = loom_name[i]; host[i] = loom_name[i];
else else
break; break;
} }
if(i == n) if (i == n)
die("loom host name %s too long\n", loom_name); die("loom host name %s too long\n", loom_name);
host[i] = '\0'; host[i] = '\0';
@ -408,24 +374,21 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir)
{ {
DIR *dir; DIR *dir;
if((dir = opendir(tracedir)) == NULL) if ((dir = opendir(tracedir)) == NULL) {
{
err("opendir %s failed: %s\n", tracedir, strerror(errno)); err("opendir %s failed: %s\n", tracedir, strerror(errno));
return -1; return -1;
} }
trace->nlooms = count_dir_prefix(dir, "loom"); trace->nlooms = count_dir_prefix(dir, "loom");
if(trace->nlooms == 0) if (trace->nlooms == 0) {
{
err("cannot find any loom in %s\n", tracedir); err("cannot find any loom in %s\n", tracedir);
return -1; return -1;
} }
trace->loom = calloc(trace->nlooms, sizeof(struct ovni_loom)); trace->loom = calloc(trace->nlooms, sizeof(struct ovni_loom));
if(trace->loom == NULL) if (trace->loom == NULL) {
{
perror("calloc failed\n"); perror("calloc failed\n");
return -1; return -1;
} }
@ -435,25 +398,21 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir)
size_t l = 0; size_t l = 0;
struct dirent *dirent; struct dirent *dirent;
while((dirent = readdir(dir)) != NULL) while ((dirent = readdir(dir)) != NULL) {
{
struct ovni_loom *loom = &trace->loom[l]; struct ovni_loom *loom = &trace->loom[l];
const char *loom_name; const char *loom_name;
if(find_dir_prefix_str(dirent->d_name, "loom", &loom_name) != 0) if (find_dir_prefix_str(dirent->d_name, "loom", &loom_name) != 0) {
{
/* Ignore other files in tracedir */ /* Ignore other files in tracedir */
continue; continue;
} }
if(l >= trace->nlooms) if (l >= trace->nlooms) {
{
err("extra loom detected\n"); err("extra loom detected\n");
return -1; return -1;
} }
/* Copy the complete loom directory name to looms */ /* Copy the complete loom directory name to looms */
if(snprintf(loom->dname, PATH_MAX, "%s", dirent->d_name) >= PATH_MAX) if (snprintf(loom->dname, PATH_MAX, "%s", dirent->d_name) >= PATH_MAX) {
{
err("error: loom name %s too long\n", dirent->d_name); err("error: loom name %s too long\n", dirent->d_name);
return -1; return -1;
} }
@ -465,30 +424,28 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir)
/* Sort the looms, so we get the hostnames in alphanumeric order */ /* Sort the looms, so we get the hostnames in alphanumeric order */
qsort(trace->loom, trace->nlooms, sizeof(struct ovni_loom), qsort(trace->loom, trace->nlooms, sizeof(struct ovni_loom),
compare_looms); compare_looms);
for(size_t i = 0; i < trace->nlooms; i++) for (size_t i = 0; i < trace->nlooms; i++) {
{
struct ovni_loom *loom = &trace->loom[i]; struct ovni_loom *loom = &trace->loom[i];
const char *name = NULL; const char *name = NULL;
if(find_dir_prefix_str(loom->dname, "loom", &name) != 0) if (find_dir_prefix_str(loom->dname, "loom", &name) != 0) {
{
err("error: mismatch for loom %s\n", loom->dname); err("error: mismatch for loom %s\n", loom->dname);
return -1; return -1;
} }
loom_to_host(name, loom->hostname, sizeof(loom->hostname)); loom_to_host(name, loom->hostname, sizeof(loom->hostname));
if(snprintf(loom->path, PATH_MAX, "%s/%s", if (snprintf(loom->path, PATH_MAX, "%s/%s",
tracedir, loom->dname) >= PATH_MAX) tracedir, loom->dname)
{ >= PATH_MAX) {
err("error: loom path %s/%s too long\n", err("error: loom path %s/%s too long\n",
tracedir, loom->dname); tracedir, loom->dname);
return -1; return -1;
} }
if(load_loom(loom, loom->path) != 0) if (load_loom(loom, loom->path) != 0)
return -1; return -1;
} }
@ -500,30 +457,27 @@ check_stream_header(struct ovni_stream *stream)
{ {
int ret = 0; int ret = 0;
if(stream->size < sizeof(struct ovni_stream_header)) if (stream->size < sizeof(struct ovni_stream_header)) {
{
err("stream %d: incomplete stream header\n", err("stream %d: incomplete stream header\n",
stream->tid); stream->tid);
return -1; return -1;
} }
struct ovni_stream_header *h = struct ovni_stream_header *h =
(struct ovni_stream_header *) stream->buf; (struct ovni_stream_header *) stream->buf;
if(memcmp(h->magic, OVNI_STREAM_MAGIC, 4) != 0) if (memcmp(h->magic, OVNI_STREAM_MAGIC, 4) != 0) {
{
char magic[5]; char magic[5];
memcpy(magic, h->magic, 4); memcpy(magic, h->magic, 4);
magic[4] = '\0'; magic[4] = '\0';
err("stream %d: wrong stream magic '%s' (expected '%s')\n", err("stream %d: wrong stream magic '%s' (expected '%s')\n",
stream->tid, magic, OVNI_STREAM_MAGIC); stream->tid, magic, OVNI_STREAM_MAGIC);
ret = -1; ret = -1;
} }
if(h->version != OVNI_STREAM_VERSION) if (h->version != OVNI_STREAM_VERSION) {
{
err("stream %d: stream version mismatch %u (expected %u)\n", err("stream %d: stream version mismatch %u (expected %u)\n",
stream->tid, h->version, OVNI_STREAM_VERSION); stream->tid, h->version, OVNI_STREAM_VERSION);
ret = -1; ret = -1;
} }
@ -534,15 +488,13 @@ static int
load_stream_fd(struct ovni_stream *stream, int fd) load_stream_fd(struct ovni_stream *stream, int fd)
{ {
struct stat st; struct stat st;
if(fstat(fd, &st) < 0) if (fstat(fd, &st) < 0) {
{
perror("fstat failed"); perror("fstat failed");
return -1; return -1;
} }
/* Error because it doesn't have the header */ /* Error because it doesn't have the header */
if(st.st_size == 0) if (st.st_size == 0) {
{
err("stream %d is empty\n", stream->tid); err("stream %d is empty\n", stream->tid);
return -1; return -1;
} }
@ -550,8 +502,7 @@ load_stream_fd(struct ovni_stream *stream, int fd)
int prot = PROT_READ | PROT_WRITE; int prot = PROT_READ | PROT_WRITE;
stream->buf = mmap(NULL, st.st_size, prot, MAP_PRIVATE, fd, 0); stream->buf = mmap(NULL, st.st_size, prot, MAP_PRIVATE, fd, 0);
if(stream->buf == MAP_FAILED) if (stream->buf == MAP_FAILED) {
{
perror("mmap failed"); perror("mmap failed");
return -1; return -1;
} }
@ -566,31 +517,28 @@ load_stream_buf(struct ovni_stream *stream, struct ovni_ethread *thread)
{ {
int fd; int fd;
if((fd = open(thread->tracefile, O_RDWR)) == -1) if ((fd = open(thread->tracefile, O_RDWR)) == -1) {
{
perror("open failed"); perror("open failed");
return -1; return -1;
} }
if(load_stream_fd(stream, fd) != 0) if (load_stream_fd(stream, fd) != 0)
return -1; return -1;
if(check_stream_header(stream) != 0) if (check_stream_header(stream) != 0) {
{
err("stream %d: bad header\n", stream->tid); err("stream %d: bad header\n", stream->tid);
return -1; return -1;
} }
stream->offset = sizeof(struct ovni_stream_header); stream->offset = sizeof(struct ovni_stream_header);
if(stream->offset == stream->size) if (stream->offset == stream->size)
stream->active = 0; stream->active = 0;
else else
stream->active = 1; stream->active = 1;
/* No need to keep the fd open */ /* No need to keep the fd open */
if(close(fd)) if (close(fd)) {
{
perror("close failed"); perror("close failed");
return -1; return -1;
} }
@ -610,14 +558,11 @@ ovni_load_streams(struct ovni_trace *trace)
trace->nstreams = 0; trace->nstreams = 0;
for(i=0; i<trace->nlooms; i++) for (i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
for(j=0; j<loom->nprocs; j++) for (j = 0; j < loom->nprocs; j++) {
{
proc = &loom->proc[j]; proc = &loom->proc[j];
for(k=0; k<proc->nthreads; k++) for (k = 0; k < proc->nthreads; k++) {
{
trace->nstreams++; trace->nstreams++;
} }
} }
@ -625,22 +570,18 @@ ovni_load_streams(struct ovni_trace *trace)
trace->stream = calloc(trace->nstreams, sizeof(struct ovni_stream)); trace->stream = calloc(trace->nstreams, sizeof(struct ovni_stream));
if(trace->stream == NULL) if (trace->stream == NULL) {
{
perror("calloc failed"); perror("calloc failed");
return -1; return -1;
} }
err("loaded %ld streams\n", trace->nstreams); err("loaded %ld streams\n", trace->nstreams);
for(s=0, i=0; i<trace->nlooms; i++) for (s = 0, i = 0; i < trace->nlooms; i++) {
{
loom = &trace->loom[i]; loom = &trace->loom[i];
for(j=0; j<loom->nprocs; j++) for (j = 0; j < loom->nprocs; j++) {
{
proc = &loom->proc[j]; proc = &loom->proc[j];
for(k=0; k<proc->nthreads; k++) for (k = 0; k < proc->nthreads; k++) {
{
thread = &proc->thread[k]; thread = &proc->thread[k];
stream = &trace->stream[s++]; stream = &trace->stream[s++];
@ -652,12 +593,10 @@ ovni_load_streams(struct ovni_trace *trace)
stream->offset = 0; stream->offset = 0;
stream->cur_ev = NULL; stream->cur_ev = NULL;
if(load_stream_buf(stream, thread) != 0) if (load_stream_buf(stream, thread) != 0) {
{
err("load_stream_buf failed\n"); err("load_stream_buf failed\n");
return -1; return -1;
} }
} }
} }
} }
@ -668,10 +607,9 @@ ovni_load_streams(struct ovni_trace *trace)
void void
ovni_free_streams(struct ovni_trace *trace) ovni_free_streams(struct ovni_trace *trace)
{ {
for(size_t i = 0; i < trace->nstreams; i++) for (size_t i = 0; i < trace->nstreams; i++) {
{
struct ovni_stream *stream = &trace->stream[i]; struct ovni_stream *stream = &trace->stream[i];
if(munmap(stream->buf, stream->size) != 0) if (munmap(stream->buf, stream->size) != 0)
die("munmap stream failed: %s\n", strerror(errno)); die("munmap stream failed: %s\n", strerror(errno));
} }
@ -683,10 +621,8 @@ ovni_free_trace(struct ovni_trace *trace)
{ {
size_t i, j; size_t i, j;
for(i=0; i<trace->nlooms; i++) for (i = 0; i < trace->nlooms; i++) {
{ for (j = 0; j < trace->loom[i].nprocs; j++) {
for(j=0; j<trace->loom[i].nprocs; j++)
{
free(trace->loom[i].proc[j].thread); free(trace->loom[i].proc[j].thread);
} }
@ -699,23 +635,21 @@ ovni_free_trace(struct ovni_trace *trace)
int int
ovni_load_next_event(struct ovni_stream *stream) ovni_load_next_event(struct ovni_stream *stream)
{ {
if(stream->active == 0) if (stream->active == 0) {
{
dbg("stream is inactive, cannot load more events\n"); dbg("stream is inactive, cannot load more events\n");
return -1; return -1;
} }
/* Only step the offset if we have load an event */ /* Only step the offset if we have load an event */
if(stream->cur_ev != NULL) if (stream->cur_ev != NULL)
stream->offset += ovni_ev_size(stream->cur_ev); stream->offset += ovni_ev_size(stream->cur_ev);
/* It cannot overflow, otherwise we are reading garbage */ /* It cannot overflow, otherwise we are reading garbage */
if(stream->offset > stream->size) if (stream->offset > stream->size)
die("ovni_load_next_event: stream offset exceeds size\n"); die("ovni_load_next_event: stream offset exceeds size\n");
/* We have reached the end */ /* We have reached the end */
if(stream->offset == stream->size) if (stream->offset == stream->size) {
{
stream->active = 0; stream->active = 0;
stream->cur_ev = NULL; stream->cur_ev = NULL;
dbg("stream %d runs out of events\n", stream->tid); dbg("stream %d runs out of events\n", stream->tid);

View File

@ -4,8 +4,8 @@
#ifndef OVNI_TRACE_H #ifndef OVNI_TRACE_H
#define OVNI_TRACE_H #define OVNI_TRACE_H
#include "ovni.h"
#include "emu.h" #include "emu.h"
#include "ovni.h"
int ovni_load_next_event(struct ovni_stream *stream); int ovni_load_next_event(struct ovni_stream *stream);

1853
uthash.h

File diff suppressed because it is too large Load Diff

1795
utlist.h

File diff suppressed because it is too large Load Diff