Handle all events with CPU and thread channels
This commit is contained in:
		
							parent
							
								
									cd430a35ce
								
							
						
					
					
						commit
						3f22afc4b3
					
				
							
								
								
									
										26
									
								
								emu.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								emu.c
									
									
									
									
									
								
							| @ -149,6 +149,13 @@ emit_channels(struct ovni_emu *emu) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| hook_init(struct ovni_emu *emu) | ||||
| { | ||||
| 	hook_init_ovni(emu); | ||||
| 	hook_init_nosv(emu); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| hook_pre(struct ovni_emu *emu) | ||||
| { | ||||
| @ -160,9 +167,6 @@ hook_pre(struct ovni_emu *emu) | ||||
| 			  break; | ||||
| 		case 'V': hook_pre_nosv(emu); | ||||
| 			  break; | ||||
| 		case '*': hook_pre_nosv(emu); | ||||
| 			  hook_pre_ovni(emu); | ||||
| 			  break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| @ -177,13 +181,6 @@ hook_emit(struct ovni_emu *emu) | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.model) | ||||
| 	{ | ||||
| 		case 'O': hook_emit_ovni(emu); | ||||
| 			  break; | ||||
| 		case 'V': hook_emit_nosv(emu); | ||||
| 			  break; | ||||
| 		case '*': hook_emit_nosv(emu); | ||||
| 			  hook_emit_ovni(emu); | ||||
| 			  break; | ||||
| 		default: | ||||
| 			  //dbg("unknown model %c\n", emu->cur_ev->model);
 | ||||
| 			  break; | ||||
| @ -197,13 +194,6 @@ hook_post(struct ovni_emu *emu) | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.model) | ||||
| 	{ | ||||
| 		case 'O': hook_post_ovni(emu); | ||||
| 			  break; | ||||
| 		case 'V': hook_post_nosv(emu); | ||||
| 			  break; | ||||
| 		case '*': hook_post_nosv(emu); | ||||
| 			  hook_post_ovni(emu); | ||||
| 			  break; | ||||
| 		default: | ||||
| 			  //dbg("unknown model %c\n", emu->cur_ev->model);
 | ||||
| 			  break; | ||||
| @ -315,6 +305,8 @@ emulate(struct ovni_emu *emu) | ||||
| 
 | ||||
| 	emu->lastclock = 0; | ||||
| 
 | ||||
| 	hook_init(emu); | ||||
| 
 | ||||
| 	/* Then process all events */ | ||||
| 	while(next_event(emu) == 0) | ||||
| 	{ | ||||
|  | ||||
							
								
								
									
										3
									
								
								emu.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								emu.h
									
									
									
									
									
								
							| @ -353,14 +353,17 @@ struct ovni_emu { | ||||
| 
 | ||||
| void emu_emit(struct ovni_emu *emu); | ||||
| 
 | ||||
| void hook_init_ovni(struct ovni_emu *emu); | ||||
| void hook_pre_ovni(struct ovni_emu *emu); | ||||
| void hook_emit_ovni(struct ovni_emu *emu); | ||||
| void hook_post_ovni(struct ovni_emu *emu); | ||||
| 
 | ||||
| void hook_init_nosv(struct ovni_emu *emu); | ||||
| void hook_pre_nosv(struct ovni_emu *emu); | ||||
| void hook_emit_nosv(struct ovni_emu *emu); | ||||
| void hook_post_nosv(struct ovni_emu *emu); | ||||
| 
 | ||||
| void hook_init_nosv_ss(struct ovni_emu *emu); | ||||
| void hook_pre_nosv_ss(struct ovni_emu *emu); | ||||
| void hook_emit_nosv_ss(struct ovni_emu *emu); | ||||
| void hook_post_nosv_ss(struct ovni_emu *emu); | ||||
|  | ||||
							
								
								
									
										229
									
								
								emu_nosv.c
									
									
									
									
									
								
							
							
						
						
									
										229
									
								
								emu_nosv.c
									
									
									
									
									
								
							| @ -7,34 +7,53 @@ | ||||
| #include "prv.h" | ||||
| #include "chan.h" | ||||
| 
 | ||||
| enum nosv_prv_type { | ||||
| 	PRV_TYPE_PROCID | ||||
| }; | ||||
| 
 | ||||
| struct hook_entry { | ||||
| 	char id[4]; | ||||
| 	void (*hook)(struct ovni_emu *); | ||||
| }; | ||||
| 
 | ||||
| /* --------------------------- init ------------------------------- */ | ||||
| 
 | ||||
| void | ||||
| hook_nosv_init(struct ovni_emu *emu) | ||||
| hook_init_nosv(struct ovni_emu *emu) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 	struct ovni_cpu *cpu; | ||||
| 	struct ovni_trace *trace; | ||||
| 	int i, row, type; | ||||
| 	FILE *prv; | ||||
| 	FILE *prv_th, *prv_cpu; | ||||
| 	int64_t *clock; | ||||
| 
 | ||||
| 	clock = &emu->delta_time; | ||||
| 	prv_th = emu->prv_thread; | ||||
| 	prv_cpu = emu->prv_cpu; | ||||
| 	trace = &emu->trace; | ||||
| 
 | ||||
| 	/* Init the channels in all threads */ | ||||
| 	for(i=0; i<emu->total_nthreads; i++) | ||||
| 	{ | ||||
| 		th = emu->global_thread[i]; | ||||
| 		row = th->gindex + 1; | ||||
| 
 | ||||
| 		//chan_init(struct ovni_chan *chan, int row, int type, FILE *prv, int64_t *clock)
 | ||||
| 		chan_th_init(th, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock); | ||||
| 		chan_enable(&th->chan[CHAN_NOSV_TASKID], 1); | ||||
| 		chan_set(&th->chan[CHAN_NOSV_TASKID], 0); | ||||
| 		chan_enable(&th->chan[CHAN_NOSV_TASKID], 0); | ||||
| 
 | ||||
| 		chan_init(th->chan[CHAN_NOSV_TASK_ID], row, PTT_TASK_ID, prv, | ||||
| 				clock); | ||||
| 		chan_th_init(th, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock); | ||||
| 		chan_th_init(th, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock); | ||||
| 		chan_th_init(th, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, row, prv_th, clock); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Init the nosv channels in all cpus */ | ||||
| 	for(i=0; i<emu->total_ncpus; i++) | ||||
| 	{ | ||||
| 		cpu = emu->global_cpu[i]; | ||||
| 		row = cpu->gindex + 1; | ||||
| 
 | ||||
| 		chan_cpu_init(cpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock); | ||||
| 		chan_enable(&cpu->chan[CHAN_NOSV_TASKID], 1); | ||||
| 		chan_set(&cpu->chan[CHAN_NOSV_TASKID], 0); | ||||
| 		chan_enable(&cpu->chan[CHAN_NOSV_TASKID], 0); | ||||
| 
 | ||||
| 		chan_cpu_init(cpu, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock); | ||||
| 		chan_cpu_init(cpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock); | ||||
| 		chan_cpu_init(cpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -169,10 +188,39 @@ pre_task_end(struct ovni_emu *emu) | ||||
| 	dbg("task id=%d ends\n", task->id); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pre_task_running(struct ovni_emu *emu, struct nosv_task *task) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 	struct ovni_eproc *proc; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	proc = emu->cur_proc; | ||||
| 
 | ||||
| 	chan_set(&th->chan[CHAN_NOSV_TASKID], task->id + 1); | ||||
| 	chan_set(&th->chan[CHAN_NOSV_TYPEID], task->type_id + 1); | ||||
| 	chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid + 1); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pre_task_not_running(struct ovni_emu *emu, struct nosv_task *task) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 
 | ||||
| 	chan_set(&th->chan[CHAN_NOSV_TASKID], 0); | ||||
| 	chan_set(&th->chan[CHAN_NOSV_TYPEID], 0); | ||||
| 	chan_set(&th->chan[CHAN_NOSV_APPID], 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pre_task(struct ovni_emu *emu) | ||||
| { | ||||
| 	emu_emit(emu); | ||||
| 	struct nosv_task *task; | ||||
| 
 | ||||
| 	task = emu->cur_task; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| 		case 'c': pre_task_create(emu); break; | ||||
| @ -181,8 +229,22 @@ pre_task(struct ovni_emu *emu) | ||||
| 		case 'p': pre_task_pause(emu); break; | ||||
| 		case 'r': pre_task_resume(emu); break; | ||||
| 		default: | ||||
| 			  emu->cur_task = NULL; | ||||
| 			  break; | ||||
| 			  abort(); | ||||
| 	} | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| 		case 'x': | ||||
| 		case 'r': | ||||
| 			pre_task_running(emu, task); | ||||
| 			break; | ||||
| 		case 'p': | ||||
| 		case 'e': | ||||
| 			pre_task_not_running(emu, task); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -243,89 +305,100 @@ pre_type(struct ovni_emu *emu) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_pre_nosv(struct ovni_emu *emu) | ||||
| { | ||||
| 	switch(emu->cur_ev->header.model) | ||||
| 	{ | ||||
| 		/* Only listen for nosv events */ | ||||
| 		case 'V': | ||||
| 			switch(emu->cur_ev->header.class) | ||||
| 			{ | ||||
| 				case 'T': pre_task(emu); break; | ||||
| 				case 'Y': pre_type(emu); break; | ||||
| 				default: | ||||
| 					break; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	hook_pre_nosv_ss(emu); | ||||
| } | ||||
| 
 | ||||
| /* --------------------------- emit ------------------------------- */ | ||||
| 
 | ||||
| static void | ||||
| emit_task_running(struct ovni_emu *emu, struct nosv_task *task) | ||||
| pre_sched(struct ovni_emu *emu) | ||||
| { | ||||
| 	prv_ev_autocpu(emu, PTC_TASK_ID, task->id + 1); | ||||
| 	prv_ev_autocpu(emu, PTC_TASK_TYPE_ID, task->type_id + 1); | ||||
| 	prv_ev_autocpu(emu, PTC_APP_ID, emu->cur_proc->appid + 1); | ||||
| } | ||||
| 	struct ovni_ethread *th; | ||||
| 	struct ovni_chan *chan_th; | ||||
| 
 | ||||
| static void | ||||
| emit_task_not_running(struct ovni_emu *emu, struct nosv_task *task) | ||||
| { | ||||
| 	prv_ev_autocpu(emu, PTC_TASK_ID, 0); | ||||
| 	prv_ev_autocpu(emu, PTC_TASK_TYPE_ID, 0); | ||||
| 	prv_ev_autocpu(emu, PTC_APP_ID, 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| emit_task(struct ovni_emu *emu) | ||||
| { | ||||
| 	struct nosv_task *task; | ||||
| 
 | ||||
| 	task = emu->cur_task; | ||||
| 	th = emu->cur_thread; | ||||
| 	chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| 		case 'x': | ||||
| 		case 'h': | ||||
| 			chan_push(chan_th, ST_SCHED_HUNGRY); | ||||
| 			break; | ||||
| 		case 'f': /* Fill: no longer hungry */ | ||||
| 			chan_pop(chan_th, ST_SCHED_HUNGRY); | ||||
| 			break; | ||||
| 		case '[': /* Server enter */ | ||||
| 			chan_push(chan_th, ST_SCHED_SERVING); | ||||
| 			break; | ||||
| 		case ']': /* Server exit */ | ||||
| 			chan_pop(chan_th, ST_SCHED_SERVING); | ||||
| 			break; | ||||
| 		case '@': | ||||
| 			chan_ev(chan_th, EV_SCHED_SELF); | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			emit_task_running(emu, task); | ||||
| 			chan_ev(chan_th, EV_SCHED_RECV); | ||||
| 			break; | ||||
| 		case 'p': | ||||
| 		case 'e': | ||||
| 			emit_task_not_running(emu, task); | ||||
| 		case 's': | ||||
| 			chan_ev(chan_th, EV_SCHED_SEND); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_emit_nosv(struct ovni_emu *emu) | ||||
| static void | ||||
| pre_submit(struct ovni_emu *emu) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 	int i; | ||||
| 	struct ovni_chan *chan_th; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| 		case '[': | ||||
| 			chan_push(chan_th, ST_SCHED_SUBMITTING); | ||||
| 			break; | ||||
| 		case ']': | ||||
| 			chan_pop(chan_th, ST_SCHED_SUBMITTING); | ||||
| 			break; | ||||
| 		default: | ||||
| 			  break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pre_memory(struct ovni_emu *emu) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 	struct ovni_chan *chan_th; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| 		case '[':  | ||||
| 			chan_push(chan_th, ST_MEM_ALLOCATING); | ||||
| 			break; | ||||
| 		case ']': | ||||
| 			chan_pop(chan_th, ST_MEM_ALLOCATING); | ||||
| 			break; | ||||
| 		default: | ||||
| 			  break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_pre_nosv(struct ovni_emu *emu) | ||||
| { | ||||
| 	assert(emu->cur_ev->header.model == 'V'); | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.class) | ||||
| 	{ | ||||
| 		case 'T': emit_task(emu); break; | ||||
| 		case 'T': pre_task(emu); break; | ||||
| 		case 'Y': pre_type(emu); break; | ||||
| 		case 'S': pre_sched(emu); break; | ||||
| 		case 'U': pre_submit(emu); break; | ||||
| 		case 'M': pre_memory(emu); break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	hook_emit_nosv_ss(emu); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_post_nosv(struct ovni_emu *emu) | ||||
| { | ||||
| 	hook_post_nosv_ss(emu); | ||||
| } | ||||
|  | ||||
| @ -13,6 +13,30 @@ | ||||
|  * execution. Events such as task received by a thread are emitted as | ||||
|  * fake events with very short period. */ | ||||
| 
 | ||||
| /* --------------------------- init ------------------------------- */ | ||||
| 
 | ||||
| void | ||||
| hook_init_nosv_ss(struct ovni_emu *emu) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 	int i, row, type, track; | ||||
| 	FILE *prv; | ||||
| 	int64_t *clock; | ||||
| 
 | ||||
| 	clock = &emu->delta_time; | ||||
| 	prv = emu->prv_thread; | ||||
| 	track = CHAN_TRACK_TH_RUNNING; | ||||
| 
 | ||||
| 	/* Init the channels in all threads */ | ||||
| 	for(i=0; i<emu->total_nthreads; i++) | ||||
| 	{ | ||||
| 		th = emu->global_thread[i]; | ||||
| 		row = th->gindex + 1; | ||||
| 
 | ||||
| 		chan_th_init(th, CHAN_NOSV_SUBSYSTEM, track, row, prv, clock); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* --------------------------- pre ------------------------------- */ | ||||
| 
 | ||||
| static void | ||||
| @ -22,7 +46,7 @@ pre_sched(struct ovni_emu *emu) | ||||
| 	struct ovni_chan *chan; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	chan = &th->chan[CHAN_NOSV_SS]; | ||||
| 	chan = &th->chan[CHAN_NOSV_SUBSYSTEM]; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| @ -53,7 +77,7 @@ pre_submit(struct ovni_emu *emu) | ||||
| 	struct ovni_chan *chan; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	chan = &th->chan[CHAN_NOSV_SS]; | ||||
| 	chan = &th->chan[CHAN_NOSV_SUBSYSTEM]; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| @ -71,7 +95,7 @@ pre_memory(struct ovni_emu *emu) | ||||
| 	struct ovni_chan *chan; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	chan = &th->chan[CHAN_NOSV_SS]; | ||||
| 	chan = &th->chan[CHAN_NOSV_SUBSYSTEM]; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.value) | ||||
| 	{ | ||||
| @ -107,7 +131,7 @@ hook_emit_nosv_ss(struct ovni_emu *emu) | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 
 | ||||
| 	chan_emit(&th->chan[CHAN_NOSV_SS]); | ||||
| 	chan_emit(&th->chan[CHAN_NOSV_SUBSYSTEM]); | ||||
| } | ||||
| 
 | ||||
| /* --------------------------- post ------------------------------- */ | ||||
|  | ||||
							
								
								
									
										345
									
								
								emu_ovni.c
									
									
									
									
									
								
							
							
						
						
									
										345
									
								
								emu_ovni.c
									
									
									
									
									
								
							| @ -8,14 +8,88 @@ | ||||
| /* The emulator ovni module provides the execution model by tracking the thread
 | ||||
|  * state and which threads run in each CPU */ | ||||
| 
 | ||||
| /* --------------------------- init ------------------------------- */ | ||||
| 
 | ||||
| void | ||||
| hook_init_ovni(struct ovni_emu *emu) | ||||
| { | ||||
| 	struct ovni_ethread *th; | ||||
| 	struct ovni_cpu *cpu; | ||||
| 	struct ovni_trace *trace; | ||||
| 	int i, row, type; | ||||
| 	FILE *prv_th, *prv_cpu; | ||||
| 	int64_t *clock; | ||||
| 
 | ||||
| 	clock = &emu->delta_time; | ||||
| 	prv_th = emu->prv_thread; | ||||
| 	prv_cpu = emu->prv_cpu; | ||||
| 	trace = &emu->trace; | ||||
| 
 | ||||
| 	/* Init the ovni channels in all threads */ | ||||
| 	for(i=0; i<emu->total_nthreads; i++) | ||||
| 	{ | ||||
| 		th = emu->global_thread[i]; | ||||
| 		row = th->gindex + 1; | ||||
| 
 | ||||
| 		chan_th_init(th, CHAN_OVNI_TID, CHAN_TRACK_NONE, row, prv_th, clock); | ||||
| 		chan_th_init(th, CHAN_OVNI_PID, CHAN_TRACK_NONE, row, prv_th, clock); | ||||
| 		chan_th_init(th, CHAN_OVNI_CPU, CHAN_TRACK_NONE, row, prv_th, clock); | ||||
| 		chan_th_init(th, CHAN_OVNI_STATE, CHAN_TRACK_NONE, row, prv_th, clock); | ||||
| 
 | ||||
| 		chan_enable(&th->chan[CHAN_OVNI_TID], 1); | ||||
| 		chan_set(&th->chan[CHAN_OVNI_TID], th->tid); | ||||
| 		chan_enable(&th->chan[CHAN_OVNI_TID], 0); | ||||
| 
 | ||||
| 		chan_enable(&th->chan[CHAN_OVNI_PID], 1); | ||||
| 		chan_set(&th->chan[CHAN_OVNI_PID], th->proc->pid); | ||||
| 		chan_enable(&th->chan[CHAN_OVNI_PID], 0); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Init the ovni channels in all cpus */ | ||||
| 	for(i=0; i<emu->total_ncpus; i++) | ||||
| 	{ | ||||
| 		cpu = emu->global_cpu[i]; | ||||
| 		row = cpu->gindex + 1; | ||||
| 
 | ||||
| 		chan_cpu_init(cpu, CHAN_OVNI_TID, CHAN_TRACK_NONE, row, prv_cpu, clock); | ||||
| 		chan_cpu_init(cpu, CHAN_OVNI_PID, CHAN_TRACK_NONE, row, prv_cpu, clock); | ||||
| 		chan_cpu_init(cpu, CHAN_OVNI_NTHREADS, CHAN_TRACK_NONE, row, prv_cpu, clock); | ||||
| 
 | ||||
| 		chan_enable(&cpu->chan[CHAN_OVNI_TID], 1); | ||||
| 		chan_set(&cpu->chan[CHAN_OVNI_TID], 0); | ||||
| 		chan_emit(&cpu->chan[CHAN_OVNI_TID]); | ||||
| 
 | ||||
| 		chan_enable(&cpu->chan[CHAN_OVNI_PID], 1); | ||||
| 		chan_set(&cpu->chan[CHAN_OVNI_PID], 0); | ||||
| 		chan_emit(&cpu->chan[CHAN_OVNI_PID]); | ||||
| 
 | ||||
| 		chan_enable(&cpu->chan[CHAN_OVNI_NTHREADS], 1); | ||||
| 		chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], cpu->nthreads); | ||||
| 		chan_emit(&cpu->chan[CHAN_OVNI_NTHREADS]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* --------------------------- pre ------------------------------- */ | ||||
| 
 | ||||
| static void | ||||
| thread_set_channel_enabled(struct ovni_ethread *th, int enabled) | ||||
| { | ||||
| 	struct ovni_chan *chan; | ||||
| 	int i; | ||||
| 
 | ||||
| 	for(i=0; i<CHAN_MAX; i++) | ||||
| 		chan_enable(&th->chan[i], enabled); | ||||
| 	{ | ||||
| 		chan = &th->chan[i]; | ||||
| 
 | ||||
| 		if(chan->track == CHAN_TRACK_TH_RUNNING) | ||||
| 		{ | ||||
| 			chan_enable(chan, enabled); | ||||
| 			dbg("thread %d: %s chan %d\n", | ||||
| 					th->tid, | ||||
| 					enabled ? "enable" : "disable", | ||||
| 					i); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -33,18 +107,54 @@ thread_set_state(struct ovni_ethread *th, int state) | ||||
| void | ||||
| update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu) | ||||
| { | ||||
| 	int i, tid, pid, enabled; | ||||
| 	struct ovni_loom *loom; | ||||
| 	struct ovni_ethread *th; | ||||
| 	struct ovni_chan *chan; | ||||
| 
 | ||||
| 	loom = emu->cur_loom; | ||||
| 
 | ||||
| 	if(loom->nupdated_cpus >= OVNI_MAX_CPU) | ||||
| 		abort(); | ||||
| 	chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], cpu->nthreads); | ||||
| 
 | ||||
| 	if(cpu->updated) | ||||
| 		return; | ||||
| 	th = NULL; | ||||
| 
 | ||||
| 	cpu->updated = 1; | ||||
| 	loom->updated_cpu[loom->nupdated_cpus++] = cpu; | ||||
| 	if(cpu->nthreads == 0) | ||||
| 	{ | ||||
| 		/* No thread running */ | ||||
| 		tid = pid = 0; | ||||
| 	} | ||||
| 	else if(cpu->nthreads == 1) | ||||
| 	{ | ||||
| 		/* Take the info from the unique thread */ | ||||
| 		tid = cpu->thread[0]->tid; | ||||
| 		pid = cpu->thread[0]->proc->pid; | ||||
| 		th = cpu->thread[0]; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* Multiple threads */ | ||||
| 		tid = pid = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	chan_set(&cpu->chan[CHAN_OVNI_TID], tid); | ||||
| 	chan_set(&cpu->chan[CHAN_OVNI_PID], pid); | ||||
| 
 | ||||
| //	enabled = (th != NULL && th->state == TH_ST_RUNNING ? 1 : 0);
 | ||||
| //
 | ||||
| //	/* Update all channels that need to follow the running thread */
 | ||||
| //	for(i=0; i<CHAN_MAX; i++)
 | ||||
| //	{
 | ||||
| //		chan = &cpu->chan[i];
 | ||||
| //
 | ||||
| //		if(chan->track == CHAN_TRACK_TH_RUNNING)
 | ||||
| //		{
 | ||||
| //			chan_enable(chan, enabled);
 | ||||
| //			dbg("cpu thread %d: %s chan %d\n",
 | ||||
| //					tid,
 | ||||
| //					enabled ? "enable" : "disable",
 | ||||
| //					i);
 | ||||
| //		}
 | ||||
| //	}
 | ||||
| } | ||||
| 
 | ||||
| struct ovni_cpu * | ||||
| @ -102,9 +212,7 @@ emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_et | ||||
| 		abort(); | ||||
| 
 | ||||
| 	for(j=i; j+1 < cpu->nthreads; j++) | ||||
| 	{ | ||||
| 		cpu->thread[i] = cpu->thread[j+1]; | ||||
| 	} | ||||
| 
 | ||||
| 	cpu->nthreads--; | ||||
| 
 | ||||
| @ -158,18 +266,43 @@ pre_thread_execute(struct ovni_emu *emu) | ||||
| 	th->cpu = cpu; | ||||
| 
 | ||||
| 	emu_cpu_add_thread(emu, cpu, th); | ||||
| 
 | ||||
| 	/* Enable the cpu channel of the thread */ | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_CPU], 1); | ||||
| 	chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1); | ||||
| 
 | ||||
| 	/* Enable thread TID and PID */ | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_TID], 1); | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_PID], 1); | ||||
| 
 | ||||
| 	/* Enable and set the thread state */ | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_STATE], 1); | ||||
| 	chan_set(&th->chan[CHAN_OVNI_STATE], th->state); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pre_thread_end(struct ovni_emu *emu) | ||||
| { | ||||
| 	assert(emu->cur_thread->state == TH_ST_RUNNING); | ||||
| 	assert(emu->cur_thread->cpu); | ||||
| 	struct ovni_ethread *th; | ||||
| 
 | ||||
| 	emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); | ||||
| 	th = emu->cur_thread; | ||||
| 	assert(th->state == TH_ST_RUNNING); | ||||
| 	assert(th->cpu); | ||||
| 
 | ||||
| 	thread_set_state(emu->cur_thread, TH_ST_DEAD); | ||||
| 	emu->cur_thread->cpu = NULL; | ||||
| 	emu_cpu_remove_thread(emu, th->cpu, th); | ||||
| 
 | ||||
| 	thread_set_state(th, TH_ST_DEAD); | ||||
| 	th->cpu = NULL; | ||||
| 
 | ||||
| 	/* Disable the cpu channel of the thread */ | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_CPU], 0); | ||||
| 
 | ||||
| 	/* Disable thread TID and PID */ | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_TID], 0); | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_PID], 0); | ||||
| 
 | ||||
| 	/* Disable thread state */ | ||||
| 	chan_enable(&th->chan[CHAN_OVNI_STATE], 0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -181,6 +314,7 @@ pre_thread_pause(struct ovni_emu *emu) | ||||
| 	emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); | ||||
| 
 | ||||
| 	thread_set_state(emu->cur_thread, TH_ST_PAUSED); | ||||
| 	chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -192,6 +326,7 @@ pre_thread_resume(struct ovni_emu *emu) | ||||
| 	emu_cpu_add_thread(emu, emu->cur_thread->cpu, emu->cur_thread); | ||||
| 
 | ||||
| 	thread_set_state(emu->cur_thread, TH_ST_RUNNING); | ||||
| 	chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -243,11 +378,22 @@ pre_affinity_set(struct ovni_emu *emu) | ||||
| 	/* Migrate current cpu to the one at cpuid */ | ||||
| 	newcpu = emu_get_cpu(emu->cur_loom, cpuid); | ||||
| 
 | ||||
| 	if(emu->cur_thread->cpu == newcpu) | ||||
| 	{ | ||||
| 		err("warning: thread %d affinity already set to cpu %d\n", | ||||
| 				emu->cur_thread->tid, | ||||
| 				emu->cur_thread->cpu->gindex); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); | ||||
| 	emu_cpu_add_thread(emu, newcpu, emu->cur_thread); | ||||
| 
 | ||||
| 	emu->cur_thread->cpu = newcpu; | ||||
| 
 | ||||
| 	chan_set(&emu->cur_thread->chan[CHAN_OVNI_CPU], | ||||
| 			newcpu->gindex + 1); | ||||
| 
 | ||||
| 	//dbg("cpu %d now runs %d\n", cpuid, emu->cur_thread->tid);
 | ||||
| } | ||||
| 
 | ||||
