Read clock offsets in emu_system
This commit is contained in:
parent
183df35459
commit
e1880e09f6
@ -176,6 +176,21 @@ find_loom(struct emu_system *sys, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_loom_hostname(char host[PATH_MAX], const char loom_name[PATH_MAX])
|
||||||
|
{
|
||||||
|
/* Copy until dot or end */
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < PATH_MAX - 1; i++) {
|
||||||
|
if (loom_name[i] == '.' || loom_name[i] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
host[i] = loom_name[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
host[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
static struct emu_loom *
|
static struct emu_loom *
|
||||||
new_loom(const char *tracedir, const char *name)
|
new_loom(const char *tracedir, const char *name)
|
||||||
{
|
{
|
||||||
@ -193,6 +208,8 @@ new_loom(const char *tracedir, const char *name)
|
|||||||
if (snprintf(loom->path, PATH_MAX, "%s/%s", tracedir, loom->relpath) >= PATH_MAX)
|
if (snprintf(loom->path, PATH_MAX, "%s/%s", tracedir, loom->relpath) >= PATH_MAX)
|
||||||
die("new_loom: path too long: %s/%s\n", tracedir, loom->relpath);
|
die("new_loom: path too long: %s/%s\n", tracedir, loom->relpath);
|
||||||
|
|
||||||
|
set_loom_hostname(loom->hostname, loom->name);
|
||||||
|
|
||||||
err("new loom '%s'\n", loom->name);
|
err("new loom '%s'\n", loom->name);
|
||||||
|
|
||||||
return loom;
|
return loom;
|
||||||
@ -212,7 +229,7 @@ create_loom(struct emu_system *sys, const char *tracedir, const char *relpath)
|
|||||||
relpath);
|
relpath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_loom *loom = find_loom(sys, name);
|
struct emu_loom *loom = find_loom(sys, name);
|
||||||
|
|
||||||
if (loom == NULL) {
|
if (loom == NULL) {
|
||||||
@ -225,7 +242,7 @@ create_loom(struct emu_system *sys, const char *tracedir, const char *relpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_system(struct emu_system *sys, struct emu_trace *trace)
|
create_lpt(struct emu_system *sys, struct emu_trace *trace)
|
||||||
{
|
{
|
||||||
const char *dir = trace->tracedir;
|
const char *dir = trace->tracedir;
|
||||||
for (struct emu_stream *s = trace->streams; s ; s = s->next) {
|
for (struct emu_stream *s = trace->streams; s ; s = s->next) {
|
||||||
@ -237,20 +254,20 @@ create_system(struct emu_system *sys, struct emu_trace *trace)
|
|||||||
|
|
||||||
struct emu_loom *loom = create_loom(sys, dir, s->relpath);
|
struct emu_loom *loom = create_loom(sys, dir, s->relpath);
|
||||||
if (loom == NULL) {
|
if (loom == NULL) {
|
||||||
err("create_system: create_loom failed\n");
|
err("create_lpt: create_loom failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_proc *proc = create_proc(loom, dir, s->relpath);
|
struct emu_proc *proc = create_proc(loom, dir, s->relpath);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
err("create_system: create_proc failed\n");
|
err("create_lpt: create_proc failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The thread sets the stream */
|
/* The thread sets the stream */
|
||||||
struct emu_thread *thread = create_thread(proc, dir, s);
|
struct emu_thread *thread = create_thread(proc, dir, s);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
err("create_system: create_thread failed\n");
|
err("create_lpt: create_thread failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,7 +309,7 @@ cmp_loom(struct emu_loom *a, struct emu_loom *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sort_system(struct emu_system *sys)
|
sort_lpt(struct emu_system *sys)
|
||||||
{
|
{
|
||||||
DL_SORT(sys->looms, cmp_loom);
|
DL_SORT(sys->looms, cmp_loom);
|
||||||
|
|
||||||
@ -724,30 +741,148 @@ link_streams_to_threads(struct emu_system *sys)
|
|||||||
emu_stream_data_set(th->stream, th);
|
emu_stream_data_set(th->stream, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
emu_system_load(struct emu_system *sys, struct emu_trace *trace)
|
load_clock_offsets(struct clkoff *clkoff, struct emu_args *args)
|
||||||
{
|
{
|
||||||
/* Parse the emu_trace and create the looms, procs and threads */
|
const char *tracedir = args->tracedir;
|
||||||
if (create_system(sys, trace) != 0) {
|
char def_file[PATH_MAX];
|
||||||
err("emu_system_load: create system failed\n");
|
char def_name[] = "clock-offsets.txt";
|
||||||
|
|
||||||
|
clkoff_init(clkoff);
|
||||||
|
|
||||||
|
if (snprintf(def_file, PATH_MAX, "%s/%s",
|
||||||
|
tracedir, def_name) >= PATH_MAX) {
|
||||||
|
err("load_clock_offsets: path too long\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *offset_file = args->clock_offset_file;
|
||||||
|
int is_optional = 0;
|
||||||
|
|
||||||
|
/* Use the default path if not given */
|
||||||
|
if (offset_file == NULL) {
|
||||||
|
offset_file = def_file;
|
||||||
|
is_optional = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = fopen(offset_file, "r");
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
if (is_optional) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err("load_clock_offsets: fopen %s failed: %s\n",
|
||||||
|
offset_file, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clkoff_load(clkoff, f) != 0) {
|
||||||
|
err("load_clock_offsets: clkoff_load failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
err("loaded clock offset table from '%s' with %d entries\n",
|
||||||
|
offset_file, clkoff_count(clkoff));
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_clkoff_entry(struct emu_loom *looms, struct clkoff_entry *entry)
|
||||||
|
{
|
||||||
|
size_t matches = 0;
|
||||||
|
|
||||||
|
/* Use the median as the offset */
|
||||||
|
size_t offset = entry->median;
|
||||||
|
const char *host = entry->name;
|
||||||
|
|
||||||
|
struct emu_loom *loom;
|
||||||
|
DL_FOREACH(looms, loom) {
|
||||||
|
/* Match the hostname exactly */
|
||||||
|
if (strcmp(loom->hostname, host) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (loom->clock_offset != 0) {
|
||||||
|
err("parse_clkoff_entry: loom %s already has a clock offset\n",
|
||||||
|
loom->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
loom->clock_offset = offset;
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches == 0) {
|
||||||
|
err("parse_clkoff_entry: cannot find any loom with hostname '%s'\n",
|
||||||
|
host);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_offsets(struct emu_system *sys)
|
||||||
|
{
|
||||||
|
struct clkoff *table = &sys->clkoff;
|
||||||
|
int n = clkoff_count(table);
|
||||||
|
|
||||||
|
/* If we have more than one hostname and no offset table has been found,
|
||||||
|
* we won't be able to synchronize the clocks */
|
||||||
|
if (n == 0 && sys->nlooms > 1) {
|
||||||
|
err("warning: no clock offset file loaded with %ld looms\n",
|
||||||
|
sys->nlooms);
|
||||||
|
|
||||||
|
if (sys->args->linter_mode)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
struct clkoff_entry *entry = clkoff_get(table, i);
|
||||||
|
if (parse_clkoff_entry(sys->looms, entry) != 0) {
|
||||||
|
err("init_offsets: cannot parse clock offset entry %d\n", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the stream clock offsets too */
|
||||||
|
struct emu_thread *thread;
|
||||||
|
DL_FOREACH2(sys->threads, thread, gnext) {
|
||||||
|
struct emu_loom *loom = thread->proc->loom;
|
||||||
|
emu_stream_clkoff(thread->stream, loom->clock_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
emu_system_init(struct emu_system *sys, struct emu_args *args, struct emu_trace *trace)
|
||||||
|
{
|
||||||
|
memset(sys, 0, sizeof(struct emu_system));
|
||||||
|
sys->args = args;
|
||||||
|
|
||||||
|
/* Parse the trace and create the looms, procs and threads */
|
||||||
|
if (create_lpt(sys, trace) != 0) {
|
||||||
|
err("emu_system_init: create system failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure they are sorted so they are easier to read */
|
/* Ensure they are sorted so they are easier to read */
|
||||||
sort_system(sys);
|
sort_lpt(sys);
|
||||||
|
|
||||||
/* Init global lists build after sorting */
|
/* Init global lists after sorting */
|
||||||
init_global_lpt_lists(sys);
|
init_global_lpt_lists(sys);
|
||||||
|
|
||||||
/* Now load all process metadata and set attributes */
|
/* Now load all process metadata and set attributes */
|
||||||
if (load_metadata(sys) != 0) {
|
if (load_metadata(sys) != 0) {
|
||||||
err("emu_system_load: load_metadata() failed\n");
|
err("emu_system_init: load_metadata() failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* From the metadata extract the CPUs too */
|
/* From the metadata extract the CPUs too */
|
||||||
if (init_cpus(sys) != 0) {
|
if (init_cpus(sys) != 0) {
|
||||||
err("emu_system_load: load_cpus() failed\n");
|
err("emu_system_init: load_cpus() failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,13 +891,27 @@ emu_system_load(struct emu_system *sys, struct emu_trace *trace)
|
|||||||
/* Now that we have loaded all resources, populate the indices */
|
/* Now that we have loaded all resources, populate the indices */
|
||||||
init_global_indices(sys);
|
init_global_indices(sys);
|
||||||
|
|
||||||
|
/* Set CPU names like "CPU 1.34" */
|
||||||
if (init_cpu_names(sys) != 0) {
|
if (init_cpu_names(sys) != 0) {
|
||||||
err("emu_system_load: init_cpu_names() failed\n");
|
err("emu_system_init: init_cpu_names() failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need to retrieve the thread from the stream too */
|
||||||
link_streams_to_threads(sys);
|
link_streams_to_threads(sys);
|
||||||
|
|
||||||
|
/* Load the clock offsets table */
|
||||||
|
if (load_clock_offsets(&sys->clkoff, args) != 0) {
|
||||||
|
err("emu_system_init: load_clock_offsets() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the offsets of the looms and streams */
|
||||||
|
if (init_offsets(sys) != 0) {
|
||||||
|
err("emu_system_init: init_offsets() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finaly dump the system */
|
/* Finaly dump the system */
|
||||||
print_system(sys);
|
print_system(sys);
|
||||||
|
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
#ifndef EMU_SYSTEM_H
|
#ifndef EMU_SYSTEM_H
|
||||||
#define EMU_SYSTEM_H
|
#define EMU_SYSTEM_H
|
||||||
|
|
||||||
|
#include "emu_args.h"
|
||||||
#include "emu_trace.h"
|
#include "emu_trace.h"
|
||||||
|
#include "emu_stream.h"
|
||||||
#include "parson.h"
|
#include "parson.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
|
#include "clkoff.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define MAX_CPU_NAME 32
|
#define MAX_CPU_NAME 32
|
||||||
@ -146,8 +149,7 @@ struct emu_loom {
|
|||||||
char name[PATH_MAX]; /* Loom directory name */
|
char name[PATH_MAX]; /* Loom directory name */
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
char relpath[PATH_MAX]; /* Relative to tracedir */
|
char relpath[PATH_MAX]; /* Relative to tracedir */
|
||||||
|
char hostname[PATH_MAX];
|
||||||
char hostname[OVNI_MAX_HOSTNAME];
|
|
||||||
|
|
||||||
size_t max_ncpus;
|
size_t max_ncpus;
|
||||||
size_t max_phyid;
|
size_t max_phyid;
|
||||||
@ -189,10 +191,13 @@ struct emu_system {
|
|||||||
struct emu_proc *cur_proc;
|
struct emu_proc *cur_proc;
|
||||||
struct emu_thread *cur_thread;
|
struct emu_thread *cur_thread;
|
||||||
|
|
||||||
|
struct clkoff clkoff;
|
||||||
|
struct emu_args *args;
|
||||||
|
|
||||||
struct model_ctx ctx;
|
struct model_ctx ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
int emu_system_load(struct emu_system *system, struct emu_trace *trace);
|
int emu_system_init(struct emu_system *sys, struct emu_args *args, struct emu_trace *trace);
|
||||||
|
|
||||||
int model_ctx_set(struct model_ctx *ctx, int model, void *data);
|
int model_ctx_set(struct model_ctx *ctx, int model, void *data);
|
||||||
int model_ctx_get(struct model_ctx *ctx, int model, void *data);
|
int model_ctx_get(struct model_ctx *ctx, int model, void *data);
|
||||||
|
Loading…
Reference in New Issue
Block a user