enhanced the gc finalization process a bit more
This commit is contained in:
parent
447012b214
commit
a46113abad
@ -290,10 +290,10 @@ class SemaphoreHeap(Object)
|
||||
|
||||
class(#final,#limited) ProcessScheduler(Object)
|
||||
{
|
||||
var(#get) active.
|
||||
var(#get) runnable_count.
|
||||
var(#get) active, total_count := 0.
|
||||
var(#get) runnable_count := 0.
|
||||
var runnable_head, runnable_tail.
|
||||
var(#get) suspended_count.
|
||||
var(#get) suspended_count := 0.
|
||||
var suspended_head, suspended_tail.
|
||||
|
||||
method activeProcess
|
||||
@ -348,6 +348,12 @@ class(#final,#limited) ProcessScheduler(Object)
|
||||
self primitiveFailed.
|
||||
}
|
||||
|
||||
method signalOnGCFin: semaphore
|
||||
{
|
||||
<primitive: #_processor_add_gcfin_semaphore>
|
||||
self primitiveFailed.
|
||||
}
|
||||
|
||||
method signal: semaphore onInput: file
|
||||
{
|
||||
<primitive: #_processor_add_input_semaphore>
|
||||
|
@ -32,39 +32,48 @@ class System(Apex)
|
||||
|
||||
method(#class) __gc_finalizer
|
||||
{
|
||||
| tmp gc |
|
||||
| tmp gc fin_sem |
|
||||
|
||||
gc := false.
|
||||
while (true)
|
||||
{
|
||||
|
||||
while ((tmp := self _popCollectable) notError)
|
||||
fin_sem := Semaphore new.
|
||||
|
||||
Processor signalOnGCFin: fin_sem.
|
||||
[
|
||||
while (true)
|
||||
{
|
||||
## TODO: Do i have to protected this in an exception handler???
|
||||
if (tmp respondsTo: #finalize) { tmp finalize }.
|
||||
}.
|
||||
|
||||
##if (Processor runnable_count == 1 and: [Processor active == thisProcess])
|
||||
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
|
||||
if (gc)
|
||||
{
|
||||
System logNl: 'Exiting the GC finalization process...'.
|
||||
break
|
||||
while ((tmp := self _popCollectable) notError)
|
||||
{
|
||||
## TODO: Do i have to protected this in an exception handler???
|
||||
if (tmp respondsTo: #finalize) { tmp finalize }.
|
||||
}.
|
||||
|
||||
self collectGarbage.
|
||||
gc := true.
|
||||
}
|
||||
else
|
||||
{
|
||||
gc := false.
|
||||
}.
|
||||
if (Processor total_count == 1)
|
||||
{
|
||||
## exit from this loop when there are no other processes running except this finalizer process
|
||||
if (gc)
|
||||
{
|
||||
System logNl: 'Exiting the GC finalization process'.
|
||||
break
|
||||
}.
|
||||
|
||||
##System logNl: 'gc_waiting....'.
|
||||
Processor sleepFor: 1. ## TODO: wait on semaphore instead..
|
||||
}
|
||||
System logNl: 'Forcing garbage collection before termination in ' & (thisProcess id) asString.
|
||||
self collectGarbage.
|
||||
gc := true.
|
||||
}
|
||||
else
|
||||
{
|
||||
gc := false.
|
||||
}.
|
||||
|
||||
##System logNl: '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^gc_waiting....'.
|
||||
##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.
|
||||
|
270
moo/lib/exec.c
270
moo/lib/exec.c
@ -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)
|
||||
{
|
||||
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);
|
||||
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));
|
||||
#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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
@ -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));
|
||||
|
||||
sleep_active_process (moo, new_state_for_old_active);
|
||||
wake_new_process (moo, proc);
|
||||
wake_process (moo, proc);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
* link it to the processor's process list. */
|
||||
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.next == moo->_nil);*/
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->suspended, proc, ps);
|
||||
|
||||
suspended_count--;
|
||||
moo->processor->suspended.count = MOO_SMOOI_TO_OOP(suspended_count);
|
||||
}
|
||||
suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count);
|
||||
MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->suspended, proc, ps);
|
||||
suspended_count--;
|
||||
moo->processor->suspended.count = MOO_SMOOI_TO_OOP(suspended_count);
|
||||
|
||||
/* append to the runnable list */
|
||||
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++;
|
||||
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 suspended_count;
|
||||
moo_ooi_t total_count;
|
||||
|
||||
/* the processor's process chain must be composed of running/runnable
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
||||
/* append to the suspended list */
|
||||
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_OOP_TO_SMOOI(moo->processor->total_count);
|
||||
total_count--;
|
||||
moo->processor->total_count = MOO_SMOOI_TO_OOP(total_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
proc->ps.prev = (moo_oop_process_t)moo->_nil;
|
||||
proc->ps.next = (moo_oop_process_t)moo->_nil;
|
||||
/* append to the suspended process list */
|
||||
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--;
|
||||
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 */
|
||||
|
||||
#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
|
||||
|
||||
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 */
|
||||
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
|
||||
{
|
||||
@ -404,10 +422,11 @@ static void terminate_process (moo_t* moo, moo_oop_process_t proc)
|
||||
{
|
||||
/* SUSPENDED ---> TERMINATED */
|
||||
#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
|
||||
|
||||
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 */
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING))
|
||||
{
|
||||
/* WAITING ---> TERMINATED */
|
||||
/* TODO: */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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);*/
|
||||
|
||||
#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
|
||||
|
||||
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->state = MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE);
|
||||
|
||||
/* don't switch to this process. just set the state to RUNNING */
|
||||
}
|
||||
#if 0
|
||||
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
|
||||
{
|
||||
/* keep the unchained process at the runnable state for
|
||||
* the immediate call to switch_to_process() below */
|
||||
unchain_from_processor (moo, proc, PROC_STATE_RUNNABLE);
|
||||
/* unchain_from_processor() leaves the active process
|
||||
* untouched unless the unchained process is the last
|
||||
* running/runnable process. so calling switch_to_process()
|
||||
* which expects the active process to be valid is safe */
|
||||
/* unchain_from_processor moves the process to the suspended
|
||||
* process and sets its state to the given state(SUSPENDED here).
|
||||
* it doesn't change the active process. we switch the active
|
||||
* process with switch_to_process(). setting the state of the
|
||||
* old active process to SUSPENDED is redundant because it's
|
||||
* done in unchain_from_processor(). the state of the active
|
||||
* 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);
|
||||
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 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
|
||||
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
|
||||
* make it runnable */
|
||||
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--;
|
||||
|
||||
@ -893,14 +914,18 @@ static void signal_io_semaphore (moo_t* moo, moo_ooi_t mask, void* ctx)
|
||||
{
|
||||
/* this is the only runnable process.
|
||||
* 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
|
||||
* process at this moment */
|
||||
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
|
||||
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;
|
||||
#else
|
||||
switch_to_process_from_nil (moo, proc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (!proc) return MOO_NULL;
|
||||
|
||||
if (chain_into_processor (moo, proc) <= -1) return MOO_NULL;
|
||||
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */
|
||||
chain_into_processor (moo, proc, PROC_STATE_RUNNING);
|
||||
moo->processor->active = proc;
|
||||
|
||||
/* do somthing that resume_process() would do with less overhead */
|
||||
@ -1159,7 +1183,6 @@ static int start_initial_process_and_context (moo_t* moo, const moo_oocs_t* objn
|
||||
static moo_ooch_t str_startup[] = { 's', 't', 'a', 'r', 't', 'u', 'p' };
|
||||
|
||||
#if defined(INVOKE_DIRECTLY)
|
||||
|
||||
|
||||
ass = moo_lookupsysdic (moo, objname);
|
||||
if (!ass || MOO_CLASSOF(moo, ass->value) != moo->_class)
|
||||
@ -1196,43 +1219,31 @@ TODO: overcome this problem - accept parameters....
|
||||
if (!mth)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
return -1;
|
||||
goto oops;
|
||||
}
|
||||
/* TODO: check if it's variadic.... it should be. and accept more than 2... */
|
||||
|
||||
moo_pushtmp (moo, (moo_oop_t*)&mth); tmp_count++;
|
||||
s1 = moo_makesymbol (moo, objname->ptr, objname->len);
|
||||
if (!s1)
|
||||
{
|
||||
moo_poptmps (moo, tmp_count);
|
||||
return -1;
|
||||
}
|
||||
if (!s1) goto oops;
|
||||
|
||||
moo_pushtmp (moo, (moo_oop_t*)&s1);
|
||||
s2 = moo_makesymbol (moo, mthname->ptr, mthname->len);
|
||||
if (!s2)
|
||||
{
|
||||
moo_poptmps (moo, tmp_count);
|
||||
return -1;
|
||||
}
|
||||
if (!s2) goto oops;
|
||||
|
||||
moo_pushtmp (moo, (moo_oop_t*)&s2);
|
||||
#endif
|
||||
|
||||
/* 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));
|
||||
if (!ctx)
|
||||
{
|
||||
moo_poptmps (moo, tmp_count);
|
||||
return -1;
|
||||
}
|
||||
if (!ctx) goto oops;
|
||||
|
||||
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);
|
||||
moo_poptmps (moo, tmp_count); tmp_count = 0;
|
||||
if (!proc) return -1;
|
||||
if (!proc) goto oops;
|
||||
|
||||
#if defined(INVOKE_DIRECTLY)
|
||||
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
|
||||
return activate_new_method (moo, mth, 2);
|
||||
#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;
|
||||
}
|
||||
|
||||
resume_process (moo, (moo_oop_process_t)rcv); /* TODO: error check */
|
||||
resume_process (moo, (moo_oop_process_t)rcv);
|
||||
|
||||
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@ -2428,6 +2472,11 @@ static moo_pfrc_t pf_processor_remove_semaphore (moo_t* moo, moo_ooi_t nargs)
|
||||
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) &&
|
||||
sem->heap_index != MOO_SMOOI_TO_OOP(-1))
|
||||
{
|
||||
@ -3875,14 +3924,14 @@ static pf_t pftab[] =
|
||||
{ "_block_value", { pf_block_value, 0, MA } },
|
||||
{ "_block_new_process", { pf_block_new_process, 0, 1 } },
|
||||
|
||||
|
||||
{ "_processor_schedule", { pf_processor_schedule, 1, 1 } },
|
||||
{ "_processor_add_timed_semaphore", { pf_processor_add_timed_semaphore, 2, 3 } },
|
||||
{ "_processor_add_gcfin_semaphore", { pf_processor_add_gcfin_semaphore, 1, 1 } },
|
||||
{ "_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_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_return_to", { pf_processor_return_to, 2, 2 } },
|
||||
{ "_processor_schedule", { pf_processor_schedule, 1, 1 } },
|
||||
|
||||
{ "_integer_add", { pf_integer_add, 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]);
|
||||
/* [NOTE] no moo_pushtmp() on proc. no GC must occur
|
||||
* 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 */
|
||||
|
||||
/* 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.
|
||||
* 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
|
||||
* process at this moment */
|
||||
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
|
||||
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;
|
||||
#else
|
||||
switch_to_process_from_nil (moo, proc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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.
|
||||
* the break in the else part further down will get hit
|
||||
* 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
|
||||
* moment the next inspection occurs. */
|
||||
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)
|
||||
{
|
||||
/* no more waiting semaphore and no more process */
|
||||
|
@ -291,6 +291,7 @@ static int ignite_2 (moo_t* moo)
|
||||
if (!tmp) return -1;
|
||||
moo->processor = (moo_oop_process_scheduler_t)tmp;
|
||||
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->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_gcfin = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_gcfin);
|
||||
|
||||
for (i = 0; i < moo->tmp_count; 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->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 */
|
||||
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->sem_gcfin_count = 0;
|
||||
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);
|
||||
@ -908,8 +914,7 @@ static void move_finalizable_objects (moo_t* moo)
|
||||
/* add it to the collectable list */
|
||||
MOO_APPEND_TO_LIST (&moo->collectable, x);
|
||||
|
||||
// TODO: singal semaphore..
|
||||
//signal_semaphore (moo, moo->collectable_semaphore);
|
||||
moo->sem_gcfin_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -808,13 +808,14 @@ struct moo_semaphore_t
|
||||
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_oop_process_scheduler_t;
|
||||
struct moo_process_scheduler_t
|
||||
{
|
||||
MOO_OBJ_HEADER;
|
||||
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
|
||||
{
|
||||
@ -825,7 +826,7 @@ struct moo_process_scheduler_t
|
||||
|
||||
struct
|
||||
{
|
||||
moo_oop_t count; /* SmallInteger */
|
||||
moo_oop_t count; /* SmallInteger - suspended*/
|
||||
moo_oop_process_t first;
|
||||
moo_oop_process_t last;
|
||||
} suspended;
|
||||
@ -1171,6 +1172,11 @@ struct moo_t
|
||||
moo_oow_t sem_io_capa;
|
||||
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_oow_t tmp_count;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user