Add loom and proc
This commit is contained in:
parent
f5db3a9814
commit
12bfd3fe26
@ -14,10 +14,14 @@ include_directories(
|
|||||||
add_library(emu STATIC
|
add_library(emu STATIC
|
||||||
../common.c
|
../common.c
|
||||||
cpu.c
|
cpu.c
|
||||||
|
loom.c
|
||||||
|
proc.c
|
||||||
thread.c
|
thread.c
|
||||||
|
path.c
|
||||||
|
metadata.c
|
||||||
emu.c
|
emu.c
|
||||||
emu_system.c
|
#emu_system.c
|
||||||
emu_system_thread.c
|
#emu_system_thread.c
|
||||||
emu_args.c
|
emu_args.c
|
||||||
emu_stream.c
|
emu_stream.c
|
||||||
emu_trace.c
|
emu_trace.c
|
||||||
@ -29,10 +33,10 @@ add_library(emu STATIC
|
|||||||
mux.c
|
mux.c
|
||||||
prv.c
|
prv.c
|
||||||
clkoff.c
|
clkoff.c
|
||||||
ovni/probe.c
|
#ovni/probe.c
|
||||||
ovni/create.c
|
#ovni/create.c
|
||||||
ovni/connect.c
|
#ovni/connect.c
|
||||||
ovni/event.c
|
#ovni/event.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(ovni)
|
add_subdirectory(ovni)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "chan.h"
|
#include "chan.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...)
|
chan_init(struct chan *chan, enum chan_type type, const char *fmt, ...)
|
||||||
|
@ -8,13 +8,17 @@
|
|||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
cpu_init(struct cpu *cpu, int i, int phyid, int is_virtual)
|
cpu_init(struct cpu *cpu, int phyid)
|
||||||
{
|
{
|
||||||
memset(cpu, 0, sizeof(struct cpu));
|
memset(cpu, 0, sizeof(struct cpu));
|
||||||
|
|
||||||
cpu->i = i;
|
|
||||||
cpu->phyid = phyid;
|
cpu->phyid = phyid;
|
||||||
cpu->is_virtual = is_virtual;
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cpu_get_phyid(struct cpu *cpu)
|
||||||
|
{
|
||||||
|
return cpu->phyid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -24,17 +28,10 @@ cpu_set_gindex(struct cpu *cpu, int64_t gindex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cpu_set_name(struct cpu *cpu, int64_t loom)
|
cpu_set_name(struct cpu *cpu, const char *name)
|
||||||
{
|
{
|
||||||
int n;
|
if (snprintf(cpu->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
||||||
if (cpu->is_virtual)
|
die("cpu name too long");
|
||||||
n = snprintf(cpu->name, PATH_MAX, "vCPU %ld.*", loom);
|
|
||||||
else
|
|
||||||
n = snprintf(cpu->name, PATH_MAX, "CPU %ld.%d", loom, cpu->i);
|
|
||||||
|
|
||||||
/* Unlikely */
|
|
||||||
if (n >= PATH_MAX)
|
|
||||||
die("cpu_set_name: cpu name too long\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct thread *
|
static struct thread *
|
||||||
|
@ -6,9 +6,10 @@
|
|||||||
|
|
||||||
struct cpu;
|
struct cpu;
|
||||||
|
|
||||||
#include "loom.h"
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "chan.h"
|
#include "chan.h"
|
||||||
|
#include "uthash.h"
|
||||||
|
#include <linux/limits.h>
|
||||||
|
|
||||||
struct cpu_chan {
|
struct cpu_chan {
|
||||||
struct chan pid_running;
|
struct chan pid_running;
|
||||||
@ -21,7 +22,7 @@ struct cpu {
|
|||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
|
|
||||||
/* Logical index: 0 to ncpus - 1 */
|
/* Logical index: 0 to ncpus - 1 */
|
||||||
int i;
|
//int index;
|
||||||
|
|
||||||
/* Physical id: as reported by lscpu(1) */
|
/* Physical id: as reported by lscpu(1) */
|
||||||
int phyid;
|
int phyid;
|
||||||
@ -35,6 +36,10 @@ struct cpu {
|
|||||||
|
|
||||||
int is_virtual;
|
int is_virtual;
|
||||||
|
|
||||||
|
/* Loom list sorted by phyid */
|
||||||
|
struct cpu *lnext;
|
||||||
|
struct cpu *lprev;
|
||||||
|
|
||||||
/* Global list */
|
/* Global list */
|
||||||
struct cpu *next;
|
struct cpu *next;
|
||||||
struct cpu *prev;
|
struct cpu *prev;
|
||||||
@ -43,11 +48,15 @@ struct cpu {
|
|||||||
struct cpu_chan chan;
|
struct cpu_chan chan;
|
||||||
|
|
||||||
//struct model_ctx ctx;
|
//struct model_ctx ctx;
|
||||||
|
|
||||||
|
UT_hash_handle hh; /* CPUs in the loom */
|
||||||
};
|
};
|
||||||
|
|
||||||
void cpu_init(struct cpu *cpu, int i, int phyid, int is_virtual);
|
void cpu_init(struct cpu *cpu, int phyid);
|
||||||
|
int cpu_get_phyid(struct cpu *cpu);
|
||||||
|
//int cpu_get_index(struct cpu *cpu);
|
||||||
void cpu_set_gindex(struct cpu *cpu, int64_t gindex);
|
void cpu_set_gindex(struct cpu *cpu, int64_t gindex);
|
||||||
void cpu_set_name(struct cpu *cpu, int64_t loom);
|
void cpu_set_name(struct cpu *cpu, const char *name);
|
||||||
int cpu_add_thread(struct cpu *cpu, struct thread *thread);
|
int cpu_add_thread(struct cpu *cpu, struct thread *thread);
|
||||||
|
|
||||||
#endif /* CPU_H */
|
#endif /* CPU_H */
|
||||||
|
@ -22,39 +22,39 @@ emu_init(struct emu *emu, int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the trace and build the emu_system */
|
// /* Parse the trace and build the emu_system */
|
||||||
if (emu_system_init(&emu->system, &emu->args, &emu->trace) != 0) {
|
// if (emu_system_init(&emu->system, &emu->args, &emu->trace) != 0) {
|
||||||
err("emu_init: cannot init system for trace '%s'\n",
|
// err("emu_init: cannot init system for trace '%s'\n",
|
||||||
emu->args.tracedir);
|
// emu->args.tracedir);
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (emu_player_init(&emu->player, &emu->trace) != 0) {
|
// if (emu_player_init(&emu->player, &emu->trace) != 0) {
|
||||||
err("emu_init: cannot init player for trace '%s'\n",
|
// err("emu_init: cannot init player for trace '%s'\n",
|
||||||
emu->args.tracedir);
|
// emu->args.tracedir);
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/* Initialize the bay */
|
// /* Initialize the bay */
|
||||||
bay_init(&emu->bay);
|
// bay_init(&emu->bay);
|
||||||
|
//
|
||||||
/* Register all the models */
|
// /* Register all the models */
|
||||||
emu_model_register(&emu->model, &ovni_model_spec, emu);
|
// emu_model_register(&emu->model, &ovni_model_spec, emu);
|
||||||
|
//
|
||||||
if (ovni_model_spec.probe(emu) != 0) {
|
// if (ovni_model_spec.probe(emu) != 0) {
|
||||||
err("emu_init: ovni probe failed\n");
|
// err("emu_init: ovni probe failed\n");
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (ovni_model_spec.create(emu) != 0) {
|
// if (ovni_model_spec.create(emu) != 0) {
|
||||||
err("emu_init: ovni create failed\n");
|
// err("emu_init: ovni create failed\n");
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (ovni_model_spec.connect(emu) != 0) {
|
// if (ovni_model_spec.connect(emu) != 0) {
|
||||||
err("emu_init: ovni connect failed\n");
|
// err("emu_init: ovni connect failed\n");
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -74,17 +74,17 @@ emu_step(struct emu *emu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
emu->ev = emu_player_ev(&emu->player);
|
// emu->ev = emu_player_ev(&emu->player);
|
||||||
emu->stream = emu_player_stream(&emu->player);
|
// emu->stream = emu_player_stream(&emu->player);
|
||||||
emu->thread = emu_system_get_thread(emu->stream);
|
// emu->thread = emu_system_get_thread(emu->stream);
|
||||||
emu->proc = emu->thread->proc;
|
// emu->proc = emu->thread->proc;
|
||||||
emu->loom = emu->proc->loom;
|
// emu->loom = emu->proc->loom;
|
||||||
|
//
|
||||||
/* Otherwise progress */
|
// /* Otherwise progress */
|
||||||
if (ovni_model_spec.event(emu) != 0) {
|
// if (ovni_model_spec.event(emu) != 0) {
|
||||||
err("emu_init: ovni event failed\n");
|
// err("emu_init: ovni event failed\n");
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,169 +0,0 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
||||||
|
|
||||||
#ifndef EMU_SYSTEM_H
|
|
||||||
#define EMU_SYSTEM_H
|
|
||||||
|
|
||||||
#include "emu_args.h"
|
|
||||||
#include "emu_trace.h"
|
|
||||||
#include "emu_stream.h"
|
|
||||||
#include "parson.h"
|
|
||||||
#include "ovni.h"
|
|
||||||
#include "clkoff.h"
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define MAX_CPU_NAME 32
|
|
||||||
|
|
||||||
struct emu_cpu;
|
|
||||||
struct emu_thread;
|
|
||||||
struct emu_proc;
|
|
||||||
struct emu_loom;
|
|
||||||
struct emu_system;
|
|
||||||
|
|
||||||
#define MAX_MODELS 256
|
|
||||||
|
|
||||||
struct model_ctx {
|
|
||||||
void *data[MAX_MODELS];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Emulated thread runtime status */
|
|
||||||
enum emu_thread_state {
|
|
||||||
TH_ST_UNKNOWN,
|
|
||||||
TH_ST_RUNNING,
|
|
||||||
TH_ST_PAUSED,
|
|
||||||
TH_ST_DEAD,
|
|
||||||
TH_ST_COOLING,
|
|
||||||
TH_ST_WARMING,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct emu_thread {
|
|
||||||
size_t gindex; /* In the system */
|
|
||||||
|
|
||||||
char name[PATH_MAX];
|
|
||||||
char path[PATH_MAX];
|
|
||||||
char relpath[PATH_MAX];
|
|
||||||
|
|
||||||
int tid;
|
|
||||||
int index; /* In loom */
|
|
||||||
|
|
||||||
/* The process associated with this thread */
|
|
||||||
struct emu_proc *proc;
|
|
||||||
|
|
||||||
enum emu_thread_state state;
|
|
||||||
int is_running;
|
|
||||||
int is_active;
|
|
||||||
|
|
||||||
/* Stream linked to this thread */
|
|
||||||
struct emu_stream *stream;
|
|
||||||
|
|
||||||
/* Current cpu, NULL if not unique affinity */
|
|
||||||
struct emu_cpu *cpu;
|
|
||||||
|
|
||||||
/* Linked list of threads in each CPU */
|
|
||||||
struct emu_thread *cpu_prev;
|
|
||||||
struct emu_thread *cpu_next;
|
|
||||||
|
|
||||||
/* Local list */
|
|
||||||
struct emu_thread *lprev;
|
|
||||||
struct emu_thread *lnext;
|
|
||||||
|
|
||||||
/* Global list */
|
|
||||||
struct emu_thread *gnext;
|
|
||||||
struct emu_thread *gprev;
|
|
||||||
|
|
||||||
struct model_ctx ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* State of each emulated process */
|
|
||||||
struct emu_proc {
|
|
||||||
size_t gindex;
|
|
||||||
|
|
||||||
char name[PATH_MAX]; /* Proc directory name */
|
|
||||||
char path[PATH_MAX];
|
|
||||||
char relpath[PATH_MAX];
|
|
||||||
|
|
||||||
int pid;
|
|
||||||
int index;
|
|
||||||
int appid;
|
|
||||||
int rank;
|
|
||||||
|
|
||||||
struct emu_loom *loom;
|
|
||||||
|
|
||||||
JSON_Value *meta;
|
|
||||||
|
|
||||||
int nthreads;
|
|
||||||
struct emu_thread *threads;
|
|
||||||
|
|
||||||
/* Local list */
|
|
||||||
struct emu_proc *lnext;
|
|
||||||
struct emu_proc *lprev;
|
|
||||||
|
|
||||||
/* Global list */
|
|
||||||
struct emu_proc *gnext;
|
|
||||||
struct emu_proc *gprev;
|
|
||||||
|
|
||||||
struct model_ctx ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct emu_loom {
|
|
||||||
size_t gindex;
|
|
||||||
|
|
||||||
char name[PATH_MAX]; /* Loom directory name */
|
|
||||||
char path[PATH_MAX];
|
|
||||||
char relpath[PATH_MAX]; /* Relative to tracedir */
|
|
||||||
char hostname[PATH_MAX];
|
|
||||||
|
|
||||||
size_t max_ncpus;
|
|
||||||
size_t max_phyid;
|
|
||||||
size_t ncpus;
|
|
||||||
size_t offset_ncpus;
|
|
||||||
struct emu_cpu *cpu;
|
|
||||||
int rank_enabled;
|
|
||||||
|
|
||||||
int64_t clock_offset;
|
|
||||||
|
|
||||||
/* Virtual CPU */
|
|
||||||
struct emu_cpu *vcpu;
|
|
||||||
|
|
||||||
/* Local list */
|
|
||||||
size_t nprocs;
|
|
||||||
struct emu_proc *procs;
|
|
||||||
|
|
||||||
/* Global list */
|
|
||||||
struct emu_loom *next;
|
|
||||||
struct emu_loom *prev;
|
|
||||||
|
|
||||||
struct model_ctx ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct emu_system {
|
|
||||||
/* Total counters */
|
|
||||||
size_t nlooms;
|
|
||||||
size_t nthreads;
|
|
||||||
size_t nprocs;
|
|
||||||
size_t ncpus; /* Physical */
|
|
||||||
|
|
||||||
struct emu_loom *looms;
|
|
||||||
struct emu_proc *procs;
|
|
||||||
struct emu_thread *threads;
|
|
||||||
struct emu_cpu *cpus;
|
|
||||||
|
|
||||||
/* From current event */
|
|
||||||
struct emu_loom *cur_loom;
|
|
||||||
struct emu_proc *cur_proc;
|
|
||||||
struct emu_thread *cur_thread;
|
|
||||||
|
|
||||||
struct clkoff clkoff;
|
|
||||||
struct emu_args *args;
|
|
||||||
|
|
||||||
struct model_ctx ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
int emu_system_init(struct emu_system *sys, struct emu_args *args, struct emu_trace *trace);
|
|
||||||
struct emu_thread *emu_system_get_thread(struct emu_stream *stream);
|
|
||||||
struct emu_cpu *emu_system_find_cpu(struct emu_loom *loom, int cpuid);
|
|
||||||
|
|
||||||
int model_ctx_set(struct model_ctx *ctx, int model, void *data);
|
|
||||||
int model_ctx_get(struct model_ctx *ctx, int model, void *data);
|
|
||||||
|
|
||||||
#endif /* EMU_SYSTEM_H */
|
|
164
src/emu/loom.c
164
src/emu/loom.c
@ -3,10 +3,68 @@
|
|||||||
|
|
||||||
#include "loom.h"
|
#include "loom.h"
|
||||||
|
|
||||||
void
|
#include <string.h>
|
||||||
loom_init(struct loom *loom)
|
#include "cpu.h"
|
||||||
|
#include "proc.h"
|
||||||
|
#include "uthash.h"
|
||||||
|
#include "utlist.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_hostname(char host[PATH_MAX], const char name[PATH_MAX])
|
||||||
|
{
|
||||||
|
/* Copy until dot or end */
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < PATH_MAX - 1; i++) {
|
||||||
|
if (name[i] == '.' || name[i] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
host[i] = name[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
host[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
has_prefix(const char *path, const char *prefix)
|
||||||
|
{
|
||||||
|
if (strncmp(path, prefix, strlen(prefix)) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loom_matches(const char *path)
|
||||||
|
{
|
||||||
|
return has_prefix(path, "loom.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loom_init_begin(struct loom *loom, const char *name)
|
||||||
{
|
{
|
||||||
memset(loom, 0, sizeof(struct loom));
|
memset(loom, 0, sizeof(struct loom));
|
||||||
|
|
||||||
|
char prefix[] = "loom.";
|
||||||
|
if (!has_prefix(name, prefix)) {
|
||||||
|
err("loom name must start with '%s': %s", prefix, name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr(name, '/') != NULL) {
|
||||||
|
err("loom name cannot contain '/': %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(loom->name, PATH_MAX, "%s", name) >= PATH_MAX) {
|
||||||
|
err("name too long: %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_hostname(loom->hostname, loom->name);
|
||||||
|
loom->id = loom->name;
|
||||||
|
loom->is_ready = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -15,11 +73,42 @@ loom_set_gindex(struct loom *loom, int64_t gindex)
|
|||||||
loom->gindex = gindex;
|
loom->gindex = gindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
struct cpu *
|
||||||
loom_set_cpus(struct loom *loom, struct cpu *cpus, size_t ncpus)
|
loom_find_cpu(struct loom *loom, int phyid)
|
||||||
{
|
{
|
||||||
loom->ncpus = ncpus;
|
if (phyid == -1)
|
||||||
loom->cpu = cpus;
|
return loom->vcpu;
|
||||||
|
|
||||||
|
struct cpu *cpu = NULL;
|
||||||
|
HASH_FIND_INT(loom->cpus, &phyid, cpu);
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loom_add_cpu(struct loom *loom, struct cpu *cpu)
|
||||||
|
{
|
||||||
|
int phyid = cpu_get_phyid(cpu);
|
||||||
|
|
||||||
|
if (phyid < 0) {
|
||||||
|
err("cannot use negative cpu phyid %d", phyid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loom_find_cpu(loom, phyid) != NULL) {
|
||||||
|
err("cpu with phyid %d already in loom", phyid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loom->is_ready) {
|
||||||
|
err("cannot modify CPUs of ready loom");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HASH_ADD_INT(loom->cpus, phyid, cpu);
|
||||||
|
//DL_SORT2(loom->cpus, cmp_cpus, lprev, lnext); // Maybe?
|
||||||
|
loom->ncpus++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -28,12 +117,65 @@ loom_set_vcpu(struct loom *loom, struct cpu *vcpu)
|
|||||||
loom->vcpu = vcpu;
|
loom->vcpu = vcpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_proc *
|
static int
|
||||||
loom_find_proc(struct emu_loom *loom, pid_t pid)
|
cmp_cpus(struct cpu *c1, struct cpu *c2)
|
||||||
{
|
{
|
||||||
for (struct emu_proc *proc = loom->procs; proc; proc = proc->lnext) {
|
int id1 = cpu_get_phyid(c1);
|
||||||
if (proc->pid == pid)
|
int id2 = cpu_get_phyid(c2);
|
||||||
|
|
||||||
|
if (id1 < id2)
|
||||||
|
return -1;
|
||||||
|
if (id1 > id2)
|
||||||
|
return +1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
loom_init_end(struct loom *loom)
|
||||||
|
{
|
||||||
|
/* Sort CPUs by phyid */
|
||||||
|
DL_SORT2(loom->scpus, cmp_cpus, lprev, lnext);
|
||||||
|
|
||||||
|
/* Set rank enabled */
|
||||||
|
for (struct proc *p = loom->procs; p; p = p->hh.next) {
|
||||||
|
if (p->rank >= 0) {
|
||||||
|
loom->rank_enabled = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loom->is_ready = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct proc *
|
||||||
|
loom_find_proc(struct loom *loom, int pid)
|
||||||
|
{
|
||||||
|
struct proc *proc = NULL;
|
||||||
|
HASH_FIND_INT(loom->procs, &pid, proc);
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
|
int
|
||||||
|
loom_add_proc(struct loom *loom, struct proc *proc)
|
||||||
|
{
|
||||||
|
int pid = proc_get_pid(proc);
|
||||||
|
|
||||||
|
if (loom_find_proc(loom, pid) != NULL) {
|
||||||
|
err("proc with pid %d already in loom", pid);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loom->is_ready) {
|
||||||
|
err("cannot modify procs of ready loom");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HASH_ADD_INT(loom->procs, pid, proc);
|
||||||
|
loom->nprocs++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -9,24 +9,30 @@ struct loom;
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
struct loom {
|
struct loom {
|
||||||
size_t gindex;
|
size_t gindex;
|
||||||
|
int is_ready;
|
||||||
|
|
||||||
char name[PATH_MAX]; /* Loom directory name */
|
char name[PATH_MAX];
|
||||||
char path[PATH_MAX];
|
|
||||||
char relpath[PATH_MAX]; /* Relative to tracedir */
|
|
||||||
char hostname[PATH_MAX];
|
char hostname[PATH_MAX];
|
||||||
|
char *id;
|
||||||
|
|
||||||
size_t max_ncpus;
|
size_t max_ncpus;
|
||||||
size_t max_phyid;
|
size_t max_phyid;
|
||||||
size_t ncpus;
|
size_t ncpus;
|
||||||
size_t offset_ncpus;
|
size_t offset_ncpus;
|
||||||
struct cpu *cpu;
|
|
||||||
int rank_enabled;
|
int rank_enabled;
|
||||||
|
|
||||||
int64_t clock_offset;
|
int64_t clock_offset;
|
||||||
|
|
||||||
|
/* Sorted double linked list of CPUs by phyid */
|
||||||
|
struct cpu *scpus;
|
||||||
|
|
||||||
|
/* Physical CPUs hash table by phyid */
|
||||||
|
struct cpu *cpus;
|
||||||
|
|
||||||
/* Virtual CPU */
|
/* Virtual CPU */
|
||||||
struct cpu *vcpu;
|
struct cpu *vcpu;
|
||||||
|
|
||||||
@ -41,6 +47,14 @@ struct loom {
|
|||||||
//struct model_ctx ctx;
|
//struct model_ctx ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
void loom_init(struct loom *loom);
|
int loom_matches(const char *relpath);
|
||||||
|
int loom_init_begin(struct loom *loom, const char *name);
|
||||||
|
int loom_init_end(struct loom *loom);
|
||||||
|
int loom_add_cpu(struct loom *loom, struct cpu *cpu);
|
||||||
|
void loom_set_gindex(struct loom *loom, int64_t gindex);
|
||||||
|
struct cpu *loom_find_cpu(struct loom *loom, int phyid);
|
||||||
|
void loom_set_vcpu(struct loom *loom, struct cpu *vcpu);
|
||||||
|
struct proc *loom_find_proc(struct loom *loom, pid_t pid);
|
||||||
|
int loom_add_proc(struct loom *loom, struct proc *proc);
|
||||||
|
|
||||||
#endif /* LOOM_H */
|
#endif /* LOOM_H */
|
||||||
|
144
src/emu/metadata.c
Normal file
144
src/emu/metadata.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
#include "parson.h"
|
||||||
|
|
||||||
|
static JSON_Object *
|
||||||
|
load_json(const char *path)
|
||||||
|
{
|
||||||
|
JSON_Value *vmeta = json_parse_file_with_comments(path);
|
||||||
|
if (vmeta == NULL) {
|
||||||
|
err("json_parse_file_with_comments() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Object *meta = json_value_get_object(vmeta);
|
||||||
|
if (meta == NULL) {
|
||||||
|
err("json_value_get_object() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_version(JSON_Object *meta)
|
||||||
|
{
|
||||||
|
JSON_Value *version_val = json_object_get_value(meta, "version");
|
||||||
|
if (version_val == NULL) {
|
||||||
|
err("missing attribute \"version\"");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = (int) json_number(version_val);
|
||||||
|
|
||||||
|
if (version != OVNI_METADATA_VERSION) {
|
||||||
|
err("metadata version mismatch %d (expected %d)",
|
||||||
|
version, OVNI_METADATA_VERSION);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Value *mversion_val = json_object_get_value(meta, "model_version");
|
||||||
|
if (mversion_val == NULL) {
|
||||||
|
err("missing attribute \"model_version\"");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mversion = json_string(mversion_val);
|
||||||
|
if (strcmp(mversion, OVNI_MODEL_VERSION) != 0) {
|
||||||
|
err("model version mismatch '%s' (expected '%s')",
|
||||||
|
mversion, OVNI_MODEL_VERSION);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
has_cpus(JSON_Object *meta)
|
||||||
|
{
|
||||||
|
/* Only check for the "cpus" key, if it has zero elements is an error
|
||||||
|
* that will be reported later */
|
||||||
|
if (json_object_get_array(meta, "cpus") != NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_cpus(struct loom *loom, JSON_Object *meta)
|
||||||
|
{
|
||||||
|
JSON_Array *cpuarray = json_object_get_array(meta, "cpus");
|
||||||
|
if (cpuarray == NULL) {
|
||||||
|
err("cannot find 'cpus' array");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ncpus = json_array_get_count(cpuarray);
|
||||||
|
if (ncpus == 0) {
|
||||||
|
err("empty 'cpus' array in metadata");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loom->ncpus > 0) {
|
||||||
|
err("loom %s already has cpus", loom->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ncpus; i++) {
|
||||||
|
JSON_Object *jcpu = json_array_get_object(cpuarray, i);
|
||||||
|
if (jcpu == NULL) {
|
||||||
|
err("json_array_get_object() failed for cpu");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cast from double */
|
||||||
|
//int index = (int) json_object_get_number(jcpu, "index");
|
||||||
|
int phyid = (int) json_object_get_number(jcpu, "phyid");
|
||||||
|
|
||||||
|
struct cpu *cpu = calloc(1, sizeof(struct cpu));
|
||||||
|
if (cpu == NULL) {
|
||||||
|
err("calloc failed:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_init(cpu, phyid);
|
||||||
|
|
||||||
|
if (loom_add_cpu(loom, cpu) != 0) {
|
||||||
|
err("loom_add_cpu() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
metadata_load(const char *path, struct loom *loom, struct proc *proc)
|
||||||
|
{
|
||||||
|
JSON_Object *meta = load_json(path);
|
||||||
|
if (meta == NULL) {
|
||||||
|
err("cannot load metadata from file %s", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_version(meta) != 0) {
|
||||||
|
err("version check failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The appid is populated from the metadata */
|
||||||
|
if (proc_load_metadata(proc, meta) != 0) {
|
||||||
|
err("cannot load process attributes");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_cpus(meta) && load_cpus(loom, meta) != 0) {
|
||||||
|
err("cannot load loom cpus");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
12
src/emu/metadata.h
Normal file
12
src/emu/metadata.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#ifndef METADATA_H
|
||||||
|
#define METADATA_H
|
||||||
|
|
||||||
|
#include "loom.h"
|
||||||
|
#include "proc.h"
|
||||||
|
|
||||||
|
int metadata_load(const char *path, struct loom *loom, struct proc *proc);
|
||||||
|
|
||||||
|
#endif /* METADATA_H */
|
15
src/emu/path.c
Normal file
15
src/emu/path.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#include "path.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
path_has_prefix(const char *path, const char *prefix)
|
||||||
|
{
|
||||||
|
if (strncmp(path, prefix, strlen(prefix)) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
9
src/emu/path.h
Normal file
9
src/emu/path.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#ifndef PATH_H
|
||||||
|
#define PATH_H
|
||||||
|
|
||||||
|
int path_has_prefix(const char *path, const char *prefix);
|
||||||
|
|
||||||
|
#endif /* PATH_H */
|
161
src/emu/proc.c
161
src/emu/proc.c
@ -1,67 +1,39 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "emu_system.h"
|
#include "proc.h"
|
||||||
|
|
||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
|
#include "path.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
void
|
static const char prefix[] = "proc.";
|
||||||
proc_init(struct proc *proc, struct loom *loom, pid_t pid)
|
|
||||||
{
|
|
||||||
memset(proc, 0, sizeof(struct proc));
|
|
||||||
|
|
||||||
if (snprintf(proc->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
|
||||||
die("new_proc: name too long: %s\n", name);
|
|
||||||
|
|
||||||
if (snprintf(proc->relpath, PATH_MAX, "%s/%s", loom->name, proc->name) >= PATH_MAX)
|
|
||||||
die("new_proc: relative path too long: %s/%s", loom->name, proc->name);
|
|
||||||
|
|
||||||
if (snprintf(proc->path, PATH_MAX, "%s/%s", tracedir, proc->relpath) >= PATH_MAX)
|
|
||||||
die("new_proc: path too long: %s/%s", tracedir, proc->relpath);
|
|
||||||
|
|
||||||
proc->pid = pid;
|
|
||||||
proc->loom = loom;
|
|
||||||
proc->id = proc->relpath;
|
|
||||||
|
|
||||||
err("new proc '%s'\n", proc->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
check_proc_metadata(JSON_Value *meta_val, const char *path)
|
set_id(struct proc *proc, const char *id)
|
||||||
{
|
{
|
||||||
JSON_Object *meta = json_value_get_object(meta_val);
|
/* The id must be like "loom.123/proc.345" */
|
||||||
if (meta == NULL) {
|
|
||||||
err("check_proc_metadata: json_value_get_object() failed: %s\n",
|
const char *p = strchr(id, '/');
|
||||||
path);
|
if (p == NULL) {
|
||||||
|
err("proc relpath missing '/': %s", id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_Value *version_val = json_object_get_value(meta, "version");
|
p++; /* Skip slash */
|
||||||
if (version_val == NULL) {
|
if (strchr(p, '/') != NULL) {
|
||||||
err("check_proc_metadata: missing attribute \"version\": %s\n",
|
err("proc id contains multiple '/': %s", id);
|
||||||
path);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int version = (int) json_number(version_val);
|
/* Ensure the prefix is ok */
|
||||||
|
if (!path_has_prefix(p, prefix)) {
|
||||||
if (version != OVNI_METADATA_VERSION) {
|
err("proc name must start with '%s': %s", prefix, id);
|
||||||
err("check_proc_metadata: metadata version mismatch %d (expected %d) in %s\n",
|
|
||||||
version, OVNI_METADATA_VERSION, path);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_Value *mversion_val = json_object_get_value(meta, "model_version");
|
if (snprintf(proc->id, PATH_MAX, "%s", id) >= PATH_MAX) {
|
||||||
if (mversion_val == NULL) {
|
err("proc id too long: %s", id);
|
||||||
err("check_proc_metadata: missing attribute \"model_version\" in %s\n",
|
|
||||||
path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *mversion = json_string(mversion_val);
|
|
||||||
if (strcmp(mversion, OVNI_MODEL_VERSION) != 0) {
|
|
||||||
err("check_proc_metadata: model version mismatch '%s' (expected '%s') in %s\n",
|
|
||||||
mversion, OVNI_MODEL_VERSION, path);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,44 +41,105 @@ check_proc_metadata(JSON_Value *meta_val, const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
proc_load_metadata(struct emu_proc *proc, char *metadata_file)
|
proc_init(struct proc *proc, const char *id, int pid)
|
||||||
{
|
{
|
||||||
if (proc->meta != NULL) {
|
memset(proc, 0, sizeof(struct proc));
|
||||||
err("proc_load_metadata: process '%s' already has metadata\n",
|
|
||||||
proc->id);
|
if (set_id(proc, id) != 0) {
|
||||||
|
err("cannot set process id");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc->meta = json_parse_file_with_comments(metadata_file);
|
proc->pid = pid;
|
||||||
if (proc->meta == NULL) {
|
|
||||||
err("proc_load_metadata: failed to load metadata: %s\n",
|
return 0;
|
||||||
metadata_file);
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_metadata_version(JSON_Object *meta)
|
||||||
|
{
|
||||||
|
JSON_Value *version_val = json_object_get_value(meta, "version");
|
||||||
|
if (version_val == NULL) {
|
||||||
|
err("missing attribute \"version\"");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_proc_metadata(proc->meta, path) != 0) {
|
int version = (int) json_number(version_val);
|
||||||
err("load_proc_metadata: invalid metadata: %s\n",
|
|
||||||
metadata_file);
|
if (version != OVNI_METADATA_VERSION) {
|
||||||
|
err("metadata version mismatch %d (expected %d)",
|
||||||
|
version, OVNI_METADATA_VERSION);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The appid is populated from the metadata */
|
JSON_Value *mversion_val = json_object_get_value(meta, "model_version");
|
||||||
if (load_proc_attributes(proc, path) != 0) {
|
if (mversion_val == NULL) {
|
||||||
err("load_proc_metadata: invalid attributes: %s\n",
|
err("missing attribute \"model_version\"");
|
||||||
metadata_file);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mversion = json_string(mversion_val);
|
||||||
|
if (strcmp(mversion, OVNI_MODEL_VERSION) != 0) {
|
||||||
|
err("model version mismatch '%s' (expected '%s')",
|
||||||
|
mversion, OVNI_MODEL_VERSION);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_attributes(struct proc *proc, JSON_Object *meta)
|
||||||
|
{
|
||||||
|
JSON_Value *appid_val = json_object_get_value(meta, "app_id");
|
||||||
|
if (appid_val == NULL) {
|
||||||
|
err("missing attribute 'app_id' in metadata\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->appid = (int) json_number(appid_val);
|
||||||
|
|
||||||
|
JSON_Value *rank_val = json_object_get_value(meta, "rank");
|
||||||
|
|
||||||
|
if (rank_val != NULL)
|
||||||
|
proc->rank = (int) json_number(rank_val);
|
||||||
|
else
|
||||||
|
proc->rank = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
proc_load_metadata(struct proc *proc, JSON_Object *meta)
|
||||||
|
{
|
||||||
|
if (proc->metadata_loaded) {
|
||||||
|
err("process %s already loaded metadata", proc->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load_attributes(proc, meta) != 0) {
|
||||||
|
err("cannot load attributes for process %s", proc->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->metadata_loaded = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct thread *
|
struct thread *
|
||||||
proc_find_thread(struct proc *proc, pid_t tid)
|
proc_find_thread(struct proc *proc, int tid)
|
||||||
{
|
{
|
||||||
struct thread *th;
|
struct thread *th;
|
||||||
DL_FOREACH2(proc->threads, th, lnext) {
|
DL_FOREACH2(proc->threads, th, lnext) {
|
||||||
if (t->tid == tid)
|
if (th->tid == tid)
|
||||||
return t;
|
return th;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
proc_get_pid(struct proc *proc)
|
||||||
|
{
|
||||||
|
return proc->pid;
|
||||||
|
}
|
||||||
|
@ -6,32 +6,24 @@
|
|||||||
|
|
||||||
struct proc;
|
struct proc;
|
||||||
|
|
||||||
#include "loom.h"
|
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "parson.h"
|
#include "parson.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct proc {
|
struct proc {
|
||||||
size_t gindex;
|
size_t gindex;
|
||||||
|
char id[PATH_MAX];
|
||||||
|
|
||||||
char name[PATH_MAX]; /* Proc directory name */
|
int metadata_loaded;
|
||||||
char fullpath[PATH_MAX];
|
int pid;
|
||||||
char relpath[PATH_MAX];
|
|
||||||
char *id; /* Points to relpath */
|
|
||||||
|
|
||||||
pid_t pid;
|
|
||||||
int index;
|
int index;
|
||||||
int appid;
|
int appid;
|
||||||
int rank;
|
int rank;
|
||||||
|
|
||||||
struct loom *loom;
|
|
||||||
|
|
||||||
JSON_Value *meta;
|
|
||||||
|
|
||||||
int nthreads;
|
int nthreads;
|
||||||
struct thread *threads;
|
struct thread *threads;
|
||||||
|
|
||||||
/* Local list */
|
/* Loom list */
|
||||||
struct proc *lnext;
|
struct proc *lnext;
|
||||||
struct proc *lprev;
|
struct proc *lprev;
|
||||||
|
|
||||||
@ -40,8 +32,12 @@ struct proc {
|
|||||||
struct proc *gprev;
|
struct proc *gprev;
|
||||||
|
|
||||||
//struct model_ctx ctx;
|
//struct model_ctx ctx;
|
||||||
|
UT_hash_handle hh; /* procs in the loom */
|
||||||
};
|
};
|
||||||
|
|
||||||
void proc_init(struct proc *proc);
|
int proc_init(struct proc *proc, const char *id, int pid);
|
||||||
|
int proc_get_pid(struct proc *proc);
|
||||||
|
int proc_load_metadata(struct proc *proc, JSON_Object *meta);
|
||||||
|
struct thread *proc_find_thread(struct proc *proc, int tid);
|
||||||
|
|
||||||
#endif /* PROC_H */
|
#endif /* PROC_H */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
#include "emu_system.h"
|
#include "system.h"
|
||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
@ -14,10 +14,10 @@ has_prefix(const char *path, const char *prefix)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_thread *
|
static struct thread *
|
||||||
new_thread(struct emu_proc *proc, const char *tracedir, const char *name, struct emu_stream *stream)
|
new_thread(struct proc *proc, const char *tracedir, const char *name, struct emu_stream *stream)
|
||||||
{
|
{
|
||||||
struct emu_thread *thread = calloc(1, sizeof(struct emu_thread));
|
struct thread *thread = calloc(1, sizeof(struct thread));
|
||||||
|
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
die("calloc failed\n");
|
die("calloc failed\n");
|
||||||
@ -39,18 +39,18 @@ new_thread(struct emu_proc *proc, const char *tracedir, const char *name, struct
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_thread *
|
static struct thread *
|
||||||
find_thread(struct emu_proc *proc, const char *name)
|
find_thread(struct proc *proc, const char *name)
|
||||||
{
|
{
|
||||||
for (struct emu_thread *t = proc->threads; t; t = t->lnext) {
|
for (struct thread *t = proc->threads; t; t = t->lnext) {
|
||||||
if (strcmp(t->name, name) == 0)
|
if (strcmp(t->name, name) == 0)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_thread *
|
static struct thread *
|
||||||
create_thread(struct emu_proc *proc, const char *tracedir, struct emu_stream *stream)
|
create_thread(struct proc *proc, const char *tracedir, struct emu_stream *stream)
|
||||||
{
|
{
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
if (snprintf(name, PATH_MAX, "%s", stream->relpath) >= PATH_MAX) {
|
if (snprintf(name, PATH_MAX, "%s", stream->relpath) >= PATH_MAX) {
|
||||||
@ -81,7 +81,7 @@ create_thread(struct emu_proc *proc, const char *tracedir, struct emu_stream *st
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_thread *thread = find_thread(proc, threadname);
|
struct thread *thread = find_thread(proc, threadname);
|
||||||
|
|
||||||
if (thread != NULL) {
|
if (thread != NULL) {
|
||||||
err("create_thread: thread already exists: %s\n", threadname);
|
err("create_thread: thread already exists: %s\n", threadname);
|
||||||
@ -95,10 +95,10 @@ create_thread(struct emu_proc *proc, const char *tracedir, struct emu_stream *st
|
|||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_proc *
|
static struct proc *
|
||||||
new_proc(struct emu_loom *loom, const char *tracedir, const char *name)
|
new_proc(struct loom *loom, const char *tracedir, const char *name)
|
||||||
{
|
{
|
||||||
struct emu_proc *proc = calloc(1, sizeof(struct emu_proc));
|
struct proc *proc = calloc(1, sizeof(struct proc));
|
||||||
|
|
||||||
if (proc == NULL)
|
if (proc == NULL)
|
||||||
die("calloc failed\n");
|
die("calloc failed\n");
|
||||||
@ -119,18 +119,18 @@ new_proc(struct emu_loom *loom, const char *tracedir, const char *name)
|
|||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_proc *
|
static struct proc *
|
||||||
find_proc(struct emu_loom *loom, const char *name)
|
find_proc(struct loom *loom, const char *name)
|
||||||
{
|
{
|
||||||
for (struct emu_proc *proc = loom->procs; proc; proc = proc->lnext) {
|
for (struct proc *proc = loom->procs; proc; proc = proc->lnext) {
|
||||||
if (strcmp(proc->name, name) == 0)
|
if (strcmp(proc->name, name) == 0)
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_proc *
|
static struct proc *
|
||||||
create_proc(struct emu_loom *loom, const char *tracedir, const char *relpath)
|
create_proc(struct loom *loom, const char *tracedir, const char *relpath)
|
||||||
{
|
{
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
if (snprintf(name, PATH_MAX, "%s", relpath) >= PATH_MAX) {
|
if (snprintf(name, PATH_MAX, "%s", relpath) >= PATH_MAX) {
|
||||||
@ -155,7 +155,7 @@ create_proc(struct emu_loom *loom, const char *tracedir, const char *relpath)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_proc *proc = find_proc(loom, procname);
|
struct proc *proc = find_proc(loom, procname);
|
||||||
|
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
proc = new_proc(loom, tracedir, procname);
|
proc = new_proc(loom, tracedir, procname);
|
||||||
@ -166,11 +166,11 @@ create_proc(struct emu_loom *loom, const char *tracedir, const char *relpath)
|
|||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_loom *
|
static struct loom *
|
||||||
find_loom(struct emu_system *sys, const char *name)
|
find_loom(struct system *sys, const char *id)
|
||||||
{
|
{
|
||||||
for (struct emu_loom *loom = sys->looms; loom; loom = loom->next) {
|
for (struct loom *loom = sys->looms; loom; loom = loom->next) {
|
||||||
if (strcmp(loom->name, name) == 0)
|
if (strcmp(loom->id, id) == 0)
|
||||||
return loom;
|
return loom;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -191,14 +191,17 @@ set_loom_hostname(char host[PATH_MAX], const char loom_name[PATH_MAX])
|
|||||||
host[i] = '\0';
|
host[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_loom *
|
static struct loom *
|
||||||
new_loom(const char *tracedir, const char *name)
|
new_loom(const char *tracedir, const char *name)
|
||||||
{
|
{
|
||||||
struct emu_loom *loom = calloc(1, sizeof(struct emu_loom));
|
struct loom *loom = calloc(1, sizeof(struct loom));
|
||||||
|
|
||||||
if (loom == NULL)
|
if (loom == NULL)
|
||||||
die("calloc failed\n");
|
die("calloc failed\n");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, name) != 0)
|
||||||
|
re
|
||||||
|
|
||||||
if (snprintf(loom->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
if (snprintf(loom->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
||||||
die("new_loom: name too long: %s\n", name);
|
die("new_loom: name too long: %s\n", name);
|
||||||
|
|
||||||
@ -215,25 +218,35 @@ new_loom(const char *tracedir, const char *name)
|
|||||||
return loom;
|
return loom;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_loom *
|
static struct loom *
|
||||||
create_loom(struct emu_system *sys, const char *tracedir, const char *relpath)
|
create_loom(struct system *sys, const char *tracedir, const char *relpath)
|
||||||
{
|
{
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
if (snprintf(name, PATH_MAX, "%s", relpath) >= PATH_MAX) {
|
if (snprintf(name, PATH_MAX, "%s", relpath) >= PATH_MAX) {
|
||||||
err("create_loom: path too long: %s\n", relpath);
|
err("path too long: %s", relpath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strtok(name, "/") == NULL) {
|
if (strtok(name, "/") == NULL) {
|
||||||
err("create_looms: cannot find first '/': %s\n",
|
err("cannot find first '/': %s", relpath);
|
||||||
relpath);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_loom *loom = find_loom(sys, name);
|
struct loom *loom = find_loom(sys, name);
|
||||||
|
|
||||||
if (loom == NULL) {
|
if (loom == NULL) {
|
||||||
loom = new_loom(tracedir, name);
|
loom = malloc(sizeof(struct loom));
|
||||||
|
|
||||||
|
if (loom == NULL) {
|
||||||
|
err("calloc failed:");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, name) != 0) {
|
||||||
|
err("loom_init_begin failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
DL_APPEND(sys->looms, loom);
|
DL_APPEND(sys->looms, loom);
|
||||||
sys->nlooms++;
|
sys->nlooms++;
|
||||||
}
|
}
|
||||||
@ -242,32 +255,31 @@ create_loom(struct emu_system *sys, const char *tracedir, const char *relpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_lpt(struct emu_system *sys, struct emu_trace *trace)
|
create_lpt(struct 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) {
|
||||||
if (!has_prefix(s->relpath, "loom")) {
|
if (!loom_matches(s->relpath)) {
|
||||||
err("warning: ignoring unknown steam %s\n",
|
err("warning: ignoring unknown stream %s", s->relpath);
|
||||||
s->relpath);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_loom *loom = create_loom(sys, dir, s->relpath);
|
struct loom *loom = create_loom(sys, dir, s->relpath);
|
||||||
if (loom == NULL) {
|
if (loom == NULL) {
|
||||||
err("create_lpt: create_loom failed\n");
|
err("create_loom failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emu_proc *proc = create_proc(loom, dir, s->relpath);
|
struct proc *proc = create_proc(loom, dir, s->relpath);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
err("create_lpt: create_proc failed\n");
|
err("create_proc failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The thread sets the stream */
|
/* The thread sets the stream */
|
||||||
struct emu_thread *thread = create_thread(proc, dir, s);
|
struct thread *thread = create_thread(proc, dir, s);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
err("create_lpt: create_thread failed\n");
|
err("create_thread failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,53 +288,53 @@ create_lpt(struct emu_system *sys, struct emu_trace *trace)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_thread(struct emu_thread *a, struct emu_thread *b)
|
cmp_thread(struct thread *a, struct thread *b)
|
||||||
{
|
{
|
||||||
return strcmp(a->name, b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sort_proc(struct emu_proc *proc)
|
sort_proc(struct proc *proc)
|
||||||
{
|
{
|
||||||
DL_SORT2(proc->threads, cmp_thread, lprev, lnext);
|
DL_SORT2(proc->threads, cmp_thread, lprev, lnext);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_proc(struct emu_proc *a, struct emu_proc *b)
|
cmp_proc(struct proc *a, struct proc *b)
|
||||||
{
|
{
|
||||||
return strcmp(a->name, b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sort_loom(struct emu_loom *loom)
|
sort_loom(struct loom *loom)
|
||||||
{
|
{
|
||||||
DL_SORT2(loom->procs, cmp_proc, lprev, lnext);
|
DL_SORT2(loom->procs, cmp_proc, lprev, lnext);
|
||||||
|
|
||||||
for (struct emu_proc *p = loom->procs; p; p = p->gnext)
|
for (struct proc *p = loom->procs; p; p = p->gnext)
|
||||||
sort_proc(p);
|
sort_proc(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_loom(struct emu_loom *a, struct emu_loom *b)
|
cmp_loom(struct loom *a, struct loom *b)
|
||||||
{
|
{
|
||||||
return strcmp(a->name, b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sort_lpt(struct emu_system *sys)
|
sort_lpt(struct system *sys)
|
||||||
{
|
{
|
||||||
DL_SORT(sys->looms, cmp_loom);
|
DL_SORT(sys->looms, cmp_loom);
|
||||||
|
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next)
|
for (struct loom *l = sys->looms; l; l = l->next)
|
||||||
sort_loom(l);
|
sort_loom(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_global_lpt_lists(struct emu_system *sys)
|
init_global_lpt_lists(struct system *sys)
|
||||||
{
|
{
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
for (struct loom *l = sys->looms; l; l = l->next) {
|
||||||
for (struct emu_proc *p = l->procs; p; p = p->lnext) {
|
for (struct proc *p = l->procs; p; p = p->lnext) {
|
||||||
for (struct emu_thread *t = p->threads; t; t = t->lnext) {
|
for (struct thread *t = p->threads; t; t = t->lnext) {
|
||||||
DL_APPEND2(sys->threads, t, gprev, gnext);
|
DL_APPEND2(sys->threads, t, gprev, gnext);
|
||||||
}
|
}
|
||||||
DL_APPEND2(sys->procs, p, gprev, gnext);
|
DL_APPEND2(sys->procs, p, gprev, gnext);
|
||||||
@ -333,9 +345,9 @@ init_global_lpt_lists(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_global_cpus_list(struct emu_system *sys)
|
init_global_cpus_list(struct system *sys)
|
||||||
{
|
{
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
for (struct loom *l = sys->looms; l; l = l->next) {
|
||||||
for (size_t i = 0; i < l->ncpus; i++) {
|
for (size_t i = 0; i < l->ncpus; i++) {
|
||||||
struct cpu *cpu = &l->cpu[i];
|
struct cpu *cpu = &l->cpu[i];
|
||||||
DL_APPEND2(sys->cpus, cpu, prev, next);
|
DL_APPEND2(sys->cpus, cpu, prev, next);
|
||||||
@ -347,22 +359,22 @@ init_global_cpus_list(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_system(struct emu_system *sys)
|
print_system(struct system *sys)
|
||||||
{
|
{
|
||||||
err("content of system:\n");
|
err("content of system:\n");
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
for (struct loom *l = sys->looms; l; l = l->next) {
|
||||||
err("%s\n", l->name);
|
err("%s\n", l->name);
|
||||||
err("- gindex %ld\n", l->gindex);
|
err("- gindex %ld\n", l->gindex);
|
||||||
err("- path %s\n", l->path);
|
err("- path %s\n", l->path);
|
||||||
err("- relpath %s\n", l->relpath);
|
err("- relpath %s\n", l->relpath);
|
||||||
err("- processes:\n");
|
err("- processes:\n");
|
||||||
for (struct emu_proc *p = l->procs; p; p = p->lnext) {
|
for (struct proc *p = l->procs; p; p = p->lnext) {
|
||||||
err(" %s\n", p->name);
|
err(" %s\n", p->name);
|
||||||
err(" - gindex %ld\n", p->gindex);
|
err(" - gindex %ld\n", p->gindex);
|
||||||
err(" - path %s\n", p->path);
|
err(" - path %s\n", p->path);
|
||||||
err(" - relpath %s\n", p->relpath);
|
err(" - relpath %s\n", p->relpath);
|
||||||
err(" - threads:\n");
|
err(" - threads:\n");
|
||||||
for (struct emu_thread *t = p->threads; t; t = t->lnext) {
|
for (struct thread *t = p->threads; t; t = t->lnext) {
|
||||||
err(" %s\n", t->name);
|
err(" %s\n", t->name);
|
||||||
err(" - gindex %ld\n", t->gindex);
|
err(" - gindex %ld\n", t->gindex);
|
||||||
err(" - path %s\n", t->path);
|
err(" - path %s\n", t->path);
|
||||||
@ -387,7 +399,7 @@ print_system(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
load_proc_attributes(struct emu_proc *proc, const char *path)
|
load_proc_attributes(struct proc *proc, const char *path)
|
||||||
{
|
{
|
||||||
JSON_Object *meta = json_value_get_object(proc->meta);
|
JSON_Object *meta = json_value_get_object(proc->meta);
|
||||||
if (meta == NULL) {
|
if (meta == NULL) {
|
||||||
@ -458,7 +470,7 @@ check_proc_metadata(JSON_Value *pmeta, const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
load_proc_metadata(struct emu_proc *proc)
|
load_proc_metadata(struct proc *proc)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
if (snprintf(path, PATH_MAX, "%s/%s", proc->path, "metadata.json") >= PATH_MAX) {
|
if (snprintf(path, PATH_MAX, "%s/%s", proc->path, "metadata.json") >= PATH_MAX) {
|
||||||
@ -489,9 +501,9 @@ load_proc_metadata(struct emu_proc *proc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
load_metadata(struct emu_system *sys)
|
load_metadata(struct system *sys)
|
||||||
{
|
{
|
||||||
for (struct emu_proc *p = sys->procs; p; p = p->gnext) {
|
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||||
if (load_proc_metadata(p) != 0) {
|
if (load_proc_metadata(p) != 0) {
|
||||||
err("error loading metadata for %s\n", p->relpath);
|
err("error loading metadata for %s\n", p->relpath);
|
||||||
return -1;
|
return -1;
|
||||||
@ -521,27 +533,11 @@ has_cpus_array(JSON_Value *metadata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_new_cpu(struct emu_loom *loom, int i, int phyid, int ncpus)
|
load_proc_cpus(struct proc *proc)
|
||||||
{
|
|
||||||
struct cpu *cpu = &loom->cpu[i];
|
|
||||||
|
|
||||||
if (i < 0 || i >= ncpus) {
|
|
||||||
err("add_new_cpu: new CPU i=%d out of bounds in %s\n",
|
|
||||||
i, loom->relpath);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu_init(cpu, loom, i, phyid, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
load_proc_cpus(struct emu_proc *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) {
|
||||||
err("load_proc_cpus: json_value_get_object() failed\n");
|
err("json_value_get_object() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,69 +545,65 @@ load_proc_cpus(struct emu_proc *proc)
|
|||||||
|
|
||||||
/* This process doesn't have the cpu list, but it should */
|
/* This process doesn't have the cpu list, but it should */
|
||||||
if (cpuarray == NULL) {
|
if (cpuarray == NULL) {
|
||||||
err("load_proc_cpus: json_object_get_array() failed\n");
|
err("json_object_get_array() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ncpus = json_array_get_count(cpuarray);
|
size_t ncpus = json_array_get_count(cpuarray);
|
||||||
if (ncpus == 0) {
|
if (ncpus == 0) {
|
||||||
err("load_proc_cpus: the 'cpus' array is empty in metadata of %s\n",
|
err("empty cpus array in metadata of %s", proc->id);
|
||||||
proc->relpath);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct emu_loom *loom = proc->loom;
|
|
||||||
struct cpu *cpus = calloc(ncpus, sizeof(struct cpu));
|
|
||||||
|
|
||||||
if (loom->cpu == NULL) {
|
|
||||||
err("load_proc_cpus: calloc failed: %s\n", strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct loom *loom = proc->loom;
|
||||||
for (size_t i = 0; i < ncpus; i++) {
|
for (size_t i = 0; i < ncpus; i++) {
|
||||||
JSON_Object *cpu = json_array_get_object(cpuarray, i);
|
JSON_Object *jcpu = json_array_get_object(cpuarray, i);
|
||||||
|
if (jcpu == NULL) {
|
||||||
|
err("json_array_get_object() failed for cpu");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cast from double */
|
||||||
|
int index = (int) json_object_get_number(jcpu, "index");
|
||||||
|
int phyid = (int) json_object_get_number(jcpu, "phyid");
|
||||||
|
|
||||||
|
struct cpu *cpu = calloc(1, sizeof(struct cpu));
|
||||||
if (cpu == NULL) {
|
if (cpu == NULL) {
|
||||||
err("proc_load_cpus: json_array_get_object() failed for cpu\n");
|
err("calloc failed:");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = (int) json_object_get_number(cpu, "index");
|
cpu_init(cpu, i, phyid, 0);
|
||||||
int phyid = (int) json_object_get_number(cpu, "phyid");
|
if (loom_add_cpu(loom, cpu) != 0) {
|
||||||
|
err("loom_add_cpu() failed");
|
||||||
if (add_new_cpu(loom, index, phyid) != 0) {
|
|
||||||
err("proc_load_cpus: add_new_cpu() failed\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loom_set_cpus(loom, cpus, ncpus);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
load_loom_cpus(struct emu_loom *loom)
|
load_loom_cpus(struct loom *loom)
|
||||||
{
|
{
|
||||||
/* The process that contains the CPU list */
|
/* The process that contains the CPU list */
|
||||||
struct emu_proc *proc_cpus = NULL;
|
struct proc *proc_cpus = NULL;
|
||||||
|
|
||||||
/* Search for the cpu list in all processes.
|
/* Search for the cpu list in all processes.
|
||||||
* Only one should contain it. */
|
* Only one should contain it. */
|
||||||
for (struct emu_proc *p = loom->procs; p; p = p->lnext) {
|
for (struct proc *p = loom->procs; p; p = p->lnext) {
|
||||||
if (!has_cpus_array(p->meta))
|
if (!has_cpus_array(p->meta))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (proc_cpus != NULL) {
|
if (proc_cpus != NULL) {
|
||||||
err("load_loom_cpus: duplicated cpu list provided in '%s' and '%s'\n",
|
err("duplicated cpu list provided in '%s' and '%s'",
|
||||||
proc_cpus->relpath,
|
proc_cpus->relpath,
|
||||||
p->relpath);
|
p->relpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_proc_cpus(p) != 0) {
|
if (load_proc_cpus(p) != 0) {
|
||||||
err("load_loom_cpus: load_proc_cpus failed: %s\n",
|
err("load_proc_cpus failed: %s", p->id);
|
||||||
p->relpath);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,9 +631,9 @@ load_loom_cpus(struct emu_loom *loom)
|
|||||||
|
|
||||||
/* Obtain CPUs in the metadata files and other data */
|
/* Obtain CPUs in the metadata files and other data */
|
||||||
static int
|
static int
|
||||||
init_cpus(struct emu_system *sys)
|
init_cpus(struct system *sys)
|
||||||
{
|
{
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
for (struct loom *l = sys->looms; l; l = l->next) {
|
||||||
if (load_loom_cpus(l) != 0) {
|
if (load_loom_cpus(l) != 0) {
|
||||||
err("init_cpus: load_loom_cpus() failed\n");
|
err("init_cpus: load_loom_cpus() failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -652,18 +644,18 @@ init_cpus(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_global_indices(struct emu_system *sys)
|
init_global_indices(struct system *sys)
|
||||||
{
|
{
|
||||||
size_t iloom = 0;
|
size_t iloom = 0;
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next)
|
for (struct loom *l = sys->looms; l; l = l->next)
|
||||||
loom_set_gindex(l, iloom++);
|
loom_set_gindex(l, iloom++);
|
||||||
|
|
||||||
sys->nprocs = 0;
|
sys->nprocs = 0;
|
||||||
for (struct emu_proc *p = sys->procs; p; p = p->gnext)
|
for (struct proc *p = sys->procs; p; p = p->gnext)
|
||||||
p->gindex = sys->nprocs++;
|
p->gindex = sys->nprocs++;
|
||||||
|
|
||||||
sys->nthreads = 0;
|
sys->nthreads = 0;
|
||||||
for (struct emu_thread *t = sys->threads; t; t = t->gnext)
|
for (struct thread *t = sys->threads; t; t = t->gnext)
|
||||||
t->gindex = sys->nprocs++;
|
t->gindex = sys->nprocs++;
|
||||||
|
|
||||||
sys->ncpus = 0;
|
sys->ncpus = 0;
|
||||||
@ -692,7 +684,7 @@ init_cpu_name(struct cpu *cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_cpu_names(struct emu_system *sys)
|
init_cpu_names(struct system *sys)
|
||||||
{
|
{
|
||||||
for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
|
for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
|
||||||
if (init_cpu_name(cpu) != 0)
|
if (init_cpu_name(cpu) != 0)
|
||||||
@ -703,9 +695,9 @@ init_cpu_names(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
link_streams_to_threads(struct emu_system *sys)
|
link_streams_to_threads(struct system *sys)
|
||||||
{
|
{
|
||||||
for (struct emu_thread *th = sys->threads; th; th = th->gnext)
|
for (struct thread *th = sys->threads; th; th = th->gnext)
|
||||||
emu_stream_data_set(th->stream, th);
|
emu_stream_data_set(th->stream, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +749,7 @@ load_clock_offsets(struct clkoff *clkoff, struct emu_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_clkoff_entry(struct emu_loom *looms, struct clkoff_entry *entry)
|
parse_clkoff_entry(struct loom *looms, struct clkoff_entry *entry)
|
||||||
{
|
{
|
||||||
size_t matches = 0;
|
size_t matches = 0;
|
||||||
|
|
||||||
@ -765,7 +757,7 @@ parse_clkoff_entry(struct emu_loom *looms, struct clkoff_entry *entry)
|
|||||||
size_t offset = entry->median;
|
size_t offset = entry->median;
|
||||||
const char *host = entry->name;
|
const char *host = entry->name;
|
||||||
|
|
||||||
struct emu_loom *loom;
|
struct loom *loom;
|
||||||
DL_FOREACH(looms, loom) {
|
DL_FOREACH(looms, loom) {
|
||||||
/* Match the hostname exactly */
|
/* Match the hostname exactly */
|
||||||
if (strcmp(loom->hostname, host) != 0)
|
if (strcmp(loom->hostname, host) != 0)
|
||||||
@ -791,7 +783,7 @@ parse_clkoff_entry(struct emu_loom *looms, struct clkoff_entry *entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_offsets(struct emu_system *sys)
|
init_offsets(struct system *sys)
|
||||||
{
|
{
|
||||||
struct clkoff *table = &sys->clkoff;
|
struct clkoff *table = &sys->clkoff;
|
||||||
int n = clkoff_count(table);
|
int n = clkoff_count(table);
|
||||||
@ -815,9 +807,9 @@ init_offsets(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set the stream clock offsets too */
|
/* Set the stream clock offsets too */
|
||||||
struct emu_thread *thread;
|
struct thread *thread;
|
||||||
DL_FOREACH2(sys->threads, thread, gnext) {
|
DL_FOREACH2(sys->threads, thread, gnext) {
|
||||||
struct emu_loom *loom = thread->proc->loom;
|
struct loom *loom = thread->proc->loom;
|
||||||
int64_t offset = loom->clock_offset;
|
int64_t offset = loom->clock_offset;
|
||||||
if (emu_stream_clkoff_set(thread->stream, offset) != 0) {
|
if (emu_stream_clkoff_set(thread->stream, offset) != 0) {
|
||||||
err("init_offsets: cannot set clock offset\n");
|
err("init_offsets: cannot set clock offset\n");
|
||||||
@ -829,63 +821,70 @@ init_offsets(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
emu_system_init(struct emu_system *sys, struct emu_args *args, struct emu_trace *trace)
|
system_init(struct system *sys, struct emu_args *args, struct emu_trace *trace)
|
||||||
{
|
{
|
||||||
memset(sys, 0, sizeof(struct emu_system));
|
memset(sys, 0, sizeof(struct system));
|
||||||
sys->args = args;
|
sys->args = args;
|
||||||
|
|
||||||
/* Parse the trace and create the looms, procs and threads */
|
/* Parse the trace and create the looms, procs and threads */
|
||||||
if (create_lpt(sys, trace) != 0) {
|
if (create_lpt(sys, trace) != 0) {
|
||||||
err("emu_system_init: create system failed\n");
|
err("system_init: create system failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure they are sorted so they are easier to read */
|
|
||||||
sort_lpt(sys);
|
|
||||||
|
|
||||||
/* Init global lists after sorting */
|
/* Create global lists and indices */
|
||||||
init_global_lpt_lists(sys);
|
|
||||||
|
|
||||||
/* Now load all process metadata and set attributes */
|
|
||||||
if (load_metadata(sys) != 0) {
|
|
||||||
err("emu_system_init: load_metadata() failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* From the metadata extract the CPUs too */
|
/* Setup names */
|
||||||
if (init_cpus(sys) != 0) {
|
|
||||||
err("emu_system_init: load_cpus() failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_global_cpus_list(sys);
|
|
||||||
|
|
||||||
/* Now that we have loaded all resources, populate the indices */
|
// /* Ensure they are sorted so they are easier to read */
|
||||||
init_global_indices(sys);
|
// sort_lpt(sys);
|
||||||
|
//
|
||||||
/* Set CPU names like "CPU 1.34" */
|
// /* Init global lists after sorting */
|
||||||
if (init_cpu_names(sys) != 0) {
|
// init_global_lpt_lists(sys);
|
||||||
err("emu_system_init: init_cpu_names() failed\n");
|
//
|
||||||
return -1;
|
// /* Now load all process metadata and set attributes */
|
||||||
}
|
// if (load_metadata(sys) != 0) {
|
||||||
|
// err("system_init: load_metadata() failed\n");
|
||||||
/* We need to retrieve the thread from the stream too */
|
// return -1;
|
||||||
link_streams_to_threads(sys);
|
// }
|
||||||
|
//
|
||||||
/* Load the clock offsets table */
|
// /* From the metadata extract the CPUs too */
|
||||||
if (load_clock_offsets(&sys->clkoff, args) != 0) {
|
// if (init_cpus(sys) != 0) {
|
||||||
err("emu_system_init: load_clock_offsets() failed\n");
|
// err("system_init: load_cpus() failed\n");
|
||||||
return -1;
|
// return -1;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/* Set the offsets of the looms and streams */
|
// init_global_cpus_list(sys);
|
||||||
if (init_offsets(sys) != 0) {
|
//
|
||||||
err("emu_system_init: init_offsets() failed\n");
|
// /* Now that we have loaded all resources, populate the indices */
|
||||||
return -1;
|
// init_global_indices(sys);
|
||||||
}
|
//
|
||||||
|
// /* Set CPU names like "CPU 1.34" */
|
||||||
/* Finaly dump the system */
|
// if (init_cpu_names(sys) != 0) {
|
||||||
print_system(sys);
|
// err("system_init: init_cpu_names() failed\n");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* We need to retrieve the thread from the stream too */
|
||||||
|
// link_streams_to_threads(sys);
|
||||||
|
//
|
||||||
|
// /* Load the clock offsets table */
|
||||||
|
// if (load_clock_offsets(&sys->clkoff, args) != 0) {
|
||||||
|
// err("system_init: load_clock_offsets() failed\n");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* Set the offsets of the looms and streams */
|
||||||
|
// if (init_offsets(sys) != 0) {
|
||||||
|
// err("system_init: init_offsets() failed\n");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* Finaly dump the system */
|
||||||
|
// print_system(sys);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
41
src/emu/system.h
Normal file
41
src/emu/system.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#ifndef EMU_SYSTEM_H
|
||||||
|
#define EMU_SYSTEM_H
|
||||||
|
|
||||||
|
#include "emu_args.h"
|
||||||
|
#include "emu_trace.h"
|
||||||
|
#include "emu_stream.h"
|
||||||
|
#include "loom.h"
|
||||||
|
#include "proc.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "clkoff.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct system {
|
||||||
|
/* Total counters */
|
||||||
|
size_t nlooms;
|
||||||
|
size_t nthreads;
|
||||||
|
size_t nprocs;
|
||||||
|
size_t ncpus; /* Physical */
|
||||||
|
|
||||||
|
struct loom *looms;
|
||||||
|
struct proc *procs;
|
||||||
|
struct thread *threads;
|
||||||
|
struct cpu *cpus;
|
||||||
|
|
||||||
|
struct clkoff clkoff;
|
||||||
|
struct emu_args *args;
|
||||||
|
|
||||||
|
//struct model_ctx ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
int system_init(struct system *sys, struct emu_args *args, struct emu_trace *trace);
|
||||||
|
//struct emu_thread *system_get_thread(struct emu_stream *stream);
|
||||||
|
//struct emu_cpu *system_find_cpu(struct emu_loom *loom, int cpuid);
|
||||||
|
//int model_ctx_set(struct model_ctx *ctx, int model, void *data);
|
||||||
|
//int model_ctx_get(struct model_ctx *ctx, int model, void *data);
|
||||||
|
|
||||||
|
#endif /* EMU_SYSTEM_H */
|
@ -19,3 +19,6 @@ unit_test(emu_trace.c)
|
|||||||
unit_test(emu.c)
|
unit_test(emu.c)
|
||||||
unit_test(clkoff.c)
|
unit_test(clkoff.c)
|
||||||
unit_test(emu_stream.c)
|
unit_test(emu_stream.c)
|
||||||
|
unit_test(loom.c)
|
||||||
|
unit_test(thread.c)
|
||||||
|
unit_test(proc.c)
|
||||||
|
98
test/unit/cpu.c
Normal file
98
test/unit/cpu.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include "emu/bay.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_remove(struct bay *bay)
|
||||||
|
{
|
||||||
|
struct chan chan;
|
||||||
|
chan_init(&chan, CHAN_SINGLE, "removeme");
|
||||||
|
|
||||||
|
if (bay_register(bay, &chan) != 0)
|
||||||
|
die("bay_register failed\n");
|
||||||
|
|
||||||
|
if (bay_find(bay, chan.name) == NULL)
|
||||||
|
die("bay_find failed\n");
|
||||||
|
|
||||||
|
if (bay_remove(bay, &chan) != 0)
|
||||||
|
die("bay_remove failed\n");
|
||||||
|
|
||||||
|
if (bay_find(bay, chan.name) != NULL)
|
||||||
|
die("bay_find didn't fail\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_duplicate(struct bay *bay)
|
||||||
|
{
|
||||||
|
struct chan chan;
|
||||||
|
chan_init(&chan, CHAN_SINGLE, "dup");
|
||||||
|
|
||||||
|
if (bay_register(bay, &chan) != 0)
|
||||||
|
die("bay_register failed\n");
|
||||||
|
|
||||||
|
if (bay_register(bay, &chan) == 0)
|
||||||
|
die("bay_register didn't fail\n");
|
||||||
|
|
||||||
|
if (bay_remove(bay, &chan) != 0)
|
||||||
|
die("bay_remove failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
callback(struct chan *chan, void *ptr)
|
||||||
|
{
|
||||||
|
struct value value;
|
||||||
|
if (chan_read(chan, &value) != 0)
|
||||||
|
die("callback: chan_read failed\n");
|
||||||
|
|
||||||
|
if (value.type != VALUE_INT64)
|
||||||
|
die("callback: unexpected value type\n");
|
||||||
|
|
||||||
|
int64_t *ival = ptr;
|
||||||
|
*ival = value.i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_callback(struct bay *bay)
|
||||||
|
{
|
||||||
|
struct chan chan;
|
||||||
|
chan_init(&chan, CHAN_SINGLE, "testchan");
|
||||||
|
|
||||||
|
if (bay_register(bay, &chan) != 0)
|
||||||
|
die("bay_register failed\n");
|
||||||
|
|
||||||
|
int64_t data = 0;
|
||||||
|
if (bay_add_cb(bay, BAY_CB_DIRTY, &chan, callback, &data) != 0)
|
||||||
|
die("bay_add_cb failed\n");
|
||||||
|
|
||||||
|
if (data != 0)
|
||||||
|
die("data changed after bay_chan_append_cb\n");
|
||||||
|
|
||||||
|
if (chan_set(&chan, value_int64(1)) != 0)
|
||||||
|
die("chan_set failed\n");
|
||||||
|
|
||||||
|
if (data != 0)
|
||||||
|
die("data changed after chan_set\n");
|
||||||
|
|
||||||
|
/* Now the callback should modify 'data' */
|
||||||
|
if (bay_propagate(bay) != 0)
|
||||||
|
die("bay_propagate failed\n");
|
||||||
|
|
||||||
|
if (data != 1)
|
||||||
|
die("data didn't change after bay_propagate\n");
|
||||||
|
|
||||||
|
if (bay_remove(bay, &chan) != 0)
|
||||||
|
die("bay_remove failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct bay bay;
|
||||||
|
bay_init(&bay);
|
||||||
|
|
||||||
|
test_remove(&bay);
|
||||||
|
test_duplicate(&bay);
|
||||||
|
test_callback(&bay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
134
test/unit/loom.c
Normal file
134
test/unit/loom.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include "emu/loom.h"
|
||||||
|
#include "emu/cpu.h"
|
||||||
|
#include "emu/proc.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "utlist.h"
|
||||||
|
|
||||||
|
char testloom[] = "loom.0";
|
||||||
|
char testproc[] = "loom.0/proc.1";
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_bad_name(struct loom *loom)
|
||||||
|
{
|
||||||
|
if (loom_init_begin(loom, "blah") == 0)
|
||||||
|
die("loom_init_begin didn't fail");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, "loom/blah") == 0)
|
||||||
|
die("loom_init_begin didn't fail");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, "loom.123/testloom") == 0)
|
||||||
|
die("loom_init_begin didn't fail");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, "loom.123/") == 0)
|
||||||
|
die("loom_init_begin didn't fail");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, "/loom.123") == 0)
|
||||||
|
die("loom_init_begin didn't fail");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, "./loom.123") == 0)
|
||||||
|
die("loom_init_begin didn't fail");
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, "loom.123") != 0)
|
||||||
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
|
err("ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_negative_cpu(struct loom *loom)
|
||||||
|
{
|
||||||
|
if (loom_init_begin(loom, testloom) != 0)
|
||||||
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
|
struct cpu cpu;
|
||||||
|
cpu_init(&cpu, -1);
|
||||||
|
|
||||||
|
if (loom_add_cpu(loom, &cpu) == 0)
|
||||||
|
die("loom_add_cpu didn't fail");
|
||||||
|
|
||||||
|
err("ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_duplicate_cpus(struct loom *loom)
|
||||||
|
{
|
||||||
|
if (loom_init_begin(loom, testloom) != 0)
|
||||||
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
|
struct cpu cpu;
|
||||||
|
cpu_init(&cpu, 123);
|
||||||
|
if (loom_add_cpu(loom, &cpu) != 0)
|
||||||
|
die("loom_add_cpu failed");
|
||||||
|
|
||||||
|
if (loom_add_cpu(loom, &cpu) == 0)
|
||||||
|
die("loom_add_cpu didn't fail");
|
||||||
|
|
||||||
|
err("ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_sort_cpus(struct loom *loom)
|
||||||
|
{
|
||||||
|
int ncpus = 10;
|
||||||
|
|
||||||
|
if (loom_init_begin(loom, testloom) != 0)
|
||||||
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
|
for (int i = 0; i < ncpus; i++) {
|
||||||
|
int phyid = 1000 - i * i;
|
||||||
|
struct cpu *cpu = malloc(sizeof(struct cpu));
|
||||||
|
if (cpu == NULL)
|
||||||
|
die("malloc failed:");
|
||||||
|
|
||||||
|
cpu_init(cpu, phyid);
|
||||||
|
if (loom_add_cpu(loom, cpu) != 0)
|
||||||
|
die("loom_add_cpu failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loom_init_end(loom) != 0)
|
||||||
|
die("loom_init_end failed");
|
||||||
|
|
||||||
|
if (loom->ncpus != (size_t) ncpus)
|
||||||
|
die("ncpus mismatch");
|
||||||
|
|
||||||
|
struct cpu *cpu = NULL;
|
||||||
|
int lastphyid = -1;
|
||||||
|
DL_FOREACH2(loom->scpus, cpu, lnext) {
|
||||||
|
int phyid = cpu_get_phyid(cpu);
|
||||||
|
if (lastphyid >= phyid)
|
||||||
|
die("unsorted scpus");
|
||||||
|
lastphyid = phyid;
|
||||||
|
}
|
||||||
|
|
||||||
|
err("ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_duplicate_procs(struct loom *loom)
|
||||||
|
{
|
||||||
|
if (loom_init_begin(loom, testloom) != 0)
|
||||||
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
|
struct proc proc;
|
||||||
|
proc_init(&proc, testproc, 1);
|
||||||
|
if (loom_add_proc(loom, &proc) != 0)
|
||||||
|
die("loom_add_proc failed");
|
||||||
|
|
||||||
|
if (loom_add_proc(loom, &proc) == 0)
|
||||||
|
die("loom_add_proc didn't fail");
|
||||||
|
|
||||||
|
err("ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct loom loom;
|
||||||
|
|
||||||
|
test_bad_name(&loom);
|
||||||
|
test_negative_cpu(&loom);
|
||||||
|
test_duplicate_cpus(&loom);
|
||||||
|
test_sort_cpus(&loom);
|
||||||
|
test_duplicate_procs(&loom);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
33
test/unit/proc.c
Normal file
33
test/unit/proc.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "emu/proc.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
char meta[] =
|
||||||
|
"{\n"
|
||||||
|
" \"version\": 1,\n"
|
||||||
|
" \"model_version\": \"O1 V1 T1 M1 D1 K1 61\",\n"
|
||||||
|
" \"app_id\": 1,\n"
|
||||||
|
" \"cpus\": [ 0, 1, 2, 3 ]\n"
|
||||||
|
//" \"cpus\": [\n"
|
||||||
|
//" {\n"
|
||||||
|
//" \"index\": 0,\n"
|
||||||
|
//" \"phyid\": 0\n"
|
||||||
|
//" },\n"
|
||||||
|
//" {\n"
|
||||||
|
//" \"index\": 1,\n"
|
||||||
|
//" \"phyid\": 1\n"
|
||||||
|
//" },\n"
|
||||||
|
//" {\n"
|
||||||
|
//" \"index\": 2,\n"
|
||||||
|
//" \"phyid\": 2\n"
|
||||||
|
//" },\n"
|
||||||
|
//" {\n"
|
||||||
|
//" \"index\": 3,\n"
|
||||||
|
//" \"phyid\": 3\n"
|
||||||
|
//" }\n"
|
||||||
|
//" ]\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
8
test/unit/thread.c
Normal file
8
test/unit/thread.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "emu/thread.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user