Split nanos6 model into separate files
This commit is contained in:
		
							parent
							
								
									0e8b23c918
								
							
						
					
					
						commit
						cc5582c493
					
				| @ -15,6 +15,7 @@ void vdie(const char *func, const char *errstr, ...); | ||||
| 
 | ||||
| /* clang-format off */ | ||||
| 
 | ||||
| #define rerr(...) fprintf(stderr, __VA_ARGS__); | ||||
| #define err(...) verr(__func__, __VA_ARGS__); | ||||
| #define die(...) vdie(__func__, __VA_ARGS__); | ||||
| 
 | ||||
|  | ||||
| @ -8,9 +8,6 @@ include_directories( | ||||
|   "${CMAKE_SOURCE_DIR}/include" | ||||
| ) | ||||
| 
 | ||||
| #add_library(trace STATIC trace.c) | ||||
| #target_link_libraries(trace parson ovni-static) | ||||
| 
 | ||||
| add_library(emu STATIC | ||||
|   ../common.c | ||||
|   bay.c | ||||
| @ -26,7 +23,6 @@ add_library(emu STATIC | ||||
|   emu_trace.c | ||||
|   loom.c | ||||
|   metadata.c | ||||
|   model_nanos6.c | ||||
|   model_ust.c | ||||
|   mux.c | ||||
|   path.c | ||||
| @ -38,26 +34,15 @@ add_library(emu STATIC | ||||
|   task.c | ||||
|   thread.c | ||||
|   extend.c | ||||
|   nanos6/probe.c | ||||
|   nanos6/connect.c | ||||
|   nanos6/create.c | ||||
|   nanos6/event.c | ||||
| ) | ||||
| 
 | ||||
| #add_library(emu STATIC | ||||
| #  chan.c | ||||
| #  emu.c | ||||
| #  nosv.c | ||||
| #  openmp.c | ||||
| #  ovni.c | ||||
| #  tampi.c | ||||
| #  nodes.c | ||||
| #  kernel.c | ||||
| #  nanos6.c | ||||
| #  task.c | ||||
| #  pcf.c | ||||
| #  prv.c | ||||
| #) | ||||
| # | ||||
| #add_executable(ovniemu ovniemu.c) | ||||
| #target_link_libraries(ovniemu emu trace) | ||||
| # | ||||
| add_executable(ovniemu ovniemu.c) | ||||
| target_link_libraries(ovniemu emu parson-static ovni-static) | ||||
| 
 | ||||
| #add_executable(ovnidump ovnidump.c) | ||||
| #target_link_libraries(ovnidump emu trace) | ||||
| # | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| #define ENABLE_DEBUG | ||||
| //#define ENABLE_DEBUG
 | ||||
| 
 | ||||
| #include "bay.h" | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /* Copyright (c) 2021-2022 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #define ENABLE_DEBUG | ||||
| //#define ENABLE_DEBUG
 | ||||
| 
 | ||||
| #include "chan.h" | ||||
| #include "common.h" | ||||
|  | ||||
| @ -37,7 +37,7 @@ cpu_init_begin(struct cpu *cpu, int phyid) | ||||
| 
 | ||||
| 	cpu->phyid = phyid; | ||||
| 
 | ||||
| 	err("cpu init %d", phyid); | ||||
| 	dbg("cpu init %d", phyid); | ||||
| } | ||||
| 
 | ||||
| int | ||||
|  | ||||
| @ -3,13 +3,13 @@ | ||||
| 
 | ||||
| #define _POSIX_C_SOURCE 2 | ||||
| 
 | ||||
| #define ENABLE_DEBUG | ||||
| //#define ENABLE_DEBUG
 | ||||
| 
 | ||||
| #include "emu.h" | ||||
| 
 | ||||
| #include <unistd.h> | ||||
| #include "model_ust.h" | ||||
| #include "model_nanos6.h" | ||||
| #include "models.h" | ||||
| 
 | ||||
| int | ||||
| emu_init(struct emu *emu, int argc, char *argv[]) | ||||
| @ -54,8 +54,6 @@ emu_init(struct emu *emu, int argc, char *argv[]) | ||||
| 
 | ||||
| //	/* Register all the models */
 | ||||
| //	emu_model_register(&emu->model, &ovni_model_spec, emu);
 | ||||
| //
 | ||||
| 
 | ||||
| 
 | ||||
| 	if (model_ust.create && model_ust.create(emu) != 0) { | ||||
| 		err("model ust create failed"); | ||||
|  | ||||
| @ -14,16 +14,16 @@ static char progname[] = "ovniemu"; | ||||
| static void | ||||
| usage(void) | ||||
| { | ||||
| 	err("Usage: %s [-c offsetfile] tracedir\n", progname); | ||||
| 	err("\n"); | ||||
| 	err("Options:\n"); | ||||
| 	err("  -c offsetfile      Use the given offset file to correct\n"); | ||||
| 	err("                     the clocks among nodes. It can be\n"); | ||||
| 	err("                     generated by the ovnisync program\n"); | ||||
| 	err("\n"); | ||||
| 	err("  tracedir           The output trace dir generated by ovni.\n"); | ||||
| 	err("\n"); | ||||
| 	err("The output PRV files are placed in the tracedir directory.\n"); | ||||
| 	rerr("Usage: %s [-c offsetfile] tracedir\n", progname); | ||||
| 	rerr("\n"); | ||||
| 	rerr("Options:\n"); | ||||
| 	rerr("  -c offsetfile      Use the given offset file to correct\n"); | ||||
| 	rerr("                     the clocks among nodes. It can be\n"); | ||||
| 	rerr("                     generated by the ovnisync program\n"); | ||||
| 	rerr("\n"); | ||||
| 	rerr("  tracedir           The output trace dir generated by ovni.\n"); | ||||
| 	rerr("\n"); | ||||
| 	rerr("The output PRV files are placed in the tracedir directory.\n"); | ||||
| 
 | ||||
| 	exit(EXIT_FAILURE); | ||||
| } | ||||
| @ -34,7 +34,7 @@ emu_args_init(struct emu_args *args, int argc, char *argv[]) | ||||
| 	memset(args, 0, sizeof(struct emu_args)); | ||||
| 
 | ||||
| 	int opt; | ||||
| 	while ((opt = getopt(argc, argv, "c:l")) != -1) { | ||||
| 	while ((opt = getopt(argc, argv, "c:lh")) != -1) { | ||||
| 		switch (opt) { | ||||
| 			case 'c': | ||||
| 				args->clock_offset_file = optarg; | ||||
| @ -42,6 +42,7 @@ emu_args_init(struct emu_args *args, int argc, char *argv[]) | ||||
| 			case 'l': | ||||
| 				args->linter_mode = 1; | ||||
| 				break; | ||||
| 			case 'h': | ||||
| 			default: /* '?' */ | ||||
| 				usage(); | ||||
| 		} | ||||
|  | ||||
| @ -84,7 +84,7 @@ emu_stream_load(struct emu_stream *stream, const char *tracedir, const char *rel | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	err("emu_stream_load: loading %s\n", stream->relpath); | ||||
| 	dbg("emu_stream_load: loading %s\n", stream->relpath); | ||||
| 
 | ||||
| 	if ((fd = open(stream->path, O_RDWR)) == -1) { | ||||
| 		err("emu_stream_load: open failed: %s\n", stream->path); | ||||
|  | ||||
| @ -95,13 +95,13 @@ emu_trace_load(struct emu_trace *trace, const char *tracedir) | ||||
| 	cur_trace = trace; | ||||
| 
 | ||||
| 	if (snprintf(trace->tracedir, PATH_MAX, "%s", tracedir) >= PATH_MAX) { | ||||
| 		err("emu_trace_load: path too long: %s\n", tracedir); | ||||
| 		err("path too long: %s", tracedir); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Search recursively all streams in the trace directory */ | ||||
| 	if (nftw(tracedir, cb_nftw, 50, 0) != 0) { | ||||
| 		err("emu_trace_load: nftw failed\n"); | ||||
| 		err("nftw failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| @ -110,7 +110,7 @@ emu_trace_load(struct emu_trace *trace, const char *tracedir) | ||||
| 	/* Sort the streams */ | ||||
| 	DL_SORT(trace->streams, cmp_streams); | ||||
| 
 | ||||
| 	err("emu_trace_load: loaded %ld streams\n", trace->nstreams); | ||||
| 	err("loaded %ld streams", trace->nstreams); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -66,7 +66,7 @@ loom_init_begin(struct loom *loom, const char *name) | ||||
| 
 | ||||
| 	cpu_init_begin(&loom->vcpu, -1); | ||||
| 
 | ||||
| 	err("creating new loom %s", loom->id); | ||||
| 	dbg("creating new loom %s", loom->id); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,34 +0,0 @@ | ||||
| /* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #ifndef MODEL_NANOS6_H | ||||
| #define MODEL_NANOS6_H | ||||
| 
 | ||||
| #include "emu_model.h" | ||||
| 
 | ||||
| extern struct model_spec model_nanos6; | ||||
| 
 | ||||
| #include "chan.h" | ||||
| #include "mux.h" | ||||
| #include "task.h" | ||||
| 
 | ||||
| struct nanos6_thread { | ||||
| 	struct chan *ch;	/* Raw, modified by nanos6 */ | ||||
| 	struct chan *ch_run;	/* Tracking running thread */ | ||||
| 	struct chan *ch_act;	/* Tracking active thread */ | ||||
| 	struct chan **ch_out;	/* Output to PRV */ | ||||
| 	struct mux *mux_run; | ||||
| 	struct mux *mux_act; | ||||
| 	struct task_stack task_stack; | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_cpu { | ||||
| 	struct chan *ch; | ||||
| 	struct mux *mux; | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_proc { | ||||
| 	struct task_info task_info; | ||||
| }; | ||||
| 
 | ||||
| #endif /* MODEL_NANOS6_H */ | ||||
							
								
								
									
										12
									
								
								src/emu/models.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/emu/models.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| /* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #ifndef MODELS_H | ||||
| #define MODELS_H | ||||
| 
 | ||||
| #include "emu_model.h" | ||||
| 
 | ||||
| extern struct model_spec model_ust; | ||||
| extern struct model_spec model_nanos6; | ||||
| 
 | ||||
| #endif /* MODELS_H */ | ||||
| @ -1,4 +1,4 @@ | ||||
| #define ENABLE_DEBUG | ||||
| //#define ENABLE_DEBUG
 | ||||
| 
 | ||||
| #include "mux.h" | ||||
| 
 | ||||
| @ -57,6 +57,7 @@ cb_select(struct chan *sel_chan, void *ptr) | ||||
| 	} | ||||
| 
 | ||||
| 	char buf[128]; | ||||
| 	UNUSED(buf); | ||||
| 	dbg("select channel got value %s\n", | ||||
| 			value_str(sel_value, buf)); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										253
									
								
								src/emu/nanos6/connect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								src/emu/nanos6/connect.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,253 @@ | ||||
| #include "nanos6_priv.h" | ||||
| 
 | ||||
| static const char *th_track[] = { | ||||
| 	[CH_TASKID]    = "running", | ||||
| 	[CH_TYPE]      = "running", | ||||
| 	[CH_SUBSYSTEM] = "active", | ||||
| 	[CH_RANK]      = "running", | ||||
| 	[CH_THREAD]    = "none", | ||||
| }; | ||||
| 
 | ||||
| static const char *cpu_track[] = { | ||||
| 	[CH_TASKID]    = "running", | ||||
| 	[CH_TYPE]      = "running", | ||||
| 	[CH_SUBSYSTEM] = "running", | ||||
| 	[CH_RANK]      = "running", | ||||
| 	[CH_THREAD]    = "running", | ||||
| }; | ||||
| 
 | ||||
| static const int th_type[] = { | ||||
| 	[CH_TASKID]    = 35, | ||||
| 	[CH_TYPE]      = 36, | ||||
| 	[CH_SUBSYSTEM] = 37, | ||||
| 	[CH_RANK]      = 38, | ||||
| 	[CH_THREAD]    = 39, | ||||
| }; | ||||
| 
 | ||||
| static const int *cpu_type = th_type; | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| connect_thread_mux(struct emu *emu, struct thread *thread) | ||||
| { | ||||
| 	struct nanos6_thread *th = extend_get(&thread->ext, '6'); | ||||
| 	for (int i = 0; i < CH_MAX; i++) { | ||||
| 
 | ||||
| 		/* TODO: Let the thread take the select channel
 | ||||
| 		 * and build the mux as a tracking mode */ | ||||
| 		struct chan *inp = &th->ch[i]; | ||||
| 		struct chan *sel = &thread->chan[TH_CHAN_STATE]; | ||||
| 
 | ||||
| 		struct mux *mux_run = &th->mux_run[i]; | ||||
| 		mux_select_func_t selrun = thread_select_running; | ||||
| 		if (mux_init(mux_run, &emu->bay, sel, &th->ch_run[i], selrun) != 0) { | ||||
| 			err("mux_init failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (mux_add_input(mux_run, value_int64(0), inp) != 0) { | ||||
| 			err("mux_add_input failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		struct mux *mux_act = &th->mux_act[i]; | ||||
| 		mux_select_func_t selact = thread_select_active; | ||||
| 		if (mux_init(mux_act, &emu->bay, sel, &th->ch_act[i], selact) != 0) { | ||||
| 			err("mux_init failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (mux_add_input(mux_act, value_int64(0), inp) != 0) { | ||||
| 			err("mux_add_input failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (mux_act->ninputs != 1) | ||||
| 			die("expecting one input only"); | ||||
| 
 | ||||
| 		/* The tracking only sets the ch_out, but we keep both tracking
 | ||||
| 		 * updated as the CPU tracking channels may use them. */ | ||||
| 		const char *tracking = th_track[i]; | ||||
| 		if (strcmp(tracking, "running") == 0) { | ||||
| 			th->ch_out[i] = &th->ch_run[i]; | ||||
| 		} else if (strcmp(tracking, "active") == 0) { | ||||
| 			th->ch_out[i] = &th->ch_act[i]; | ||||
| 		} else { | ||||
| 			th->ch_out[i] = &th->ch[i]; | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| connect_thread_prv(struct emu *emu, struct thread *thread, struct prv *prv) | ||||
| { | ||||
| 	struct nanos6_thread *th = extend_get(&thread->ext, '6'); | ||||
| 	for (int i = 0; i < CH_MAX; i++) { | ||||
| 		struct chan *out = th->ch_out[i]; | ||||
| 		long type = th_type[i]; | ||||
| 		long row = thread->gindex; | ||||
| 		if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) { | ||||
| 			err("prv_register failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| add_inputs_cpu_mux(struct emu *emu, struct mux *mux, int i) | ||||
| { | ||||
| 	for (struct thread *t = emu->system.threads; t; t = t->gnext) { | ||||
| 		struct nanos6_thread *th = extend_get(&t->ext, '6'); | ||||
| 
 | ||||
| 		/* Choose input thread channel based on tracking mode */ | ||||
| 		const char *tracking = cpu_track[i]; | ||||
| 		struct chan *inp; | ||||
| 		if (strcmp(tracking, "running") == 0) { | ||||
| 			inp = &th->ch_run[i]; | ||||
| 		} else if (strcmp(tracking, "active") == 0) { | ||||
| 			inp = &th->ch_act[i]; | ||||
| 		} else { | ||||
| 			die("cpu tracking must be 'running' or 'active'"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (mux_add_input(mux, value_int64(t->gindex), inp) != 0) { | ||||
| 			err("mux_add_input failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| connect_cpu_mux(struct emu *emu, struct cpu *scpu) | ||||
| { | ||||
| 	struct nanos6_cpu *cpu = extend_get(&scpu->ext, '6'); | ||||
| 	for (int i = 0; i < CH_MAX; i++) { | ||||
| 		struct mux *mux = &cpu->mux[i]; | ||||
| 		struct chan *out = &cpu->ch[i]; | ||||
| 		const char *tracking = cpu_track[i]; | ||||
| 
 | ||||
| 		/* Choose select CPU channel based on tracking mode */ | ||||
| 		struct chan *sel; | ||||
| 		if (strcmp(tracking, "running") == 0) { | ||||
| 			sel = &scpu->chan[CPU_CHAN_THRUN]; | ||||
| 		} else if (strcmp(tracking, "active") == 0) { | ||||
| 			sel = &scpu->chan[CPU_CHAN_THACT]; | ||||
| 		} else { | ||||
| 			die("cpu tracking must be 'running' or 'active'"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (mux_init(mux, &emu->bay, sel, out, NULL) != 0) { | ||||
| 			err("mux_init failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (add_inputs_cpu_mux(emu, mux, i) != 0) { | ||||
| 			err("add_inputs_cpu_mux failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| connect_threads(struct emu *emu) | ||||
| { | ||||
| 	struct system *sys = &emu->system; | ||||
| 
 | ||||
| 	/* threads */ | ||||
| 	for (struct thread *t = sys->threads; t; t = t->gnext) { | ||||
| 		if (connect_thread_mux(emu, t) != 0) { | ||||
| 			err("connect_thread_mux failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Get thread PRV */ | ||||
| 	struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread"); | ||||
| 	if (pvt == NULL) { | ||||
| 		err("cannot find thread pvt"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	struct prv *prv = pvt_get_prv(pvt); | ||||
| 
 | ||||
| 	for (struct thread *t = sys->threads; t; t = t->gnext) { | ||||
| 		if (connect_thread_prv(emu, t, prv) != 0) { | ||||
| 			err("connect_thread_prv failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv) | ||||
| { | ||||
| 	struct nanos6_cpu *cpu = extend_get(&scpu->ext, '6'); | ||||
| 	for (int i = 0; i < CH_MAX; i++) { | ||||
| 		struct chan *out = &cpu->ch[i]; | ||||
| 		long type = cpu_type[i]; | ||||
| 		long row = scpu->gindex; | ||||
| 		if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) { | ||||
| 			err("prv_register failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| connect_cpus(struct emu *emu) | ||||
| { | ||||
| 	struct system *sys = &emu->system; | ||||
| 
 | ||||
| 	/* cpus */ | ||||
| 	for (struct cpu *c = sys->cpus; c; c = c->next) { | ||||
| 		if (connect_cpu_mux(emu, c) != 0) { | ||||
| 			err("connect_cpu_mux failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Get cpu PRV */ | ||||
| 	struct pvt *pvt = recorder_find_pvt(&emu->recorder, "cpu"); | ||||
| 	if (pvt == NULL) { | ||||
| 		err("cannot find cpu pvt"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	struct prv *prv = pvt_get_prv(pvt); | ||||
| 
 | ||||
| 	for (struct cpu *c = sys->cpus; c; c = c->next) { | ||||
| 		if (connect_cpu_prv(emu, c, prv) != 0) { | ||||
| 			err("connect_cpu_prv failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| nanos6_connect(struct emu *emu) | ||||
| { | ||||
| 	if (connect_threads(emu) != 0) { | ||||
| 		err("connect_threads failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (connect_cpus(emu) != 0) { | ||||
| 		err("connect_cpus failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										180
									
								
								src/emu/nanos6/create.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/emu/nanos6/create.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,180 @@ | ||||
| #include "nanos6_priv.h" | ||||
| 
 | ||||
| static const char chan_fmt_cpu_raw[] = "nanos6.cpu%ld.%s"; | ||||
| //static const char chan_fmt_cpu_run[] = "nanos6.cpu%ld.%s.run";
 | ||||
| //static const char chan_fmt_cpu_act[] = "nanos6.cpu%ld.%s.act";
 | ||||
| static const char chan_fmt_th_raw[] = "nanos6.thread%ld.%s.raw"; | ||||
| static const char chan_fmt_th_run[] = "nanos6.thread%ld.%s.run"; | ||||
| static const char chan_fmt_th_act[] = "nanos6.thread%ld.%s.act"; | ||||
| 
 | ||||
| static const char *chan_name[] = { | ||||
| 	[CH_TASKID]    = "taskid", | ||||
| 	[CH_TYPE]      = "task_type", | ||||
| 	[CH_SUBSYSTEM] = "subsystem", | ||||
| 	[CH_RANK]      = "rank", | ||||
| 	[CH_THREAD]    = "thread_type", | ||||
| }; | ||||
| 
 | ||||
| static const int chan_stack[] = { | ||||
| 	[CH_SUBSYSTEM] = 1, | ||||
| 	[CH_THREAD] = 1, | ||||
| }; | ||||
| 
 | ||||
| static int | ||||
| init_chans(struct bay *bay, struct chan *chans, const char *fmt, int64_t gindex, int filtered) | ||||
| { | ||||
| 	for (int i = 0; i < CH_MAX; i++) { | ||||
| 		struct chan *c = &chans[i]; | ||||
| 		int type = (chan_stack[i] && !filtered) ? CHAN_STACK : CHAN_SINGLE; | ||||
| 		chan_init(c, type, fmt, gindex, chan_name[i]); | ||||
| 
 | ||||
| 		if (bay_register(bay, c) != 0) { | ||||
| 			err("bay_register failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| init_cpu(struct bay *bay, struct cpu *syscpu) | ||||
| { | ||||
| 	struct nanos6_cpu *cpu = calloc(1, sizeof(struct nanos6_cpu)); | ||||
| 	if (cpu == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	cpu->ch = calloc(CH_MAX, sizeof(struct chan)); | ||||
| 	if (cpu->ch == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	cpu->mux = calloc(CH_MAX, sizeof(struct mux)); | ||||
| 	if (cpu->mux == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (init_chans(bay, cpu->ch, chan_fmt_cpu_raw, syscpu->gindex, 1) != 0) { | ||||
| 		err("init_chans failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	extend_set(&syscpu->ext, '6', cpu); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| init_thread(struct bay *bay, struct thread *systh) | ||||
| { | ||||
| 	struct nanos6_thread *th = calloc(1, sizeof(struct nanos6_thread)); | ||||
| 	if (th == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	th->ch = calloc(CH_MAX, sizeof(struct chan)); | ||||
| 	if (th->ch == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	th->ch_run = calloc(CH_MAX, sizeof(struct chan)); | ||||
| 	if (th->ch_run == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	th->ch_act = calloc(CH_MAX, sizeof(struct chan)); | ||||
| 	if (th->ch_act == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	th->ch_out = calloc(CH_MAX, sizeof(struct chan *)); | ||||
| 	if (th->ch_out == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	th->mux_run = calloc(CH_MAX, sizeof(struct mux)); | ||||
| 	if (th->mux_run == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	th->mux_act = calloc(CH_MAX, sizeof(struct mux)); | ||||
| 	if (th->mux_act == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (init_chans(bay, th->ch, chan_fmt_th_raw, systh->gindex, 0) != 0) { | ||||
| 		err("init_chans failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (init_chans(bay, th->ch_run, chan_fmt_th_run, systh->gindex, 1) != 0) { | ||||
| 		err("init_chans failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (init_chans(bay, th->ch_act, chan_fmt_th_act, systh->gindex, 1) != 0) { | ||||
| 		err("init_chans failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	th->task_stack.thread = systh; | ||||
| 
 | ||||
| 	extend_set(&systh->ext, '6', th); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| init_proc(struct proc *sysproc) | ||||
| { | ||||
| 	struct nanos6_proc *proc = calloc(1, sizeof(struct nanos6_proc)); | ||||
| 	if (proc == NULL) { | ||||
| 		err("calloc failed:"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	extend_set(&sysproc->ext, '6', proc); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| nanos6_create(struct emu *emu) | ||||
| { | ||||
| 	struct system *sys = &emu->system; | ||||
| 	struct bay *bay = &emu->bay; | ||||
| 
 | ||||
| 	for (struct cpu *c = sys->cpus; c; c = c->next) { | ||||
| 		if (init_cpu(bay, c) != 0) { | ||||
| 			err("init_cpu failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct thread *t = sys->threads; t; t = t->gnext) { | ||||
| 		if (init_thread(bay, t) != 0) { | ||||
| 			err("init_thread failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct proc *p = sys->procs; p; p = p->gnext) { | ||||
| 		if (init_proc(p) != 0) { | ||||
| 			err("init_proc failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										525
									
								
								src/emu/nanos6/event.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										525
									
								
								src/emu/nanos6/event.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,525 @@ | ||||
| #include "nanos6_priv.h" | ||||
| 
 | ||||
| enum { PUSH = 1, POP = 2, IGN = 3 }; | ||||
| 
 | ||||
| #define CHSS CH_SUBSYSTEM | ||||
| #define CHTH CH_THREAD | ||||
| 
 | ||||
| static const int ss_table[256][256][3] = { | ||||
| 	['W'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_WORKER_LOOP }, | ||||
| 		[']'] = { CHSS, POP,  ST_WORKER_LOOP }, | ||||
| 		['t'] = { CHSS, PUSH, ST_HANDLING_TASK }, | ||||
| 		['T'] = { CHSS, POP,  ST_HANDLING_TASK }, | ||||
| 		['w'] = { CHSS, PUSH, ST_SWITCH_TO }, | ||||
| 		['W'] = { CHSS, POP,  ST_SWITCH_TO }, | ||||
| 		['m'] = { CHSS, PUSH, ST_MIGRATE }, | ||||
| 		['M'] = { CHSS, POP,  ST_MIGRATE }, | ||||
| 		['s'] = { CHSS, PUSH, ST_SUSPEND }, | ||||
| 		['S'] = { CHSS, POP,  ST_SUSPEND }, | ||||
| 		['r'] = { CHSS, PUSH, ST_RESUME }, | ||||
| 		['R'] = { CHSS, POP,  ST_RESUME }, | ||||
| 		['*'] = { CHSS, IGN,  -1 }, | ||||
| 	}, | ||||
| 	['C'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_TASK_CREATING }, | ||||
| 		[']'] = { CHSS, POP,  ST_TASK_CREATING }, | ||||
| 	}, | ||||
| 	['U'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_TASK_SUBMIT }, | ||||
| 		[']'] = { CHSS, POP,  ST_TASK_SUBMIT }, | ||||
| 	}, | ||||
| 	['F'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_TASK_SPAWNING }, | ||||
| 		[']'] = { CHSS, POP,  ST_TASK_SPAWNING }, | ||||
| 	}, | ||||
| 	['O'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_TASK_FOR }, | ||||
| 		[']'] = { CHSS, POP,  ST_TASK_FOR }, | ||||
| 	}, | ||||
| 	['t'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_TASK_BODY }, | ||||
| 		[']'] = { CHSS, POP,  ST_TASK_BODY }, | ||||
| 	}, | ||||
| 	['M'] = { | ||||
| 		['a'] = { CHSS, PUSH, ST_ALLOCATING }, | ||||
| 		['A'] = { CHSS, POP,  ST_ALLOCATING }, | ||||
| 		['f'] = { CHSS, PUSH, ST_FREEING }, | ||||
| 		['F'] = { CHSS, POP,  ST_FREEING }, | ||||
| 	}, | ||||
| 	['D'] = { | ||||
| 		['r'] = { CHSS, PUSH, ST_DEP_REG }, | ||||
| 		['R'] = { CHSS, POP,  ST_DEP_REG }, | ||||
| 		['u'] = { CHSS, PUSH, ST_DEP_UNREG }, | ||||
| 		['U'] = { CHSS, POP,  ST_DEP_UNREG }, | ||||
| 	}, | ||||
| 	['S'] = { | ||||
| 		['['] = { CHSS, PUSH, ST_SCHED_SERVING }, | ||||
| 		[']'] = { CHSS, POP,  ST_SCHED_SERVING }, | ||||
| 		['a'] = { CHSS, PUSH, ST_SCHED_ADDING }, | ||||
| 		['A'] = { CHSS, POP,  ST_SCHED_ADDING }, | ||||
| 		['p'] = { CHSS, PUSH, ST_SCHED_PROCESSING }, | ||||
| 		['P'] = { CHSS, POP,  ST_SCHED_PROCESSING }, | ||||
| 		['@'] = { CHSS, IGN,  -1 }, | ||||
| 		['r'] = { CHSS, IGN,  -1 }, | ||||
| 		['s'] = { CHSS, IGN,  -1 }, | ||||
| 	}, | ||||
| 	['B'] = { | ||||
| 		['b'] = { CHSS, PUSH, ST_BLK_BLOCKING }, | ||||
| 		['B'] = { CHSS, POP,  ST_BLK_BLOCKING }, | ||||
| 		['u'] = { CHSS, PUSH, ST_BLK_UNBLOCKING }, | ||||
| 		['U'] = { CHSS, POP,  ST_BLK_UNBLOCKING }, | ||||
| 		['w'] = { CHSS, PUSH, ST_BLK_TASKWAIT }, | ||||
| 		['W'] = { CHSS, POP,  ST_BLK_TASKWAIT }, | ||||
| 		['f'] = { CHSS, PUSH, ST_BLK_WAITFOR }, | ||||
| 		['F'] = { CHSS, POP,  ST_BLK_WAITFOR }, | ||||
| 	}, | ||||
| 	['H'] = { | ||||
| 		['e'] = { CHTH, PUSH, ST_TH_EXTERNAL }, | ||||
| 		['E'] = { CHTH, POP,  ST_TH_EXTERNAL }, | ||||
| 		['w'] = { CHTH, PUSH, ST_TH_WORKER }, | ||||
| 		['W'] = { CHTH, POP,  ST_TH_WORKER }, | ||||
| 		['l'] = { CHTH, PUSH, ST_TH_LEADER }, | ||||
| 		['L'] = { CHTH, POP,  ST_TH_LEADER }, | ||||
| 		['m'] = { CHTH, PUSH, ST_TH_MAIN }, | ||||
| 		['M'] = { CHTH, POP,  ST_TH_MAIN }, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static int | ||||
| simple(struct emu *emu) | ||||
| { | ||||
| 	const int *entry = ss_table[emu->ev->c][emu->ev->v]; | ||||
| 	int chind = entry[0]; | ||||
| 	int action = entry[1]; | ||||
| 	int st = entry[2]; | ||||
| 
 | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 	struct chan *ch = &th->ch[chind]; | ||||
| 
 | ||||
| 	if (action == PUSH) { | ||||
| 		return chan_push(ch, value_int64(st)); | ||||
| 	} else if (action == POP) { | ||||
| 		return chan_pop(ch, value_int64(st)); | ||||
| 	} else if (action == IGN) { | ||||
| 		return 0; /* do nothing */ | ||||
| 	} else { | ||||
| 		err("unknown Nanos6 subsystem event"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| chan_task_stopped(struct emu *emu) | ||||
| { | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 
 | ||||
| 	struct value null = value_null(); | ||||
| 	if (chan_set(&th->ch[CH_TASKID], null) != 0) { | ||||
| 		err("chan_set taskid failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (chan_set(&th->ch[CH_TYPE], null) != 0) { | ||||
| 		err("chan_set type failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	struct proc *proc = emu->proc; | ||||
| 	if (proc->rank >= 0) { | ||||
| 		if (chan_set(&th->ch[CH_RANK], null) != 0) { | ||||
| 			err("chan_set rank failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| chan_task_running(struct emu *emu, struct task *task) | ||||
| { | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 	struct proc *proc = emu->proc; | ||||
| 
 | ||||
| 	if (task->id == 0) { | ||||
| 		err("task id cannot be 0"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (task->type->gid == 0) { | ||||
| 		err("task type gid cannot be 0"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (chan_set(&th->ch[CH_TASKID], value_int64(task->id)) != 0) { | ||||
| 		err("chan_set taskid failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (chan_set(&th->ch[CH_TYPE], value_int64(task->type->gid)) != 0) { | ||||
| 		err("chan_set type failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (proc->rank >= 0) { | ||||
| 		struct value vrank = value_int64(proc->rank + 1); | ||||
| 		if (chan_set(&th->ch[CH_RANK], vrank) != 0) { | ||||
| 			err("chan_set rank failed"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| chan_task_switch(struct emu *emu, | ||||
| 		struct task *prev, struct task *next) | ||||
| { | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 
 | ||||
| 	if (!prev || !next) { | ||||
| 		err("cannot switch to or from a NULL task"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (prev == next) { | ||||
| 		err("cannot switch to the same task"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (next->id == 0) { | ||||
| 		err("next task id cannot be 0"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (next->type->gid == 0) { | ||||
| 		err("next task type id cannot be 0"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (prev->thread != next->thread) { | ||||
| 		err("cannot switch to a task of another thread"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* No need to change the rank as we will switch to tasks from
 | ||||
| 	 * same thread */ | ||||
| 	if (chan_set(&th->ch[CH_TASKID], value_int64(next->id)) != 0) { | ||||
| 		err("chan_set taskid failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* TODO: test when switching to another task with the same type. We
 | ||||
| 	 * should emit the same type state value as previous task. */ | ||||
| 	if (chan_set(&th->ch[CH_TYPE], value_int64(next->type->gid)) != 0) { | ||||
| 		err("chan_set type failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| update_task_state(struct emu *emu) | ||||
| { | ||||
| 	if (emu->ev->payload_size < 4) { | ||||
| 		err("missing task id in payload"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	uint32_t task_id = emu->ev->payload->u32[0]; | ||||
| 
 | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 	struct nanos6_proc *proc = extend_get(&emu->proc->ext, '6'); | ||||
| 
 | ||||
| 	struct task_info *info = &proc->task_info; | ||||
| 	struct task_stack *stack = &th->task_stack; | ||||
| 
 | ||||
| 	struct task *task = task_find(info->tasks, task_id); | ||||
| 
 | ||||
| 	if (task == NULL) { | ||||
| 		err("cannot find task with id %u", task_id); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	int ret = 0; | ||||
| 	switch (emu->ev->v) { | ||||
| 		case 'x': | ||||
| 			ret = task_execute(stack, task); | ||||
| 			break; | ||||
| 		case 'e': | ||||
| 			ret = task_end(stack, task); | ||||
| 			break; | ||||
| 		case 'p': | ||||
| 			ret = task_pause(stack, task); | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			ret = task_resume(stack, task); | ||||
| 			break; | ||||
| 		default: | ||||
| 			err("unexpected Nanos6 task event"); | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ret != 0) { | ||||
| 		err("cannot change task state"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p) | ||||
| { | ||||
| 	char tr = emu->ev->v; | ||||
| 
 | ||||
| 	/* Ensure we don't clobber the value */ | ||||
| 	if (tr == 'X' || tr == 'E') { | ||||
| 		err("unexpected event value %c", tr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Modify the event value to detect nested transitions */ | ||||
| 	if (tr == 'x' && was_running) | ||||
| 		tr = 'X'; /* Execute a new nested task */ | ||||
| 	else if (tr == 'e' && runs_now) | ||||
| 		tr = 'E'; /* End a nested task */ | ||||
| 
 | ||||
| 	*tr_p = tr; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| update_task_channels(struct emu *emu, | ||||
| 		char tr, struct task *prev, struct task *next) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	switch (tr) { | ||||
| 		case 'x': | ||||
| 		case 'r': | ||||
| 			ret = chan_task_running(emu, next); | ||||
| 			break; | ||||
| 		case 'e': | ||||
| 		case 'p': | ||||
| 			ret = chan_task_stopped(emu); | ||||
| 			break; | ||||
| 			/* Additional nested transitions */ | ||||
| 		case 'X': | ||||
| 		case 'E': | ||||
| 			ret = chan_task_switch(emu, prev, next); | ||||
| 			break; | ||||
| 		default: | ||||
| 			err("unexpected transition value %c", tr); | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ret != 0) { | ||||
| 		err("cannot update task channels"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| enforce_task_rules(struct emu *emu, char tr, struct task *next) | ||||
| { | ||||
| 	if (tr != 'x' && tr != 'X') | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* If a task has just entered the running state, it must show
 | ||||
| 	 * the running task body subsystem */ | ||||
| 
 | ||||
| 	if (next->state != TASK_ST_RUNNING) { | ||||
| 		err("task not in running state on begin"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 	struct value ss; | ||||
| 	if (chan_read(&th->ch[CH_SUBSYSTEM], &ss) != 0) { | ||||
| 		err("chan_read failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ss.type == VALUE_INT64 && ss.i != ST_TASK_BODY) { | ||||
| 		err("wrong subsystem state on task begin"); | ||||
| 		//return -1;
 | ||||
| 		return 0; // FIXME
 | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| update_task(struct emu *emu) | ||||
| { | ||||
| 	struct nanos6_thread *th = extend_get(&emu->thread->ext, '6'); | ||||
| 	struct task_stack *stack = &th->task_stack; | ||||
| 
 | ||||
| 	struct task *prev = task_get_running(stack); | ||||
| 
 | ||||
| 	/* Update the emulator state, but don't modify the channels */ | ||||
| 	if (update_task_state(emu) != 0) { | ||||
| 		err("update_task_state failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	struct task *next = task_get_running(stack); | ||||
| 
 | ||||
| 	int was_running = (prev != NULL); | ||||
| 	int runs_now = (next != NULL); | ||||
| 	char tr; | ||||
| 	if (expand_transition_value(emu, was_running, runs_now, &tr) != 0) { | ||||
| 		err("expand_transition_value failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Update the task related channels now */ | ||||
| 	update_task_channels(emu, tr, prev, next); | ||||
| 
 | ||||
| 	if (enforce_task_rules(emu, tr, next) != 0) { | ||||
| 		err("enforce_task_rules failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| create_task(struct emu *emu) | ||||
| { | ||||
| 	if (emu->ev->payload_size != 8) { | ||||
| 		err("unexpected payload size"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	uint32_t task_id = emu->ev->payload->u32[0]; | ||||
| 	uint32_t type_id = emu->ev->payload->u32[1]; | ||||
| 
 | ||||
| 	struct nanos6_proc *proc = extend_get(&emu->proc->ext, '6'); | ||||
| 	struct task_info *info = &proc->task_info; | ||||
| 
 | ||||
| 	if (task_create(info, type_id, task_id) != 0) { | ||||
| 		err("task_create failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| pre_task(struct emu *emu) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	switch (emu->ev->v) { | ||||
| 		case 'C': | ||||
| 			err("warning: got old 6TC event, ignoring"); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			ret = create_task(emu); | ||||
| 			break; | ||||
| 		case 'x': | ||||
| 		case 'e': | ||||
| 		case 'r': | ||||
| 		case 'p': | ||||
| 			ret = update_task(emu); | ||||
| 			break; | ||||
| 		default: | ||||
| 			err("unexpected Nanos6 task event value"); | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ret != 0) { | ||||
| 		err("cannot update task state"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| pre_type(struct emu *emu) | ||||
| { | ||||
| 	uint8_t value = emu->ev->v; | ||||
| 
 | ||||
| 	if (value != 'c') { | ||||
| 		err("unexpected event value %c", value); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!emu->ev->is_jumbo) { | ||||
| 		err("expecting a jumbo event"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	const uint8_t *data = &emu->ev->payload->jumbo.data[0]; | ||||
| 	uint32_t typeid = *(uint32_t *) data; | ||||
| 	data += 4; | ||||
| 
 | ||||
| 	const char *label = (const char *) data; | ||||
| 
 | ||||
| 	struct nanos6_proc *proc = extend_get(&emu->proc->ext, '6'); | ||||
| 	struct task_info *info = &proc->task_info; | ||||
| 
 | ||||
| 	if (task_type_create(info, typeid, label) != 0) { | ||||
| 		err("task_type_create failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| process_ev(struct emu *emu) | ||||
| { | ||||
| 	if (!emu->thread->is_active) { | ||||
| 		err("current thread %d not active", emu->thread->tid); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (emu->ev->c) { | ||||
| 		case 'C': | ||||
| 		case 'S': | ||||
| 		case 'U': | ||||
| 		case 'F': | ||||
| 		case 'O': | ||||
| 		case 't': | ||||
| 		case 'H': | ||||
| 		case 'D': | ||||
| 		case 'B': | ||||
| 		case 'W': | ||||
| 			return simple(emu); | ||||
| 		case 'T': | ||||
| 			return pre_task(emu); | ||||
| 		case 'Y': | ||||
| 			return pre_type(emu); | ||||
| 		default: | ||||
| 			err("unknown Nanos6 event category"); | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Not reached */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| nanos6_event(struct emu *emu) | ||||
| { | ||||
| 	if (emu->ev->m != '6') { | ||||
| 		err("unexpected event model %c\n", emu->ev->m); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	dbg("got nanos6 event %s", emu->ev->mcv); | ||||
| 	if (process_ev(emu) != 0) { | ||||
| 		err("error processing Nanos6 event"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	//check_affinity(emu);
 | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| @ -1,69 +0,0 @@ | ||||
| /* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #ifndef OVNI_MODEL_H | ||||
| #define OVNI_MODEL_H | ||||
| 
 | ||||
| #include "ovni/ovni_model.h" | ||||
| #include "chan.h" | ||||
| 
 | ||||
| /* The values of nanos6_ss_state are synced to the previous
 | ||||
|  * CTF implementation. */ | ||||
| enum nanos6_ss_state { | ||||
| 	ST_NANOS6_TASK_BODY = 1, | ||||
| 	ST_NANOS6_TASK_CREATING, | ||||
| 	ST_NANOS6_TASK_SUBMIT, | ||||
| 	ST_NANOS6_TASK_SPAWNING, | ||||
| 	ST_NANOS6_TASK_FOR, | ||||
| 	ST_NANOS6_SCHED_ADDING, | ||||
| 	ST_NANOS6_SCHED_PROCESSING, | ||||
| 	ST_NANOS6_SCHED_SERVING, | ||||
| 	ST_NANOS6_DEP_REG, | ||||
| 	ST_NANOS6_DEP_UNREG, | ||||
| 	ST_NANOS6_BLK_TASKWAIT, | ||||
| 	ST_NANOS6_BLK_WAITFOR, | ||||
| 	ST_NANOS6_BLK_BLOCKING, | ||||
| 	ST_NANOS6_BLK_UNBLOCKING, | ||||
| 	ST_NANOS6_ALLOCATING, | ||||
| 	ST_NANOS6_FREEING, | ||||
| 	ST_NANOS6_HANDLING_TASK, | ||||
| 	ST_NANOS6_WORKER_LOOP, | ||||
| 	ST_NANOS6_SWITCH_TO, | ||||
| 	ST_NANOS6_MIGRATE, | ||||
| 	ST_NANOS6_SUSPEND, | ||||
| 	ST_NANOS6_RESUME, | ||||
| 
 | ||||
| 	/* Value 51 is broken in old Paraver */ | ||||
| 	EV_NANOS6_SCHED_RECV = 60, | ||||
| 	EV_NANOS6_SCHED_SEND, | ||||
| 	EV_NANOS6_SCHED_SELF, | ||||
| 	EV_NANOS6_CPU_IDLE, | ||||
| 	EV_NANOS6_CPU_ACTIVE, | ||||
| 	EV_NANOS6_SIGNAL, | ||||
| }; | ||||
| 
 | ||||
| enum nanos6_thread_type { | ||||
| 	ST_NANOS6_TH_LEADER = 1, | ||||
| 	ST_NANOS6_TH_MAIN = 2, | ||||
| 	ST_NANOS6_TH_WORKER = 3, | ||||
| 	ST_NANOS6_TH_EXTERNAL = 4, | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_thread { | ||||
| 	struct task_stack nanos6_task_stack; | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_proc { | ||||
| 	struct task_info nanos6_task_info; | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_emu { | ||||
| 	struct ovni_emu *ovni; | ||||
| }; | ||||
| 
 | ||||
| int nanos6_model_probe(struct emu *emu); | ||||
| int nanos6_model_create(struct emu *emu); | ||||
| int nanos6_model_connect(struct emu *emu); | ||||
| int nanos6_model_event(struct emu *emu); | ||||
| 
 | ||||
| #endif /* OVNI_MODEL_H */ | ||||
							
								
								
									
										86
									
								
								src/emu/nanos6/nanos6_priv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/emu/nanos6/nanos6_priv.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | ||||
| /* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #ifndef NANOS6_PRIV_H | ||||
| #define NANOS6_PRIV_H | ||||
| 
 | ||||
| #include "emu.h" | ||||
| #include "chan.h" | ||||
| #include "mux.h" | ||||
| #include "task.h" | ||||
| 
 | ||||
| /* Private enums */ | ||||
| enum nanos6_chan_type { | ||||
| 	CH_TASKID = 0, | ||||
| 	CH_TYPE, | ||||
| 	CH_SUBSYSTEM, | ||||
| 	CH_RANK, | ||||
| 	CH_THREAD, | ||||
| 	CH_MAX, | ||||
| }; | ||||
| 
 | ||||
| enum nanos6_ss_state { | ||||
| 	ST_TASK_BODY = 1, | ||||
| 	ST_TASK_CREATING, | ||||
| 	ST_TASK_SUBMIT, | ||||
| 	ST_TASK_SPAWNING, | ||||
| 	ST_TASK_FOR, | ||||
| 	ST_SCHED_ADDING, | ||||
| 	ST_SCHED_PROCESSING, | ||||
| 	ST_SCHED_SERVING, | ||||
| 	ST_DEP_REG, | ||||
| 	ST_DEP_UNREG, | ||||
| 	ST_BLK_TASKWAIT, | ||||
| 	ST_BLK_WAITFOR, | ||||
| 	ST_BLK_BLOCKING, | ||||
| 	ST_BLK_UNBLOCKING, | ||||
| 	ST_ALLOCATING, | ||||
| 	ST_FREEING, | ||||
| 	ST_HANDLING_TASK, | ||||
| 	ST_WORKER_LOOP, | ||||
| 	ST_SWITCH_TO, | ||||
| 	ST_MIGRATE, | ||||
| 	ST_SUSPEND, | ||||
| 	ST_RESUME, | ||||
| 
 | ||||
| 	/* Value 51 is broken in old Paraver */ | ||||
| 	EV_SCHED_RECV = 60, | ||||
| 	EV_SCHED_SEND, | ||||
| 	EV_SCHED_SELF, | ||||
| 	EV_CPU_IDLE, | ||||
| 	EV_CPU_ACTIVE, | ||||
| 	EV_SIGNAL, | ||||
| }; | ||||
| 
 | ||||
| enum nanos6_thread_type { | ||||
| 	ST_TH_LEADER = 1, | ||||
| 	ST_TH_MAIN = 2, | ||||
| 	ST_TH_WORKER = 3, | ||||
| 	ST_TH_EXTERNAL = 4, | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_thread { | ||||
| 	struct chan *ch;	/* Raw, modified by nanos6 */ | ||||
| 	struct chan *ch_run;	/* Tracking running thread */ | ||||
| 	struct chan *ch_act;	/* Tracking active thread */ | ||||
| 	struct chan **ch_out;	/* Output to PRV */ | ||||
| 	struct mux *mux_run; | ||||
| 	struct mux *mux_act; | ||||
| 	struct task_stack task_stack; | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_cpu { | ||||
| 	struct chan *ch; | ||||
| 	struct mux *mux; | ||||
| }; | ||||
| 
 | ||||
| struct nanos6_proc { | ||||
| 	struct task_info task_info; | ||||
| }; | ||||
| 
 | ||||
| int nanos6_probe(struct emu *emu); | ||||
| int nanos6_create(struct emu *emu); | ||||
| int nanos6_connect(struct emu *emu); | ||||
| int nanos6_event(struct emu *emu); | ||||
| 
 | ||||
| #endif /* NANOS6_PRIV_H */ | ||||
							
								
								
									
										19
									
								
								src/emu/nanos6/probe.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/emu/nanos6/probe.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| #include "nanos6_priv.h" | ||||
| 
 | ||||
| struct model_spec model_nanos6 = { | ||||
| 	.name = "nanos6", | ||||
| 	.model = '6', | ||||
| 	.create  = nanos6_create, | ||||
| 	.connect = nanos6_connect, | ||||
| 	.event   = nanos6_event, | ||||
| 	.probe   = nanos6_probe, | ||||
| }; | ||||
| 
 | ||||
| int | ||||
| nanos6_probe(struct emu *emu) | ||||
| { | ||||
| 	if (emu->system.nthreads == 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| @ -1,23 +1,35 @@ | ||||
| #include "emu.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include "common.h" | ||||
| 
 | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	struct ovni_emu *emu = malloc(sizeof(struct ovni_emu)); | ||||
| 	progname_set("ovniemu"); | ||||
| 
 | ||||
| 	struct emu *emu = calloc(1, sizeof(struct emu)); | ||||
| 
 | ||||
| 	if (emu == NULL) { | ||||
| 		perror("malloc"); | ||||
| 		err("malloc failed:"); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	emu_init(emu, argc, argv); | ||||
| 	if (emu_init(emu, argc, argv) != 0) | ||||
| 		die("emu_init failed\n"); | ||||
| 
 | ||||
| 	if (emu_connect(emu) != 0) | ||||
| 		die("emu_connect failed\n"); | ||||
| 
 | ||||
| 	err("emulation starts\n"); | ||||
| 	emu_run(emu); | ||||
| 	emu_post(emu); | ||||
| 	emu_destroy(emu); | ||||
| 	int ret = 0; | ||||
| 	while ((ret = emu_step(emu)) == 0); | ||||
| 
 | ||||
| 	if (ret < 0) | ||||
| 		die("emu_step failed\n"); | ||||
| 
 | ||||
| 	err("emulation ends\n"); | ||||
| 
 | ||||
| 	free(emu); | ||||
| 
 | ||||
| 	return 0; | ||||
|  | ||||
| @ -84,7 +84,7 @@ proc_init_begin(struct proc *proc, const char *relpath) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	err("created proc %s", proc->id); | ||||
| 	dbg("created proc %s", proc->id); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #define ENABLE_DEBUG | ||||
| //#define ENABLE_DEBUG
 | ||||
| 
 | ||||
| #include "prv.h" | ||||
| #include <stdio.h> | ||||
|  | ||||
| @ -515,7 +515,8 @@ system_init(struct system *sys, struct emu_args *args, struct emu_trace *trace) | ||||
| 	} | ||||
| 
 | ||||
| 	/* Finaly dump the system */ | ||||
| 	print_system(sys); | ||||
| 	if (0) | ||||
| 		print_system(sys); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user