diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 5c96d63..4e537cd 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -109,6 +109,7 @@ class Semaphore(Object) method(#primitive) signalOnInput: io_handle. method(#primitive) signalOnOutput: io_handle. method(#primitive) signalOnGCFin. + method(#primitive) signalOnIntr. method(#primitive) unsignal. // ================================================================== diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index 09b2a0b..2ba6094 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -55,7 +55,7 @@ class System(Apex) // start the gc finalizer process [ 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??? ret := class perform: method_name. @@ -78,8 +78,12 @@ class System(Apex) { while ((tmp := self _popCollectable) notError) { - // TODO: Do i have to protected this in an exception handler??? - if (tmp respondsTo: #finalize) { tmp finalize }. + if (tmp respondsTo: #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) @@ -88,11 +92,11 @@ class System(Apex) // exit from this loop when there are no other processes running except this finalizer process if (gc) { - System logNl: 'Exiting the GC finalization process ' & (thisProcess id) asString. + System logNl: "Exiting the GC finalization process " & (thisProcess id) asString. 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. 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_sig_sem signalOnSystemSignal. + os_intr_sem := Semaphore new. + os_intr_sem signalOnIntr. [ 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) { - System logNl: 'Exiting the GC finalization process ' & (thisProcess id) asString. + System logNl: 'Exiting os interrupt handling process ' & (thisProcess id) asString. break. }. - os_sig_sem wait. + os_intr_sem wait. } ] ensure: [ - os_sig_sem unsignal. + os_intr_sem unsignal. System logNl: 'End of OS signal handler process ' & (thisProcess id) asString. ]. } + method(#class,#primitive) _dequeueIntr. method(#class,#primitive) _popCollectable. method(#class,#primitive) collectGarbage. method(#class,#primitive) gc. diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 6dbcd9d..7b69f67 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -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); 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_STACK_SETRETTORCV (moo, nargs); /* ^self */ 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) { 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; } + 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)) { @@ -4126,6 +4144,7 @@ static pf_t pftab[] = { "Semaphore_signalAfterSecs:nanosecs:", { pf_semaphore_signal_timed, 2, 2 } }, { "Semaphore_signalOnGCFin", { pf_semaphore_signal_on_gcfin, 0, 0 } }, { "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_unsignal", { pf_semaphore_unsignal, 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_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_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) { - moo_oop_t receiver; 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) { + 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) { /* handle timed semaphores */ @@ -6133,6 +6166,13 @@ void moo_abort (moo_t* moo) 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 n; diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 02c7e1f..5942d19 100644 --- a/moo/lib/gc.c +++ b/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_intr = (moo_oop_semaphore_t)moo_moveoop(moo, (moo_oop_t)moo->sem_intr); for (i = 0; i < moo->proc_map_capa; 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) @@ -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. * change your code not to exceede the stack limit */ - MOO_ASSERT (moo, moo->tmp_count < MOO_COUNTOF(moo->tmp_stack)); - moo->tmp_stack[moo->tmp_count++] = oop_ptr; + MOO_ASSERT (moo, moo->volat_count < MOO_COUNTOF(moo->volat_stack)); + moo->volat_stack[moo->volat_count++] = oop_ptr; } void moo_popvolat (moo_t* moo) { - MOO_ASSERT (moo, moo->tmp_count > 0); - moo->tmp_count--; + MOO_ASSERT (moo, moo->volat_count > 0); + moo->volat_count--; } void moo_popvolats (moo_t* moo, moo_oow_t count) { - MOO_ASSERT (moo, moo->tmp_count >= count); - moo->tmp_count -= count; + MOO_ASSERT (moo, moo->volat_count >= count); + moo->volat_count -= count; } moo_oop_t moo_shallowcopy (moo_t* moo, moo_oop_t oop) @@ -1202,7 +1203,7 @@ static moo_oow_t move_finalizable_objects (moo_t* moo) 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); - x->oop = moo_moveoop (moo, x->oop); + x->oop = moo_moveoop(moo, x->oop); } for (x = moo->finalizable.first; x; ) @@ -1222,7 +1223,7 @@ static moo_oow_t move_finalizable_objects (moo_t* moo) * however this is quite unlikely because some key objects for VM execution * like context objects doesn't require finalization. */ - x->oop = moo_moveoop (moo, x->oop); + x->oop = moo_moveoop(moo, x->oop); /* remove it from the finalizable list */ MOO_DELETE_FROM_LIST (&moo->finalizable, x); diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index bcd4a8c..80a1c73 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -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_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_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); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 9ed5587..21b22a8 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1597,8 +1597,14 @@ struct moo_t moo_oop_semaphore_t sem_gcfin; int sem_gcfin_sigreq; - moo_oop_t* tmp_stack[256]; /* stack for temporaries */ - moo_oow_t tmp_count; + moo_oop_semaphore_t sem_intr; + + 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; @@ -2134,6 +2140,10 @@ MOO_EXPORT void moo_abort ( moo_t* moo ); +MOO_EXPORT void moo_reportintr ( + moo_t* moo, + int intrno +); #if defined(MOO_HAVE_INLINE) static MOO_INLINE void moo_switchprocess(moo_t* moo) { moo->switch_proc = 1; } diff --git a/moo/lib/pf-sys.c b/moo/lib/pf-sys.c index 664b5b9..ff6f7e9 100644 --- a/moo/lib/pf-sys.c +++ b/moo/lib/pf-sys.c @@ -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; } +/* ------------------------------------------------------------------------------------- */ +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) diff --git a/moo/lib/std.c b/moo/lib/std.c index 7c53b80..f230199 100644 --- a/moo/lib/std.c +++ b/moo/lib/std.c @@ -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 */ if (g_moo) @@ -2904,7 +2904,8 @@ static MOO_INLINE void abort_all_moos (int unused) do { xtn_t* xtn = GET_XTN(moo); - moo_abortstd (moo); + /*moo_abortstd (moo);*/ + moo_reportintr (moo, signo); moo = xtn->next; } while (moo);