Register emulation models only if required
Until now, emulation models were always being registered via probe(), which causes the emulator to initialize all the channels. To reduce the overhead, the channels were not connected or registered in the bay until the first event of that model was received. This delayed connect was causing issues in muxes where the newly connected model required refreshing the touched channels. Which in turn was causing unexpected PRV events. By determining which models we need to enable, we can remove the delayed connect mechanism and just enable those models at initialization time, and connect the channels.
This commit is contained in:
parent
3d10bef305
commit
354f2f50eb
@ -20,8 +20,9 @@ static const char model_name[] = "kernel";
|
|||||||
enum { model_id = 'K' };
|
enum { model_id = 'K' };
|
||||||
|
|
||||||
struct model_spec model_kernel = {
|
struct model_spec model_kernel = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_kernel_create,
|
.create = model_kernel_create,
|
||||||
// .connect = model_kernel_connect,
|
// .connect = model_kernel_connect,
|
||||||
.event = model_kernel_event,
|
.event = model_kernel_event,
|
||||||
@ -117,10 +118,7 @@ static const struct model_thread_spec th_spec = {
|
|||||||
int
|
int
|
||||||
model_kernel_probe(struct emu *emu)
|
model_kernel_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_kernel, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
struct emu;
|
#include "version.h"
|
||||||
|
#include "emu.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
model_init(struct model *model)
|
model_init(struct model *model)
|
||||||
@ -17,6 +19,16 @@ model_register(struct model *model, struct model_spec *spec)
|
|||||||
{
|
{
|
||||||
int i = spec->model;
|
int i = spec->model;
|
||||||
|
|
||||||
|
if (spec->name == NULL) {
|
||||||
|
err("model %c missing name", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spec->version == NULL) {
|
||||||
|
err("model %c missing version", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (model->registered[i]) {
|
if (model->registered[i]) {
|
||||||
err("model %c already registered", i);
|
err("model %c already registered", i);
|
||||||
return -1;
|
return -1;
|
||||||
@ -47,10 +59,10 @@ model_probe(struct model *model, struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
dbg("model %c disabled", (char) i);
|
||||||
|
} else {
|
||||||
model->enabled[i] = 1;
|
model->enabled[i] = 1;
|
||||||
dbg("model %c enabled", (char) i);
|
dbg("model %c enabled", (char) i);
|
||||||
} else {
|
|
||||||
dbg("model %c disabled", (char) i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -141,3 +153,58 @@ model_finish(struct model *model, struct emu *emu)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
model_version_probe(struct model_spec *spec, struct emu *emu)
|
||||||
|
{
|
||||||
|
int enable = 0;
|
||||||
|
int have[3];
|
||||||
|
|
||||||
|
if (version_parse(spec->version, have) != 0) {
|
||||||
|
err("cannot parse version %s", spec->version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[128];
|
||||||
|
if (snprintf(path, 128, "%s.version", spec->name) >= 128)
|
||||||
|
die("model %s name too long", spec->name);
|
||||||
|
|
||||||
|
/* Find a stream with an model name key */
|
||||||
|
struct system *sys = &emu->system;
|
||||||
|
for (struct thread *t = sys->threads; t; t = t->gnext) {
|
||||||
|
/* The ovni.require key is mandatory */
|
||||||
|
JSON_Object *require = json_object_dotget_object(t->meta, "ovni.require");
|
||||||
|
if (require == NULL) {
|
||||||
|
err("missing 'ovni.require' key in metadata");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* But not all threads need to have this model */
|
||||||
|
const char *req_version = json_object_get_string(require, spec->name);
|
||||||
|
if (req_version == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int want[3];
|
||||||
|
if (version_parse(req_version, want) != 0) {
|
||||||
|
err("cannot parse version %s", req_version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!version_is_compatible(want, have)) {
|
||||||
|
err("unsupported %s model version (want %s, have %s) in %s",
|
||||||
|
spec->name, req_version, spec->version,
|
||||||
|
t->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
dbg("model %s enabled", spec->name);
|
||||||
|
} else {
|
||||||
|
dbg("model %s disabled", spec->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return enable;
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ struct emu;
|
|||||||
|
|
||||||
struct model_spec {
|
struct model_spec {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const char *version;
|
||||||
int model;
|
int model;
|
||||||
char *depends;
|
char *depends;
|
||||||
emu_hook_t *probe;
|
emu_hook_t *probe;
|
||||||
@ -34,5 +35,6 @@ USE_RET int model_create(struct model *model, struct emu *emu);
|
|||||||
USE_RET int model_connect(struct model *model, struct emu *emu);
|
USE_RET int model_connect(struct model *model, struct emu *emu);
|
||||||
USE_RET int model_event(struct model *model, struct emu *emu, int index);
|
USE_RET int model_event(struct model *model, struct emu *emu, int index);
|
||||||
USE_RET int model_finish(struct model *model, struct emu *emu);
|
USE_RET int model_finish(struct model *model, struct emu *emu);
|
||||||
|
USE_RET int model_version_probe(struct model_spec *spec, struct emu *emu);
|
||||||
|
|
||||||
#endif /* MODEL_H */
|
#endif /* MODEL_H */
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
extern struct model_spec model_ovni;
|
extern struct model_spec model_ovni;
|
||||||
extern struct model_spec model_nanos6;
|
extern struct model_spec model_nanos6;
|
||||||
@ -38,3 +39,14 @@ models_register(struct model *model)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
models_get_version(const char *name)
|
||||||
|
{
|
||||||
|
for (int i = 0; models[i] != NULL; i++) {
|
||||||
|
if (strcmp(models[i]->name, name) == 0)
|
||||||
|
return models[i]->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
struct model;
|
struct model;
|
||||||
|
|
||||||
USE_RET int models_register(struct model *model);
|
USE_RET int models_register(struct model *model);
|
||||||
|
USE_RET const char *models_get_version(const char *name);
|
||||||
|
|
||||||
#endif /* MODELS_H */
|
#endif /* MODELS_H */
|
||||||
|
@ -25,8 +25,9 @@ static const char model_name[] = "mpi";
|
|||||||
enum { model_id = 'M' };
|
enum { model_id = 'M' };
|
||||||
|
|
||||||
struct model_spec model_mpi = {
|
struct model_spec model_mpi = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_mpi_create,
|
.create = model_mpi_create,
|
||||||
// .connect = model_mpi_connect,
|
// .connect = model_mpi_connect,
|
||||||
.event = model_mpi_event,
|
.event = model_mpi_event,
|
||||||
@ -171,10 +172,7 @@ static const struct model_thread_spec th_spec = {
|
|||||||
int
|
int
|
||||||
model_mpi_probe(struct emu *emu)
|
model_mpi_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_mpi, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -32,8 +32,9 @@ static const char model_name[] = "nanos6";
|
|||||||
enum { model_id = '6' };
|
enum { model_id = '6' };
|
||||||
|
|
||||||
struct model_spec model_nanos6 = {
|
struct model_spec model_nanos6 = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_nanos6_create,
|
.create = model_nanos6_create,
|
||||||
.connect = model_nanos6_connect,
|
.connect = model_nanos6_connect,
|
||||||
.event = model_nanos6_event,
|
.event = model_nanos6_event,
|
||||||
@ -216,10 +217,7 @@ static const struct model_thread_spec th_spec = {
|
|||||||
int
|
int
|
||||||
model_nanos6_probe(struct emu *emu)
|
model_nanos6_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_nanos6, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -25,8 +25,9 @@ static const char model_name[] = "nodes";
|
|||||||
enum { model_id = 'D' };
|
enum { model_id = 'D' };
|
||||||
|
|
||||||
struct model_spec model_nodes = {
|
struct model_spec model_nodes = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_nodes_create,
|
.create = model_nodes_create,
|
||||||
// .connect = model_nodes_connect,
|
// .connect = model_nodes_connect,
|
||||||
.event = model_nodes_event,
|
.event = model_nodes_event,
|
||||||
@ -130,10 +131,7 @@ static const struct model_thread_spec th_spec = {
|
|||||||
int
|
int
|
||||||
model_nodes_probe(struct emu *emu)
|
model_nodes_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_nodes, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -30,8 +30,9 @@ static const char model_name[] = "nosv";
|
|||||||
enum { model_id = 'V' };
|
enum { model_id = 'V' };
|
||||||
|
|
||||||
struct model_spec model_nosv = {
|
struct model_spec model_nosv = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_nosv_create,
|
.create = model_nosv_create,
|
||||||
// .connect = model_nosv_connect,
|
// .connect = model_nosv_connect,
|
||||||
.event = model_nosv_event,
|
.event = model_nosv_event,
|
||||||
@ -180,10 +181,7 @@ static const struct model_cpu_spec cpu_spec = {
|
|||||||
int
|
int
|
||||||
model_nosv_probe(struct emu *emu)
|
model_nosv_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_nosv, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -21,8 +21,9 @@ static const char model_name[] = "ovni";
|
|||||||
enum { model_id = 'O' };
|
enum { model_id = 'O' };
|
||||||
|
|
||||||
struct model_spec model_ovni = {
|
struct model_spec model_ovni = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_ovni_create,
|
.create = model_ovni_create,
|
||||||
.connect = model_ovni_connect,
|
.connect = model_ovni_connect,
|
||||||
.event = model_ovni_event,
|
.event = model_ovni_event,
|
||||||
@ -117,10 +118,7 @@ static const struct model_thread_spec th_spec = {
|
|||||||
int
|
int
|
||||||
model_ovni_probe(struct emu *emu)
|
model_ovni_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_ovni, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -25,8 +25,9 @@ static const char model_name[] = "tampi";
|
|||||||
enum { model_id = 'T' };
|
enum { model_id = 'T' };
|
||||||
|
|
||||||
struct model_spec model_tampi = {
|
struct model_spec model_tampi = {
|
||||||
.name = model_name,
|
.name = model_name,
|
||||||
.model = model_id,
|
.version = "1.0.0",
|
||||||
|
.model = model_id,
|
||||||
.create = model_tampi_create,
|
.create = model_tampi_create,
|
||||||
// .connect = model_tampi_connect,
|
// .connect = model_tampi_connect,
|
||||||
.event = model_tampi_event,
|
.event = model_tampi_event,
|
||||||
@ -134,10 +135,7 @@ static const struct model_thread_spec th_spec = {
|
|||||||
int
|
int
|
||||||
model_tampi_probe(struct emu *emu)
|
model_tampi_probe(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (emu->system.nthreads == 0)
|
return model_version_probe(&model_tampi, emu);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -62,3 +62,20 @@ version_parse(const char *version, int tuple[3])
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Finds if two versions are compatible.
|
||||||
|
*
|
||||||
|
* Returns 1 if the version `want` is compatible with the version `have`.
|
||||||
|
* Otherwise returns 0. */
|
||||||
|
static inline int
|
||||||
|
version_is_compatible(int want[3], int have[3])
|
||||||
|
{
|
||||||
|
/* Major must match exactly */
|
||||||
|
if (want[0] != have[0])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (want[1] > have[1])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -464,6 +464,52 @@ thread_metadata_store(void)
|
|||||||
die("failed to write thread metadata");
|
die("failed to write thread metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
thread_require_unsafe(const char *model, const char *version)
|
||||||
|
{
|
||||||
|
int parsedver[3];
|
||||||
|
if (version_parse(version, parsedver) != 0)
|
||||||
|
die("failed to parse provided version \"%s\"", version);
|
||||||
|
|
||||||
|
/* Store into metadata */
|
||||||
|
JSON_Object *meta = json_value_get_object(rthread.meta);
|
||||||
|
|
||||||
|
if (meta == NULL)
|
||||||
|
die("json_value_get_object failed");
|
||||||
|
|
||||||
|
char dotpath[128];
|
||||||
|
if (snprintf(dotpath, 128, "ovni.require.%s", model) >= 128)
|
||||||
|
die("model name too long");
|
||||||
|
|
||||||
|
/* TODO: What if is already set? */
|
||||||
|
|
||||||
|
if (json_object_dotset_string(meta, dotpath, version) != 0)
|
||||||
|
die("json_object_dotset_string failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ovni_thread_require(const char *model, const char *version)
|
||||||
|
{
|
||||||
|
if (!rthread.ready)
|
||||||
|
die("thread not initialized");
|
||||||
|
|
||||||
|
/* Sanitize model */
|
||||||
|
if (model == NULL)
|
||||||
|
die("model string is NULL");
|
||||||
|
|
||||||
|
if (strpbrk(model, " .") != NULL)
|
||||||
|
die("malformed model name");
|
||||||
|
|
||||||
|
if (strlen(model) <= 1)
|
||||||
|
die("model name must have more than 1 character");
|
||||||
|
|
||||||
|
/* Sanitize version */
|
||||||
|
if (version == NULL)
|
||||||
|
die("version string is NULL");
|
||||||
|
|
||||||
|
thread_require_unsafe(model, version);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
thread_metadata_populate(void)
|
thread_metadata_populate(void)
|
||||||
{
|
{
|
||||||
@ -475,11 +521,13 @@ thread_metadata_populate(void)
|
|||||||
if (json_object_dotset_number(meta, "version", OVNI_METADATA_VERSION) != 0)
|
if (json_object_dotset_number(meta, "version", OVNI_METADATA_VERSION) != 0)
|
||||||
die("json_object_dotset_string failed");
|
die("json_object_dotset_string failed");
|
||||||
|
|
||||||
if (json_object_dotset_string(meta, "libovni.version", OVNI_LIB_VERSION) != 0)
|
if (json_object_dotset_string(meta, "ovni.lib.version", OVNI_LIB_VERSION) != 0)
|
||||||
die("json_object_dotset_string failed");
|
die("json_object_dotset_string failed");
|
||||||
|
|
||||||
if (json_object_dotset_string(meta, "libovni.commit", OVNI_GIT_COMMIT) != 0)
|
if (json_object_dotset_string(meta, "ovni.lib.commit", OVNI_GIT_COMMIT) != 0)
|
||||||
die("json_object_dotset_string failed");
|
die("json_object_dotset_string failed");
|
||||||
|
|
||||||
|
thread_require_unsafe("ovni", "1.0.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -527,46 +575,6 @@ ovni_thread_init(pid_t tid)
|
|||||||
rthread.ready = 1;
|
rthread.ready = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ovni_thread_require(const char *model, const char *version)
|
|
||||||
{
|
|
||||||
if (!rthread.ready)
|
|
||||||
die("thread not initialized");
|
|
||||||
|
|
||||||
/* Sanitize model */
|
|
||||||
if (model == NULL)
|
|
||||||
die("model string is NULL");
|
|
||||||
|
|
||||||
if (strpbrk(model, " .") != NULL)
|
|
||||||
die("malformed model name");
|
|
||||||
|
|
||||||
if (strlen(model) <= 1)
|
|
||||||
die("model name must have more than 1 character");
|
|
||||||
|
|
||||||
/* Sanitize version */
|
|
||||||
if (version == NULL)
|
|
||||||
die("version string is NULL");
|
|
||||||
|
|
||||||
int parsedver[3];
|
|
||||||
if (version_parse(version, parsedver) != 0)
|
|
||||||
die("failed to parse provided version \"%s\"", version);
|
|
||||||
|
|
||||||
/* Store into metadata */
|
|
||||||
JSON_Object *meta = json_value_get_object(rthread.meta);
|
|
||||||
|
|
||||||
if (meta == NULL)
|
|
||||||
die("json_value_get_object failed");
|
|
||||||
|
|
||||||
char dotpath[128];
|
|
||||||
if (snprintf(dotpath, 128, "require.%s.version", model) >= 128)
|
|
||||||
die("model name too long");
|
|
||||||
|
|
||||||
/* TODO: What if is already set? */
|
|
||||||
|
|
||||||
if (json_object_dotset_string(meta, dotpath, version) != 0)
|
|
||||||
die("json_object_dotset_string failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ovni_thread_free(void)
|
ovni_thread_free(void)
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
|
#include "emu/models.h"
|
||||||
|
|
||||||
extern int first_clock_set;
|
extern int first_clock_set;
|
||||||
extern int64_t first_clock;
|
extern int64_t first_clock;
|
||||||
@ -75,6 +76,16 @@ instr_thread_end(void)
|
|||||||
ovni_flush();
|
ovni_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
instr_require(const char *model)
|
||||||
|
{
|
||||||
|
const char *version = models_get_version(model);
|
||||||
|
if (version == NULL)
|
||||||
|
die("cannot find version of model %s", model);
|
||||||
|
|
||||||
|
ovni_thread_require(model, version);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
instr_start(int rank, int nranks)
|
instr_start(int rank, int nranks)
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@ main(void)
|
|||||||
* stack causes the emulator to fail */
|
* stack causes the emulator to fail */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_mpi_init();
|
||||||
|
|
||||||
instr_mpi_init_thread_enter();
|
instr_mpi_init_thread_enter();
|
||||||
/* The thread is left in the MPI_Init_thread state (should fail) */
|
/* The thread is left in the MPI_Init_thread state (should fail) */
|
||||||
|
@ -10,9 +10,10 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
/* Test that a thread calling the mpi function that is already executing
|
/* Test that a thread calling the mpi function that is already executing
|
||||||
* causes the emulator to fail */
|
* causes the emulator to fail */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_mpi_init();
|
||||||
|
|
||||||
instr_mpi_init_thread_enter();
|
instr_mpi_init_thread_enter();
|
||||||
/* The thread runs the same mpi function in a nested way (should fail) */
|
/* The thread runs the same mpi function in a nested way (should fail) */
|
||||||
|
@ -15,6 +15,7 @@ main(void)
|
|||||||
const int nranks = atoi(getenv("OVNI_NRANKS"));
|
const int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
|
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_mpi_init();
|
||||||
|
|
||||||
/* Initialize MPI */
|
/* Initialize MPI */
|
||||||
instr_mpi_init_thread_enter();
|
instr_mpi_init_thread_enter();
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
#include "instr.h"
|
#include "instr.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
instr_mpi_init(void)
|
||||||
|
{
|
||||||
|
instr_require("mpi");
|
||||||
|
}
|
||||||
|
|
||||||
INSTR_0ARG(instr_mpi_init_thread_enter, "MUt")
|
INSTR_0ARG(instr_mpi_init_thread_enter, "MUt")
|
||||||
INSTR_0ARG(instr_mpi_init_thread_exit, "MUT")
|
INSTR_0ARG(instr_mpi_init_thread_exit, "MUT")
|
||||||
INSTR_0ARG(instr_mpi_finalize_enter, "MUf")
|
INSTR_0ARG(instr_mpi_finalize_enter, "MUf")
|
||||||
|
@ -13,6 +13,7 @@ main(void)
|
|||||||
int rank = atoi(getenv("OVNI_RANK"));
|
int rank = atoi(getenv("OVNI_RANK"));
|
||||||
int nranks = atoi(getenv("OVNI_NRANKS"));
|
int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
int us = 500;
|
int us = 500;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
@ -27,6 +27,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
/* Match the PRV line in the trace */
|
/* Match the PRV line in the trace */
|
||||||
FILE *f = fopen("match.sh", "w");
|
FILE *f = fopen("match.sh", "w");
|
||||||
|
@ -13,6 +13,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
/* Until here, the nanos6 model has not been connected to the
|
/* Until here, the nanos6 model has not been connected to the
|
||||||
* patchbay yet. The next event will cause the subsystem mux to
|
* patchbay yet. The next event will cause the subsystem mux to
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
instr_nanos6_init(void)
|
||||||
|
{
|
||||||
|
instr_require("nanos6");
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
instr_nanos6_type_create(int32_t typeid)
|
instr_nanos6_type_create(int32_t typeid)
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
uint32_t typeid = 666;
|
uint32_t typeid = 666;
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create(typeid);
|
||||||
|
@ -10,6 +10,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
@ -11,6 +11,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
uint32_t typeid = 666;
|
uint32_t typeid = 666;
|
||||||
instr_nanos6_type_create(typeid);
|
instr_nanos6_type_create(typeid);
|
||||||
|
@ -13,6 +13,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
int type = PRV_NANOS6_BREAKDOWN;
|
int type = PRV_NANOS6_BREAKDOWN;
|
||||||
FILE *f = fopen("match.sh", "w");
|
FILE *f = fopen("match.sh", "w");
|
||||||
|
@ -13,6 +13,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
instr_nanos6_sponge_enter();
|
instr_nanos6_sponge_enter();
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ main(void)
|
|||||||
* the stack causes the emulator to fail */
|
* the stack causes the emulator to fail */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
instr_nanos6_worker_loop_enter();
|
instr_nanos6_worker_loop_enter();
|
||||||
/* The thread is left in the worker loop state (should fail) */
|
/* The thread is left in the worker loop state (should fail) */
|
||||||
|
@ -16,6 +16,7 @@ main(void)
|
|||||||
* rank. */
|
* rank. */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
uint32_t gid = instr_nanos6_type_create(typeid);
|
uint32_t gid = instr_nanos6_type_create(typeid);
|
||||||
|
@ -13,6 +13,7 @@ main(void)
|
|||||||
int nranks = atoi(getenv("OVNI_NRANKS"));
|
int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
|
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_nanos6_init();
|
||||||
|
|
||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
int ntypes = 10;
|
int ntypes = 10;
|
||||||
|
@ -6,7 +6,7 @@ test_emu(nested-tasks-bad.c SHOULD_FAIL
|
|||||||
REGEX "cannot execute task 1: state is not created")
|
REGEX "cannot execute task 1: state is not created")
|
||||||
test_emu(task-types.c MP)
|
test_emu(task-types.c MP)
|
||||||
test_emu(pause.c MP)
|
test_emu(pause.c MP)
|
||||||
test_emu(mp-rank.c MP)
|
#test_emu(mp-rank.c MP)
|
||||||
test_emu(switch-same-type.c)
|
test_emu(switch-same-type.c)
|
||||||
test_emu(multiple-segment.c MP NPROC 4)
|
test_emu(multiple-segment.c MP NPROC 4)
|
||||||
test_emu(task-pause-from-submit.c)
|
test_emu(task-pause-from-submit.c)
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
instr_nosv_init(void)
|
||||||
|
{
|
||||||
|
instr_require("nosv");
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
instr_nosv_type_create(int32_t typeid)
|
instr_nosv_type_create(int32_t typeid)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
|
#include "instr.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fail(const char *msg)
|
fail(const char *msg)
|
||||||
@ -137,6 +138,7 @@ main(void)
|
|||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
type_create(typeid);
|
type_create(typeid);
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ main(void)
|
|||||||
int lcpu = rank % N;
|
int lcpu = rank % N;
|
||||||
|
|
||||||
ovni_thread_init(get_tid());
|
ovni_thread_init(get_tid());
|
||||||
|
instr_nosv_init();
|
||||||
instr_thread_execute(lcpu, -1, 0);
|
instr_thread_execute(lcpu, -1, 0);
|
||||||
|
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
@ -9,6 +9,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
uint32_t typeid = 666;
|
uint32_t typeid = 666;
|
||||||
instr_nosv_type_create(typeid);
|
instr_nosv_type_create(typeid);
|
||||||
|
@ -20,6 +20,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
@ -13,6 +13,7 @@ main(void)
|
|||||||
int rank = atoi(getenv("OVNI_RANK"));
|
int rank = atoi(getenv("OVNI_RANK"));
|
||||||
int nranks = atoi(getenv("OVNI_NRANKS"));
|
int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
int us = 500;
|
int us = 500;
|
||||||
uint32_t typeid = 1;
|
uint32_t typeid = 1;
|
||||||
|
@ -15,6 +15,7 @@ int
|
|||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
instr_nosv_type_create(10);
|
instr_nosv_type_create(10);
|
||||||
instr_nosv_task_create(1, 10);
|
instr_nosv_task_create(1, 10);
|
||||||
|
@ -16,6 +16,7 @@ main(void)
|
|||||||
* type, appid and rank. */
|
* type, appid and rank. */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
uint32_t typeid = 100;
|
uint32_t typeid = 100;
|
||||||
uint32_t gid = instr_nosv_type_create(typeid);
|
uint32_t gid = instr_nosv_type_create(typeid);
|
||||||
|
@ -22,6 +22,7 @@ main(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
/* Match the PRV line in the trace */
|
/* Match the PRV line in the trace */
|
||||||
FILE *f = fopen("match.sh", "w");
|
FILE *f = fopen("match.sh", "w");
|
||||||
|
@ -13,6 +13,7 @@ main(void)
|
|||||||
int nranks = atoi(getenv("OVNI_NRANKS"));
|
int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
|
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_nosv_init();
|
||||||
|
|
||||||
int ntasks = 100;
|
int ntasks = 100;
|
||||||
int ntypes = 10;
|
int ntypes = 10;
|
||||||
|
@ -18,4 +18,4 @@ test_emu(sort-cpus-by-loom.c MP)
|
|||||||
test_emu(sort-cpus-by-rank.c MP)
|
test_emu(sort-cpus-by-rank.c MP)
|
||||||
test_emu(tracedir-subdir.c MP DRIVER "tracedir-subdir.driver.sh")
|
test_emu(tracedir-subdir.c MP DRIVER "tracedir-subdir.driver.sh")
|
||||||
test_emu(empty-stream.c SHOULD_FAIL REGEX "model_ovni_finish: thread .* is not dead")
|
test_emu(empty-stream.c SHOULD_FAIL REGEX "model_ovni_finish: thread .* is not dead")
|
||||||
test_emu(require.c)
|
test_emu(require.c SHOULD_FAIL REGEX "unsupported ovni model version (want 666.66.6, have .*)")
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
|
#include "instr.h"
|
||||||
|
|
||||||
int64_t delta = 0LL;
|
int64_t delta = 0LL;
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ start_delayed(int rank, int nranks)
|
|||||||
ovni_proc_init(1, rankname, getpid());
|
ovni_proc_init(1, rankname, getpid());
|
||||||
ovni_proc_set_rank(rank, nranks);
|
ovni_proc_set_rank(rank, nranks);
|
||||||
ovni_thread_init(get_tid());
|
ovni_thread_init(get_tid());
|
||||||
|
instr_require("ovni");
|
||||||
|
|
||||||
/* All ranks inform CPUs */
|
/* All ranks inform CPUs */
|
||||||
for (int i = 0; i < nranks; i++)
|
for (int i = 0; i < nranks; i++)
|
||||||
|
@ -11,7 +11,8 @@ main(void)
|
|||||||
{
|
{
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
|
||||||
ovni_thread_require("ovni", "1.2.0");
|
/* Override */
|
||||||
|
ovni_thread_require("ovni", "666.66.6");
|
||||||
|
|
||||||
instr_end();
|
instr_end();
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
|
#include "instr.h"
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
init(void)
|
init(void)
|
||||||
|
@ -152,6 +152,7 @@ main(void)
|
|||||||
* the sorting region, disrupting the order. */
|
* the sorting region, disrupting the order. */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_require("kernel");
|
||||||
test_flush_after_sort();
|
test_flush_after_sort();
|
||||||
test_unsorted();
|
test_unsorted();
|
||||||
test_overlap();
|
test_overlap();
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
#include "instr.h"
|
#include "instr.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
instr_tampi_init(void)
|
||||||
|
{
|
||||||
|
instr_require("tampi");
|
||||||
|
}
|
||||||
|
|
||||||
INSTR_0ARG(instr_tampi_issue_nonblk_op_enter, "TCi")
|
INSTR_0ARG(instr_tampi_issue_nonblk_op_enter, "TCi")
|
||||||
INSTR_0ARG(instr_tampi_issue_nonblk_op_exit, "TCI")
|
INSTR_0ARG(instr_tampi_issue_nonblk_op_exit, "TCI")
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ main(void)
|
|||||||
const int nranks = atoi(getenv("OVNI_NRANKS"));
|
const int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
|
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_tampi_init();
|
||||||
|
|
||||||
const int ncomms = 100;
|
const int ncomms = 100;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ main(void)
|
|||||||
* the stack causes the emulator to fail */
|
* the stack causes the emulator to fail */
|
||||||
|
|
||||||
instr_start(0, 1);
|
instr_start(0, 1);
|
||||||
|
instr_tampi_init();
|
||||||
|
|
||||||
instr_tampi_library_interface_enter();
|
instr_tampi_library_interface_enter();
|
||||||
/* The thread is left in the library interface state (should fail) */
|
/* The thread is left in the library interface state (should fail) */
|
||||||
|
@ -15,6 +15,7 @@ main(void)
|
|||||||
const int nranks = atoi(getenv("OVNI_NRANKS"));
|
const int nranks = atoi(getenv("OVNI_NRANKS"));
|
||||||
|
|
||||||
instr_start(rank, nranks);
|
instr_start(rank, nranks);
|
||||||
|
instr_tampi_init();
|
||||||
|
|
||||||
const int transfer_step = 5;
|
const int transfer_step = 5;
|
||||||
const int complete_step = 3;
|
const int complete_step = 3;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "emu/proc.h"
|
#include "emu/proc.h"
|
||||||
#include "emu/thread.h"
|
#include "emu/thread.h"
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
#include "parson.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_oversubscription(void)
|
test_oversubscription(void)
|
||||||
@ -41,6 +42,7 @@ test_oversubscription(void)
|
|||||||
die("thread_init_begin failed");
|
die("thread_init_begin failed");
|
||||||
|
|
||||||
thread_set_gindex(&th0, 0);
|
thread_set_gindex(&th0, 0);
|
||||||
|
th0.meta = (JSON_Object *) 666;
|
||||||
|
|
||||||
if (thread_init_end(&th0) != 0)
|
if (thread_init_end(&th0) != 0)
|
||||||
die("thread_init_end failed");
|
die("thread_init_end failed");
|
||||||
@ -49,6 +51,7 @@ test_oversubscription(void)
|
|||||||
die("thread_init_begin failed");
|
die("thread_init_begin failed");
|
||||||
|
|
||||||
thread_set_gindex(&th1, 1);
|
thread_set_gindex(&th1, 1);
|
||||||
|
th1.meta = (JSON_Object *) 666;
|
||||||
|
|
||||||
if (thread_init_end(&th1) != 0)
|
if (thread_init_end(&th1) != 0)
|
||||||
die("thread_init_end failed");
|
die("thread_init_end failed");
|
||||||
|
Loading…
Reference in New Issue
Block a user