Port Nanos6 model to tasks with bodies
For now we still allow Nanos6 to use the relaxed nest model, so a nested task can begin the execution without the parent being paused.
This commit is contained in:
		
							parent
							
								
									815633221d
								
							
						
					
					
						commit
						50837d6173
					
				| @ -224,11 +224,6 @@ chan_task_switch(struct emu *emu, | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (prev->thread != next->thread) { | ||||
| 		err("cannot switch to a task of another thread"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (chan_set(&th->m.ch[CH_TASKID], value_int64(next->id)) != 0) { | ||||
| 		err("chan_set taskid failed"); | ||||
| 		return -1; | ||||
| @ -271,19 +266,22 @@ update_task_state(struct emu *emu) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Nanos6 doesn't have parallel tasks */ | ||||
| 	uint32_t body_id = 1; | ||||
| 
 | ||||
| 	int ret = 0; | ||||
| 	switch (emu->ev->v) { | ||||
| 		case 'x': | ||||
| 			ret = task_execute(stack, task); | ||||
| 			ret = task_execute(stack, task, body_id); | ||||
| 			break; | ||||
| 		case 'e': | ||||
| 			ret = task_end(stack, task); | ||||
| 			ret = task_end(stack, task, body_id); | ||||
| 			break; | ||||
| 		case 'p': | ||||
| 			ret = task_pause(stack, task); | ||||
| 			ret = task_pause(stack, task, body_id); | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			ret = task_resume(stack, task); | ||||
| 			ret = task_resume(stack, task, body_id); | ||||
| 			break; | ||||
| 		default: | ||||
| 			err("unexpected Nanos6 task event"); | ||||
| @ -352,7 +350,7 @@ update_task_channels(struct emu *emu, | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| enforce_task_rules(struct emu *emu, char tr, struct task *next) | ||||
| enforce_task_rules(struct emu *emu, char tr, struct body *bnext) | ||||
| { | ||||
| 	if (tr != 'x' && tr != 'X') | ||||
| 		return 0; | ||||
| @ -360,8 +358,9 @@ enforce_task_rules(struct emu *emu, char tr, struct task *next) | ||||
| 	/* 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"); | ||||
| 	if (body_get_state(bnext) != BODY_ST_RUNNING) { | ||||
| 		err("task body %u not in running state on begin", | ||||
| 				body_get_id(bnext)); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| @ -407,7 +406,8 @@ update_task(struct emu *emu) | ||||
| 	struct nanos6_thread *th = EXT(emu->thread, '6'); | ||||
| 	struct task_stack *stack = &th->task_stack; | ||||
| 
 | ||||
| 	struct task *prev = task_get_running(stack); | ||||
| 	struct body *bprev = task_get_running(stack); | ||||
| 	struct task *prev = bprev == NULL ? NULL : body_get_task(bprev); | ||||
| 
 | ||||
| 	/* Update the emulator state, but don't modify the channels */ | ||||
| 	if (update_task_state(emu) != 0) { | ||||
| @ -415,7 +415,8 @@ update_task(struct emu *emu) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	struct task *next = task_get_running(stack); | ||||
| 	struct body *bnext = task_get_running(stack); | ||||
| 	struct task *next = bnext == NULL ? NULL : body_get_task(bnext); | ||||
| 
 | ||||
| 	/* Update the subsystem channel */ | ||||
| 	if (update_task_ss_channel(emu, emu->ev->v) != 0) { | ||||
| @ -437,7 +438,7 @@ update_task(struct emu *emu) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (enforce_task_rules(emu, tr, next) != 0) { | ||||
| 	if (enforce_task_rules(emu, tr, bnext) != 0) { | ||||
| 		err("enforce_task_rules failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
| @ -459,7 +460,14 @@ create_task(struct emu *emu) | ||||
| 	struct nanos6_proc *proc = EXT(emu->proc, '6'); | ||||
| 	struct task_info *info = &proc->task_info; | ||||
| 
 | ||||
| 	if (task_create(info, type_id, task_id) != 0) { | ||||
| 	/* Only allow pausing the tasks, no parallel or resurrect */ | ||||
| 	int flags = TASK_FLAG_PAUSE; | ||||
| 
 | ||||
| 	/* TODO: Nanos6 still submits inline tasks without pausing the previous
 | ||||
| 	 * task, so we relax the model to allow this for now. */ | ||||
| 	flags |= TASK_FLAG_RELAX_NESTING; | ||||
| 
 | ||||
| 	if (task_create(info, type_id, task_id, flags) != 0) { | ||||
| 		err("task_create failed"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -297,12 +297,6 @@ model_nanos6_create(struct emu *emu) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Init task stack thread pointer */ | ||||
| 	for (struct thread *t = sys->threads; t; t = t->gnext) { | ||||
| 		struct nanos6_thread *th = EXT(t, model_id); | ||||
| 		th->task_stack.thread = t; | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct proc *p = sys->procs; p; p = p->gnext) { | ||||
| 		if (init_proc(p) != 0) { | ||||
| 			err("init_proc failed"); | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
| test_emu(nested-tasks.c) | ||||
| test_emu(nested-tasks-bad.c SHOULD_FAIL | ||||
|   REGEX "cannot execute task 1: state is not created") | ||||
|   REGEX "body_execute: body 1 state must be Created but is Running") | ||||
| test_emu(task-types.c MP) | ||||
| test_emu(blocking.c MP) | ||||
| test_emu(ss-mismatch.c SHOULD_FAIL | ||||
| @ -13,8 +13,5 @@ test_emu(switch-same-type.c) | ||||
| test_emu(sponge.c) | ||||
| test_emu(sponge-breakdown.c BREAKDOWN) | ||||
| test_emu(breakdown-no-black.c BREAKDOWN) | ||||
| 
 | ||||
| # FIXME: Disabled to support the taskiter in NODES until we have more detailed | ||||
| # task states instrumentation. | ||||
| test_emu(rerun-task-bad.c DISABLED SHOULD_FAIL | ||||
|   REGEX "task_execute: cannot execute task [0-9]\\+: state is not created") | ||||
| test_emu(rerun-task-bad.c SHOULD_FAIL | ||||
|   REGEX "body_execute: body 1 cannot resurrect") | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user