ovni/src/emu/proc.c

203 lines
3.5 KiB
C

/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "proc.h"
#include "utlist.h"
#include "path.h"
#include <errno.h>
static int
get_pid(const char *id, int *pid)
{
/* TODO: Store the PID the metadata.json instead */
/* The id must be like "loom.host01.123/proc.345" */
if (path_count(id, '/') != 1) {
err("proc id can only contain one '/': %s", id);
return -1;
}
/* Get the proc.345 part */
const char *procname;
if (path_next(id, '/', &procname) != 0) {
err("cannot get proc name");
return -1;
}
/* Ensure the prefix is ok */
const char prefix[] = "proc.";
if (!path_has_prefix(procname, prefix)) {
err("proc name must start with '%s': %s", prefix, id);
return -1;
}
/* Get the 345 part */
const char *pidstr;
if (path_next(procname, '.', &pidstr) != 0) {
err("cannot find proc dot in '%s'", id);
return -1;
}
*pid = atoi(pidstr);
return 0;
}
int
proc_relpath_get_pid(const char *relpath, int *pid)
{
char id[PATH_MAX];
if (snprintf(id, PATH_MAX, "%s", relpath) >= PATH_MAX) {
err("path too long");
return -1;
}
if (path_keep(id, 2) != 0) {
err("cannot delimite proc dir");
return -1;
}
return get_pid(id, pid);
}
int
proc_init_begin(struct proc *proc, const char *relpath)
{
memset(proc, 0, sizeof(struct proc));
proc->gindex = -1;
if (snprintf(proc->id, PATH_MAX, "%s", relpath) >= PATH_MAX) {
err("path too long");
return -1;
}
if (path_keep(proc->id, 2) != 0) {
err("cannot delimite proc dir");
return -1;
}
if (get_pid(proc->id, &proc->pid) != 0) {
err("cannot parse proc pid");
return -1;
}
dbg("created proc %s", proc->id);
return 0;
}
void
proc_set_gindex(struct proc *proc, int64_t gindex)
{
proc->gindex = gindex;
}
void
proc_set_loom(struct proc *proc, struct loom *loom)
{
proc->loom = loom;
}
int
proc_load_metadata(struct proc *proc, JSON_Object *meta)
{
if (proc->metadata_loaded) {
err("process %s already loaded metadata", proc->id);
return -1;
}
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;
proc->metadata_loaded = 1;
return 0;
}
struct thread *
proc_find_thread(struct proc *proc, int tid)
{
struct thread *thread = NULL;
HASH_FIND_INT(proc->threads, &tid, thread);
return thread;
}
int
proc_add_thread(struct proc *proc, struct thread *thread)
{
if (proc->is_init) {
err("cannot modify threads of initialized proc");
return -1;
}
int tid = thread_get_tid(thread);
if (proc_find_thread(proc, tid) != NULL) {
err("thread with tid %d already in proc %s", tid, proc->id);
return -1;
}
HASH_ADD_INT(proc->threads, tid, thread);
proc->nthreads++;
return 0;
}
static int
by_tid(struct thread *t1, struct thread *t2)
{
int id1 = thread_get_tid(t1);
int id2 = thread_get_tid(t2);
if (id1 < id2)
return -1;
if (id1 > id2)
return +1;
else
return 0;
}
void
proc_sort(struct proc *proc)
{
HASH_SORT(proc->threads, by_tid);
}
int
proc_init_end(struct proc *proc)
{
if (proc->gindex < 0) {
err("gindex not set");
return -1;
}
if (!proc->metadata_loaded) {
err("metadata not loaded");
return -1;
}
proc->is_init = 1;
return 0;
}
int
proc_get_pid(struct proc *proc)
{
return proc->pid;
}