| @ -291,6 +437,9 @@ pre_affinity_remote(struct ovni_emu *emu) | ||||
| 	/* Always set the assigned CPU in the thread */ | ||||
| 	thread->cpu = newcpu; | ||||
| 
 | ||||
| 	chan_set(&thread->chan[CHAN_OVNI_CPU], | ||||
| 			newcpu->gindex + 1); | ||||
| 
 | ||||
| 	//dbg("thread %d switches to cpu %d by remote petition\n", tid,
 | ||||
| 	//		cpuid);
 | ||||
| } | ||||
| @ -334,177 +483,9 @@ hook_pre_ovni(struct ovni_emu *emu) | ||||
| 	//print_threads_state(emu);
 | ||||
| } | ||||
| 
 | ||||
| /* --------------------------- emit ------------------------------- */ | ||||
| 
 | ||||
| static void | ||||
| emit_thread_state(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i, row; | ||||
| 	struct ovni_ethread *th; | ||||
| 
 | ||||
| 	th = emu->cur_thread; | ||||
| 	row = th->gindex + 1; | ||||
| 
 | ||||
| 	prv_ev_thread(emu, row, PTT_THREAD_STATE, th->state); | ||||
| 
 | ||||
| 	if(th->state == TH_ST_RUNNING) | ||||
| 		prv_ev_thread(emu, row, PTT_THREAD_TID, th->tid); | ||||
| 	else | ||||
| 		prv_ev_thread(emu, row, PTT_THREAD_TID, 0); | ||||
| 
 | ||||
| 	chan_set(&th->chan[CHAN_OVNI_TID], th->tid); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| emit_thread_count(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i, n, row, pid, tid; | ||||
| 	struct ovni_loom *loom; | ||||
| 
 | ||||
| 	loom = emu->cur_loom; | ||||
| 
 | ||||
| 	/* TODO: Use a table to quickly access the updated elements */ | ||||
| 
 | ||||
| 	/* Check every CPU looking for a change in nthreads */ | ||||
| 	for(i=0; i<loom->ncpus; i++) | ||||
| 	{ | ||||
| 		if(loom->cpu[i].last_nthreads != loom->cpu[i].nthreads) | ||||
| 		{ | ||||
| 			/* Start at 1 */ | ||||
| 			row = loom->offset_ncpus + i + 1; | ||||
| 			n = loom->cpu[i].nthreads; | ||||
| 			prv_ev_cpu(emu, row, PTC_NTHREADS, n); | ||||
| 
 | ||||
| 			pid = n == 1 ? loom->cpu[i].thread[0]->proc->pid : 1; | ||||
| 			prv_ev_cpu(emu, row, PTC_PROC_PID, pid); | ||||
| 
 | ||||
| 			tid = n == 1 ? loom->cpu[i].thread[0]->tid : 1; | ||||
| 			prv_ev_cpu(emu, row, PTC_THREAD_TID, tid); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Same with the virtual CPU */ | ||||
| 	if(loom->vcpu.last_nthreads != loom->vcpu.nthreads) | ||||
| 	{ | ||||
| 		/* Place the virtual CPU after the physical CPUs */ | ||||
| 		row = loom->ncpus + 1; | ||||
| 		n = loom->vcpu.nthreads; | ||||
| 		prv_ev_cpu(emu, row, PTC_NTHREADS, n); | ||||
| 
 | ||||
| 		pid = n == 1 ? loom->vcpu.thread[0]->proc->pid : 1; | ||||
| 		prv_ev_cpu(emu, row, PTC_PROC_PID, pid); | ||||
| 
 | ||||
| 		tid = n == 1 ? loom->vcpu.thread[0]->tid : 1; | ||||
| 		prv_ev_cpu(emu, row, PTC_THREAD_TID, tid); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| emit_current_pid(struct ovni_emu *emu) | ||||
| { | ||||
| 	if(emu->cur_thread->cpu == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	prv_ev_autocpu(emu, PTC_PROC_PID, emu->cur_proc->pid); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_emit_ovni(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	if(emu->cur_ev->header.model != 'O') | ||||
| 		return; | ||||
| 
 | ||||
| 	switch(emu->cur_ev->header.class) | ||||
| 	{ | ||||
| 		case 'H': | ||||
| 			emit_thread_state(emu); | ||||
| 			/* falltrough */ | ||||
| 		case 'A': | ||||
| 			emit_thread_count(emu); | ||||
| 			//emit_current_pid(emu);
 | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Emit all enabled channels */ | ||||
| 	for(i=0; i<CHAN_MAX; i++) | ||||
| 		chan_emit(&emu->cur_thread->chan[i]); | ||||
| } | ||||
| 
 | ||||
| /* --------------------------- post ------------------------------- */ | ||||
| 
 | ||||
| /* Reset thread state */ | ||||
| static void | ||||
| post_virtual_thread(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i; | ||||
| 	struct ovni_loom *loom; | ||||
| 
 | ||||
| 	loom = emu->cur_loom; | ||||
| 
 | ||||
| 	/* Should be executed *before* we reset the CPUs updated flags */ | ||||
| 	assert(loom->nupdated_cpus > 0); | ||||
| 
 | ||||
| 	/* Update last_nthreads in the CPUs */ | ||||
| 	for(i=0; i<loom->ncpus; i++) | ||||
| 		loom->cpu[i].last_nthreads = loom->cpu[i].nthreads; | ||||
| 
 | ||||
| 	/* Fix the virtual CPU as well */ | ||||
| 	loom->vcpu.last_nthreads = loom->vcpu.nthreads; | ||||
| } | ||||
| 
 | ||||
| /* Reset CPU state */ | ||||
| static void | ||||
| post_virtual_cpu(struct ovni_emu *emu) | ||||
| { | ||||
| 	int i; | ||||
| 	struct ovni_loom *loom; | ||||
| 
 | ||||
| 	loom = emu->cur_loom; | ||||
| 
 | ||||
| 	for(i=0; i<loom->nupdated_cpus; i++) | ||||
| 	{ | ||||
| 		/* Remove the update flags */ | ||||
| 		assert(loom->updated_cpu[i]->updated == 1); | ||||
| 		loom->updated_cpu[i]->updated = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Fix the virtual CPU as well */ | ||||
| 	loom->vcpu.last_nthreads = loom->vcpu.nthreads; | ||||
| 
 | ||||
| 	/* Restore 0 updated CPUs */ | ||||
| 	loom->nupdated_cpus = 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| post_virtual(struct ovni_emu *emu) | ||||
| { | ||||
| 	switch(emu->cur_ev->header.class) | ||||
| 	{ | ||||
| 		case 'H': | ||||
| 			post_virtual_thread(emu); | ||||
| 			break; | ||||
| 		case 'C': | ||||
| 			post_virtual_cpu(emu); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| hook_post_ovni(struct ovni_emu *emu) | ||||
| { | ||||
| 	switch(emu->cur_ev->header.model) | ||||
| 	{ | ||||
| 		case '*': | ||||
| 			post_virtual(emu); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user