diff --git a/lib/exec.c b/lib/exec.c index 9950f13..c68b4c4 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -57,6 +57,23 @@ #define PROC_STATE_SUSPENDED 0 #define PROC_STATE_TERMINATED -1 + +static HCL_INLINE const char* proc_state_to_string (int state) +{ + static const hcl_bch_t* str[] = + { + "TERMINATED", + "SUSPENDED", + "RUNNABLE", + "WAITING", + "RUNNING" + }; + + return str[state + 1]; +} + +#define PROC_MAP_INC 64 + #define SEM_LIST_INC 256 #define SEM_HEAP_INC 256 #define SEM_LIST_MAX (SEM_LIST_INC * 1000) @@ -273,11 +290,88 @@ static HCL_INLINE hcl_oop_t make_context (hcl_t* hcl, hcl_ooi_t ntmprs) return hcl_allocoopobj (hcl, HCL_BRAND_CONTEXT, HCL_CONTEXT_NAMED_INSTVARS + (hcl_oow_t)ntmprs); } + +static HCL_INLINE int prepare_to_alloc_pid (hcl_t* hcl) +{ + hcl_oow_t new_capa; + hcl_ooi_t i, j; + hcl_oop_t* tmp; + + HCL_ASSERT (hcl, hcl->proc_map_free_first <= -1); + HCL_ASSERT (hcl, hcl->proc_map_free_last <= -1); + + new_capa = hcl->proc_map_capa + PROC_MAP_INC; + if (new_capa > HCL_SMOOI_MAX) + { + if (hcl->proc_map_capa >= HCL_SMOOI_MAX) + { + #if defined(HCL_DEBUG_VM_PROCESSOR) + HCL_LOG0 (hcl, HCL_LOG_IC | HCL_LOG_FATAL, "Processor - too many processes\n"); + #endif + hcl_seterrnum (hcl, HCL_EPFULL); + return -1; + } + + new_capa = HCL_SMOOI_MAX; + } + + tmp = hcl_reallocmem (hcl, hcl->proc_map, HCL_SIZEOF(hcl_oop_t) * new_capa); + if (!tmp) return -1; + + hcl->proc_map_free_first = hcl->proc_map_capa; + for (i = hcl->proc_map_capa, j = hcl->proc_map_capa + 1; j < new_capa; i++, j++) + { + tmp[i] = HCL_SMOOI_TO_OOP(j); + } + tmp[i] = HCL_SMOOI_TO_OOP(-1); + hcl->proc_map_free_last = i; + + hcl->proc_map = tmp; + hcl->proc_map_capa = new_capa; + + return 0; +} + +static HCL_INLINE void alloc_pid (hcl_t* hcl, hcl_oop_process_t proc) +{ + hcl_ooi_t pid; + + pid = hcl->proc_map_free_first; + proc->id = HCL_SMOOI_TO_OOP(pid); + HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(hcl->proc_map[pid])); + hcl->proc_map_free_first = HCL_OOP_TO_SMOOI(hcl->proc_map[pid]); + if (hcl->proc_map_free_first <= -1) hcl->proc_map_free_last = -1; + hcl->proc_map[pid] = (hcl_oop_t)proc; +} + +static HCL_INLINE void free_pid (hcl_t* hcl, hcl_oop_process_t proc) +{ + hcl_ooi_t pid; + + pid = HCL_OOP_TO_SMOOI(proc->id); + HCL_ASSERT (hcl, pid < hcl->proc_map_capa); + + hcl->proc_map[pid] = HCL_SMOOI_TO_OOP(-1); + if (hcl->proc_map_free_last <= -1) + { + HCL_ASSERT (hcl, hcl->proc_map_free_first <= -1); + hcl->proc_map_free_first = pid; + } + else + { + hcl->proc_map[hcl->proc_map_free_last] = HCL_SMOOI_TO_OOP(pid); + } + hcl->proc_map_free_last = pid; +} + + static hcl_oop_process_t make_process (hcl_t* hcl, hcl_oop_context_t c) { hcl_oop_process_t proc; hcl_oow_t stksize; + if (hcl->proc_map_free_first <= -1 && prepare_to_alloc_pid(hcl) <= -1) return HCL_NULL; + stksize = hcl->option.dfl_procstk_size; if (stksize > HCL_TYPE_MAX(hcl_oow_t) - HCL_PROCESS_NAMED_INSTVARS) stksize = HCL_TYPE_MAX(hcl_oow_t) - HCL_PROCESS_NAMED_INSTVARS; @@ -287,6 +381,9 @@ static hcl_oop_process_t make_process (hcl_t* hcl, hcl_oop_context_t c) hcl_poptmp (hcl); if (!proc) return HCL_NULL; + /* assign a process id to the process */ + alloc_pid (hcl, proc); + proc->state = HCL_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); proc->initial_context = c; proc->current_context = c; @@ -295,7 +392,7 @@ static hcl_oop_process_t make_process (hcl_t* hcl, hcl_oop_context_t c) HCL_ASSERT (hcl, (hcl_oop_t)c->sender == hcl->_nil); #if defined(HCL_DEBUG_VM_PROCESSOR) - HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - made process %O of size %zu\n", proc, HCL_OBJ_GET_SIZE(proc)); + HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] **CREATED**->%hs\n", HCL_OOP_TO_SMOOI(proc->id), proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state))); #endif return proc; } @@ -308,6 +405,10 @@ static HCL_INLINE void sleep_active_process (hcl_t* hcl, int state) STORE_ACTIVE_SP(hcl); +#if defined(HCL_DEBUG_VM_PROCESSOR) + HCL_LOG3 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] %hs->%hs in sleep_active_process\n", HCL_OOP_TO_SMOOI(hcl->processor->active->id), proc_state_to_string(HCL_OOP_TO_SMOOI(hcl->processor->active->state)), proc_state_to_string(state)); +#endif + /* store the current active context to the current process. * it is the suspended context of the process to be suspended */ HCL_ASSERT (hcl, hcl->processor->active != hcl->nil_process); @@ -317,6 +418,11 @@ static HCL_INLINE void sleep_active_process (hcl_t* hcl, int state) static HCL_INLINE void wake_new_process (hcl_t* hcl, hcl_oop_process_t proc) { + +#if defined(HCL_DEBUG_VM_PROCESSOR) + HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] %hs->RUNNING in wake_process\n", HCL_OOP_TO_SMOOI(proc->id), proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state))); +#endif + /* activate the given process */ proc->state = HCL_SMOOI_TO_OOP(PROC_STATE_RUNNING); hcl->processor->active = proc; @@ -326,8 +432,8 @@ static HCL_INLINE void wake_new_process (hcl_t* hcl, hcl_oop_process_t proc) /* activate the suspended context of the new process */ SWITCH_ACTIVE_CONTEXT (hcl, proc->current_context); -#if defined(HCL_DEBUG_VM_PROCESSOR) - HCL_LOG3 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - woke up process %O context %O ip=%zd\n", hcl->processor->active, hcl->active_context, hcl->ip); +#if defined(HCL_DEBUG_VM_PROCESSOR) && (HCL_DEBUG_VM_PROCESSOR >= 2) + HCL_LOG3 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - woke up process[%zd] context %O ip=%zd\n", HCL_OOP_TO_SMOOI(hcl->processor->active->id), hcl->active_context, hcl->ip); #endif } @@ -364,7 +470,7 @@ static HCL_INLINE void switch_to_next_runnable_process (hcl_t* hcl) if (nrp != hcl->processor->active) switch_to_process (hcl, nrp, PROC_STATE_RUNNABLE); } -static HCL_INLINE int chain_into_processor (hcl_t* hcl, hcl_oop_process_t proc) +static HCL_INLINE int chain_into_processor (hcl_t* hcl, hcl_oop_process_t proc, int new_state) { /* the process is not scheduled at all. * link it to the processor's process list. */ @@ -375,6 +481,14 @@ static HCL_INLINE int chain_into_processor (hcl_t* hcl, hcl_oop_process_t proc) HCL_ASSERT (hcl, proc->state == HCL_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)); +#if defined(HCL_DEBUG_VM_PROCESSOR) + HCL_LOG3 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, + "Processor - process[%zd] %hs->%hs in chain_into_processor\n", + HCL_OOP_TO_SMOOI(proc->id), + proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state)), + proc_state_to_string(new_state)); +#endif + tally = HCL_OOP_TO_SMOOI(hcl->processor->tally); HCL_ASSERT (hcl, tally >= 0); @@ -398,6 +512,7 @@ static HCL_INLINE int chain_into_processor (hcl_t* hcl, hcl_oop_process_t proc) hcl->processor->runnable_head = proc; } hcl->processor->runnable_tail = proc; + proc->state = HCL_SMOOI_TO_OOP(new_state); tally++; hcl->processor->tally = HCL_SMOOI_TO_OOP(tally); @@ -405,14 +520,14 @@ static HCL_INLINE int chain_into_processor (hcl_t* hcl, hcl_oop_process_t proc) return 0; } -static HCL_INLINE void unchain_from_processor (hcl_t* hcl, hcl_oop_process_t proc, int state) +static HCL_INLINE void unchain_from_processor (hcl_t* hcl, hcl_oop_process_t proc, int new_state) { hcl_ooi_t tally; /* the processor's process chain must be composed of running/runnable * processes only */ HCL_ASSERT (hcl, proc->state == HCL_SMOOI_TO_OOP(PROC_STATE_RUNNING) || - proc->state == HCL_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); + proc->state == HCL_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); tally = HCL_OOP_TO_SMOOI(hcl->processor->tally); HCL_ASSERT (hcl, tally > 0); @@ -422,13 +537,19 @@ static HCL_INLINE void unchain_from_processor (hcl_t* hcl, hcl_oop_process_t pro if ((hcl_oop_t)proc->next != hcl->_nil) proc->next->prev = proc->prev; else hcl->processor->runnable_tail = proc->prev; +#if defined(HCL_DEBUG_VM_PROCESSOR) + HCL_LOG3 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] %hs->%hs in unchain_from_processor\n", HCL_OOP_TO_SMOOI(proc->id), proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state)), proc_state_to_string(HCL_OOP_TO_SMOOI(new_state))); +#endif + proc->prev = (hcl_oop_process_t)hcl->_nil; proc->next = (hcl_oop_process_t)hcl->_nil; - proc->state = HCL_SMOOI_TO_OOP(state); + proc->state = HCL_SMOOI_TO_OOP(new_state); tally--; if (tally == 0) hcl->processor->active = hcl->nil_process; hcl->processor->tally = HCL_SMOOI_TO_OOP(tally); + + } static HCL_INLINE void chain_into_semaphore (hcl_t* hcl, hcl_oop_process_t proc, hcl_oop_semaphore_t sem) @@ -480,7 +601,7 @@ static void terminate_process (hcl_t* hcl, hcl_oop_process_t proc) /* RUNNING/RUNNABLE ---> TERMINATED */ #if defined(HCL_DEBUG_VM_PROCESSOR) - HCL_LOG1 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process %O RUNNING/RUNNABLE->TERMINATED\n", proc); + HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] %hs->TERMINATED in terminate_process\n", HCL_OOP_TO_SMOOI(proc->id), proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state))); #endif if (proc == hcl->processor->active) @@ -513,12 +634,15 @@ static void terminate_process (hcl_t* hcl, hcl_oop_process_t proc) unchain_from_processor (hcl, proc, PROC_STATE_TERMINATED); proc->sp = HCL_SMOOI_TO_OOP(-1); /* invalidate the process stack */ } + + /* when terminated, clear it from the pid table and set the process id to a negative number */ + free_pid (hcl, proc); } else if (proc->state == HCL_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)) { /* SUSPENDED ---> TERMINATED */ #if defined(HCL_DEBUG_VM_PROCESSOR) - HCL_LOG1 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process %O SUSPENDED->TERMINATED\n", proc); + HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] %hs->TERMINATED in terminate_process\n", HCL_OOP_TO_SMOOI(proc->id), proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state))); #endif proc->state = HCL_SMOOI_TO_OOP(PROC_STATE_TERMINATED); @@ -528,6 +652,9 @@ static void terminate_process (hcl_t* hcl, hcl_oop_process_t proc) { unchain_from_semaphore (hcl, proc); } + + /* when terminated, clear it from the pid table and set the process id to a negative number */ + free_pid (hcl, proc); } else if (proc->state == HCL_SMOOI_TO_OOP(PROC_STATE_WAITING)) { @@ -545,13 +672,12 @@ static void resume_process (hcl_t* hcl, hcl_oop_process_t proc) HCL_ASSERT (hcl, (hcl_oop_t)proc->next == hcl->_nil); #if defined(HCL_DEBUG_VM_PROCESSOR) - HCL_LOG1 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process %O SUSPENDED->RUNNING\n", proc); + HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_DEBUG, "Processor - process[%zd] %hs->RUNNABLE in resume_process\n", HCL_OOP_TO_SMOOI(proc->id), proc_state_to_string(HCL_OOP_TO_SMOOI(proc->state))); #endif - chain_into_processor (hcl, proc); /* TODO: error check */ - + chain_into_processor (hcl, proc, PROC_STATE_RUNNABLE); /* TODO: error check */ /*proc->current_context = proc->initial_context;*/ - proc->state = HCL_SMOOI_TO_OOP(PROC_STATE_RUNNABLE); + /* don't switch to this process. just set the state to RUNNING */ } @@ -1010,8 +1136,8 @@ static hcl_oop_process_t start_initial_process (hcl_t* hcl, hcl_oop_context_t ct proc = make_process (hcl, ctx); if (!proc) return HCL_NULL; - if (chain_into_processor (hcl, proc) <= -1) return HCL_NULL; - proc->state = HCL_SMOOI_TO_OOP(PROC_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */ + /* skip RUNNABLE and go to RUNNING */ + if (chain_into_processor (hcl, proc, PROC_STATE_RUNNING) <= -1) return HCL_NULL; hcl->processor->active = proc; /* do something that resume_process() would do with less overhead */ @@ -1201,7 +1327,7 @@ static int execute (hcl_t* hcl) if (hcl->ip >= hcl->code.bc.len) { - HCL_DEBUG0 (hcl, "IP reached the end of bytecode. Stopping execution\n"); + HCL_DEBUG2 (hcl, "IP(%zd) reached the end of bytecode(%zu). Stopping execution\n", hcl->ip, hcl->code.bc.len); break; } diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 1bac88d..32ba19e 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -56,9 +56,13 @@ * object instead of putting in in a separate byte array. */ #define HCL_USE_OBJECT_TRAILER -/* this is for gc debugging */ -/*#define HCL_DEBUG_PROCESSOR*/ -#define HCL_DEBUG_VM_EXEC + + +#if !defined(NDEBUG) +#define HCL_DEBUG_VM_PROCESSOR 1 +#define HCL_DEBUG_VM_EXEC 1 +#define MOO_DEBUG_BIGINT 1 +#endif /* allow the caller to drive process switching by calling * stix_switchprocess(). */ diff --git a/lib/hcl.c b/lib/hcl.c index 4aaaa3b..33b3b1e 100644 --- a/lib/hcl.c +++ b/lib/hcl.c @@ -116,6 +116,9 @@ int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t hcl_rbt_setstyle (&hcl->pmtable, hcl_getrbtstyle(HCL_RBT_STYLE_INLINE_COPIERS)); fill_bigint_tables (hcl); + + hcl->proc_map_free_first = -1; + hcl->proc_map_free_last = -1; return 0; oops: @@ -185,6 +188,13 @@ void hcl_fini (hcl_t* hcl) hcl->sem_heap_count = 0; } + if (hcl->proc_map) + { + hcl_freemem (hcl, hcl->proc_map); + hcl->proc_map_capa = 0; + hcl->proc_map_free_first = -1; + hcl->proc_map_free_last = -1; + } if (hcl->code.bc.arr) { diff --git a/lib/hcl.h b/lib/hcl.h index 26c896b..a1c2b6b 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -594,7 +594,7 @@ struct hcl_context_t }; -#define HCL_PROCESS_NAMED_INSTVARS 7 /* TODO: RENAME THIS TO SOMETHING ELSE */ +#define HCL_PROCESS_NAMED_INSTVARS 8 /* TODO: RENAME THIS TO SOMETHING ELSE */ typedef struct hcl_process_t hcl_process_t; typedef struct hcl_process_t* hcl_oop_process_t; @@ -608,6 +608,7 @@ struct hcl_process_t hcl_oop_context_t initial_context; hcl_oop_context_t current_context; + hcl_oop_t id; /* SmallInteger */ hcl_oop_t state; /* SmallInteger */ hcl_oop_t sp; /* stack pointer. SmallInteger */ @@ -631,7 +632,7 @@ struct hcl_semaphore_t hcl_oop_t heap_ftime_nsec; /* firing time */ }; -#define HCL_PROCESS_SCHEDULER_NAMED_INSTVARS 5 +#define HCL_PROCESS_SCHEDULER_NAMED_INSTVARS 4 typedef struct hcl_process_scheduler_t hcl_process_scheduler_t; typedef struct hcl_process_scheduler_t* hcl_oop_process_scheduler_t; struct hcl_process_scheduler_t @@ -641,7 +642,6 @@ struct hcl_process_scheduler_t hcl_oop_process_t active; /* pointer to an active process in the runnable process list */ hcl_oop_process_t runnable_head; /* runnable process list */ hcl_oop_process_t runnable_tail; /* runnable process list */ - hcl_oop_t sempq; /* SemaphoreHeap */ }; /** @@ -980,6 +980,11 @@ struct hcl_t hcl_oop_t* tmp_stack[256]; /* stack for temporaries */ hcl_oow_t tmp_count; + hcl_oop_t* proc_map; + hcl_oow_t proc_map_capa; + hcl_ooi_t proc_map_free_first; + hcl_ooi_t proc_map_free_last; + /* == EXECUTION REGISTERS == */ hcl_oop_context_t initial_context; /* fake initial context */ hcl_oop_context_t active_context;