diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 4b50650..59cccc7 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -12,6 +12,8 @@ class(#pointer,#final,#limited,#uncopyable) Process(Object) method primErrorMessage { ^self.perrmsg } method(#primitive) sp. + method(#primitive) isInnate. + method(#primitive) isNormal. method(#primitive) resume. method(#primitive) yield. method(#primitive) suspend. diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index 7024a95..e84b8b5 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -212,8 +212,11 @@ class System(Apex) while (proc notError) { pid := proc id. - System logNl: ("Requesting to terminate process of id - " & pid asString). - proc terminate. + if (proc isNormal) + { + System logNl: ("Requesting to terminate process of id - " & pid asString). + proc terminate. + }. proc := System _findNextProcess: pid. }. @@ -236,7 +239,10 @@ class System(Apex) method(#class,#primitive) _halting. method(#class,#primitive) _toggleProcessSwitching: v. method(#class,#primitive,#lenient) _findProcessById: id. - method(#class,#primitive,#lenient) _findNextProcess: id. + method(#class,#primitive,#lenient) _findFirstProcess. + method(#class,#primitive,#lenient) _findLastProcess. + method(#class,#primitive,#lenient) _findPreviousProcess: p. // process id or process object + method(#class,#primitive,#lenient) _findNextProcess: p. // process id or process object method(#class,#primitive) _popCollectable. method(#class,#primitive) collectGarbage. diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 23850fe..33c66ae 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -1628,7 +1628,7 @@ static moo_oop_process_t start_initial_process (moo_t* moo, moo_oop_context_t c) MOO_ASSERT (moo, moo->processor->runnable.count == MOO_SMOOI_TO_OOP(0)); MOO_ASSERT (moo, moo->processor->active == moo->nil_process); - proc = make_process(moo, c, MOO_OBJ_FLAGS_PROC_SYSTEM); + proc = make_process(moo, c, MOO_OBJ_FLAGS_PROC_INNATE); if (!proc) return MOO_NULL; chain_into_processor (moo, proc, PROC_STATE_RUNNING); @@ -2737,6 +2737,28 @@ static moo_pfrc_t pf_process_sp (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +static moo_pfrc_t pf_process_is_innate (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t rcv; + + rcv = MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, MOO_CLASSOF(moo,rcv) == moo->_process); + + MOO_STACK_SETRET (moo, nargs, (MOO_OBJ_GET_FLAGS_PROC(rcv) == MOO_OBJ_FLAGS_PROC_INNATE? moo->_true: moo->_false)); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t pf_process_is_normal (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t rcv; + + rcv = MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, MOO_CLASSOF(moo,rcv) == moo->_process); + + MOO_STACK_SETRET (moo, nargs, (MOO_OBJ_GET_FLAGS_PROC(rcv) == MOO_OBJ_FLAGS_PROC_NORMAL? moo->_true: moo->_false)); + return MOO_PF_SUCCESS; +} + static moo_pfrc_t pf_process_resume (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) { moo_oop_t rcv; @@ -3278,156 +3300,6 @@ static moo_pfrc_t pf_system_return_value_to_context (moo_t* moo, moo_mod_t* mod, return MOO_PF_SUCCESS; } -/* ------------------------------------------------------------------ */ -static moo_pfrc_t pf_system_toggle_process_switching (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) -{ - moo_oop_t v; - int oldnps; - - oldnps = moo->no_proc_switch; - - v = MOO_STACK_GETARG(moo, nargs, 0); - if (v == moo->_false) - { - /* disable process switching */ - moo->no_proc_switch = 1; - } - else - { - /* enable process switching */ - moo->no_proc_switch = 0; - } - - MOO_STACK_SETRET (moo, nargs, (oldnps? moo->_false: moo->_true)); - return MOO_PF_SUCCESS; -} - -static moo_pfrc_t pf_system_halting (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) -{ - moo_evtcb_t* cb; - for (cb = moo->evtcb_list; cb; cb = cb->next) - { - if (cb->halting) cb->halting (moo); - } - MOO_STACK_SETRETTORCV (moo, nargs); - return MOO_PF_SUCCESS; -} - -static moo_pfrc_t pf_system_find_process_by_id (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) -{ - moo_oop_t /*rcv,*/ id; - - /*rcv = MOO_STACK_GETRCV(moo, nargs);*/ - id = MOO_STACK_GETARG(moo, nargs, 0); - - /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ - - if (MOO_OOP_IS_SMOOI(id)) - { - moo_ooi_t index = MOO_OOP_TO_SMOOI(id); - if (index >= 0) - { - if (MOO_CLASSOF(moo, moo->proc_map[index]) == moo->_process) - { - MOO_STACK_SETRET (moo, nargs, moo->proc_map[index]); - return MOO_PF_SUCCESS; - } - - /* it must be in a free list since the pid slot is not allocated. see alloc_pid() and free_pid() */ - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->proc_map[index])); - } - } - - MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); - return MOO_PF_FAILURE; -} - - -static MOO_INLINE moo_oop_t __find_adjacent_process_by_id_noseterr (moo_t* moo, moo_ooi_t index, int find_next, int exclude_system) -{ - if (find_next) - { - if (index < -1) index = -1; - - /* TOOD: enhance alloc_pid() and free_pid() to maintain the hightest pid number so that this loop can stop before reaching proc_map_capa */ - for (++index; index < moo->proc_map_capa; index++) - { - /* note the free slot contains a small integer which indicate the next slot index in proc_map. - * if the slot it taken, it should point to a process object. read the comment at end of this loop. */ - moo_oop_t tmp; - - tmp = moo->proc_map[index]; - if (MOO_CLASSOF(moo, tmp) == moo->_process) - { - if (exclude_system && MOO_OBJ_GET_FLAGS_PROC(tmp) == MOO_OBJ_FLAGS_PROC_SYSTEM) continue; - MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_PROC(tmp) == MOO_OBJ_FLAGS_PROC_NORMAL); - return tmp; - } - - /* it must be in a free list since the pid slot is not allocated. see alloc_pid() and free_pid() */ - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->proc_map[index])); - } - } - else - { - /* find the previous one */ - - if (index > moo->proc_map_capa || index <= -1) index = moo->proc_map_capa; - for (--index; index >= 0; index--) - { - moo_oop_t tmp; - - tmp = moo->proc_map[index]; - if (MOO_CLASSOF(moo, tmp) == moo->_process) - { - if (exclude_system && MOO_OBJ_GET_FLAGS_PROC(tmp) == MOO_OBJ_FLAGS_PROC_SYSTEM) continue; - MOO_ASSERT (moo, MOO_OBJ_GET_FLAGS_PROC(tmp) == MOO_OBJ_FLAGS_PROC_NORMAL); - return tmp; - } - - /* it must be in a free list since the pid slot is not allocated. see alloc_pid() and free_pid() */ - MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->proc_map[index])); - } - } - - return MOO_NULL; -} - -static moo_pfrc_t pf_system_find_next_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) -{ - moo_oop_t /*rcv,*/ id; - - /*rcv = MOO_STACK_GETRCV(moo, nargs);*/ - id = MOO_STACK_GETARG(moo, nargs, 0); - - /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ - - if (id == moo->_nil) - { - id = MOO_SMOOI_TO_OOP(-1); - } - else if (MOO_CLASSOF(moo, id) == moo->_process) - { - /* the argument is a process object */ - id = ((moo_oop_process_t)id)->id; - } - - if (MOO_OOP_IS_SMOOI(id)) - { - moo_oop_t tmp; - - tmp = __find_adjacent_process_by_id_noseterr(moo, MOO_OOP_TO_SMOOI(id), 1, 1); - if (tmp) - { - MOO_STACK_SETRET (moo, nargs, tmp); - return MOO_PF_SUCCESS; - } - } - - MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); - return MOO_PF_FAILURE; -} - /* ------------------------------------------------------------------ */ static moo_pfrc_t pf_number_scale (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) { @@ -4494,6 +4366,8 @@ static pf_t pftab[] = { "MethodContext_findExceptionHandler:", { pf_context_find_exception_handler, 1, 1 } }, { "MethodContext_goto:", { pf_context_goto, 1, 1 } }, + { "Process_isInnate", { pf_process_is_innate, 0, 0 } }, + { "Process_isNormal", { pf_process_is_normal, 0, 0 } }, { "Process_resume", { pf_process_resume, 0, 0 } }, { "Process_sp", { pf_process_sp, 0, 0 } }, { "Process_suspend", { pf_process_suspend, 0, 0 } }, @@ -4544,8 +4418,11 @@ 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_findNextProcess:", { pf_system_find_next_process, 1, 1 } }, - { "System_findProcessById:", { pf_system_find_process_by_id, 1, 1 } }, + { "System_findFirstProcess", { moo_pf_system_find_first_process, 0, 0 } }, + { "System_findLastProcess", { moo_pf_system_find_last_process, 0, 0 } }, + { "System_findNextProcess:", { moo_pf_system_find_next_process, 1, 1 } }, + { "System_findPreviousProcess:", { moo_pf_system_find_previous_process, 1, 1 } }, + { "System_findProcessById:", { moo_pf_system_find_process_by_id, 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 } }, @@ -4560,7 +4437,7 @@ static pf_t pftab[] = { "System_getUint32", { moo_pf_system_get_uint32, 2, 2 } }, { "System_getUint64", { moo_pf_system_get_uint64, 2, 2 } }, { "System_getUint8", { moo_pf_system_get_uint8, 2, 2 } }, - { "System_halting", { pf_system_halting, 0, 0 } }, + { "System_halting", { moo_pf_system_halting, 0, 0 } }, { "System_log", { pf_system_log, 2, MA } }, { "System_malloc", { moo_pf_system_malloc, 1, 1 } }, { "System_malloc:", { moo_pf_system_malloc, 1, 1 } }, @@ -4576,7 +4453,7 @@ static pf_t pftab[] = { "System_putUint8", { moo_pf_system_put_uint8, 3, 3 } }, { "System_return:to:", { pf_system_return_value_to_context, 2, 2 } }, { "System_setSig:", { moo_pf_system_set_sig, 1, 1 } }, - { "System_toggleProcessSwitching:", { pf_system_toggle_process_switching, 1, 1 } }, + { "System_toggleProcessSwitching:", { moo_pf_system_toggle_process_switching, 1, 1 } }, { "_dump", { pf_dump, 0, MA } }, diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 5d425e0..db2d4a8 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -1645,6 +1645,14 @@ moo_pfrc_t moo_pf_responds_to (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); /* ========================================================================= */ /* pf-sys.c */ /* ========================================================================= */ +moo_pfrc_t moo_pf_system_toggle_process_switching (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_halting (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_find_process_by_id (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_find_first_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_find_last_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_find_previous_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); +moo_pfrc_t moo_pf_system_find_next_process (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); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index e0b8706..a5ff921 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -378,7 +378,7 @@ typedef enum moo_gcfin_t moo_gcfin_t; #define MOO_OBJ_FLAGS_PROC_NOT 0 /* not process */ #define MOO_OBJ_FLAGS_PROC_NORMAL 1 /* normal process spawned with a block sent newProcess: */ -#define MOO_OBJ_FLAGS_PROC_SYSTEM 2 /* internal process */ +#define MOO_OBJ_FLAGS_PROC_INNATE 2 /* internally created process */ #define MOO_OBJ_HEADER \ moo_oow_t _flags; \ diff --git a/moo/lib/pf-sys.c b/moo/lib/pf-sys.c index 8f4bb65..b049812 100644 --- a/moo/lib/pf-sys.c +++ b/moo/lib/pf-sys.c @@ -26,6 +26,217 @@ #include "moo-prv.h" + +/* ------------------------------------------------------------------------------------- */ +moo_pfrc_t moo_pf_system_toggle_process_switching (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t v; + int oldnps; + + oldnps = moo->no_proc_switch; + + v = MOO_STACK_GETARG(moo, nargs, 0); + if (v == moo->_false) + { + /* disable process switching */ + moo->no_proc_switch = 1; + } + else + { + /* enable process switching */ + moo->no_proc_switch = 0; + } + + MOO_STACK_SETRET (moo, nargs, (oldnps? moo->_false: moo->_true)); + return MOO_PF_SUCCESS; +} + +moo_pfrc_t moo_pf_system_halting (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_evtcb_t* cb; + for (cb = moo->evtcb_list; cb; cb = cb->next) + { + if (cb->halting) cb->halting (moo); + } + MOO_STACK_SETRETTORCV (moo, nargs); + return MOO_PF_SUCCESS; +} + +moo_pfrc_t moo_pf_system_find_process_by_id (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t /*rcv,*/ id; + + /*rcv = MOO_STACK_GETRCV(moo, nargs);*/ + id = MOO_STACK_GETARG(moo, nargs, 0); + + /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ + + if (MOO_OOP_IS_SMOOI(id)) + { + moo_ooi_t index = MOO_OOP_TO_SMOOI(id); + if (index >= 0) + { + if (MOO_CLASSOF(moo, moo->proc_map[index]) == moo->_process) + { + MOO_STACK_SETRET (moo, nargs, moo->proc_map[index]); + return MOO_PF_SUCCESS; + } + + /* it must be in a free list since the pid slot is not allocated. see alloc_pid() and free_pid() */ + MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->proc_map[index])); + } + } + + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + return MOO_PF_FAILURE; +} + + +static MOO_INLINE moo_oop_t __find_adjacent_process_by_id_noseterr (moo_t* moo, moo_ooi_t index, int find_next) +{ + if (find_next) + { + moo_ooi_t end_index; + MOO_ASSERT (moo, moo->proc_map_capa <= MOO_SMOOI_MAX); + + end_index = moo->proc_map_capa - 1; + if (index < -1) index = -1; + + /* TOOD: enhance alloc_pid() and free_pid() to maintain the hightest pid number so that this loop can stop before reaching proc_map_capa */ + while (index < end_index) + { + /* note the free slot contains a small integer which indicate the next slot index in proc_map. + * if the slot it taken, it should point to a process object. read the comment at end of this loop. */ + moo_oop_t tmp; + + tmp = moo->proc_map[++index]; + if (MOO_CLASSOF(moo, tmp) == moo->_process) return tmp; + + /* it must be in a free list since the pid slot is not allocated. see alloc_pid() and free_pid() */ + MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(tmp)); + } + } + else + { + /* find the previous one */ + + if (index > moo->proc_map_capa || index <= -1) index = moo->proc_map_capa; + while (index > 0) + { + moo_oop_t tmp; + + tmp = moo->proc_map[--index]; + if (MOO_CLASSOF(moo, tmp) == moo->_process) return tmp; + + /* it must be in a free list since the pid slot is not allocated. see alloc_pid() and free_pid() */ + MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(tmp)); + } + } + + return MOO_NULL; +} + +moo_pfrc_t moo_pf_system_find_first_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t tmp; + + tmp = __find_adjacent_process_by_id_noseterr(moo, -1, 1); + if (tmp) + { + MOO_STACK_SETRET (moo, nargs, tmp); + return MOO_PF_SUCCESS; + } + + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + return MOO_PF_FAILURE; +} + +moo_pfrc_t moo_pf_system_find_last_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t tmp; + + tmp = __find_adjacent_process_by_id_noseterr(moo, moo->proc_map_capa, 0); + if (tmp) + { + MOO_STACK_SETRET (moo, nargs, tmp); + return MOO_PF_SUCCESS; + } + + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + return MOO_PF_FAILURE; +} + +moo_pfrc_t moo_pf_system_find_previous_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t /*rcv,*/ id; + + /*rcv = MOO_STACK_GETRCV(moo, nargs);*/ + id = MOO_STACK_GETARG(moo, nargs, 0); + + /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ + + if (id == moo->_nil) + { + id = MOO_SMOOI_TO_OOP(-1); + } + else if (MOO_CLASSOF(moo, id) == moo->_process) + { + /* the argument is a process object */ + id = ((moo_oop_process_t)id)->id; + } + + if (MOO_OOP_IS_SMOOI(id)) + { + moo_oop_t tmp; + + tmp = __find_adjacent_process_by_id_noseterr(moo, MOO_OOP_TO_SMOOI(id), 0); + if (tmp) + { + MOO_STACK_SETRET (moo, nargs, tmp); + return MOO_PF_SUCCESS; + } + } + + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + return MOO_PF_FAILURE; +} + +moo_pfrc_t moo_pf_system_find_next_process (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t /*rcv,*/ id; + + /*rcv = MOO_STACK_GETRCV(moo, nargs);*/ + id = MOO_STACK_GETARG(moo, nargs, 0); + + /*MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor);*/ + + if (id == moo->_nil) + { + id = MOO_SMOOI_TO_OOP(-1); + } + else if (MOO_CLASSOF(moo, id) == moo->_process) + { + /* the argument is a process object */ + id = ((moo_oop_process_t)id)->id; + } + + if (MOO_OOP_IS_SMOOI(id)) + { + moo_oop_t tmp; + + tmp = __find_adjacent_process_by_id_noseterr(moo, MOO_OOP_TO_SMOOI(id), 1); + if (tmp) + { + MOO_STACK_SETRET (moo, nargs, tmp); + return MOO_PF_SUCCESS; + } + } + + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + return MOO_PF_FAILURE; +} +/* ------------------------------------------------------------------------------------- */ + moo_pfrc_t moo_pf_system_collect_garbage (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) { moo_gc (moo);