enhancing VM to handle OS signals properly. work in progress
This commit is contained in:
parent
62777b97d6
commit
3253b8fe0a
@ -109,6 +109,7 @@ class Semaphore(Object)
|
|||||||
method(#primitive) signalOnInput: io_handle.
|
method(#primitive) signalOnInput: io_handle.
|
||||||
method(#primitive) signalOnOutput: io_handle.
|
method(#primitive) signalOnOutput: io_handle.
|
||||||
method(#primitive) signalOnGCFin.
|
method(#primitive) signalOnGCFin.
|
||||||
|
method(#primitive) signalOnIntr.
|
||||||
method(#primitive) unsignal.
|
method(#primitive) unsignal.
|
||||||
|
|
||||||
// ==================================================================
|
// ==================================================================
|
||||||
|
@ -55,7 +55,7 @@ class System(Apex)
|
|||||||
|
|
||||||
// start the gc finalizer process
|
// start the gc finalizer process
|
||||||
[ self __gc_finalizer ] fork.
|
[ self __gc_finalizer ] fork.
|
||||||
[ self __os_signal_handler ] fork.
|
[ self __os_intr_handler ] fork.
|
||||||
|
|
||||||
// TODO: change the method signature to variadic and pass extra arguments to perform???
|
// TODO: change the method signature to variadic and pass extra arguments to perform???
|
||||||
ret := class perform: method_name.
|
ret := class perform: method_name.
|
||||||
@ -78,8 +78,12 @@ class System(Apex)
|
|||||||
{
|
{
|
||||||
while ((tmp := self _popCollectable) notError)
|
while ((tmp := self _popCollectable) notError)
|
||||||
{
|
{
|
||||||
// TODO: Do i have to protected this in an exception handler???
|
if (tmp respondsTo: #finalize)
|
||||||
if (tmp respondsTo: #finalize) { tmp finalize }.
|
{
|
||||||
|
// finalize is protected with an exception handler.
|
||||||
|
// the exception is ignored except it's logged.
|
||||||
|
[ tmp finalize ] on: Exception do: [:ex | System longNl: "Exception in finalize - " & ex messageText ]
|
||||||
|
}.
|
||||||
}.
|
}.
|
||||||
|
|
||||||
//if (Processor total_count == 1)
|
//if (Processor total_count == 1)
|
||||||
@ -88,11 +92,11 @@ class System(Apex)
|
|||||||
// 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 ' & (thisProcess id) asString.
|
System logNl: "Exiting the GC finalization process " & (thisProcess id) asString.
|
||||||
break.
|
break.
|
||||||
}.
|
}.
|
||||||
|
|
||||||
System logNl: 'Forcing garbage collection before termination in ' & (thisProcess id) asString.
|
System logNl: "Forcing garbage collection before termination in " & (thisProcess id) asString.
|
||||||
self collectGarbage.
|
self collectGarbage.
|
||||||
gc := true.
|
gc := true.
|
||||||
}
|
}
|
||||||
@ -109,31 +113,39 @@ class System(Apex)
|
|||||||
].
|
].
|
||||||
}
|
}
|
||||||
|
|
||||||
method(#class) __os_signal_handler
|
method(#class) __os_intr_handler
|
||||||
{
|
{
|
||||||
| os_sig_sem |
|
| os_intr_sem tmp |
|
||||||
|
|
||||||
os_sig_sem := Semaphore new.
|
os_intr_sem := Semaphore new.
|
||||||
//os_sig_sem signalOnSystemSignal.
|
os_intr_sem signalOnIntr.
|
||||||
|
|
||||||
[
|
[
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
while ((tmp := self _dequeueIntr) notError)
|
||||||
|
{
|
||||||
|
// TODO: Do i have to protected this in an exception handler???
|
||||||
|
//TODO: Execute Handler for tmp.
|
||||||
|
System logNl: 'Interrupt dectected - signal no - ' & tmp asString.
|
||||||
|
}.
|
||||||
|
|
||||||
if (Processor should_exit)
|
if (Processor should_exit)
|
||||||
{
|
{
|
||||||
System logNl: 'Exiting the GC finalization process ' & (thisProcess id) asString.
|
System logNl: 'Exiting os interrupt handling process ' & (thisProcess id) asString.
|
||||||
break.
|
break.
|
||||||
}.
|
}.
|
||||||
|
|
||||||
os_sig_sem wait.
|
os_intr_sem wait.
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
ensure: [
|
ensure: [
|
||||||
os_sig_sem unsignal.
|
os_intr_sem unsignal.
|
||||||
System logNl: 'End of OS signal handler process ' & (thisProcess id) asString.
|
System logNl: 'End of OS signal handler process ' & (thisProcess id) asString.
|
||||||
].
|
].
|
||||||
}
|
}
|
||||||
|
|
||||||
|
method(#class,#primitive) _dequeueIntr.
|
||||||
method(#class,#primitive) _popCollectable.
|
method(#class,#primitive) _popCollectable.
|
||||||
method(#class,#primitive) collectGarbage.
|
method(#class,#primitive) collectGarbage.
|
||||||
method(#class,#primitive) gc.
|
method(#class,#primitive) gc.
|
||||||
|
@ -2662,13 +2662,27 @@ static moo_pfrc_t pf_semaphore_signal_on_gcfin (moo_t* moo, moo_mod_t* mod, moo_
|
|||||||
sem = (moo_oop_semaphore_t)MOO_STACK_GETRCV(moo, nargs);
|
sem = (moo_oop_semaphore_t)MOO_STACK_GETRCV(moo, nargs);
|
||||||
MOO_PF_CHECK_RCV (moo, moo_iskindof(moo, (moo_oop_t)sem, moo->_semaphore));
|
MOO_PF_CHECK_RCV (moo, moo_iskindof(moo, (moo_oop_t)sem, moo->_semaphore));
|
||||||
|
|
||||||
/* TODO: no overwriting.. */
|
/* TODO: should i prevent overwriting? */
|
||||||
moo->sem_gcfin = sem;
|
moo->sem_gcfin = sem;
|
||||||
|
|
||||||
MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */
|
MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */
|
||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static moo_pfrc_t pf_semaphore_signal_on_intr (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||||
|
{
|
||||||
|
moo_oop_semaphore_t sem;
|
||||||
|
|
||||||
|
sem = (moo_oop_semaphore_t)MOO_STACK_GETRCV(moo, nargs);
|
||||||
|
MOO_PF_CHECK_RCV (moo, moo_iskindof(moo, (moo_oop_t)sem, moo->_semaphore));
|
||||||
|
|
||||||
|
/* TODO: should i prevent overwriting? */
|
||||||
|
moo->sem_intr = sem;
|
||||||
|
|
||||||
|
MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static moo_pfrc_t pf_semaphore_signal_timed (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
static moo_pfrc_t pf_semaphore_signal_timed (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||||
{
|
{
|
||||||
moo_oop_semaphore_t sem;
|
moo_oop_semaphore_t sem;
|
||||||
@ -2825,6 +2839,10 @@ static moo_pfrc_t pf_semaphore_unsignal (moo_t* moo, moo_mod_t* mod, moo_ooi_t n
|
|||||||
{
|
{
|
||||||
moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil;
|
moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil;
|
||||||
}
|
}
|
||||||
|
else if (sem == moo->sem_intr)
|
||||||
|
{
|
||||||
|
moo->sem_intr = (moo_oop_semaphore_t)moo->_nil;
|
||||||
|
}
|
||||||
|
|
||||||
if (sem->subtype == MOO_SMOOI_TO_OOP(MOO_SEMAPHORE_SUBTYPE_TIMED))
|
if (sem->subtype == MOO_SMOOI_TO_OOP(MOO_SEMAPHORE_SUBTYPE_TIMED))
|
||||||
{
|
{
|
||||||
@ -4126,6 +4144,7 @@ static pf_t pftab[] =
|
|||||||
{ "Semaphore_signalAfterSecs:nanosecs:", { pf_semaphore_signal_timed, 2, 2 } },
|
{ "Semaphore_signalAfterSecs:nanosecs:", { pf_semaphore_signal_timed, 2, 2 } },
|
||||||
{ "Semaphore_signalOnGCFin", { pf_semaphore_signal_on_gcfin, 0, 0 } },
|
{ "Semaphore_signalOnGCFin", { pf_semaphore_signal_on_gcfin, 0, 0 } },
|
||||||
{ "Semaphore_signalOnInput:", { pf_semaphore_signal_on_input, 1, 1 } },
|
{ "Semaphore_signalOnInput:", { pf_semaphore_signal_on_input, 1, 1 } },
|
||||||
|
{ "Semaphore_signalOnIntr", { pf_semaphore_signal_on_intr, 0, 0 } },
|
||||||
{ "Semaphore_signalOnOutput:", { pf_semaphore_signal_on_output, 1, 1 } },
|
{ "Semaphore_signalOnOutput:", { pf_semaphore_signal_on_output, 1, 1 } },
|
||||||
{ "Semaphore_unsignal", { pf_semaphore_unsignal, 0, 0 } },
|
{ "Semaphore_unsignal", { pf_semaphore_unsignal, 0, 0 } },
|
||||||
{ "Semaphore_wait", { pf_semaphore_wait, 0, 0 } },
|
{ "Semaphore_wait", { pf_semaphore_wait, 0, 0 } },
|
||||||
@ -4161,6 +4180,7 @@ static pf_t pftab[] =
|
|||||||
{ "System_calloc", { moo_pf_system_calloc, 1, 1 } },
|
{ "System_calloc", { moo_pf_system_calloc, 1, 1 } },
|
||||||
{ "System_calloc:", { moo_pf_system_calloc, 1, 1 } },
|
{ "System_calloc:", { moo_pf_system_calloc, 1, 1 } },
|
||||||
{ "System_collectGarbage", { moo_pf_system_collect_garbage, 0, 0 } },
|
{ "System_collectGarbage", { moo_pf_system_collect_garbage, 0, 0 } },
|
||||||
|
{ "System_dequeueIntr", { moo_pf_system_dequeue_intr, 0, 0 } },
|
||||||
{ "System_free", { moo_pf_system_free, 1, 1 } },
|
{ "System_free", { moo_pf_system_free, 1, 1 } },
|
||||||
{ "System_free:", { moo_pf_system_free, 1, 1 } },
|
{ "System_free:", { moo_pf_system_free, 1, 1 } },
|
||||||
{ "System_gc", { moo_pf_system_collect_garbage, 0, 0 } },
|
{ "System_gc", { moo_pf_system_collect_garbage, 0, 0 } },
|
||||||
@ -4601,7 +4621,6 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
|
|||||||
|
|
||||||
static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, int to_super)
|
static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, int to_super)
|
||||||
{
|
{
|
||||||
|
|
||||||
moo_oop_t receiver;
|
moo_oop_t receiver;
|
||||||
moo_oop_method_t method;
|
moo_oop_method_t method;
|
||||||
|
|
||||||
@ -4646,6 +4665,20 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, i
|
|||||||
|
|
||||||
static MOO_INLINE int switch_process_if_needed (moo_t* moo)
|
static MOO_INLINE int switch_process_if_needed (moo_t* moo)
|
||||||
{
|
{
|
||||||
|
if (moo->intr_qstart != moo->intr_qend && (moo_oop_t)moo->sem_intr != moo->_nil)
|
||||||
|
{
|
||||||
|
moo_oop_process_t proc;
|
||||||
|
|
||||||
|
proc = signal_semaphore(moo, moo->sem_intr);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
goto switch_to_next;
|
||||||
|
}
|
||||||
|
|
||||||
if (moo->sem_heap_count > 0)
|
if (moo->sem_heap_count > 0)
|
||||||
{
|
{
|
||||||
/* handle timed semaphores */
|
/* handle timed semaphores */
|
||||||
@ -6133,6 +6166,13 @@ void moo_abort (moo_t* moo)
|
|||||||
moo->abort_req = 1;
|
moo->abort_req = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void moo_reportintr (moo_t* moo, int intrno)
|
||||||
|
{
|
||||||
|
moo->intr_queue[moo->intr_qend] = intrno;
|
||||||
|
moo->intr_qend = (moo->intr_qend + 1) % MOO_COUNTOF(moo->intr_queue);
|
||||||
|
if (moo->intr_qend == moo->intr_qstart) moo->intr_qstart = (moo->intr_qstart + 1) % MOO_COUNTOF(moo->intr_queue);
|
||||||
|
}
|
||||||
|
|
||||||
int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname)
|
int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
17
moo/lib/gc.c
17
moo/lib/gc.c
@ -975,15 +975,16 @@ void moo_gc (moo_t* moo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
moo->sem_gcfin = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_gcfin);
|
moo->sem_gcfin = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_gcfin);
|
||||||
|
moo->sem_intr = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_intr);
|
||||||
|
|
||||||
for (i = 0; i < moo->proc_map_capa; i++)
|
for (i = 0; i < moo->proc_map_capa; i++)
|
||||||
{
|
{
|
||||||
moo->proc_map[i] = moo_moveoop(moo, moo->proc_map[i]);
|
moo->proc_map[i] = moo_moveoop(moo, moo->proc_map[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < moo->tmp_count; i++)
|
for (i = 0; i < moo->volat_count; i++)
|
||||||
{
|
{
|
||||||
*moo->tmp_stack[i] = moo_moveoop(moo, *moo->tmp_stack[i]);
|
*moo->volat_stack[i] = moo_moveoop(moo, *moo->volat_stack[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moo->initial_context)
|
if (moo->initial_context)
|
||||||
@ -1070,20 +1071,20 @@ void moo_pushvolat (moo_t* moo, moo_oop_t* oop_ptr)
|
|||||||
{
|
{
|
||||||
/* if you have too many temporaries pushed, something must be wrong.
|
/* if you have too many temporaries pushed, something must be wrong.
|
||||||
* change your code not to exceede the stack limit */
|
* change your code not to exceede the stack limit */
|
||||||
MOO_ASSERT (moo, moo->tmp_count < MOO_COUNTOF(moo->tmp_stack));
|
MOO_ASSERT (moo, moo->volat_count < MOO_COUNTOF(moo->volat_stack));
|
||||||
moo->tmp_stack[moo->tmp_count++] = oop_ptr;
|
moo->volat_stack[moo->volat_count++] = oop_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void moo_popvolat (moo_t* moo)
|
void moo_popvolat (moo_t* moo)
|
||||||
{
|
{
|
||||||
MOO_ASSERT (moo, moo->tmp_count > 0);
|
MOO_ASSERT (moo, moo->volat_count > 0);
|
||||||
moo->tmp_count--;
|
moo->volat_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void moo_popvolats (moo_t* moo, moo_oow_t count)
|
void moo_popvolats (moo_t* moo, moo_oow_t count)
|
||||||
{
|
{
|
||||||
MOO_ASSERT (moo, moo->tmp_count >= count);
|
MOO_ASSERT (moo, moo->volat_count >= count);
|
||||||
moo->tmp_count -= count;
|
moo->volat_count -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
moo_oop_t moo_shallowcopy (moo_t* moo, moo_oop_t oop)
|
moo_oop_t moo_shallowcopy (moo_t* moo, moo_oop_t oop)
|
||||||
|
@ -1626,6 +1626,8 @@ moo_pfrc_t moo_pf_responds_to (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
|||||||
moo_pfrc_t moo_pf_system_collect_garbage (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
moo_pfrc_t moo_pf_system_collect_garbage (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
||||||
moo_pfrc_t moo_pf_system_pop_collectable (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
moo_pfrc_t moo_pf_system_pop_collectable (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
||||||
|
|
||||||
|
moo_pfrc_t moo_pf_system_dequeue_intr (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
||||||
|
|
||||||
moo_pfrc_t moo_pf_system_malloc (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
moo_pfrc_t moo_pf_system_malloc (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
||||||
moo_pfrc_t moo_pf_system_calloc (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
moo_pfrc_t moo_pf_system_calloc (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
||||||
moo_pfrc_t moo_pf_system_free (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
moo_pfrc_t moo_pf_system_free (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs);
|
||||||
|
@ -1597,8 +1597,14 @@ struct moo_t
|
|||||||
moo_oop_semaphore_t sem_gcfin;
|
moo_oop_semaphore_t sem_gcfin;
|
||||||
int sem_gcfin_sigreq;
|
int sem_gcfin_sigreq;
|
||||||
|
|
||||||
moo_oop_t* tmp_stack[256]; /* stack for temporaries */
|
moo_oop_semaphore_t sem_intr;
|
||||||
moo_oow_t tmp_count;
|
|
||||||
|
int intr_queue[256]; /* TODO: make it dynamic? */
|
||||||
|
int intr_qstart;
|
||||||
|
int intr_qend;
|
||||||
|
|
||||||
|
moo_oop_t* volat_stack[256]; /* stack for temporaries */
|
||||||
|
moo_oow_t volat_count;
|
||||||
|
|
||||||
|
|
||||||
moo_oop_t* proc_map;
|
moo_oop_t* proc_map;
|
||||||
@ -2134,6 +2140,10 @@ MOO_EXPORT void moo_abort (
|
|||||||
moo_t* moo
|
moo_t* moo
|
||||||
);
|
);
|
||||||
|
|
||||||
|
MOO_EXPORT void moo_reportintr (
|
||||||
|
moo_t* moo,
|
||||||
|
int intrno
|
||||||
|
);
|
||||||
|
|
||||||
#if defined(MOO_HAVE_INLINE)
|
#if defined(MOO_HAVE_INLINE)
|
||||||
static MOO_INLINE void moo_switchprocess(moo_t* moo) { moo->switch_proc = 1; }
|
static MOO_INLINE void moo_switchprocess(moo_t* moo) { moo->switch_proc = 1; }
|
||||||
|
@ -63,6 +63,24 @@ moo_pfrc_t moo_pf_system_pop_collectable (moo_t* moo, moo_mod_t* mod, moo_ooi_t
|
|||||||
return MOO_PF_SUCCESS;
|
return MOO_PF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------- */
|
||||||
|
moo_pfrc_t moo_pf_system_dequeue_intr (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
|
||||||
|
{
|
||||||
|
if (moo->intr_qstart != moo->intr_qend)
|
||||||
|
{
|
||||||
|
moo_ooi_t intr_no;
|
||||||
|
intr_no = moo->intr_queue[moo->intr_qstart];
|
||||||
|
moo->intr_qstart = (moo->intr_qstart + 1) % MOO_COUNTOF(moo->intr_queue);
|
||||||
|
MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(intr_no));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MOO_PF_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static MOO_INLINE moo_pfrc_t _system_alloc (moo_t* moo, moo_ooi_t nargs, int clear)
|
static MOO_INLINE moo_pfrc_t _system_alloc (moo_t* moo, moo_ooi_t nargs, int clear)
|
||||||
|
@ -2895,7 +2895,7 @@ static int unset_signal_handler (int sig)
|
|||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
|
||||||
static MOO_INLINE void abort_all_moos (int unused)
|
static MOO_INLINE void abort_all_moos (int signo)
|
||||||
{
|
{
|
||||||
/* TODO: make this atomic */
|
/* TODO: make this atomic */
|
||||||
if (g_moo)
|
if (g_moo)
|
||||||
@ -2904,7 +2904,8 @@ static MOO_INLINE void abort_all_moos (int unused)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
xtn_t* xtn = GET_XTN(moo);
|
xtn_t* xtn = GET_XTN(moo);
|
||||||
moo_abortstd (moo);
|
/*moo_abortstd (moo);*/
|
||||||
|
moo_reportintr (moo, signo);
|
||||||
moo = xtn->next;
|
moo = xtn->next;
|
||||||
}
|
}
|
||||||
while (moo);
|
while (moo);
|
||||||
|
Loading…
Reference in New Issue
Block a user