added code to handle timed semaphore singalling
This commit is contained in:
		| @ -57,13 +57,14 @@ | |||||||
|  |  | ||||||
| #class Semaphore(Object) | #class Semaphore(Object) | ||||||
| { | { | ||||||
| 	#dcl count waiting_head waiting_tail heapIndex fireTime. | 	#dcl count waiting_head waiting_tail heapIndex fireTimeSec fireTimeNsec. | ||||||
|  |  | ||||||
| 	#method initialize | 	#method initialize | ||||||
| 	{ | 	{ | ||||||
| 		self.count := 0. | 		self.count := 0. | ||||||
| 		self.heapIndex := -1. | 		self.heapIndex := -1. | ||||||
| 		self.fireTime := 0. | 		self.fireTimeSec := 0. | ||||||
|  | 		self.fireTimeNsec := 0. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#method signal  | 	#method signal  | ||||||
| @ -90,17 +91,17 @@ | |||||||
|  |  | ||||||
| 	#method fireTime | 	#method fireTime | ||||||
| 	{ | 	{ | ||||||
| 		^fireTime | 		^fireTimeSec | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#method fireTime: anInteger | 	#method fireTime: anInteger | ||||||
| 	{ | 	{ | ||||||
| 		self.fireTime := anInteger. | 		self.fireTimeSec := anInteger. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#method youngerThan: aSemaphore | 	#method youngerThan: aSemaphore | ||||||
| 	{ | 	{ | ||||||
| 		^self.fireTime < (aSemaphore fireTime) | 		^self.fireTimeSec < (aSemaphore fireTime) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -153,8 +154,19 @@ | |||||||
| 		^top | 		^top | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#method updateAt: anIndex | 	#method updateAt: anIndex with: aSemaphore | ||||||
| 	{ | 	{ | ||||||
|  | 		| item | | ||||||
|  |  | ||||||
|  | 		item := self.arr at: anIndex. | ||||||
|  | 		item heapIndex: -1. | ||||||
|  |  | ||||||
|  | 		self.arr at: anIndex put: aSemaphore. | ||||||
|  | 		aSemaphore heapIndex: anIndex. | ||||||
|  |  | ||||||
|  | 		^(aSemaphore youngerThan: item) | ||||||
|  | 			ifTrue: [ self siftUp: anIndex ] | ||||||
|  | 			ifFalse: [ self siftDown: anIndex ]. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#method deleteAt: anIndex | 	#method deleteAt: anIndex | ||||||
| @ -333,6 +345,13 @@ | |||||||
|  |  | ||||||
| 	#method signal: aSemaphore after: anInteger | 	#method signal: aSemaphore after: anInteger | ||||||
| 	{ | 	{ | ||||||
| 		self.sem_heap add: aSemaphore withTimeout: anInteger. | 		<primitive: #_processor_add_timed_semaphore> | ||||||
|  | 		self primitiveFailed. | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	#method signal: aSemaphore after: aSecond and: aNanoSecond | ||||||
|  | 	{ | ||||||
|  | 		<primitive: #_processor_add_timed_semaphore> | ||||||
|  | 		self primitiveFailed. | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										485
									
								
								stix/lib/exec.c
									
									
									
									
									
								
							
							
						
						
									
										485
									
								
								stix/lib/exec.c
									
									
									
									
									
								
							| @ -26,12 +26,29 @@ | |||||||
|  |  | ||||||
| #include "stix-prv.h" | #include "stix-prv.h" | ||||||
|  |  | ||||||
|  | /* TODO: remove this header after having changed clock_gettime() to a  | ||||||
|  |  *       platform independent function */ | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
| #define PROCESS_STATE_RUNNING 3 | #define PROC_STATE_RUNNING 3 | ||||||
| #define PROCESS_STATE_WAITING 2 | #define PROC_STATE_WAITING 2 | ||||||
| #define PROCESS_STATE_RUNNABLE 1 | #define PROC_STATE_RUNNABLE 1 | ||||||
| #define PROCESS_STATE_SUSPENDED 0 | #define PROC_STATE_SUSPENDED 0 | ||||||
| #define PROCESS_STATE_TERMINATED -1 | #define PROC_STATE_TERMINATED -1 | ||||||
|  |  | ||||||
|  | #define SEM_LIST_INC 256 | ||||||
|  | #define SEM_HEAP_INC 256 | ||||||
|  | #define SEM_LIST_MAX (SEM_LIST_INC * 1000) | ||||||
|  | #define SEM_HEAP_MAX (SEM_HEAP_INC * 1000) | ||||||
|  |  | ||||||
|  | #define SEM_HEAP_PARENT(x) (((x) - 1) / 2) | ||||||
|  | #define SEM_HEAP_LEFT(x)   ((x) * 2 + 1) | ||||||
|  | #define SEM_HEAP_RIGHT(x)  ((x) * 2 + 2) | ||||||
|  |  | ||||||
|  | #define SEM_HEAP_EARLIER_THAN(stx,x,y) ( \ | ||||||
|  | 	(STIX_OOP_TO_SMOOI((x)->heap_ftime_sec) < STIX_OOP_TO_SMOOI((y)->heap_ftime_sec)) || \ | ||||||
|  | 	(STIX_OOP_TO_SMOOI((x)->heap_ftime_sec) == STIX_OOP_TO_SMOOI((y)->heap_ftime_sec) && STIX_OOP_TO_SMOOI((x)->heap_ftime_nsec) < STIX_OOP_TO_SMOOI((y)->heap_ftime_nsec)) \ | ||||||
|  | ) | ||||||
|  |  | ||||||
| #if defined(USE_DYNCALL) | #if defined(USE_DYNCALL) | ||||||
| /* TODO: defined dcAllocMem and dcFreeMeme before builing the dynload and dyncall library */ | /* TODO: defined dcAllocMem and dcFreeMeme before builing the dynload and dyncall library */ | ||||||
| @ -149,7 +166,7 @@ static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c) | |||||||
| 	stix_poptmp (stix); | 	stix_poptmp (stix); | ||||||
| 	if (!proc) return STIX_NULL; | 	if (!proc) return STIX_NULL; | ||||||
|  |  | ||||||
| 	proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED); | 	proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); | ||||||
| 	proc->initial_context = c; | 	proc->initial_context = c; | ||||||
| 	proc->current_context = c; | 	proc->current_context = c; | ||||||
| 	proc->sp = STIX_SMOOI_TO_OOP(-1); | 	proc->sp = STIX_SMOOI_TO_OOP(-1); | ||||||
| @ -166,8 +183,8 @@ static void switch_to_process (stix_t* stix, stix_oop_process_t proc, int new_st | |||||||
| 	STIX_ASSERT (stix->processor->active != proc); | 	STIX_ASSERT (stix->processor->active != proc); | ||||||
|  |  | ||||||
| 	/* the new process must be in the runnable state */ | 	/* the new process must be in the runnable state */ | ||||||
| 	STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE) || | 	STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE) || | ||||||
| 	             proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_WAITING)); | 	             proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_WAITING)); | ||||||
|  |  | ||||||
| #if defined(STIX_DEBUG_PROCESSOR) | #if defined(STIX_DEBUG_PROCESSOR) | ||||||
| printf ("ACTUAL PROCESS SWITCHING BF...%d %p\n", (int)stix->ip, stix->active_context); | printf ("ACTUAL PROCESS SWITCHING BF...%d %p\n", (int)stix->ip, stix->active_context); | ||||||
| @ -183,11 +200,11 @@ printf ("ACTUAL PROCESS SWITCHING BF...%d %p\n", (int)stix->ip, stix->active_con | |||||||
| 	 * it is the suspended context of the process to be suspended */ | 	 * it is the suspended context of the process to be suspended */ | ||||||
| 	STIX_ASSERT ((stix_oop_t)stix->processor->active != stix->_nil); | 	STIX_ASSERT ((stix_oop_t)stix->processor->active != stix->_nil); | ||||||
| 	stix->processor->active->current_context = stix->active_context; | 	stix->processor->active->current_context = stix->active_context; | ||||||
| 	/*stix->processor->active->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE);*/ | 	/*stix->processor->active->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE);*/ | ||||||
| 	stix->processor->active->state = STIX_SMOOI_TO_OOP(new_state_for_old_active); | 	stix->processor->active->state = STIX_SMOOI_TO_OOP(new_state_for_old_active); | ||||||
|  |  | ||||||
| 	/* activate the given process */ | 	/* activate the given process */ | ||||||
| 	proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING); | 	proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING); | ||||||
| 	stix->processor->active = proc; | 	stix->processor->active = proc; | ||||||
|  |  | ||||||
| #if defined(STIX_USE_PROCSTK) | #if defined(STIX_USE_PROCSTK) | ||||||
| @ -209,7 +226,7 @@ printf ("ACTUAL PROCESS SWITCHING AF...%d %p\n", (int)stix->ip, stix->active_con | |||||||
| static STIX_INLINE stix_oop_process_t find_next_runnable_process (stix_t* stix) | static STIX_INLINE stix_oop_process_t find_next_runnable_process (stix_t* stix) | ||||||
| { | { | ||||||
| 	stix_oop_process_t npr; | 	stix_oop_process_t npr; | ||||||
| 	STIX_ASSERT (stix->processor->active->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING)); | 	STIX_ASSERT (stix->processor->active->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING)); | ||||||
| 	npr = stix->processor->active->next; | 	npr = stix->processor->active->next; | ||||||
| 	if ((stix_oop_t)npr == stix->_nil) npr = stix->processor->runnable_head; | 	if ((stix_oop_t)npr == stix->_nil) npr = stix->processor->runnable_head; | ||||||
| 	return npr; | 	return npr; | ||||||
| @ -220,7 +237,7 @@ static STIX_INLINE void switch_to_next_runnable_process (stix_t* stix) | |||||||
| 	stix_oop_process_t nrp; | 	stix_oop_process_t nrp; | ||||||
|  |  | ||||||
| 	nrp = find_next_runnable_process (stix); | 	nrp = find_next_runnable_process (stix); | ||||||
| 	if (nrp != stix->processor->active) switch_to_process (stix, nrp, PROCESS_STATE_RUNNABLE); | 	if (nrp != stix->processor->active) switch_to_process (stix, nrp, PROC_STATE_RUNNABLE); | ||||||
| } | } | ||||||
|  |  | ||||||
| static STIX_INLINE int chain_into_processor (stix_t* stix, stix_oop_process_t proc) | static STIX_INLINE int chain_into_processor (stix_t* stix, stix_oop_process_t proc) | ||||||
| @ -232,7 +249,7 @@ static STIX_INLINE int chain_into_processor (stix_t* stix, stix_oop_process_t pr | |||||||
| 	STIX_ASSERT ((stix_oop_t)proc->prev == stix->_nil); | 	STIX_ASSERT ((stix_oop_t)proc->prev == stix->_nil); | ||||||
| 	STIX_ASSERT ((stix_oop_t)proc->next == stix->_nil); | 	STIX_ASSERT ((stix_oop_t)proc->next == stix->_nil); | ||||||
|  |  | ||||||
| 	STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED)); | 	STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)); | ||||||
|  |  | ||||||
| 	tally = STIX_OOP_TO_SMOOI(stix->processor->tally); | 	tally = STIX_OOP_TO_SMOOI(stix->processor->tally); | ||||||
|  |  | ||||||
| @ -271,8 +288,8 @@ static STIX_INLINE void unchain_from_processor (stix_t* stix, stix_oop_process_t | |||||||
| { | { | ||||||
| 	stix_ooi_t tally; | 	stix_ooi_t tally; | ||||||
|  |  | ||||||
| 	STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING) || | 	STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING) || | ||||||
| 	             proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE)); | 	             proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); | ||||||
|  |  | ||||||
| 	tally = STIX_OOP_TO_SMOOI(stix->processor->tally); | 	tally = STIX_OOP_TO_SMOOI(stix->processor->tally); | ||||||
| 	STIX_ASSERT (tally > 0); | 	STIX_ASSERT (tally > 0); | ||||||
| @ -327,12 +344,14 @@ static STIX_INLINE void unchain_from_semaphore (stix_t* stix, stix_oop_process_t | |||||||
|  |  | ||||||
| 	proc->prev = (stix_oop_process_t)stix->_nil; | 	proc->prev = (stix_oop_process_t)stix->_nil; | ||||||
| 	proc->next = (stix_oop_process_t)stix->_nil; | 	proc->next = (stix_oop_process_t)stix->_nil; | ||||||
|  |  | ||||||
|  | 	proc->sem = (stix_oop_semaphore_t)stix->_nil; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void terminate_process (stix_t* stix, stix_oop_process_t proc) | static void terminate_process (stix_t* stix, stix_oop_process_t proc) | ||||||
| { | { | ||||||
| 	if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING) || | 	if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING) || | ||||||
| 	    proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE)) | 	    proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)) | ||||||
| 	{ | 	{ | ||||||
| 		/* RUNNING/RUNNABLE ---> TERMINATED */ | 		/* RUNNING/RUNNABLE ---> TERMINATED */ | ||||||
| 		if (proc == stix->processor->active) | 		if (proc == stix->processor->active) | ||||||
| @ -342,7 +361,7 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc) | |||||||
| 			nrp = find_next_runnable_process (stix); | 			nrp = find_next_runnable_process (stix); | ||||||
|  |  | ||||||
| 			unchain_from_processor (stix, proc); | 			unchain_from_processor (stix, proc); | ||||||
| 			proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_TERMINATED); | 			proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_TERMINATED); | ||||||
| 			proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the process stack */ | 			proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the process stack */ | ||||||
| 			proc->current_context = proc->initial_context; /* not needed but just in case */ | 			proc->current_context = proc->initial_context; /* not needed but just in case */ | ||||||
|  |  | ||||||
| @ -357,20 +376,20 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc) | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				switch_to_process (stix, nrp, PROCESS_STATE_TERMINATED); | 				switch_to_process (stix, nrp, PROC_STATE_TERMINATED); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			unchain_from_processor (stix, proc); | 			unchain_from_processor (stix, proc); | ||||||
| 			proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_TERMINATED); | 			proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_TERMINATED); | ||||||
| 			proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the process stack */ | 			proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the process stack */ | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED)) | 	else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)) | ||||||
| 	{ | 	{ | ||||||
| 		/* SUSPENDED ---> TERMINATED */ | 		/* SUSPENDED ---> TERMINATED */ | ||||||
| 		proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_TERMINATED); | 		proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_TERMINATED); | ||||||
| 		proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the proce stack */ | 		proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the proce stack */ | ||||||
|  |  | ||||||
| 		if ((stix_oop_t)proc->sem != stix->_nil) | 		if ((stix_oop_t)proc->sem != stix->_nil) | ||||||
| @ -378,7 +397,7 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc) | |||||||
| 			unchain_from_semaphore (stix, proc); | 			unchain_from_semaphore (stix, proc); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_WAITING)) | 	else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_WAITING)) | ||||||
| 	{ | 	{ | ||||||
| 		/* WAITING ---> TERMINATED */ | 		/* WAITING ---> TERMINATED */ | ||||||
| 		/* TODO: */ | 		/* TODO: */ | ||||||
| @ -388,35 +407,36 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc) | |||||||
| static void resume_process (stix_t* stix, stix_oop_process_t proc) | static void resume_process (stix_t* stix, stix_oop_process_t proc) | ||||||
| { | { | ||||||
| printf ("TO RESUME PROCESS = %p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state)); | printf ("TO RESUME PROCESS = %p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state)); | ||||||
| 	if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED)) | 	if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)) | ||||||
| 	{ | 	{ | ||||||
| 		/* SUSPENED ---> RUNNING */ | 		/* SUSPENED ---> RUNNING */ | ||||||
|  |  | ||||||
|  | printf ("TO RESUME PROCESS = %p %d SUSPENED ----> RUNNING\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state)); | ||||||
| 		STIX_ASSERT ((stix_oop_t)proc->prev == stix->_nil); | 		STIX_ASSERT ((stix_oop_t)proc->prev == stix->_nil); | ||||||
| 		STIX_ASSERT ((stix_oop_t)proc->next == stix->_nil); | 		STIX_ASSERT ((stix_oop_t)proc->next == stix->_nil); | ||||||
|  |  | ||||||
| 		chain_into_processor (stix, proc); /* TODO: error check */ | 		chain_into_processor (stix, proc); /* TODO: error check */ | ||||||
|  |  | ||||||
| 		/*proc->current_context = proc->initial_context;*/ | 		/*proc->current_context = proc->initial_context;*/ | ||||||
| 		proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE); | 		proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE); | ||||||
|  |  | ||||||
| 		/*switch_to_process (stix, proc);*/ | 		/*switch_to_process (stix, proc);*/ | ||||||
| 	} | 	} | ||||||
| #if 0 | #if 0 | ||||||
| 	else if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE)) | 	else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)) | ||||||
| 	{ | 	{ | ||||||
| 		/* RUNNABLE ---> RUNNING */ | 		/* RUNNABLE ---> RUNNING */ | ||||||
| 		/* TODO: should i allow this? */ | 		/* TODO: should i allow this? */ | ||||||
| 		STIX_ASSERT (stix->processor->active != proc); | 		STIX_ASSERT (stix->processor->active != proc); | ||||||
| 		switch_to_process (stix, proc, PROCESS_STATE_RUNNABLE); | 		switch_to_process (stix, proc, PROC_STATE_RUNNABLE); | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| static void suspend_process (stix_t* stix, stix_oop_process_t proc) | static void suspend_process (stix_t* stix, stix_oop_process_t proc) | ||||||
| { | { | ||||||
| 	if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING) || | 	if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING) || | ||||||
| 	    proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE)) | 	    proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)) | ||||||
| 	{ | 	{ | ||||||
| 		/* RUNNING/RUNNABLE ---> SUSPENDED */ | 		/* RUNNING/RUNNABLE ---> SUSPENDED */ | ||||||
|  |  | ||||||
| @ -434,25 +454,25 @@ printf ("TO SUSPEND...%p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state)); | |||||||
| 				STIX_ASSERT (stix->processor->active == stix->nil_process); | 				STIX_ASSERT (stix->processor->active == stix->nil_process); | ||||||
| printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n"); | printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n"); | ||||||
|  |  | ||||||
| 				proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED); | 				proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); | ||||||
| 				proc->current_context = stix->active_context; | 				proc->current_context = stix->active_context; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				switch_to_process (stix, nrp, PROCESS_STATE_SUSPENDED); | 				switch_to_process (stix, nrp, PROC_STATE_SUSPENDED); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			unchain_from_processor (stix, proc); | 			unchain_from_processor (stix, proc); | ||||||
| 			proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED); | 			proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static void yield_process (stix_t* stix, stix_oop_process_t proc) | static void yield_process (stix_t* stix, stix_oop_process_t proc) | ||||||
| { | { | ||||||
| 	if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING)) | 	if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING)) | ||||||
| 	{ | 	{ | ||||||
| 		/* RUNNING --> RUNNABLE */ | 		/* RUNNING --> RUNNABLE */ | ||||||
|  |  | ||||||
| @ -465,19 +485,25 @@ static void yield_process (stix_t* stix, stix_oop_process_t proc) | |||||||
| 		 * runnable process must be different from proc */ | 		 * runnable process must be different from proc */ | ||||||
| 		if (nrp != proc)  | 		if (nrp != proc)  | ||||||
| 		{ | 		{ | ||||||
| 			switch_to_process (stix, nrp, PROCESS_STATE_RUNNABLE); | 			switch_to_process (stix, nrp, PROC_STATE_RUNNABLE); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static int async_signal_semaphore (stix_t* stix, stix_oop_semaphore_t sem) | static int async_signal_semaphore (stix_t* stix, stix_oop_semaphore_t sem) | ||||||
| { | { | ||||||
|  | 	if (stix->sem_list_count >= SEM_LIST_MAX) | ||||||
|  | 	{ | ||||||
|  | 		stix->errnum = STIX_ESLFULL; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (stix->sem_list_count >= stix->sem_list_capa) | 	if (stix->sem_list_count >= stix->sem_list_capa) | ||||||
| 	{ | 	{ | ||||||
| 		stix_oow_t new_capa; | 		stix_oow_t new_capa; | ||||||
| 		stix_oop_semaphore_t* tmp; | 		stix_oop_semaphore_t* tmp; | ||||||
|  |  | ||||||
| 		new_capa = stix->sem_list_capa * 2; /* TODO: overflow check.. */ | 		new_capa = stix->sem_list_capa + SEM_LIST_INC; /* TODO: overflow check.. */ | ||||||
| 		tmp = stix_reallocmem (stix, stix->sem_list, STIX_SIZEOF(stix_oop_semaphore_t) * new_capa); | 		tmp = stix_reallocmem (stix, stix->sem_list, STIX_SIZEOF(stix_oop_semaphore_t) * new_capa); | ||||||
| 		if (!tmp) return -1; | 		if (!tmp) return -1; | ||||||
|  |  | ||||||
| @ -541,6 +567,152 @@ printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - SUEPENDING ACTIVE PROCESS............. | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void sift_up_sem_heap (stix_t* stix, stix_ooi_t index) | ||||||
|  | { | ||||||
|  | 	if (index > 0) | ||||||
|  | 	{ | ||||||
|  | 		stix_ooi_t parent; | ||||||
|  | 		stix_oop_semaphore_t sem, parsem; | ||||||
|  |  | ||||||
|  | 		parent = SEM_HEAP_PARENT(index); | ||||||
|  | 		sem = stix->sem_heap[index]; | ||||||
|  | 		parsem = stix->sem_heap[parent]; | ||||||
|  | 		if (SEM_HEAP_EARLIER_THAN(stix, sem, parsem)) | ||||||
|  | 		{ | ||||||
|  | 			do | ||||||
|  | 			{ | ||||||
|  | 				/* move down the parent to the current position */ | ||||||
|  | 				parsem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 				stix->sem_heap[index] = parsem; | ||||||
|  |  | ||||||
|  | 				/* traverse up */ | ||||||
|  | 				index = parent; | ||||||
|  | 				if (index <= 0) break; | ||||||
|  |  | ||||||
|  | 				parent = SEM_HEAP_PARENT(parent); | ||||||
|  | 				parsem = stix->sem_heap[parent]; | ||||||
|  | 			} | ||||||
|  | 			while (SEM_HEAP_EARLIER_THAN(stix, sem, parsem)); | ||||||
|  |  | ||||||
|  | 			sem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 			stix->sem_heap[index] = sem; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void sift_down_sem_heap (stix_t* stix, stix_ooi_t index) | ||||||
|  | { | ||||||
|  | 	stix_ooi_t base = stix->sem_heap_count / 2; | ||||||
|  |  | ||||||
|  | 	if (index < base) /* at least 1 child is under the 'index' position */ | ||||||
|  | 	{ | ||||||
|  | 		stix_ooi_t left, right, child; | ||||||
|  | 		stix_oop_semaphore_t sem, chisem; | ||||||
|  |  | ||||||
|  | 		sem = stix->sem_heap[index]; | ||||||
|  | 		do | ||||||
|  | 		{ | ||||||
|  | 			left = SEM_HEAP_LEFT(index); | ||||||
|  | 			right = SEM_HEAP_RIGHT(index); | ||||||
|  |  | ||||||
|  | 			if (right < stix->sem_heap_count && SEM_HEAP_EARLIER_THAN(stix, stix->sem_heap[left], stix->sem_heap[right])) | ||||||
|  | 			{ | ||||||
|  | 				child = right; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				child = left; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			chisem = stix->sem_heap[child]; | ||||||
|  | 			if (SEM_HEAP_EARLIER_THAN(stix, sem, chisem)) break; | ||||||
|  |  | ||||||
|  | 			chisem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 			stix->sem_heap[index ] = chisem; | ||||||
|  |  | ||||||
|  | 			index = child; | ||||||
|  | 		} | ||||||
|  | 		while (index < base); | ||||||
|  |  | ||||||
|  | 		sem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 		stix->sem_heap[index] = sem; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int add_to_sem_heap (stix_t* stix, stix_oop_semaphore_t sem) | ||||||
|  | { | ||||||
|  | 	stix_ooi_t index; | ||||||
|  |  | ||||||
|  | 	if (stix->sem_heap_count >= SEM_HEAP_MAX) | ||||||
|  | 	{ | ||||||
|  | 		stix->errnum = STIX_ESHFULL; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (stix->sem_heap_count >= stix->sem_heap_capa) | ||||||
|  | 	{ | ||||||
|  | 		stix_oow_t new_capa; | ||||||
|  | 		stix_oop_semaphore_t* tmp; | ||||||
|  |  | ||||||
|  | 		/* no overflow check when calculating the new capacity | ||||||
|  | 		 * owing to SEM_HEAP_MAX check above */ | ||||||
|  | 		new_capa = stix->sem_heap_capa + SEM_HEAP_INC; | ||||||
|  | 		tmp = stix_reallocmem (stix, stix->sem_heap, STIX_SIZEOF(stix_oop_semaphore_t) * new_capa); | ||||||
|  | 		if (!tmp) return -1; | ||||||
|  |  | ||||||
|  | 		stix->sem_heap = tmp; | ||||||
|  | 		stix->sem_heap_capa = new_capa; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	STIX_ASSERT (stix->sem_heap_count <= STIX_SMOOI_MAX); | ||||||
|  |  | ||||||
|  | 	index = stix->sem_heap_count; | ||||||
|  | 	stix->sem_heap[index] = sem; | ||||||
|  | 	sem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 	stix->sem_heap_count++; | ||||||
|  |  | ||||||
|  | 	sift_up_sem_heap (stix, index); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void delete_from_sem_heap (stix_t* stix, stix_ooi_t index) | ||||||
|  | { | ||||||
|  | 	stix_oop_semaphore_t sem, lastsem; | ||||||
|  |  | ||||||
|  | 	sem = stix->sem_heap[index]; | ||||||
|  | 	sem->heap_index = STIX_SMOOI_TO_OOP(-1); | ||||||
|  |  | ||||||
|  | 	stix->sem_heap_count--; | ||||||
|  | 	if (stix->sem_heap_count > 0 && index != stix->sem_heap_count) | ||||||
|  | 	{ | ||||||
|  | 		/* move the last item to the deletion position */ | ||||||
|  | 		lastsem = stix->sem_heap[stix->sem_heap_count]; | ||||||
|  | 		lastsem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 		stix->sem_heap[index] = lastsem; | ||||||
|  |  | ||||||
|  | 		if (SEM_HEAP_EARLIER_THAN(stix, lastsem, sem))  | ||||||
|  | 			sift_up_sem_heap (stix, index); | ||||||
|  | 		else | ||||||
|  | 			sift_down_sem_heap (stix, index); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void update_sem_heap (stix_t* stix, stix_ooi_t index, stix_oop_semaphore_t newsem) | ||||||
|  | { | ||||||
|  | 	stix_oop_semaphore_t sem; | ||||||
|  |  | ||||||
|  | 	sem = stix->sem_heap[index]; | ||||||
|  | 	sem->heap_index = STIX_SMOOI_TO_OOP(-1); | ||||||
|  |  | ||||||
|  | 	newsem->heap_index = STIX_SMOOI_TO_OOP(index); | ||||||
|  | 	stix->sem_heap[index] = newsem; | ||||||
|  |  | ||||||
|  | 	if (SEM_HEAP_EARLIER_THAN(stix, newsem, sem)) | ||||||
|  | 		sift_up_sem_heap (stix, index); | ||||||
|  | 	else | ||||||
|  | 		sift_down_sem_heap (stix, index); | ||||||
|  | } | ||||||
|  |  | ||||||
| static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_t c) | static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_t c) | ||||||
| { | { | ||||||
| 	stix_oop_process_t proc; | 	stix_oop_process_t proc; | ||||||
| @ -553,7 +725,7 @@ static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_ | |||||||
| 	if (!proc) return STIX_NULL; | 	if (!proc) return STIX_NULL; | ||||||
|  |  | ||||||
| 	if (chain_into_processor (stix, proc) <= -1) return STIX_NULL; | 	if (chain_into_processor (stix, proc) <= -1) return STIX_NULL; | ||||||
| 	proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */ | 	proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */ | ||||||
| 	stix->processor->active = proc; | 	stix->processor->active = proc; | ||||||
|  |  | ||||||
| 	/* do somthing that resume_process() would do with less overhead */ | 	/* do somthing that resume_process() would do with less overhead */ | ||||||
| @ -1478,6 +1650,101 @@ static int prim_processor_sleep (stix_t* stix, stix_ooi_t nargs) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int prim_processor_add_timed_semaphore (stix_t* stix, stix_ooi_t nargs) | ||||||
|  | { | ||||||
|  | 	stix_oop_t rcv, sec, nsec; | ||||||
|  | 	stix_oop_semaphore_t sem; | ||||||
|  | 	struct timespec ts, ft; | ||||||
|  |  | ||||||
|  | 	STIX_ASSERT (nargs >= 2 || nargs <= 3); | ||||||
|  |  | ||||||
|  | 	if (nargs == 3)  | ||||||
|  | 	{ | ||||||
|  | 		nsec = ACTIVE_STACK_GET (stix, stix->sp); | ||||||
|  | 		if (!STIX_OOP_IS_SMOOI(nsec)) return 0; | ||||||
|  | 	} | ||||||
|  | 	else nsec = STIX_SMOOI_TO_OOP(0); | ||||||
|  |  | ||||||
|  | 	sec = ACTIVE_STACK_GET(stix, stix->sp - nargs + 2); | ||||||
|  | 	sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp - nargs + 1); | ||||||
|  | 	rcv = ACTIVE_STACK_GET(stix, stix->sp - nargs); | ||||||
|  |  | ||||||
|  | 	if (rcv != (stix_oop_t)stix->processor) return 0; | ||||||
|  | 	if (STIX_CLASSOF(stix,sem) != stix->_semaphore) return 0; | ||||||
|  | 	if (!STIX_OOP_IS_SMOOI(sec)) return 0; | ||||||
|  |  | ||||||
|  | 	if (STIX_OOP_IS_SMOOI(sem->heap_index) &&  | ||||||
|  | 	    sem->heap_index != STIX_SMOOI_TO_OOP(-1)) | ||||||
|  | 	{ | ||||||
|  | 		delete_from_sem_heap (stix, STIX_OOP_TO_SMOOI(sem->heap_index)); | ||||||
|  | 		STIX_ASSERT(sem->heap_index == STIX_SMOOI_TO_OOP(-1)); | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		Is this more desired??? | ||||||
|  | 		ACTIVE_STACK_POPS (stix, nargs); | ||||||
|  | 		ACTIVE_STACK_SETTOP (stix, stix->_false); | ||||||
|  | 		return 1; | ||||||
|  | 		*/ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | /* TODO: make clock_gettime to be platform independent  | ||||||
|  |  *  | ||||||
|  |  * this code assumes that the monotonic clock returns a small value | ||||||
|  |  * that can fit into a small integer, even after some addtions... */ | ||||||
|  | 	if (clock_gettime (CLOCK_MONOTONIC, &ts) == -1) | ||||||
|  | 	{ | ||||||
|  | 		/* TODO: soft error handling */ | ||||||
|  | printf ("clock_gettime() failure....\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ft.tv_nsec = ts.tv_nsec + STIX_OOP_TO_SMOOI(nsec); | ||||||
|  | 	ft.tv_sec = ts.tv_sec + STIX_OOP_TO_SMOOI(sec); | ||||||
|  | 	while (ft.tv_nsec >= 1000000000) | ||||||
|  | 	{ | ||||||
|  | 		ft.tv_sec++; | ||||||
|  | 		ft.tv_nsec -= 1000000000; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (ft.tv_sec < 0 || ft.tv_sec > STIX_SMOOI_MAX)  | ||||||
|  | 	{ | ||||||
|  | 		/* soft error - cannot represent the expiry time in | ||||||
|  | 		 *              a small integer. */ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sem->heap_ftime_sec = STIX_SMOOI_TO_OOP(ft.tv_sec); | ||||||
|  | 	sem->heap_ftime_nsec = STIX_SMOOI_TO_OOP(ft.tv_nsec); | ||||||
|  |  | ||||||
|  | 	if (add_to_sem_heap (stix, sem) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 	ACTIVE_STACK_POPS (stix, nargs); | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int prim_processor_del_time_semaphore (stix_t* stix, stix_ooi_t nargs) | ||||||
|  | { | ||||||
|  | 	stix_oop_t rcv; | ||||||
|  | 	stix_oop_semaphore_t sem; | ||||||
|  |  | ||||||
|  | 	STIX_ASSERT (nargs == 1); | ||||||
|  |  | ||||||
|  | 	sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp - 1); | ||||||
|  | 	rcv = ACTIVE_STACK_GET(stix, stix->sp); | ||||||
|  |  | ||||||
|  | 	if (rcv != (stix_oop_t)stix->processor) return 0; | ||||||
|  | 	if (STIX_CLASSOF(stix,sem) != stix->_semaphore) return 0; | ||||||
|  |  | ||||||
|  | 	if (STIX_OOP_IS_SMOOI(sem->heap_index) &&  | ||||||
|  | 	    sem->heap_index != STIX_SMOOI_TO_OOP(-1)) | ||||||
|  | 	{ | ||||||
|  | 		delete_from_sem_heap (stix, STIX_OOP_TO_SMOOI(sem)); | ||||||
|  | 		STIX_ASSERT(sem->heap_index == STIX_SMOOI_TO_OOP(-1)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int prim_integer_add (stix_t* stix, stix_ooi_t nargs) | static int prim_integer_add (stix_t* stix, stix_ooi_t nargs) | ||||||
| { | { | ||||||
| 	stix_oop_t rcv, arg, res; | 	stix_oop_t rcv, arg, res; | ||||||
| @ -2123,10 +2390,11 @@ printf ("wrong function name...\n"); | |||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #define MAX_NARGS STIX_TYPE_MAX(stix_ooi_t) | ||||||
| struct prim_t | struct prim_t | ||||||
| { | { | ||||||
| 	stix_ooi_t          nargs;   /* expected number of arguments */ | 	stix_ooi_t          min_nargs;   /* expected number of arguments */ | ||||||
|  | 	stix_ooi_t          max_nargs;   /* expected number of arguments */ | ||||||
| 	stix_prim_impl_t    handler; | 	stix_prim_impl_t    handler; | ||||||
| 	const char*         name;    /* the name is supposed to be 7-bit ascii only */ | 	const char*         name;    /* the name is supposed to be 7-bit ascii only */ | ||||||
| }; | }; | ||||||
| @ -2134,62 +2402,64 @@ typedef struct prim_t prim_t; | |||||||
|  |  | ||||||
| static prim_t primitives[] = | static prim_t primitives[] = | ||||||
| { | { | ||||||
| 	{  -1,   prim_dump,                 "_dump"                }, | 	{   0, MAX_NARGS,  prim_dump,                 "_dump"                }, | ||||||
| 	{   1,   prim_identical,            "_identical"           }, |  | ||||||
| 	{   1,   prim_not_identical,        "_not_identical"       }, |  | ||||||
| 	{   0,   prim_class,                "_class"               }, |  | ||||||
|  |  | ||||||
| 	{   0,   prim_basic_new,            "_basic_new"           }, | 	{   1,  1,  prim_identical,            "_identical"           }, | ||||||
| 	{   1,   prim_basic_new_with_size,  "_basic_new_with_size" }, | 	{   1,  1,  prim_not_identical,        "_not_identical"       }, | ||||||
| 	{   0,   prim_ngc_new,              "_ngc_new"             }, | 	{   0,  0,  prim_class,                "_class"               }, | ||||||
| 	{   1,   prim_ngc_new_with_size,    "_ngc_new_with_size"   }, |  | ||||||
| 	{   0,   prim_ngc_dispose,          "_ngc_dispose"         }, |  | ||||||
| 	{   0,   prim_shallow_copy,         "_shallow_copy"        }, |  | ||||||
|  |  | ||||||
| 	{   0,   prim_basic_size,           "_basic_size"          }, | 	{   0,  0,  prim_basic_new,            "_basic_new"           }, | ||||||
| 	{   1,   prim_basic_at,             "_basic_at"            }, | 	{   1,  1,  prim_basic_new_with_size,  "_basic_new_with_size" }, | ||||||
| 	{   2,   prim_basic_at_put,         "_basic_at_put"        }, | 	{   0,  0,  prim_ngc_new,              "_ngc_new"             }, | ||||||
|  | 	{   1,  1,  prim_ngc_new_with_size,    "_ngc_new_with_size"   }, | ||||||
|  | 	{   0,  0,  prim_ngc_dispose,          "_ngc_dispose"         }, | ||||||
|  | 	{   0,  0,  prim_shallow_copy,         "_shallow_copy"        }, | ||||||
|  |  | ||||||
|  | 	{   0,  0,  prim_basic_size,           "_basic_size"          }, | ||||||
|  | 	{   1,  1,  prim_basic_at,             "_basic_at"            }, | ||||||
|  | 	{   2,  2,  prim_basic_at_put,         "_basic_at_put"        }, | ||||||
|  |  | ||||||
|  |  | ||||||
| 	{  -1,   prim_block_value,          "_block_value"         }, | 	{   0, MAX_NARGS,  prim_block_value,          "_block_value"         }, | ||||||
| 	{  -1,   prim_block_new_process,    "_block_new_process"   }, | 	{   0, MAX_NARGS,  prim_block_new_process,    "_block_new_process"   }, | ||||||
|  |  | ||||||
| 	{   0,   prim_process_resume,       "_process_resume"       }, | 	{   0,  0,  prim_process_resume,       "_process_resume"       }, | ||||||
| 	{   0,   prim_process_terminate,    "_process_terminate"   }, | 	{   0,  0,  prim_process_terminate,    "_process_terminate"   }, | ||||||
| 	{   0,   prim_process_yield,        "_process_yield"       }, | 	{   0,  0,  prim_process_yield,        "_process_yield"       }, | ||||||
| 	{   0,   prim_semaphore_signal,     "_semaphore_signal"    }, | 	{   0,  0,  prim_semaphore_signal,     "_semaphore_signal"    }, | ||||||
| 	{   0,   prim_semaphore_wait,       "_semaphore_wait"      }, | 	{   0,  0,  prim_semaphore_wait,       "_semaphore_wait"      }, | ||||||
|  |  | ||||||
| 	{   1,   prim_processor_schedule,   "_processor_schedule"  }, | 	{   1,  1,  prim_processor_schedule,            "_processor_schedule"            }, | ||||||
| 	{   1,   prim_processor_remove,     "_processor_remove"    }, | 	{   1,  1,  prim_processor_remove,              "_processor_remove"              }, | ||||||
| 	{   1,   prim_processor_sleep,      "_processor_sleep"     }, | 	{   1,  1,  prim_processor_sleep,               "_processor_sleep"               }, | ||||||
|  | 	{   2,  3,  prim_processor_add_timed_semaphore, "_processor_add_timed_semaphore" }, | ||||||
|  |  | ||||||
| 	{   1,   prim_integer_add,          "_integer_add"         }, | 	{   1,  1,  prim_integer_add,          "_integer_add"         }, | ||||||
| 	{   1,   prim_integer_sub,          "_integer_sub"         }, | 	{   1,  1,  prim_integer_sub,          "_integer_sub"         }, | ||||||
| 	{   1,   prim_integer_mul,          "_integer_mul"         }, | 	{   1,  1,  prim_integer_mul,          "_integer_mul"         }, | ||||||
| 	{   1,   prim_integer_quo,          "_integer_quo"         }, | 	{   1,  1,  prim_integer_quo,          "_integer_quo"         }, | ||||||
| 	{   1,   prim_integer_rem,          "_integer_rem"         }, | 	{   1,  1,  prim_integer_rem,          "_integer_rem"         }, | ||||||
| 	{   1,   prim_integer_quo2,         "_integer_quo2"        }, | 	{   1,  1,  prim_integer_quo2,         "_integer_quo2"        }, | ||||||
| 	{   1,   prim_integer_rem2,         "_integer_rem2"        }, | 	{   1,  1,  prim_integer_rem2,         "_integer_rem2"        }, | ||||||
| 	{   0,   prim_integer_negated,      "_integer_negated"     }, | 	{   0,  0,  prim_integer_negated,      "_integer_negated"     }, | ||||||
| 	{   1,   prim_integer_bitat,        "_integer_bitat"       }, | 	{   1,  1,  prim_integer_bitat,        "_integer_bitat"       }, | ||||||
| 	{   1,   prim_integer_bitand,       "_integer_bitand"      }, | 	{   1,  1,  prim_integer_bitand,       "_integer_bitand"      }, | ||||||
| 	{   1,   prim_integer_bitor,        "_integer_bitor"       }, | 	{   1,  1,  prim_integer_bitor,        "_integer_bitor"       }, | ||||||
| 	{   1,   prim_integer_bitxor,       "_integer_bitxor"      }, | 	{   1,  1,  prim_integer_bitxor,       "_integer_bitxor"      }, | ||||||
| 	{   0,   prim_integer_bitinv,       "_integer_bitinv"      }, | 	{   0,  0,  prim_integer_bitinv,       "_integer_bitinv"      }, | ||||||
| 	{   1,   prim_integer_bitshift,     "_integer_bitshift"    }, | 	{   1,  1,  prim_integer_bitshift,     "_integer_bitshift"    }, | ||||||
| 	{   1,   prim_integer_eq,           "_integer_eq"          }, | 	{   1,  1,  prim_integer_eq,           "_integer_eq"          }, | ||||||
| 	{   1,   prim_integer_ne,           "_integer_ne"          }, | 	{   1,  1,  prim_integer_ne,           "_integer_ne"          }, | ||||||
| 	{   1,   prim_integer_lt,           "_integer_lt"          }, | 	{   1,  1,  prim_integer_lt,           "_integer_lt"          }, | ||||||
| 	{   1,   prim_integer_gt,           "_integer_gt"          }, | 	{   1,  1,  prim_integer_gt,           "_integer_gt"          }, | ||||||
| 	{   1,   prim_integer_le,           "_integer_le"          }, | 	{   1,  1,  prim_integer_le,           "_integer_le"          }, | ||||||
| 	{   1,   prim_integer_ge,           "_integer_ge"          }, | 	{   1,  1,  prim_integer_ge,           "_integer_ge"          }, | ||||||
| 	{   1,   prim_integer_inttostr,     "_integer_inttostr"    }, | 	{   1,  1,  prim_integer_inttostr,     "_integer_inttostr"    }, | ||||||
|  |  | ||||||
| 	{   1,   prim_ffi_open,             "_ffi_open"            }, | 	{   1,  1,  prim_ffi_open,             "_ffi_open"            }, | ||||||
| 	{   1,   prim_ffi_close,            "_ffi_close"           }, | 	{   1,  1,  prim_ffi_close,            "_ffi_close"           }, | ||||||
| 	{   2,   prim_ffi_getsym,           "_ffi_getsym"          }, | 	{   2,  2,  prim_ffi_getsym,           "_ffi_getsym"          }, | ||||||
| 	{   3,   prim_ffi_call,             "_ffi_call"            } | 	{   3,  3,  prim_ffi_call,             "_ffi_call"            } | ||||||
| 	 | 	 | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -2478,7 +2748,7 @@ printf ("]\n"); | |||||||
| 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no); | 			DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no); | ||||||
|  |  | ||||||
| 			if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&  | 			if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&  | ||||||
| 			    (primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == nargs)) | 			    (nargs >= primitives[prim_no].min_nargs && nargs <= primitives[prim_no].max_nargs)) | ||||||
| 			{ | 			{ | ||||||
| 				int n; | 				int n; | ||||||
|  |  | ||||||
| @ -2568,8 +2838,43 @@ int stix_execute (stix_t* stix) | |||||||
| 			/* no more process in the system */ | 			/* no more process in the system */ | ||||||
| 			STIX_ASSERT (stix->processor->tally = STIX_SMOOI_TO_OOP(0)); | 			STIX_ASSERT (stix->processor->tally = STIX_SMOOI_TO_OOP(0)); | ||||||
| printf ("NO MORE RUNNABLE PROCESS...\n"); | printf ("NO MORE RUNNABLE PROCESS...\n"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 			if (stix->sem_heap_count > 0) | ||||||
|  | 			{ | ||||||
|  | 				struct timespec now, ft; | ||||||
|  |  | ||||||
|  | 				clock_gettime (CLOCK_MONOTONIC, &now); | ||||||
|  |  | ||||||
|  | 				do | ||||||
|  | 				{ | ||||||
|  | 					STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->sem_heap[0]->heap_ftime_sec)); | ||||||
|  | 					STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->sem_heap[0]->heap_ftime_nsec)); | ||||||
|  |  | ||||||
|  | 					ft.tv_sec = STIX_OOP_TO_SMOOI(stix->sem_heap[0]->heap_ftime_sec); | ||||||
|  | 					ft.tv_nsec = STIX_OOP_TO_SMOOI(stix->sem_heap[0]->heap_ftime_nsec); | ||||||
|  |  | ||||||
|  | 					if (ft.tv_sec < now.tv_sec || (ft.tv_sec == now.tv_sec && ft.tv_nsec <= now.tv_nsec)) | ||||||
|  | 					{ | ||||||
|  | 						signal_semaphore (stix, stix->sem_heap[0]); | ||||||
|  | 						delete_from_sem_heap (stix, 0); | ||||||
|  | 					} | ||||||
|  | 					else  | ||||||
|  | 					{ | ||||||
|  | /* THIS PART IS JUST EXPERIMENTAL... PROPER WAITING WITH IO MULTIPLEXER IS NEEDED ... */ | ||||||
|  | 						sleep (ft.tv_sec - now.tv_sec); | ||||||
|  | 						signal_semaphore (stix, stix->sem_heap[0]); | ||||||
|  | 						delete_from_sem_heap (stix, 0); | ||||||
|  | 						goto carry_on_switching; | ||||||
|  | 					} | ||||||
|  | 				}  | ||||||
|  | 				while (stix->sem_heap_count > 0); | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | carry_on_switching: | ||||||
| /* | /* | ||||||
| 		else if (stix->processor->active == stix->idle_process) | 		else if (stix->processor->active == stix->idle_process) | ||||||
| 		{ | 		{ | ||||||
| @ -2579,9 +2884,15 @@ IDLEING WAITING FOR PROCESS WAKE-UP... | |||||||
|  |  | ||||||
| 		while (stix->sem_list_count > 0) | 		while (stix->sem_list_count > 0) | ||||||
| 		{ | 		{ | ||||||
|  | 			/* handle async signals */ | ||||||
| 			--stix->sem_list_count; | 			--stix->sem_list_count; | ||||||
| 			signal_semaphore (stix, stix->sem_list[stix->sem_list_count]); | 			signal_semaphore (stix, stix->sem_list[stix->sem_list_count]); | ||||||
| 		} | 		} | ||||||
|  | 		/* | ||||||
|  | 		if (semaphore heap has pending request) | ||||||
|  | 		{ | ||||||
|  | 			signal them... | ||||||
|  | 		}*/ | ||||||
|  |  | ||||||
| 		/* TODO: implement different process switching scheme - time-slice or clock based??? */ | 		/* TODO: implement different process switching scheme - time-slice or clock based??? */ | ||||||
| 		if (!stix->proc_switched) { switch_to_next_runnable_process (stix); } | 		if (!stix->proc_switched) { switch_to_next_runnable_process (stix); } | ||||||
|  | |||||||
| @ -341,7 +341,12 @@ printf ("STARTING GC curheap base %p ptr %p newheap base %p ptr %p\n", | |||||||
|  |  | ||||||
| 	for (i = 0; i < stix->sem_list_count; i++) | 	for (i = 0; i < stix->sem_list_count; i++) | ||||||
| 	{ | 	{ | ||||||
| 		stix->sem_list[i] = stix_moveoop (stix, stix->sem_list[i]); | 		stix->sem_list[i] = (stix_oop_semaphore_t)stix_moveoop (stix, stix->sem_list[i]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < stix->sem_heap_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		stix->sem_heap[i] = (stix_oop_semaphore_t)stix_moveoop (stix, stix->sem_heap[i]); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for (i = 0; i < stix->tmp_count; i++) | 	for (i = 0; i < stix->tmp_count; i++) | ||||||
|  | |||||||
| @ -52,6 +52,8 @@ enum stix_errnum_t | |||||||
| 	STIX_ENOENT,  /**< no matching entry */ | 	STIX_ENOENT,  /**< no matching entry */ | ||||||
| 	STIX_EDFULL,  /**< dictionary full */ | 	STIX_EDFULL,  /**< dictionary full */ | ||||||
| 	STIX_EPFULL,  /**< processor full */ | 	STIX_EPFULL,  /**< processor full */ | ||||||
|  | 	STIX_ESHFULL, /**< semaphore heap full */ | ||||||
|  | 	STIX_ESLFULL, /**< semaphore list full */ | ||||||
| 	STIX_EDIVBY0, /**< divide by zero */ | 	STIX_EDIVBY0, /**< divide by zero */ | ||||||
| 	STIX_EIOERR,  /**< I/O error */ | 	STIX_EIOERR,  /**< I/O error */ | ||||||
| 	STIX_EECERR,  /**< encoding conversion error */ | 	STIX_EECERR,  /**< encoding conversion error */ | ||||||
| @ -544,7 +546,7 @@ struct stix_context_t | |||||||
| typedef struct stix_process_t stix_process_t; | typedef struct stix_process_t stix_process_t; | ||||||
| typedef struct stix_process_t* stix_oop_process_t; | typedef struct stix_process_t* stix_oop_process_t; | ||||||
|  |  | ||||||
| #define STIX_SEMAPHORE_NAMED_INSTVARS 5 | #define STIX_SEMAPHORE_NAMED_INSTVARS 6 | ||||||
| typedef struct stix_semaphore_t stix_semaphore_t; | typedef struct stix_semaphore_t stix_semaphore_t; | ||||||
| typedef struct stix_semaphore_t* stix_oop_semaphore_t; | typedef struct stix_semaphore_t* stix_oop_semaphore_t; | ||||||
|  |  | ||||||
| @ -572,8 +574,9 @@ struct stix_semaphore_t | |||||||
| 	stix_oop_t count; /* SmallInteger */ | 	stix_oop_t count; /* SmallInteger */ | ||||||
| 	stix_oop_process_t waiting_head; | 	stix_oop_process_t waiting_head; | ||||||
| 	stix_oop_process_t waiting_tail; | 	stix_oop_process_t waiting_tail; | ||||||
| 	stix_oop_t sempq_index; | 	stix_oop_t heap_index; /* index to the heap */ | ||||||
| 	stix_oop_t sempq_firing_time; | 	stix_oop_t heap_ftime_sec; /* firing time */ | ||||||
|  | 	stix_oop_t heap_ftime_nsec; /* firing time */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define STIX_PROCESS_SCHEDULER_NAMED_INSTVARS 5 | #define STIX_PROCESS_SCHEDULER_NAMED_INSTVARS 5 | ||||||
| @ -775,11 +778,12 @@ struct stix_t | |||||||
| 	stix_oop_process_scheduler_t processor; /* instance of ProcessScheduler */ | 	stix_oop_process_scheduler_t processor; /* instance of ProcessScheduler */ | ||||||
| 	stix_oop_process_t nil_process; /* instance of Process */ | 	stix_oop_process_t nil_process; /* instance of Process */ | ||||||
|  |  | ||||||
|  | 	/* pending asynchronous semaphores */ | ||||||
| 	stix_oop_semaphore_t* sem_list; | 	stix_oop_semaphore_t* sem_list; | ||||||
| 	stix_oow_t sem_list_count; | 	stix_oow_t sem_list_count; | ||||||
| 	stix_oow_t sem_list_capa; | 	stix_oow_t sem_list_capa; | ||||||
|  |  | ||||||
| 	/* semaphores sorted according to expiry */ | 	/* semaphores sorted according to time-out */ | ||||||
| 	stix_oop_semaphore_t* sem_heap; | 	stix_oop_semaphore_t* sem_heap; | ||||||
| 	stix_oow_t sem_heap_count; | 	stix_oow_t sem_heap_count; | ||||||
| 	stix_oow_t sem_heap_capa; | 	stix_oow_t sem_heap_capa; | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user