enhanced the gc finalization process a bit more

This commit is contained in:
hyunghwan.chung 2017-07-25 15:26:04 +00:00
parent 447012b214
commit a46113abad
5 changed files with 237 additions and 127 deletions

View File

@ -290,10 +290,10 @@ class SemaphoreHeap(Object)
class(#final,#limited) ProcessScheduler(Object) class(#final,#limited) ProcessScheduler(Object)
{ {
var(#get) active. var(#get) active, total_count := 0.
var(#get) runnable_count. var(#get) runnable_count := 0.
var runnable_head, runnable_tail. var runnable_head, runnable_tail.
var(#get) suspended_count. var(#get) suspended_count := 0.
var suspended_head, suspended_tail. var suspended_head, suspended_tail.
method activeProcess method activeProcess
@ -348,6 +348,12 @@ class(#final,#limited) ProcessScheduler(Object)
self primitiveFailed. self primitiveFailed.
} }
method signalOnGCFin: semaphore
{
<primitive: #_processor_add_gcfin_semaphore>
self primitiveFailed.
}
method signal: semaphore onInput: file method signal: semaphore onInput: file
{ {
<primitive: #_processor_add_input_semaphore> <primitive: #_processor_add_input_semaphore>

View File

@ -32,28 +32,31 @@ class System(Apex)
method(#class) __gc_finalizer method(#class) __gc_finalizer
{ {
| tmp gc | | tmp gc fin_sem |
gc := false. gc := false.
fin_sem := Semaphore new.
Processor signalOnGCFin: fin_sem.
[
while (true) while (true)
{ {
while ((tmp := self _popCollectable) notError) while ((tmp := self _popCollectable) notError)
{ {
## TODO: Do i have to protected this in an exception handler??? ## TODO: Do i have to protected this in an exception handler???
if (tmp respondsTo: #finalize) { tmp finalize }. if (tmp respondsTo: #finalize) { tmp finalize }.
}. }.
##if (Processor runnable_count == 1 and: [Processor active == thisProcess]) if (Processor total_count == 1)
if (Processor runnable_count == 1 and: [Processor suspended_count == 0]) ## TODO: does it suffer from race condition?
{ {
## exit from this loop when there are no other processes running except this finalizer process ## exit from this loop when there are no other processes running except this finalizer process
if (gc) if (gc)
{ {
System logNl: 'Exiting the GC finalization process...'. System logNl: 'Exiting the GC finalization process'.
break break
}. }.
System logNl: 'Forcing garbage collection before termination in ' & (thisProcess id) asString.
self collectGarbage. self collectGarbage.
gc := true. gc := true.
} }
@ -62,9 +65,15 @@ class System(Apex)
gc := false. gc := false.
}. }.
##System logNl: 'gc_waiting....'. ##System logNl: '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^gc_waiting....'.
Processor sleepFor: 1. ## TODO: wait on semaphore instead.. ##Processor sleepFor: 1. ## TODO: wait on semaphore instead..
fin_sem wait.
##System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX gc_waitED....'.
} }
] ensure: [
Processor unsignal: fin_sem.
System logNl: 'End of GC finalization process'.
].
} }
method(#class,#primitive) _popCollectable. method(#class,#primitive) _popCollectable.

View File

@ -153,7 +153,18 @@ static MOO_INLINE void vm_muxwait (moo_t* moo, const moo_ntime_t* dur)
static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c) static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c)
{ {
moo_oop_process_t proc; moo_oop_process_t proc;
moo_ooi_t total_count;
moo_ooi_t suspended_count;
total_count = MOO_OOP_TO_SMOOI(moo->processor->total_count);
if (total_count >= MOO_SMOOI_MAX)
{
#if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many processes\n");
#endif
moo_seterrnum (moo, MOO_EPFULL);
return MOO_NULL;
}
moo_pushtmp (moo, (moo_oop_t*)&c); moo_pushtmp (moo, (moo_oop_t*)&c);
proc = (moo_oop_process_t)moo_instantiate (moo, moo->_process, MOO_NULL, moo->option.dfl_procstk_size); proc = (moo_oop_process_t)moo_instantiate (moo, moo->_process, MOO_NULL, moo->option.dfl_procstk_size);
@ -181,6 +192,15 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c)
MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - made process %O of size %zu\n", proc, MOO_OBJ_GET_SIZE(proc)); MOO_LOG2 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - made process %O of size %zu\n", proc, MOO_OBJ_GET_SIZE(proc));
#endif #endif
/* a process is created in the SUSPENDED state. chain it to the suspended process list */
suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count);
MOO_APPEND_TO_OOP_LIST (moo, &moo->processor->suspended, moo_oop_process_t, proc, ps);
suspended_count++;
moo->processor->suspended.count = MOO_SMOOI_TO_OOP(suspended_count);
total_count++;
moo->processor->total_count = MOO_SMOOI_TO_OOP(total_count);
return proc; return proc;
} }
@ -199,7 +219,7 @@ static MOO_INLINE void sleep_active_process (moo_t* moo, int state)
moo->processor->active->state = MOO_SMOOI_TO_OOP(state); moo->processor->active->state = MOO_SMOOI_TO_OOP(state);
} }
static MOO_INLINE void wake_new_process (moo_t* moo, moo_oop_process_t proc) static MOO_INLINE void wake_process (moo_t* moo, moo_oop_process_t proc)
{ {
/* activate the given process */ /* activate the given process */
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING); proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING);
@ -211,7 +231,7 @@ static MOO_INLINE void wake_new_process (moo_t* moo, moo_oop_process_t proc)
SWITCH_ACTIVE_CONTEXT (moo, proc->current_context); SWITCH_ACTIVE_CONTEXT (moo, proc->current_context);
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG3 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - woke up process %O context %O ip=%zd\n", moo->processor->active, moo->active_context, moo->ip); MOO_LOG3 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - woke up process [%zd] context %O ip=%zd\n", MOO_OOP_TO_SMOOI(moo->processor->active->id), moo->active_context, moo->ip);
#endif #endif
} }
@ -225,11 +245,18 @@ static void switch_to_process (moo_t* moo, moo_oop_process_t proc, int new_state
proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING)); proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING));
sleep_active_process (moo, new_state_for_old_active); sleep_active_process (moo, new_state_for_old_active);
wake_new_process (moo, proc); wake_process (moo, proc);
moo->proc_switched = 1; moo->proc_switched = 1;
} }
static MOO_INLINE void switch_to_process_from_nil (moo_t* moo, moo_oop_process_t proc)
{
MOO_ASSERT (moo, moo->processor->active == moo->nil_process);
wake_process (moo, proc);
moo->proc_switched = 1;
}
static MOO_INLINE moo_oop_process_t find_next_runnable_process (moo_t* moo) static MOO_INLINE moo_oop_process_t find_next_runnable_process (moo_t* moo)
{ {
moo_oop_process_t nrp; moo_oop_process_t nrp;
@ -248,52 +275,41 @@ static MOO_INLINE void switch_to_next_runnable_process (moo_t* moo)
if (nrp != moo->processor->active) switch_to_process (moo, nrp, PROC_STATE_RUNNABLE); if (nrp != moo->processor->active) switch_to_process (moo, nrp, PROC_STATE_RUNNABLE);
} }
static MOO_INLINE int chain_into_processor (moo_t* moo, moo_oop_process_t proc) static MOO_INLINE void chain_into_processor (moo_t* moo, moo_oop_process_t proc, int new_state)
{ {
/* the process is not scheduled at all. /* the process is not scheduled at all.
* link it to the processor's process list. */ * link it to the processor's process list. */
moo_ooi_t runnable_count; moo_ooi_t runnable_count;
moo_ooi_t suspended_count;
/*MOO_ASSERT (moo, (moo_oop_t)proc->ps.prev == moo->_nil); /*MOO_ASSERT (moo, (moo_oop_t)proc->ps.prev == moo->_nil);
MOO_ASSERT (moo, (moo_oop_t)proc->ps.next == moo->_nil);*/ MOO_ASSERT (moo, (moo_oop_t)proc->ps.next == moo->_nil);*/
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)); MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED));
MOO_ASSERT (moo, new_state == PROC_STATE_RUNNABLE || new_state == PROC_STATE_RUNNING);
runnable_count = MOO_OOP_TO_SMOOI(moo->processor->runnable.count); runnable_count = MOO_OOP_TO_SMOOI(moo->processor->runnable.count);
MOO_ASSERT (moo, runnable_count >= 0); MOO_ASSERT (moo, runnable_count >= 0);
if (runnable_count >= MOO_SMOOI_MAX)
{
#if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many processes\n");
#endif
moo_seterrnum (moo, MOO_EPFULL);
return -1;
}
if ((moo_oop_t)proc->ps.next != moo->_nil || (moo_oop_t)proc->ps.prev != moo->_nil || proc == moo->processor->suspended.first)
{
moo_ooi_t suspended_count;
suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count); suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count);
MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->suspended, proc, ps); MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->suspended, proc, ps);
suspended_count--; suspended_count--;
moo->processor->suspended.count = MOO_SMOOI_TO_OOP(suspended_count); moo->processor->suspended.count = MOO_SMOOI_TO_OOP(suspended_count);
}
/* append to the runnable list */ /* append to the runnable list */
MOO_APPEND_TO_OOP_LIST (moo, &moo->processor->runnable, moo_oop_process_t, proc, ps); MOO_APPEND_TO_OOP_LIST (moo, &moo->processor->runnable, moo_oop_process_t, proc, ps);
proc->state = MOO_SMOOI_TO_OOP(new_state);
runnable_count++; runnable_count++;
moo->processor->runnable.count = MOO_SMOOI_TO_OOP(runnable_count); moo->processor->runnable.count = MOO_SMOOI_TO_OOP(runnable_count);
return 0;
} }
static MOO_INLINE void unchain_from_processor (moo_t* moo, moo_oop_process_t proc, int state) static MOO_INLINE void unchain_from_processor (moo_t* moo, moo_oop_process_t proc, int new_state)
{ {
moo_ooi_t runnable_count; moo_ooi_t runnable_count;
moo_ooi_t suspended_count;
moo_ooi_t total_count;
/* the processor's process chain must be composed of running/runnable /* the processor's process chain must be composed of running/runnable
* processes only */ * processes only */
@ -305,26 +321,28 @@ static MOO_INLINE void unchain_from_processor (moo_t* moo, moo_oop_process_t pro
MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->runnable, proc, ps); MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->runnable, proc, ps);
if (state != PROC_STATE_TERMINATED) if (new_state == PROC_STATE_TERMINATED)
{ {
moo_ooi_t suspended_count; /* do not chain it to the suspended process list as it's being terminated */
proc->ps.prev = (moo_oop_process_t)moo->_nil;
proc->ps.next = (moo_oop_process_t)moo->_nil;
suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count); total_count = MOO_OOP_TO_SMOOI(moo->processor->total_count);
total_count--;
/* append to the suspended list */ moo->processor->total_count = MOO_SMOOI_TO_OOP(total_count);
MOO_APPEND_TO_OOP_LIST (moo, &moo->processor->suspended, moo_oop_process_t, proc, ps);
suspended_count++;
moo->processor->suspended.count= MOO_SMOOI_TO_OOP(suspended_count);
} }
else else
{ {
proc->ps.prev = (moo_oop_process_t)moo->_nil; /* append to the suspended process list */
proc->ps.next = (moo_oop_process_t)moo->_nil; MOO_ASSERT (moo, new_state == PROC_STATE_SUSPENDED);
suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count);
MOO_APPEND_TO_OOP_LIST (moo, &moo->processor->suspended, moo_oop_process_t, proc, ps);
suspended_count++;
moo->processor->suspended.count= MOO_SMOOI_TO_OOP(suspended_count);
} }
proc->state = MOO_SMOOI_TO_OOP(state); proc->state = MOO_SMOOI_TO_OOP(new_state);
runnable_count--; runnable_count--;
if (runnable_count == 0) moo->processor->active = moo->nil_process; if (runnable_count == 0) moo->processor->active = moo->nil_process;
@ -366,7 +384,7 @@ static void terminate_process (moo_t* moo, moo_oop_process_t proc)
/* RUNNING/RUNNABLE ---> TERMINATED */ /* RUNNING/RUNNABLE ---> TERMINATED */
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process %O RUNNING/RUNNABLE->TERMINATED\n", proc); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process [%zd] RUNNING/RUNNABLE->TERMINATED\n", MOO_OOP_TO_SMOOI(proc->id));
#endif #endif
if (proc == moo->processor->active) if (proc == moo->processor->active)
@ -387,7 +405,7 @@ static void terminate_process (moo_t* moo, moo_oop_process_t proc)
{ {
/* no runnable process after termination */ /* no runnable process after termination */
MOO_ASSERT (moo, moo->processor->active == moo->nil_process); MOO_ASSERT (moo, moo->processor->active == moo->nil_process);
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No runnable process after process termination\n"); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No runnable process after termination - process %zd\n", MOO_OOP_TO_SMOOI(proc->id));
} }
else else
{ {
@ -404,10 +422,11 @@ static void terminate_process (moo_t* moo, moo_oop_process_t proc)
{ {
/* SUSPENDED ---> TERMINATED */ /* SUSPENDED ---> TERMINATED */
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process %O SUSPENDED->TERMINATED\n", proc); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process [%zd] SUSPENDED->TERMINATED\n", MOO_OOP_TO_SMOOI(proc->id));
#endif #endif
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_TERMINATED); /*proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_TERMINATED);*/
unchain_from_processor (moo, proc, PROC_STATE_TERMINATED);
proc->sp = MOO_SMOOI_TO_OOP(-1); /* invalidate the proce stack */ proc->sp = MOO_SMOOI_TO_OOP(-1); /* invalidate the proce stack */
if ((moo_oop_t)proc->sem != moo->_nil) if ((moo_oop_t)proc->sem != moo->_nil)
@ -415,11 +434,13 @@ static void terminate_process (moo_t* moo, moo_oop_process_t proc)
unchain_from_semaphore (moo, proc); unchain_from_semaphore (moo, proc);
} }
} }
#if 0
else if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING)) else if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING))
{ {
/* WAITING ---> TERMINATED */ /* WAITING ---> TERMINATED */
/* TODO: */ /* TODO: */
} }
#endif
} }
static void resume_process (moo_t* moo, moo_oop_process_t proc) static void resume_process (moo_t* moo, moo_oop_process_t proc)
@ -431,15 +452,13 @@ static void resume_process (moo_t* moo, moo_oop_process_t proc)
MOO_ASSERT (moo, (moo_oop_t)proc->ps.next == moo->_nil);*/ MOO_ASSERT (moo, (moo_oop_t)proc->ps.next == moo->_nil);*/
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process %O SUSPENDED->RUNNING\n", proc); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process [%zd] SUSPENDED->RUNNING\n", MOO_OOP_TO_SMOOI(proc->id));
#endif #endif
chain_into_processor (moo, proc); /* TODO: error check */ /* don't switch to this process. just change the state to RUNNABLE.
* process switching should be triggerd by the process scheduler. */
chain_into_processor (moo, proc, PROC_STATE_RUNNABLE);
/*proc->current_context = proc->initial_context;*/ /*proc->current_context = proc->initial_context;*/
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE);
/* don't switch to this process. just set the state to RUNNING */
} }
#if 0 #if 0
else if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)) else if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE))
@ -482,13 +501,15 @@ static void suspend_process (moo_t* moo, moo_oop_process_t proc)
} }
else else
{ {
/* keep the unchained process at the runnable state for /* unchain_from_processor moves the process to the suspended
* the immediate call to switch_to_process() below */ * process and sets its state to the given state(SUSPENDED here).
unchain_from_processor (moo, proc, PROC_STATE_RUNNABLE); * it doesn't change the active process. we switch the active
/* unchain_from_processor() leaves the active process * process with switch_to_process(). setting the state of the
* untouched unless the unchained process is the last * old active process to SUSPENDED is redundant because it's
* running/runnable process. so calling switch_to_process() * done in unchain_from_processor(). the state of the active
* which expects the active process to be valid is safe */ * process is somewhat wrong for a short period of time until
* switch_to_process() has changed the active process. */
unchain_from_processor (moo, proc, PROC_STATE_SUSPENDED);
MOO_ASSERT (moo, moo->processor->active != moo->nil_process); MOO_ASSERT (moo, moo->processor->active != moo->nil_process);
switch_to_process (moo, nrp, PROC_STATE_SUSPENDED); switch_to_process (moo, nrp, PROC_STATE_SUSPENDED);
} }
@ -516,7 +537,7 @@ static void yield_process (moo_t* moo, moo_oop_process_t proc)
if (nrp != proc) if (nrp != proc)
{ {
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process %O RUNNING->RUNNABLE\n", proc); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process [%zd] RUNNING->RUNNABLE\n", MOO_OOP_TO_SMOOI(proc->id));
#endif #endif
switch_to_process (moo, nrp, PROC_STATE_RUNNABLE); switch_to_process (moo, nrp, PROC_STATE_RUNNABLE);
} }
@ -573,7 +594,7 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem)
/* detach a process from a semaphore's waiting list and /* detach a process from a semaphore's waiting list and
* make it runnable */ * make it runnable */
unchain_from_semaphore (moo, proc); unchain_from_semaphore (moo, proc);
resume_process (moo, proc); /* TODO: error check */ resume_process (moo, proc);
if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count--; if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count--;
@ -893,14 +914,18 @@ static void signal_io_semaphore (moo_t* moo, moo_ooi_t mask, void* ctx)
{ {
/* this is the only runnable process. /* this is the only runnable process.
* switch the process to the running state. * switch the process to the running state.
* it uses wake_new_process() instead of * it uses wake_process() instead of
* switch_to_process() as there is no running * switch_to_process() as there is no running
* process at this moment */ * process at this moment */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
MOO_ASSERT (moo, proc == moo->processor->runnable.first); MOO_ASSERT (moo, proc == moo->processor->runnable.first);
wake_new_process (moo, proc); /* switch to running */ #if 0
wake_process (moo, proc); /* switch to running */
moo->proc_switched = 1; moo->proc_switched = 1;
#else
switch_to_process_from_nil (moo, proc);
#endif
} }
} }
else else
@ -922,8 +947,7 @@ static moo_oop_process_t start_initial_process (moo_t* moo, moo_oop_context_t c)
proc = make_process (moo, c); proc = make_process (moo, c);
if (!proc) return MOO_NULL; if (!proc) return MOO_NULL;
if (chain_into_processor (moo, proc) <= -1) return MOO_NULL; chain_into_processor (moo, proc, PROC_STATE_RUNNING);
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */
moo->processor->active = proc; moo->processor->active = proc;
/* do somthing that resume_process() would do with less overhead */ /* do somthing that resume_process() would do with less overhead */
@ -1160,7 +1184,6 @@ static int start_initial_process_and_context (moo_t* moo, const moo_oocs_t* objn
#if defined(INVOKE_DIRECTLY) #if defined(INVOKE_DIRECTLY)
ass = moo_lookupsysdic (moo, objname); ass = moo_lookupsysdic (moo, objname);
if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class) if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class)
{ {
@ -1196,43 +1219,31 @@ TODO: overcome this problem - accept parameters....
if (!mth) if (!mth)
{ {
MOO_DEBUG0 (moo, "Cannot find the startup method in the system class"); MOO_DEBUG0 (moo, "Cannot find the startup method in the system class");
return -1; goto oops;
} }
if (MOO_OOP_TO_SMOOI(mth->tmpr_nargs) != 2) if (MOO_OOP_TO_SMOOI(mth->tmpr_nargs) != 2)
{ {
MOO_DEBUG1 (moo, "Weird argument count %zd for a startup method - should be 2", MOO_OOP_TO_SMOOI(mth->tmpr_nargs)); MOO_DEBUG1 (moo, "Weird argument count %zd for a startup method - should be 2", MOO_OOP_TO_SMOOI(mth->tmpr_nargs));
moo_seterrnum (moo, MOO_EINVAL); moo_seterrnum (moo, MOO_EINVAL);
return -1; goto oops;
} }
/* TODO: check if it's variadic.... it should be. and accept more than 2... */ /* TODO: check if it's variadic.... it should be. and accept more than 2... */
moo_pushtmp (moo, (moo_oop_t*)&mth); tmp_count++; moo_pushtmp (moo, (moo_oop_t*)&mth); tmp_count++;
s1 = moo_makesymbol (moo, objname->ptr, objname->len); s1 = moo_makesymbol (moo, objname->ptr, objname->len);
if (!s1) if (!s1) goto oops;
{
moo_poptmps (moo, tmp_count);
return -1;
}
moo_pushtmp (moo, (moo_oop_t*)&s1); moo_pushtmp (moo, (moo_oop_t*)&s1);
s2 = moo_makesymbol (moo, mthname->ptr, mthname->len); s2 = moo_makesymbol (moo, mthname->ptr, mthname->len);
if (!s2) if (!s2) goto oops;
{
moo_poptmps (moo, tmp_count);
return -1;
}
moo_pushtmp (moo, (moo_oop_t*)&s2); moo_pushtmp (moo, (moo_oop_t*)&s2);
#endif #endif
/* create a fake initial context. */ /* create a fake initial context. */
ctx = (moo_oop_context_t)moo_instantiate (moo, moo->_method_context, MOO_NULL, MOO_OOP_TO_SMOOI(mth->tmpr_nargs)); ctx = (moo_oop_context_t)moo_instantiate (moo, moo->_method_context, MOO_NULL, MOO_OOP_TO_SMOOI(mth->tmpr_nargs));
if (!ctx) if (!ctx) goto oops;
{
moo_poptmps (moo, tmp_count);
return -1;
}
moo_pushtmp (moo, (moo_oop_t*)&ctx); tmp_count++; moo_pushtmp (moo, (moo_oop_t*)&ctx); tmp_count++;
@ -1272,7 +1283,7 @@ TODO: overcome this problem - accept parameters....
proc = start_initial_process (moo, ctx); proc = start_initial_process (moo, ctx);
moo_poptmps (moo, tmp_count); tmp_count = 0; moo_poptmps (moo, tmp_count); tmp_count = 0;
if (!proc) return -1; if (!proc) goto oops;
#if defined(INVOKE_DIRECTLY) #if defined(INVOKE_DIRECTLY)
MOO_STACK_PUSH (moo, ass->value); /* push the receiver - the object referenced by 'objname' */ MOO_STACK_PUSH (moo, ass->value); /* push the receiver - the object referenced by 'objname' */
@ -1294,6 +1305,10 @@ TODO: overcome this problem - accept parameters....
#else #else
return activate_new_method (moo, mth, 2); return activate_new_method (moo, mth, 2);
#endif #endif
oops:
if (tmp_count > 0) moo_poptmps (moo, tmp_count);
return -1;
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -2146,7 +2161,7 @@ static moo_pfrc_t pf_process_resume (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_FAILURE; return MOO_PF_FAILURE;
} }
resume_process (moo, (moo_oop_process_t)rcv); /* TODO: error check */ resume_process (moo, (moo_oop_process_t)rcv);
MOO_STACK_SETRETTORCV (moo, nargs); MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
@ -2256,7 +2271,36 @@ static moo_pfrc_t pf_processor_schedule (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_FAILURE; return MOO_PF_FAILURE;
} }
resume_process (moo, (moo_oop_process_t)arg); /* TODO: error check */ resume_process (moo, (moo_oop_process_t)arg);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_processor_add_gcfin_semaphore (moo_t* moo, moo_ooi_t nargs)
{
moo_oop_t rcv;
moo_oop_semaphore_t sem;
MOO_ASSERT (moo, nargs == 1);
sem = (moo_oop_semaphore_t)MOO_STACK_GETARG(moo, nargs, 0);
rcv = MOO_STACK_GETRCV(moo, nargs);
if (rcv != (moo_oop_t)moo->processor)
{
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EMSGRCV);
return MOO_PF_SUCCESS;
}
if (MOO_CLASSOF(moo,sem) != moo->_semaphore)
{
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
return MOO_PF_SUCCESS;
}
/* TODO: no overwriting.. */
moo->sem_gcfin = sem;
MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
@ -2414,7 +2458,7 @@ static moo_pfrc_t pf_processor_remove_semaphore (moo_t* moo, moo_ooi_t nargs)
rcv = MOO_STACK_GETRCV(moo, nargs); rcv = MOO_STACK_GETRCV(moo, nargs);
/* TODO: remove a semaphore from IO handler if it's registered... /* TODO: remove a semaphore from IO handler if it's registered...
* remove a semaphore from XXXXXXXXXXXXXX */ * remove a semaphore from elsewhere registered too */
if (rcv != (moo_oop_t)moo->processor) if (rcv != (moo_oop_t)moo->processor)
{ {
@ -2428,6 +2472,11 @@ static moo_pfrc_t pf_processor_remove_semaphore (moo_t* moo, moo_ooi_t nargs)
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
if (sem == moo->sem_gcfin)
{
moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil;
}
if (MOO_OOP_IS_SMOOI(sem->heap_index) && if (MOO_OOP_IS_SMOOI(sem->heap_index) &&
sem->heap_index != MOO_SMOOI_TO_OOP(-1)) sem->heap_index != MOO_SMOOI_TO_OOP(-1))
{ {
@ -3875,14 +3924,14 @@ static pf_t pftab[] =
{ "_block_value", { pf_block_value, 0, MA } }, { "_block_value", { pf_block_value, 0, MA } },
{ "_block_new_process", { pf_block_new_process, 0, 1 } }, { "_block_new_process", { pf_block_new_process, 0, 1 } },
{ "_processor_add_gcfin_semaphore", { pf_processor_add_gcfin_semaphore, 1, 1 } },
{ "_processor_schedule", { pf_processor_schedule, 1, 1 } },
{ "_processor_add_timed_semaphore", { pf_processor_add_timed_semaphore, 2, 3 } },
{ "_processor_add_input_semaphore", { pf_processor_add_input_semaphore, 2, 2 } }, { "_processor_add_input_semaphore", { pf_processor_add_input_semaphore, 2, 2 } },
{ "_processor_add_output_semaphore", { pf_processor_add_output_semaphore, 2, 2 } },
{ "_processor_add_inoutput_semaphore", { pf_processor_add_inoutput_semaphore, 2, 2 } }, { "_processor_add_inoutput_semaphore", { pf_processor_add_inoutput_semaphore, 2, 2 } },
{ "_processor_add_output_semaphore", { pf_processor_add_output_semaphore, 2, 2 } },
{ "_processor_add_timed_semaphore", { pf_processor_add_timed_semaphore, 2, 3 } },
{ "_processor_remove_semaphore", { pf_processor_remove_semaphore, 1, 1 } }, { "_processor_remove_semaphore", { pf_processor_remove_semaphore, 1, 1 } },
{ "_processor_return_to", { pf_processor_return_to, 2, 2 } }, { "_processor_return_to", { pf_processor_return_to, 2, 2 } },
{ "_processor_schedule", { pf_processor_schedule, 1, 1 } },
{ "_integer_add", { pf_integer_add, 1, 1 } }, { "_integer_add", { pf_integer_add, 1, 1 } },
{ "_integer_sub", { pf_integer_sub, 1, 1 } }, { "_integer_sub", { pf_integer_sub, 1, 1 } },
@ -4449,7 +4498,7 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo)
proc = signal_semaphore (moo, moo->sem_heap[0]); proc = signal_semaphore (moo, moo->sem_heap[0]);
/* [NOTE] no moo_pushtmp() on proc. no GC must occur /* [NOTE] no moo_pushtmp() on proc. no GC must occur
* in the following line until it's used for * in the following line until it's used for
* wake_new_process() below. */ * wake_process() below. */
delete_from_sem_heap (moo, 0); /* moo->sem_heap_count is decremented */ delete_from_sem_heap (moo, 0); /* moo->sem_heap_count is decremented */
/* if no process is waiting on the semaphore, /* if no process is waiting on the semaphore,
@ -4459,14 +4508,17 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo)
{ {
/* this is the only runnable process. /* this is the only runnable process.
* switch the process to the running state. * switch the process to the running state.
* it uses wake_new_process() instead of * it uses wake_process() instead of
* switch_to_process() as there is no running * switch_to_process() as there is no running
* process at this moment */ * process at this moment */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
MOO_ASSERT (moo, proc == moo->processor->runnable.first); MOO_ASSERT (moo, proc == moo->processor->runnable.first);
#if 0
wake_new_process (moo, proc); /* switch to running */ wake_process (moo, proc); /* switch to running */
moo->proc_switched = 1; moo->proc_switched = 1;
#else
switch_to_process_from_nil (moo, proc);
#endif
} }
} }
else if (moo->processor->active == moo->nil_process) else if (moo->processor->active == moo->nil_process)
@ -4482,7 +4534,7 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo)
/* exit early if a process has been woken up. /* exit early if a process has been woken up.
* the break in the else part further down will get hit * the break in the else part further down will get hit
* eventually even if the following line doesn't exist. * eventually even if the following line doesn't exist.
* having the following line causes to skip fireing the * having the following line causes to skip firing the
* timed semaphore that would expire between now and the * timed semaphore that would expire between now and the
* moment the next inspection occurs. */ * moment the next inspection occurs. */
if (moo->processor->active != moo->nil_process) goto finalization; if (moo->processor->active != moo->nil_process) goto finalization;
@ -4524,6 +4576,38 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo)
} }
} }
if (moo->sem_gcfin_sigreq)
{
if ((moo_oop_t)moo->sem_gcfin != moo->_nil)
{
moo_oop_process_t proc;
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Signalled GCFIN semaphore\n");
proc = signal_semaphore (moo, moo->sem_gcfin);
if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil)
{
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
MOO_ASSERT (moo, proc == moo->processor->runnable.first);
switch_to_process_from_nil (moo, proc);
}
}
moo->sem_gcfin_sigreq = 0;
}
else
{
if ((moo_oop_t)moo->sem_gcfin != moo->_nil && moo->processor->active == moo->nil_process)
{
moo_oop_process_t proc;
proc = signal_semaphore (moo, moo->sem_gcfin);
if ((moo_oop_t)proc != moo->_nil)
{
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
MOO_ASSERT (moo, proc == moo->processor->runnable.first);
switch_to_process_from_nil (moo, proc);
}
}
}
if (moo->processor->active == moo->nil_process) if (moo->processor->active == moo->nil_process)
{ {
/* no more waiting semaphore and no more process */ /* no more waiting semaphore and no more process */

View File

@ -291,6 +291,7 @@ static int ignite_2 (moo_t* moo)
if (!tmp) return -1; if (!tmp) return -1;
moo->processor = (moo_oop_process_scheduler_t)tmp; moo->processor = (moo_oop_process_scheduler_t)tmp;
moo->processor->active = moo->nil_process; moo->processor->active = moo->nil_process;
moo->processor->total_count = MOO_SMOOI_TO_OOP(0);
moo->processor->runnable.count = MOO_SMOOI_TO_OOP(0); moo->processor->runnable.count = MOO_SMOOI_TO_OOP(0);
moo->processor->suspended.count = MOO_SMOOI_TO_OOP(0); moo->processor->suspended.count = MOO_SMOOI_TO_OOP(0);
@ -687,6 +688,8 @@ void moo_gc (moo_t* moo)
moo->sem_io[i] = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_io[i]); moo->sem_io[i] = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_io[i]);
} }
moo->sem_gcfin = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_gcfin);
for (i = 0; i < moo->tmp_count; i++) for (i = 0; i < moo->tmp_count; i++)
{ {
*moo->tmp_stack[i] = moo_moveoop (moo, *moo->tmp_stack[i]); *moo->tmp_stack[i] = moo_moveoop (moo, *moo->tmp_stack[i]);
@ -757,6 +760,8 @@ void moo_gc (moo_t* moo)
*/ */
if (moo->active_method) SET_ACTIVE_METHOD_CODE (moo); /* update moo->active_code */ if (moo->active_method) SET_ACTIVE_METHOD_CODE (moo); /* update moo->active_code */
/*if (moo->sem_gcfin_count > 0) signal_semaphore (moo, moo->sem_gcfin);*/
if (moo->sem_gcfin_count > 0) moo->sem_gcfin_sigreq = 1;
/* TODO: include some gc statstics like number of live objects, gc performance, etc */ /* TODO: include some gc statstics like number of live objects, gc performance, etc */
MOO_LOG4 (moo, MOO_LOG_GC | MOO_LOG_INFO, MOO_LOG4 (moo, MOO_LOG_GC | MOO_LOG_INFO,
@ -877,6 +882,7 @@ static void move_finalizable_objects (moo_t* moo)
{ {
moo_finalizable_t* x, * y; moo_finalizable_t* x, * y;
moo->sem_gcfin_count = 0;
for (x = moo->collectable.first; x; x = x->next) for (x = moo->collectable.first; x; x = x->next)
{ {
MOO_ASSERT (moo, (MOO_OBJ_GET_FLAGS_GCFIN(x->oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) == MOO_GCFIN_FINALIZABLE); MOO_ASSERT (moo, (MOO_OBJ_GET_FLAGS_GCFIN(x->oop) & (MOO_GCFIN_FINALIZABLE | MOO_GCFIN_FINALIZED)) == MOO_GCFIN_FINALIZABLE);
@ -908,8 +914,7 @@ static void move_finalizable_objects (moo_t* moo)
/* add it to the collectable list */ /* add it to the collectable list */
MOO_APPEND_TO_LIST (&moo->collectable, x); MOO_APPEND_TO_LIST (&moo->collectable, x);
// TODO: singal semaphore.. moo->sem_gcfin_count++;
//signal_semaphore (moo, moo->collectable_semaphore);
} }
else else
{ {

View File

@ -808,13 +808,14 @@ struct moo_semaphore_t
moo_oop_t io_mask; /* SmallInteger */ moo_oop_t io_mask; /* SmallInteger */
}; };
#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 7 #define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 8
typedef struct moo_process_scheduler_t moo_process_scheduler_t; typedef struct moo_process_scheduler_t moo_process_scheduler_t;
typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t; typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t;
struct moo_process_scheduler_t struct moo_process_scheduler_t
{ {
MOO_OBJ_HEADER; MOO_OBJ_HEADER;
moo_oop_process_t active; /* pointer to an active process in the runnable process list */ moo_oop_process_t active; /* pointer to an active process in the runnable process list */
moo_oop_t total_count; /* SmallIntger, total number of processes - runnable/running/suspended */
struct struct
{ {
@ -825,7 +826,7 @@ struct moo_process_scheduler_t
struct struct
{ {
moo_oop_t count; /* SmallInteger */ moo_oop_t count; /* SmallInteger - suspended*/
moo_oop_process_t first; moo_oop_process_t first;
moo_oop_process_t last; moo_oop_process_t last;
} suspended; } suspended;
@ -1171,6 +1172,11 @@ struct moo_t
moo_oow_t sem_io_capa; moo_oow_t sem_io_capa;
moo_oow_t sem_io_wait_count; moo_oow_t sem_io_wait_count;
/* semaphore to notify finalizable objects */
moo_oop_semaphore_t sem_gcfin;
int sem_gcfin_sigreq;
moo_oow_t sem_gcfin_count;
moo_oop_t* tmp_stack[256]; /* stack for temporaries */ moo_oop_t* tmp_stack[256]; /* stack for temporaries */
moo_oow_t tmp_count; moo_oow_t tmp_count;