added more code for process scheduling
This commit is contained in:
		
							
								
								
									
										122
									
								
								stix/lib/exec.c
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								stix/lib/exec.c
									
									
									
									
									
								
							| @ -100,6 +100,84 @@ | ||||
| #	define DBGOUT_EXEC_3(fmt,a1,a2,a3) | ||||
| #endif | ||||
|  | ||||
| static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c) | ||||
| { | ||||
| 	stix_oop_process_t proc; | ||||
|  | ||||
| /* TODO: do something about the stack. */ | ||||
| 	stix_pushtmp (stix, &c); | ||||
| 	proc = (stix_oop_process_t)stix_instantiate (stix, stix->_process, STIX_NULL, stix->option.dfl_procstk_size); | ||||
| 	stix_poptmp (stix); | ||||
| 	if (!proc) return STIX_NULL; | ||||
|  | ||||
| 	proc->state = STIX_OOP_FROM_SMINT(0); | ||||
| 	proc->context = c; | ||||
|  | ||||
| 	return proc; | ||||
| } | ||||
|  | ||||
| static void resume_process (stix_t* stix, stix_oop_process_t proc) | ||||
| { | ||||
| 	if (proc->state == STIX_OOP_FROM_SMINT(0)) | ||||
| 	{ | ||||
| 		stix_ooi_t tally; | ||||
| 		STIX_ASSERT (proc->prev == stix->_nil); | ||||
| 		STIX_ASSERT (proc->next == stix->_nil); | ||||
|  | ||||
| 		tally = STIX_OOP_TO_SMINT(stix->scheduler->tally); | ||||
| 		if (tally <= 0) | ||||
| 		{ | ||||
| 			stix->scheduler->head = proc; | ||||
| 			stix->scheduler->tail = proc; | ||||
| 			stix->scheduler->tally  = STIX_OOP_FROM_SMINT(1); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* TODO: over flow check or maximum number of process check? */ | ||||
| 			proc->next = stix->scheduler->head; | ||||
| 			stix->scheduler->head->prev = proc; | ||||
| 			stix->scheduler->head = proc; | ||||
| 			stix->scheduler->tally = STIX_OOP_FROM_SMINT(tally + 1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	stix->scheduler->active = proc; | ||||
| 	proc->state = STIX_OOP_FROM_SMINT(1); /* TODO: change the code properly... changing state alone doesn't help */ | ||||
| } | ||||
|  | ||||
| static stix_oop_process_t start_new_process (stix_t* stix, stix_oop_context_t c) | ||||
| { | ||||
| 	stix_oop_process_t proc; | ||||
|  | ||||
| 	proc = make_process (stix, c); | ||||
| 	if (!proc) return STIX_NULL; | ||||
|  | ||||
| 	resume_process (stix, proc); | ||||
| 	return proc; | ||||
| } | ||||
|  | ||||
| static void switch_process (stix_t* stix, stix_oop_process_t proc) | ||||
| { | ||||
| 	if (stix->scheduler->active != proc) | ||||
| 	{ | ||||
| 		SWITCH_ACTIVE_CONTEXT (stix, proc->context); | ||||
| 		/*TODO: set the state to RUNNING */ | ||||
| 		stix->scheduler->active = proc; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void switch_to_next_process (stix_t* stix) | ||||
| { | ||||
| /* TODO: this is experimental. rewrite it */ | ||||
| 	if (stix->scheduler->active->next == stix->_nil) | ||||
| 	{ | ||||
| 		switch_process (stix, stix->scheduler->head); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		switch_process (stix, stix->scheduler->active->next); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth) | ||||
| { | ||||
| @ -337,6 +415,7 @@ static int activate_initial_context (stix_t* stix, const stix_ucs_t* objname, co | ||||
| 	stix_oop_context_t ctx; | ||||
| 	stix_oop_association_t ass; | ||||
| 	stix_oop_method_t mth; | ||||
| 	stix_oop_process_t proc; | ||||
|  | ||||
| 	/* create a fake initial context */ | ||||
| 	ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, 1); | ||||
| @ -369,20 +448,30 @@ TODO: overcome this problem | ||||
|  | ||||
| 	ctx->origin = ctx; | ||||
| 	ctx->method_or_nargs = (stix_oop_t)mth; /* fake. help SWITCH_ACTIVE_CONTEXT() not fail*/ | ||||
| 	/* receiver, sender of ctx are nils */ | ||||
|  | ||||
| 	/* [NOTE] | ||||
| 	 *  the receiver field and the sender field of ctx are nils. | ||||
| 	 *  especially, the fact that the sender field is nil is used by  | ||||
| 	 *  the main execution loop for breaking out of the loop */ | ||||
|  | ||||
| 	STIX_ASSERT (stix->active_context == STIX_NULL); | ||||
| 	/* i can't use SWITCH_ACTIVE_CONTEXT() macro as there is no active context before switching */ | ||||
| 	/* i can't use SWITCH_ACTIVE_CONTEXT() macro as there is no active  | ||||
| 	 * context before switching. let's force set active_context to ctx | ||||
| 	 * directly. */ | ||||
| 	stix->active_context = ctx; | ||||
| 	ACTIVE_STACK_PUSH (stix, ass->value); /* push the receiver */ | ||||
|  | ||||
| 	STORE_ACTIVE_IP (stix); | ||||
| 	STORE_ACTIVE_SP (stix); | ||||
|  | ||||
| 	stix_pushtmp (stix, (stix_oop_t*)&mth); | ||||
| 	proc = start_new_process (stix, ctx); | ||||
| 	stix_poptmp (stix); | ||||
| 	if (!proc) return -1; | ||||
|  | ||||
| 	return activate_new_method (stix, mth); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| static int prim_dump (stix_t* stix, stix_ooi_t nargs) | ||||
| { | ||||
| @ -771,6 +860,27 @@ printf ("<<ENTERING BLOCK>>\n"); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int prim_block_new_process (stix_t* stix, stix_ooi_t nargs) | ||||
| { | ||||
| 	stix_oop_process_t proc; | ||||
| 	stix_oop_context_t rcv; | ||||
|  | ||||
| 	rcv = (stix_oop_context_t)ACTIVE_STACK_GETTOP(stix); | ||||
| 	if (STIX_CLASSOF(stix, rcv) != stix->_block_context) | ||||
| 	{ | ||||
| #if defined(STIX_DEBUG_EXEC) | ||||
| printf ("PRIMITVE VALUE RECEIVER IS NOT A BLOCK CONTEXT\n"); | ||||
| #endif | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	proc = make_process (stix, rcv); | ||||
| 	if (!proc) return -1; /* hard failure */ /* TOOD: can't this be a soft failure? */ | ||||
|  | ||||
| 	ACTIVE_STACK_SETTOP (stix, (stix_oop_t)proc); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int prim_integer_add (stix_t* stix, stix_ooi_t nargs) | ||||
| { | ||||
| 	stix_ooi_t tmp; | ||||
| @ -1319,6 +1429,7 @@ static prim_t primitives[] = | ||||
| 	{   2,   prim_basic_at_put,         "_basic_at_put"        }, | ||||
|  | ||||
| 	{  -1,   prim_block_value,          "_block_value"         }, | ||||
| 	{   0,   prim_block_new_process,    "_block_new_process"   }, | ||||
|  | ||||
| 	{   1,   prim_integer_add,          "_integer_add"         }, | ||||
| 	{   1,   prim_integer_sub,          "_integer_sub"         }, | ||||
| @ -1519,6 +1630,8 @@ int stix_execute (stix_t* stix) | ||||
| 	while (1) | ||||
| 	{ | ||||
|  | ||||
|  | ||||
| switch_to_next_process (stix); | ||||
| #if 0 | ||||
| printf ("IP => %d ", (int)stix->ip); | ||||
| #endif | ||||
| @ -2498,11 +2611,8 @@ oops: | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| int stix_invoke (stix_t* stix, const stix_ucs_t* objname, const stix_ucs_t* mthname) | ||||
| { | ||||
| 	/*stix_oop_process_t proc;*/ | ||||
|  | ||||
| 	if (activate_initial_context (stix, objname, mthname) <= -1) return -1; | ||||
| 	return stix_execute (stix); | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user