Load CPUs in emu_system
This commit is contained in:
parent
fb06a3ec32
commit
f4e8b0b8a8
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "emu_system.h"
|
#include "emu_system.h"
|
||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
static int
|
static int
|
||||||
has_prefix(const char *path, const char *prefix)
|
has_prefix(const char *path, const char *prefix)
|
||||||
@ -14,7 +15,7 @@ has_prefix(const char *path, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_thread *
|
static struct emu_thread *
|
||||||
new_thread(struct emu_proc *proc, const char *name, const char *relpath)
|
new_thread(struct emu_proc *proc, const char *tracedir, const char *name, const char *relpath)
|
||||||
{
|
{
|
||||||
struct emu_thread *thread = calloc(1, sizeof(struct emu_thread));
|
struct emu_thread *thread = calloc(1, sizeof(struct emu_thread));
|
||||||
|
|
||||||
@ -24,8 +25,11 @@ new_thread(struct emu_proc *proc, const char *name, const char *relpath)
|
|||||||
if (snprintf(thread->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
if (snprintf(thread->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
||||||
die("new_thread: name too long: %s\n", name);
|
die("new_thread: name too long: %s\n", name);
|
||||||
|
|
||||||
|
if (snprintf(thread->path, PATH_MAX, "%s/%s", tracedir, relpath) >= PATH_MAX)
|
||||||
|
die("new_thread: path too long: %s/%s\n", tracedir, relpath);
|
||||||
|
|
||||||
if (snprintf(thread->relpath, PATH_MAX, "%s", relpath) >= PATH_MAX)
|
if (snprintf(thread->relpath, PATH_MAX, "%s", relpath) >= PATH_MAX)
|
||||||
die("new_proc: relative path too long: %s\n", relpath);
|
die("new_thread: relative path too long: %s\n", relpath);
|
||||||
|
|
||||||
thread->proc = proc;
|
thread->proc = proc;
|
||||||
|
|
||||||
@ -45,7 +49,7 @@ find_thread(struct emu_proc *proc, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_thread(struct emu_proc *proc, const char *relpath)
|
create_thread(struct emu_proc *proc, 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) {
|
||||||
@ -78,7 +82,7 @@ create_thread(struct emu_proc *proc, const char *relpath)
|
|||||||
struct emu_thread *thread = find_thread(proc, threadname);
|
struct emu_thread *thread = find_thread(proc, threadname);
|
||||||
|
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
thread = new_thread(proc, threadname, relpath);
|
thread = new_thread(proc, tracedir, threadname, relpath);
|
||||||
DL_APPEND2(proc->threads, thread, lprev, lnext);
|
DL_APPEND2(proc->threads, thread, lprev, lnext);
|
||||||
proc->nthreads++;
|
proc->nthreads++;
|
||||||
}
|
}
|
||||||
@ -87,7 +91,7 @@ create_thread(struct emu_proc *proc, const char *relpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_proc *
|
static struct emu_proc *
|
||||||
new_proc(struct emu_loom *loom, const char *name, const char *relpath)
|
new_proc(struct emu_loom *loom, const char *tracedir, const char *name)
|
||||||
{
|
{
|
||||||
struct emu_proc *proc = calloc(1, sizeof(struct emu_proc));
|
struct emu_proc *proc = calloc(1, sizeof(struct emu_proc));
|
||||||
|
|
||||||
@ -97,8 +101,11 @@ new_proc(struct emu_loom *loom, const char *name, const char *relpath)
|
|||||||
if (snprintf(proc->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
if (snprintf(proc->name, PATH_MAX, "%s", name) >= PATH_MAX)
|
||||||
die("new_proc: name too long: %s\n", name);
|
die("new_proc: name too long: %s\n", name);
|
||||||
|
|
||||||
if (snprintf(proc->relpath, PATH_MAX, "%s", relpath) >= PATH_MAX)
|
if (snprintf(proc->relpath, PATH_MAX, "%s/%s", loom->name, proc->name) >= PATH_MAX)
|
||||||
die("new_proc: relative path too long: %s\n", relpath);
|
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->loom = loom;
|
proc->loom = loom;
|
||||||
|
|
||||||
@ -118,7 +125,7 @@ find_proc(struct emu_loom *loom, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_proc(struct emu_loom *loom, const char *relpath)
|
create_proc(struct emu_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) {
|
||||||
@ -146,12 +153,12 @@ create_proc(struct emu_loom *loom, const char *relpath)
|
|||||||
struct emu_proc *proc = find_proc(loom, procname);
|
struct emu_proc *proc = find_proc(loom, procname);
|
||||||
|
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
proc = new_proc(loom, procname, relpath);
|
proc = new_proc(loom, tracedir, procname);
|
||||||
DL_APPEND2(loom->procs, proc, lprev, lnext);
|
DL_APPEND2(loom->procs, proc, lprev, lnext);
|
||||||
loom->nprocs++;
|
loom->nprocs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_thread(proc, relpath);
|
return create_thread(proc, tracedir, relpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_loom *
|
static struct emu_loom *
|
||||||
@ -165,7 +172,7 @@ find_loom(struct emu_system *sys, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct emu_loom *
|
static struct emu_loom *
|
||||||
new_loom(const char *name, const char *relpath)
|
new_loom(const char *tracedir, const char *name)
|
||||||
{
|
{
|
||||||
struct emu_loom *loom = calloc(1, sizeof(struct emu_loom));
|
struct emu_loom *loom = calloc(1, sizeof(struct emu_loom));
|
||||||
|
|
||||||
@ -175,8 +182,11 @@ new_loom(const char *name, const char *relpath)
|
|||||||
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);
|
||||||
|
|
||||||
if (snprintf(loom->relpath, PATH_MAX, "%s", relpath) >= PATH_MAX)
|
if (snprintf(loom->relpath, PATH_MAX, "%s", name) >= PATH_MAX)
|
||||||
die("new_loom: relative path too long: %s\n", relpath);
|
die("new_loom: relative path too long: %s\n", name);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
err("new loom '%s'\n", loom->name);
|
err("new loom '%s'\n", loom->name);
|
||||||
|
|
||||||
@ -184,7 +194,7 @@ new_loom(const char *name, const char *relpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_loom(struct emu_system *sys, const char *relpath)
|
create_loom(struct emu_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) {
|
||||||
@ -201,12 +211,12 @@ create_loom(struct emu_system *sys, const char *relpath)
|
|||||||
struct emu_loom *loom = find_loom(sys, name);
|
struct emu_loom *loom = find_loom(sys, name);
|
||||||
|
|
||||||
if (loom == NULL) {
|
if (loom == NULL) {
|
||||||
loom = new_loom(name, relpath);
|
loom = new_loom(tracedir, name);
|
||||||
DL_APPEND(sys->looms, loom);
|
DL_APPEND(sys->looms, loom);
|
||||||
sys->nlooms++;
|
sys->nlooms++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_proc(loom, relpath);
|
return create_proc(loom, tracedir, relpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -219,7 +229,7 @@ create_system(struct emu_system *sys, struct emu_trace *trace)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_loom(sys, s->relpath) != 0) {
|
if (create_loom(sys, trace->tracedir, s->relpath) != 0) {
|
||||||
err("create loom failed\n");
|
err("create loom failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -271,7 +281,7 @@ sort_system(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
populate_global_lists(struct emu_system *sys)
|
init_global_lpt_lists(struct emu_system *sys)
|
||||||
{
|
{
|
||||||
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
||||||
for (struct emu_proc *p = l->procs; p; p = p->lnext) {
|
for (struct emu_proc *p = l->procs; p; p = p->lnext) {
|
||||||
@ -280,7 +290,22 @@ populate_global_lists(struct emu_system *sys)
|
|||||||
}
|
}
|
||||||
DL_APPEND2(sys->procs, p, gprev, gnext);
|
DL_APPEND2(sys->procs, p, gprev, gnext);
|
||||||
}
|
}
|
||||||
/* Looms are already in emu_system */
|
|
||||||
|
/* Looms are already in sys->looms */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_global_cpus_list(struct emu_system *sys)
|
||||||
|
{
|
||||||
|
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
||||||
|
for (size_t i = 0; i < l->ncpus; i++) {
|
||||||
|
struct emu_cpu *cpu = &l->cpu[i];
|
||||||
|
DL_APPEND2(sys->cpus, cpu, prev, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Virtual CPU last */
|
||||||
|
DL_APPEND2(sys->cpus, &l->vcpu, prev, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,25 +315,426 @@ print_system(struct emu_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 emu_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("- path %s\n", l->path);
|
||||||
|
err("- relpath %s\n", l->relpath);
|
||||||
|
err("- processes:\n");
|
||||||
for (struct emu_proc *p = l->procs; p; p = p->lnext) {
|
for (struct emu_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(" - path %s\n", p->path);
|
||||||
|
err(" - relpath %s\n", p->relpath);
|
||||||
|
err(" - threads:\n");
|
||||||
for (struct emu_thread *t = p->threads; t; t = t->lnext) {
|
for (struct emu_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(" - path %s\n", t->path);
|
||||||
|
err(" - relpath %s\n", t->relpath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err("- cpus:\n");
|
||||||
|
for (size_t i = 0; i < l->ncpus; i++) {
|
||||||
|
struct emu_cpu *cpu = &l->cpu[i];
|
||||||
|
err(" %s\n", cpu->name);
|
||||||
|
err(" - i %d\n", cpu->i);
|
||||||
|
err(" - phyid %d\n", cpu->phyid);
|
||||||
|
err(" - gindex %ld\n", cpu->gindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct emu_cpu *cpu = &l->vcpu;
|
||||||
|
err("- %s\n", cpu->name);
|
||||||
|
err(" - i %d\n", cpu->i);
|
||||||
|
err(" - phyid %d\n", cpu->phyid);
|
||||||
|
err(" - gindex %ld\n", cpu->gindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_proc_attributes(struct emu_proc *proc, const char *path)
|
||||||
|
{
|
||||||
|
JSON_Object *meta = json_value_get_object(proc->meta);
|
||||||
|
if (meta == NULL) {
|
||||||
|
err("load_proc_attributes: json_value_get_object() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Value *appid_val = json_object_get_value(meta, "app_id");
|
||||||
|
if (appid_val == NULL) {
|
||||||
|
err("load_proc_attributes: missing app_id in metadata %s\n", path);
|
||||||
|
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);
|
||||||
|
proc->loom->rank_enabled = 1;
|
||||||
|
} else {
|
||||||
|
proc->rank = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_proc_metadata(JSON_Value *pmeta, const char *path)
|
||||||
|
{
|
||||||
|
JSON_Object *meta = json_value_get_object(pmeta);
|
||||||
|
if (meta == NULL) {
|
||||||
|
err("check_proc_metadata: json_value_get_object() failed for %s\n",
|
||||||
|
path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Value *version_val = json_object_get_value(meta, "version");
|
||||||
|
if (version_val == NULL) {
|
||||||
|
err("check_proc_metadata: missing attribute \"version\" in %s\n",
|
||||||
|
path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = (int) json_number(version_val);
|
||||||
|
|
||||||
|
if (version != OVNI_METADATA_VERSION) {
|
||||||
|
err("check_proc_metadata: metadata version mismatch %d (expected %d) in %s\n",
|
||||||
|
version, OVNI_METADATA_VERSION, path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Value *mversion_val = json_object_get_value(meta, "model_version");
|
||||||
|
if (mversion_val == NULL) {
|
||||||
|
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 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_proc_metadata(struct emu_proc *proc)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
if (snprintf(path, PATH_MAX, "%s/%s", proc->path, "metadata.json") >= PATH_MAX) {
|
||||||
|
err("load_proc_metadata: path too large: %s/%s\n",
|
||||||
|
proc->path, "metadata.json");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->meta = json_parse_file_with_comments(path);
|
||||||
|
if (proc->meta == NULL) {
|
||||||
|
err("load_proc_metadata: json_parse_file_with_comments(%s) failed\n",
|
||||||
|
path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_proc_metadata(proc->meta, path) != 0) {
|
||||||
|
err("load_proc_metadata: invalid metadata\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The appid is populated from the metadata */
|
||||||
|
if (load_proc_attributes(proc, path) != 0) {
|
||||||
|
err("load_proc_metadata: invalid attributes\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_metadata(struct emu_system *sys)
|
||||||
|
{
|
||||||
|
for (struct emu_proc *p = sys->procs; p; p = p->gnext) {
|
||||||
|
if (load_proc_metadata(p) != 0) {
|
||||||
|
err("error loading metadata for %s\n", p->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
has_cpus_array(JSON_Value *metadata)
|
||||||
|
{
|
||||||
|
JSON_Object *meta = json_value_get_object(metadata);
|
||||||
|
if (meta == NULL) {
|
||||||
|
err("has_cpus: json_value_get_object() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only check for the "cpus" key, if it has zero elements is an error
|
||||||
|
* that will be reported later */
|
||||||
|
JSON_Array *cpuarray = json_object_get_array(meta, "cpus");
|
||||||
|
|
||||||
|
if (cpuarray != NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_new_cpu(struct emu_loom *loom, int i, int phyid)
|
||||||
|
{
|
||||||
|
struct emu_cpu *cpu = &loom->cpu[i];
|
||||||
|
|
||||||
|
if (i < 0 || i >= (int) loom->ncpus) {
|
||||||
|
err("add_new_cpu: new CPU i=%d out of bounds in %s\n",
|
||||||
|
i, loom->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpu->state != CPU_ST_UNKNOWN) {
|
||||||
|
die("add_new_cpu: new CPU i=%d in unexpected in %s\n",
|
||||||
|
i, loom->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu->state = CPU_ST_READY;
|
||||||
|
cpu->i = i;
|
||||||
|
cpu->phyid = phyid;
|
||||||
|
cpu->loom = loom;
|
||||||
|
cpu->is_virtual = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_proc_cpus(struct emu_proc *proc)
|
||||||
|
{
|
||||||
|
JSON_Object *meta = json_value_get_object(proc->meta);
|
||||||
|
if (meta == NULL) {
|
||||||
|
err("load_proc_cpus: json_value_get_object() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Array *cpuarray = json_object_get_array(meta, "cpus");
|
||||||
|
|
||||||
|
/* This process doesn't have the cpu list, but it should */
|
||||||
|
if (cpuarray == NULL) {
|
||||||
|
err("load_proc_cpus: json_object_get_array() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ncpus = json_array_get_count(cpuarray);
|
||||||
|
if (ncpus == 0) {
|
||||||
|
err("load_proc_cpus: the 'cpus' array is empty in metadata of %s\n",
|
||||||
|
proc->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct emu_loom *loom = proc->loom;
|
||||||
|
loom->ncpus = ncpus;
|
||||||
|
loom->cpu = calloc(ncpus, sizeof(struct emu_cpu));
|
||||||
|
|
||||||
|
if (loom->cpu == NULL) {
|
||||||
|
err("load_proc_cpus: calloc failed: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ncpus; i++) {
|
||||||
|
JSON_Object *cpu = json_array_get_object(cpuarray, i);
|
||||||
|
|
||||||
|
if (cpu == NULL) {
|
||||||
|
err("proc_load_cpus: json_array_get_object() failed for cpu\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = (int) json_object_get_number(cpu, "index");
|
||||||
|
int phyid = (int) json_object_get_number(cpu, "phyid");
|
||||||
|
|
||||||
|
if (add_new_cpu(loom, index, phyid) != 0) {
|
||||||
|
err("proc_load_cpus: add_new_cpu() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_virtual_cpu(struct emu_loom *loom)
|
||||||
|
{
|
||||||
|
struct emu_cpu *vcpu = &loom->vcpu;
|
||||||
|
|
||||||
|
if (vcpu->state != CPU_ST_UNKNOWN) {
|
||||||
|
err("init_virtual_cpu: unexpected virtual CPU state in %s\n",
|
||||||
|
loom->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vcpu->state = CPU_ST_READY;
|
||||||
|
vcpu->i = -1;
|
||||||
|
vcpu->phyid = -1;
|
||||||
|
vcpu->loom = loom;
|
||||||
|
vcpu->is_virtual = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_loom_cpus(struct emu_loom *loom)
|
||||||
|
{
|
||||||
|
/* The process that contains the CPU list */
|
||||||
|
struct emu_proc *proc_cpus = NULL;
|
||||||
|
|
||||||
|
/* Search for the cpu list in all processes.
|
||||||
|
* Only one should contain it. */
|
||||||
|
for (struct emu_proc *p = loom->procs; p; p = p->lnext) {
|
||||||
|
if (!has_cpus_array(p->meta))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (proc_cpus != NULL) {
|
||||||
|
err("load_loom_cpus: duplicated cpu list provided in '%s' and '%s'\n",
|
||||||
|
proc_cpus->relpath,
|
||||||
|
p->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load_proc_cpus(p) != 0) {
|
||||||
|
err("load_loom_cpus: load_proc_cpus failed: %s\n",
|
||||||
|
p->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_cpus = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One of the process must have the list of CPUs */
|
||||||
|
if (proc_cpus == NULL) {
|
||||||
|
err("load_loom_cpus: no process contains a CPU list for %s\n",
|
||||||
|
loom->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loom->ncpus == 0) {
|
||||||
|
err("load_loom_cpus: no CPUs found in loom %s\n",
|
||||||
|
loom->relpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Obtain CPUs in the metadata files and other data */
|
||||||
|
static int
|
||||||
|
init_cpus(struct emu_system *sys)
|
||||||
|
{
|
||||||
|
for (struct emu_loom *l = sys->looms; l; l = l->next) {
|
||||||
|
if (load_loom_cpus(l) != 0) {
|
||||||
|
err("init_cpus: load_loom_cpus() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_virtual_cpu(l) != 0) {
|
||||||
|
err("init_cpus: init_virtual_cpu() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_global_indices(struct emu_system *sys)
|
||||||
|
{
|
||||||
|
size_t iloom = 0;
|
||||||
|
for (struct emu_loom *l = sys->looms; l; l = l->next)
|
||||||
|
l->gindex = iloom++;
|
||||||
|
|
||||||
|
sys->nprocs = 0;
|
||||||
|
for (struct emu_proc *p = sys->procs; p; p = p->gnext)
|
||||||
|
p->gindex = sys->nprocs++;
|
||||||
|
|
||||||
|
sys->nthreads = 0;
|
||||||
|
for (struct emu_thread *t = sys->threads; t; t = t->gnext)
|
||||||
|
t->gindex = sys->nprocs++;
|
||||||
|
|
||||||
|
sys->ncpus = 0;
|
||||||
|
for (struct emu_cpu *c = sys->cpus; c; c = c->next)
|
||||||
|
c->gindex = sys->ncpus++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_cpu_name(struct emu_cpu *cpu)
|
||||||
|
{
|
||||||
|
size_t i = cpu->loom->gindex;
|
||||||
|
size_t j = cpu->i;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (cpu->is_virtual)
|
||||||
|
n = snprintf(cpu->name, PATH_MAX, "vCPU %ld.*", i);
|
||||||
|
else
|
||||||
|
n = snprintf(cpu->name, PATH_MAX, "CPU %ld.%ld", i, j);
|
||||||
|
|
||||||
|
if (n >= PATH_MAX) {
|
||||||
|
err("init_cpu_name: cpu name too long\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_cpu_names(struct emu_system *sys)
|
||||||
|
{
|
||||||
|
for (struct emu_cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
|
||||||
|
if (init_cpu_name(cpu) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
emu_system_load(struct emu_system *sys, struct emu_trace *trace)
|
emu_system_load(struct emu_system *sys, struct emu_trace *trace)
|
||||||
{
|
{
|
||||||
|
/* Parse the emu_trace and create the looms, procs and threads */
|
||||||
if (create_system(sys, trace) != 0) {
|
if (create_system(sys, trace) != 0) {
|
||||||
err("emu_system_load: create system failed\n");
|
err("emu_system_load: create system failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure they are sorted so they are easier to read */
|
||||||
sort_system(sys);
|
sort_system(sys);
|
||||||
populate_global_lists(sys);
|
|
||||||
|
/* Init global lists build after sorting */
|
||||||
|
init_global_lpt_lists(sys);
|
||||||
|
|
||||||
|
/* Now load all process metadata and set attributes */
|
||||||
|
if (load_metadata(sys) != 0) {
|
||||||
|
err("emu_system_load: load_metadata() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* From the metadata extract the CPUs too */
|
||||||
|
if (init_cpus(sys) != 0) {
|
||||||
|
err("emu_system_load: load_cpus() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_global_cpus_list(sys);
|
||||||
|
|
||||||
|
/* Now that we have loaded all resources, populate the indices */
|
||||||
|
init_global_indices(sys);
|
||||||
|
|
||||||
|
if (init_cpu_names(sys) != 0) {
|
||||||
|
err("emu_system_load: init_cpu_names() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finaly dump the system */
|
||||||
print_system(sys);
|
print_system(sys);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -29,15 +29,15 @@ struct model_ctx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct emu_cpu {
|
struct emu_cpu {
|
||||||
|
size_t gindex; /* In the system */
|
||||||
|
char name[PATH_MAX];
|
||||||
|
|
||||||
/* Logical index: 0 to ncpus - 1 */
|
/* Logical index: 0 to ncpus - 1 */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Physical id: as reported by lscpu(1) */
|
/* Physical id: as reported by lscpu(1) */
|
||||||
int phyid;
|
int phyid;
|
||||||
|
|
||||||
/* Global index for all CPUs */
|
|
||||||
int gindex;
|
|
||||||
|
|
||||||
enum emu_cpu_state state;
|
enum emu_cpu_state state;
|
||||||
|
|
||||||
/* The loom of the CPU */
|
/* The loom of the CPU */
|
||||||
@ -52,8 +52,7 @@ struct emu_cpu {
|
|||||||
size_t nactive_threads;
|
size_t nactive_threads;
|
||||||
struct emu_thread *th_active;
|
struct emu_thread *th_active;
|
||||||
|
|
||||||
/* Is this a virtual CPU? */
|
int is_virtual;
|
||||||
int virtual;
|
|
||||||
|
|
||||||
/* Global list */
|
/* Global list */
|
||||||
struct emu_cpu *next;
|
struct emu_cpu *next;
|
||||||
@ -73,12 +72,14 @@ enum emu_thread_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct emu_thread {
|
struct emu_thread {
|
||||||
|
size_t gindex; /* In the system */
|
||||||
|
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
|
char path[PATH_MAX];
|
||||||
char relpath[PATH_MAX];
|
char relpath[PATH_MAX];
|
||||||
|
|
||||||
int tid;
|
int tid;
|
||||||
int index; /* In loom */
|
int index; /* In loom */
|
||||||
int gindex; /* In emu */
|
|
||||||
|
|
||||||
/* The process associated with this thread */
|
/* The process associated with this thread */
|
||||||
struct emu_proc *proc;
|
struct emu_proc *proc;
|
||||||
@ -107,12 +108,14 @@ struct emu_thread {
|
|||||||
|
|
||||||
/* State of each emulated process */
|
/* State of each emulated process */
|
||||||
struct emu_proc {
|
struct emu_proc {
|
||||||
|
size_t gindex;
|
||||||
|
|
||||||
char name[PATH_MAX]; /* Proc directory name */
|
char name[PATH_MAX]; /* Proc directory name */
|
||||||
|
char path[PATH_MAX];
|
||||||
char relpath[PATH_MAX];
|
char relpath[PATH_MAX];
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
int index;
|
int index;
|
||||||
int gindex;
|
|
||||||
int appid;
|
int appid;
|
||||||
int rank;
|
int rank;
|
||||||
|
|
||||||
@ -135,10 +138,14 @@ struct emu_proc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct emu_loom {
|
struct emu_loom {
|
||||||
char hostname[OVNI_MAX_HOSTNAME];
|
size_t gindex;
|
||||||
|
|
||||||
char name[PATH_MAX]; /* Loom directory name */
|
char name[PATH_MAX]; /* Loom directory name */
|
||||||
|
char path[PATH_MAX];
|
||||||
char relpath[PATH_MAX]; /* Relative to tracedir */
|
char relpath[PATH_MAX]; /* Relative to tracedir */
|
||||||
|
|
||||||
|
char hostname[OVNI_MAX_HOSTNAME];
|
||||||
|
|
||||||
size_t max_ncpus;
|
size_t max_ncpus;
|
||||||
size_t max_phyid;
|
size_t max_phyid;
|
||||||
size_t ncpus;
|
size_t ncpus;
|
||||||
@ -163,6 +170,7 @@ struct emu_loom {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct emu_system {
|
struct emu_system {
|
||||||
|
/* Total counters */
|
||||||
size_t nlooms;
|
size_t nlooms;
|
||||||
size_t nthreads;
|
size_t nthreads;
|
||||||
size_t nprocs;
|
size_t nprocs;
|
||||||
|
Loading…
Reference in New Issue
Block a user