From f23a5bd22c75f0c6033de15ad5726682b923202b Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Thu, 15 Aug 2019 15:55:06 +0000 Subject: [PATCH] added two new vm primitives - vm_getsigfd and vm_getsig - to support os signal handling more promptly --- moo/kernel/Process.moo | 1 - moo/kernel/System.moo | 13 +++-- moo/lib/exec.c | 45 +-------------- moo/lib/gc.c | 1 - moo/lib/moo-prv.h | 3 +- moo/lib/moo.h | 25 ++++----- moo/lib/pf-sys.c | 30 ++++++---- moo/lib/std.c | 123 ++++++++++++++++++++++++++++------------- 8 files changed, 128 insertions(+), 113 deletions(-) diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 4e537cd..5c96d63 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -109,7 +109,6 @@ 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 2ba6094..36fedad 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_intr_handler ] fork. + [ self __os_sig_handler ] fork. // TODO: change the method signature to variadic and pass extra arguments to perform??? ret := class perform: method_name. @@ -113,21 +113,23 @@ class System(Apex) ]. } - method(#class) __os_intr_handler + method(#class) __os_sig_handler { | os_intr_sem tmp | os_intr_sem := Semaphore new. - os_intr_sem signalOnIntr. + os_intr_sem signalOnInput: System _getSigfd. [ while (true) { - while ((tmp := self _dequeueIntr) notError) + while ((tmp := self _getSig) 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 (tmp == 2) { /* TODO: terminate all processes??? */ }. }. if (Processor should_exit) @@ -145,7 +147,8 @@ class System(Apex) ]. } - method(#class,#primitive) _dequeueIntr. + method(#class,#primitive) _getSig. + method(#class,#primitive) _getSigfd. 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 7b69f67..d8b55c6 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -2669,20 +2669,6 @@ static moo_pfrc_t pf_semaphore_signal_on_gcfin (moo_t* moo, moo_mod_t* mod, moo_ 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; @@ -2839,10 +2825,6 @@ 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)) { @@ -4144,7 +4126,6 @@ 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 } }, @@ -4180,7 +4161,6 @@ 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 } }, @@ -4189,6 +4169,8 @@ static pf_t pftab[] = { "System_getInt32", { moo_pf_system_get_int32, 2, 2 } }, { "System_getInt64", { moo_pf_system_get_int64, 2, 2 } }, { "System_getInt8", { moo_pf_system_get_int8, 2, 2 } }, + { "System_getSig", { moo_pf_system_get_sig, 0, 0 } }, + { "System_getSigfd", { moo_pf_system_get_sigfd, 0, 0 } }, { "System_getUint16", { moo_pf_system_get_uint16, 2, 2 } }, { "System_getUint32", { moo_pf_system_get_uint32, 2, 2 } }, { "System_getUint64", { moo_pf_system_get_uint64, 2, 2 } }, @@ -4632,7 +4614,7 @@ static int send_message (moo_t* moo, moo_oop_char_t selector, moo_ooi_t nargs, i method = moo_findmethod(moo, receiver, selector, to_super); if (!method) - { + { method = moo_findmethod(moo, receiver, moo->does_not_understand_sym, 0); if (!method) { @@ -4665,20 +4647,6 @@ 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 */ @@ -6166,13 +6134,6 @@ 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 5942d19..f7c6183 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -975,7 +975,6 @@ 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++) { diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 80a1c73..c30a412 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -1626,7 +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_get_sigfd (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_get_sig (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); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 21b22a8..d8b8bfb 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1207,6 +1207,15 @@ typedef void (*moo_vmprim_sleep_t) ( const moo_ntime_t* duration ); +typedef moo_ooi_t (*moo_vmprim_getsigfd_t) ( + moo_t* moo +); + +typedef int (*moo_vmprim_getsig_t) ( + moo_t* moo, + moo_uint8_t* sig +); + struct moo_vmprim_t { moo_alloc_heap_t alloc_heap; @@ -1231,11 +1240,13 @@ struct moo_vmprim_t moo_vmprim_muxmod_t vm_muxmod; moo_vmprim_muxwait_t vm_muxwait; moo_vmprim_sleep_t vm_sleep; + + moo_vmprim_getsigfd_t vm_getsigfd; + moo_vmprim_getsig_t vm_getsig; }; typedef struct moo_vmprim_t moo_vmprim_t; - /* ========================================================================= * CALLBACK MANIPULATION * ========================================================================= */ @@ -1597,16 +1608,9 @@ struct moo_t moo_oop_semaphore_t sem_gcfin; int sem_gcfin_sigreq; - 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; moo_oow_t proc_map_capa; moo_ooi_t proc_map_free_first; @@ -2140,11 +2144,6 @@ 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; } #else diff --git a/moo/lib/pf-sys.c b/moo/lib/pf-sys.c index ff6f7e9..5a0d467 100644 --- a/moo/lib/pf-sys.c +++ b/moo/lib/pf-sys.c @@ -64,19 +64,25 @@ moo_pfrc_t moo_pf_system_pop_collectable (moo_t* moo, moo_mod_t* mod, moo_ooi_t } /* ------------------------------------------------------------------------------------- */ -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_get_sigfd (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); - } + moo_ooi_t fd; + fd = moo->vmprim.vm_getsigfd(moo); + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(fd)); + return MOO_PF_SUCCESS; +} + +moo_pfrc_t moo_pf_system_get_sig (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_uint8_t sig; + int n; + + n = moo->vmprim.vm_getsig(moo, &sig); + if (n <= -1) return MOO_PF_FAILURE; + + if (n == 0) MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + else MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP((moo_ooi_t)sig)); return MOO_PF_SUCCESS; } diff --git a/moo/lib/std.c b/moo/lib/std.c index f230199..5c4e293 100644 --- a/moo/lib/std.c +++ b/moo/lib/std.c @@ -333,6 +333,11 @@ struct xtn_t } iothr; #endif + struct + { + int p[2]; /* pipe for signaling */ + } sigfd; + struct { #if defined(USE_DEVPOLL) @@ -1986,11 +1991,45 @@ static int _mod_poll_fd (moo_t* moo, int fd, int event_mask) #endif } +static int open_pipe (moo_t* moo, int p[2]) +{ + int flags; + +#if defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK) + if (pipe2(p, O_CLOEXEC | O_NONBLOCK) == -1) +#else + if (pipe(p) == -1) +#endif + { + moo_seterrbfmtwithsyserr (moo, 0, errno, "unable to create pipes for iothr management"); + return -1; + } + +#if defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK) + /* do nothing */ +#else + #if defined(FD_CLOEXEC) + flags = fcntl(p[0], F_GETFD); + if (flags >= 0) fcntl (p[0], F_SETFD, flags | FD_CLOEXEC); + flags = fcntl(p[1], F_GETFD); + if (flags >= 0) fcntl (p[1], F_SETFD, flags | FD_CLOEXEC); + #endif + #if defined(O_NONBLOCK) + flags = fcntl(p[0], F_GETFL); + if (flags >= 0) fcntl (p[0], F_SETFL, flags | O_NONBLOCK); + flags = fcntl(p[1], F_GETFL); + if (flags >= 0) fcntl (p[1], F_SETFL, flags | O_NONBLOCK); + #endif +#endif + + return 0; +} static int vm_startup (moo_t* moo) { xtn_t* xtn = GET_XTN(moo); - int pcount = 0, flag; + int sigfd_pcount = 0; + int iothr_pcount = 0, flags; #if defined(_WIN32) xtn->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); @@ -2006,8 +2045,8 @@ static int vm_startup (moo_t* moo) } #if defined(FD_CLOEXEC) - flag = fcntl(xtn->ep, F_GETFD); - if (flag >= 0) fcntl (xtn->ep, F_SETFD, flag | FD_CLOEXEC); + flags = fcntl(xtn->ep, F_GETFD); + if (flags >= 0) fcntl (xtn->ep, F_SETFD, flags | FD_CLOEXEC); #endif #elif defined(USE_EPOLL) @@ -2025,8 +2064,8 @@ static int vm_startup (moo_t* moo) } #if defined(FD_CLOEXEC) - flag = fcntl(xtn->ep, F_GETFD); - if (flag >= 0 && !(flag & FD_CLOEXEC)) fcntl (xtn->ep, F_SETFD, flag | FD_CLOEXEC); + flags = fcntl(xtn->ep, F_GETFD); + if (flags >= 0 && !(flags & FD_CLOEXEC)) fcntl (xtn->ep, F_SETFD, flags | FD_CLOEXEC); #endif #elif defined(USE_POLL) @@ -2040,34 +2079,12 @@ static int vm_startup (moo_t* moo) MUTEX_INIT (&xtn->ev.reg.smtx); #endif /* USE_DEVPOLL */ -#if defined(USE_THREAD) - #if defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK) - if (pipe2(xtn->iothr.p, O_CLOEXEC | O_NONBLOCK) == -1) - #else - if (pipe(xtn->iothr.p) == -1) - #endif - { - moo_seterrbfmtwithsyserr (moo, 0, errno, "unable to create pipes for iothr management"); - goto oops; - } - pcount = 2; + if (open_pipe(moo, xtn->sigfd.p) <= -1) goto oops; + sigfd_pcount = 2; - #if defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK) - /* do nothing */ - #else - #if defined(FD_CLOEXEC) - flag = fcntl(xtn->iothr.p[0], F_GETFD); - if (flag >= 0) fcntl (xtn->iothr.p[0], F_SETFD, flag | FD_CLOEXEC); - flag = fcntl(xtn->iothr.p[1], F_GETFD); - if (flag >= 0) fcntl (xtn->iothr.p[1], F_SETFD, flag | FD_CLOEXEC); - #endif - #if defined(O_NONBLOCK) - flag = fcntl(xtn->iothr.p[0], F_GETFL); - if (flag >= 0) fcntl (xtn->iothr.p[0], F_SETFL, flag | O_NONBLOCK); - flag = fcntl(xtn->iothr.p[1], F_GETFL); - if (flag >= 0) fcntl (xtn->iothr.p[1], F_SETFL, flag | O_NONBLOCK); - #endif - #endif +#if defined(USE_THREAD) + if (open_pipe(moo, xtn->iothr.p) <= -1) goto oops; + iothr_pcount = 2; if (_add_poll_fd(moo, xtn->iothr.p[0], XPOLLIN) <= -1) goto oops; @@ -2085,15 +2102,20 @@ static int vm_startup (moo_t* moo) return 0; oops: - #if defined(USE_THREAD) - if (pcount > 0) + if (iothr_pcount > 0) { close (xtn->iothr.p[0]); close (xtn->iothr.p[1]); } #endif + if (sigfd_pcount > 0) + { + close (xtn->sigfd.p[0]); + close (xtn->sigfd.p[1]); + } + #if defined(USE_DEVPOLL) || defined(USE_EPOLL) if (xtn->ep >= 0) { @@ -2137,6 +2159,9 @@ static void vm_cleanup (moo_t* moo) close (xtn->iothr.p[0]); #endif /* USE_THREAD */ + close (xtn->sigfd.p[1]); + close (xtn->sigfd.p[0]); + #if defined(USE_DEVPOLL) if (xtn->ep >= 0) { @@ -2337,7 +2362,7 @@ static void* iothr_main (void* arg) dvp.dp_nfds = MOO_COUNTOF(xtn->ev.buf); n = ioctl (xtn->ep, DP_POLL, &dvp); #elif defined(USE_EPOLL) - n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), 10000); /* TODO: make this timeout value in the io thread */ + n = epoll_wait(xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), 10000); /* TODO: make this timeout value in the io thread */ #elif defined(USE_POLL) MUTEX_LOCK (&xtn->ev.reg.pmtx); MOO_MEMCPY (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf)); @@ -2578,9 +2603,9 @@ static void vm_muxwait (moo_t* moo, const moo_ntime_t* dur, moo_vmprim_muxwait_c dvp.dp_timeout = tmout; /* milliseconds */ dvp.dp_fds = xtn->ev.buf; dvp.dp_nfds = MOO_COUNTOF(xtn->ev.buf); - n = ioctl (xtn->ep, DP_POLL, &dvp); + n = ioctl(xtn->ep, DP_POLL, &dvp); #elif defined(USE_EPOLL) - n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), tmout); + n = epoll_wait(xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), tmout); #elif defined(USE_POLL) MOO_MEMCPY (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf)); n = poll(xtn->ev.buf, xtn->ev.reg.len, tmout); @@ -2770,6 +2795,24 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) #endif } + +static moo_ooi_t vm_getsigfd (moo_t* moo) +{ + xtn_t* xtn = GET_XTN(moo); + return xtn->sigfd.p[0]; +} + +static int vm_getsig (moo_t* moo, moo_uint8_t* u8) +{ + xtn_t* xtn = GET_XTN(moo); + if (read(xtn->sigfd.p[0], u8, MOO_SIZEOF(*u8)) == -1) + { + if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) return 0; + moo_seterrwithsyserr (moo, 0, errno); + return -1; + } + return 1; +} /* ========================================================================= */ #if defined(HAVE_SIGACTION) @@ -2904,8 +2947,10 @@ static MOO_INLINE void abort_all_moos (int signo) do { xtn_t* xtn = GET_XTN(moo); + moo_uint8_t u8; /*moo_abortstd (moo);*/ - moo_reportintr (moo, signo); + u8 = signo & 0xFF; + write (xtn->sigfd.p[1], &u8, MOO_SIZEOF(u8)); moo = xtn->next; } while (moo); @@ -3661,6 +3706,8 @@ static void fini_moo (moo_t* moo) vmprim.vm_muxmod = vm_muxmod; vmprim.vm_muxwait = vm_muxwait; vmprim.vm_sleep = vm_sleep; + vmprim.vm_getsigfd = vm_getsigfd; + vmprim.vm_getsig = vm_getsig; moo = moo_open(&sys_mmgr, MOO_SIZEOF(xtn_t) + xtnsize, ((cfg && cfg->cmgr)? cfg->cmgr: moo_get_utf8_cmgr()), &vmprim, errinfo); if (!moo) return MOO_NULL;