diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 60bb6ff..860fac5 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -1,13 +1,9 @@ class(#pointer,#final,#limited) Process(Object) { - var initial_context, current_context, state, sp, prev, next, sem, perr, perrmsg. - - method prev { ^self.prev } - method next { ^self.next } - - method next: process { self.next := process } - method prev: process { self.prev := process } + var(#get) initialContext, currentContext, id, state. + var(#get) sp, ps_prev, ps_next, sem_wait_prev, sem_wait_next. + var sem, perr, perrmsg. method primError { ^self.perr } method primErrorMessage { ^self.perrmsg } @@ -19,7 +15,7 @@ class(#pointer,#final,#limited) Process(Object) method terminate { -##search from the top context of the process down to intial_context and find ensure blocks and execute them. + ## search from the top context of the process down to intial_context and find ensure blocks and execute them. ## if a different process calls 'terminate' on a process, ## the ensureblock is not executed in the context of the ## process being terminated, but in the context of terminatig process. @@ -44,19 +40,9 @@ class(#pointer,#final,#limited) Process(Object) ##if (Processor activeProcess ~~ self) { self _suspend }. if (thisProcess ~~ self) { self _suspend }. - self.current_context unwindTo: self.initial_context return: nil. + self.currentContext unwindTo: self.initialContext return: nil. ^self _terminate } - - method sp - { - ^self.sp. - } - - method initialContext - { - ^self.initial_context - } } class Semaphore(Object) @@ -304,8 +290,11 @@ class SemaphoreHeap(Object) class(#final,#limited) ProcessScheduler(Object) { - var(#get) tally, active. - var runnable_head, runnable_tail (*, sem_heap*). + var(#get) active. + var(#get) runnable_count. + var runnable_head, runnable_tail. + var(#get) suspended_count. + var suspended_head, suspended_tail. method activeProcess { @@ -325,8 +314,8 @@ class(#final,#limited) ProcessScheduler(Object) self.tally := 1. ] ifFalse: [ - process next: self.head. - self.head prev: process. + process ps_next: self.head. + self.head ps_prev: process. self.head := process. self.tally := self.tally + 1. ]. diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index 5b2145b..ff9c0a6 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -37,26 +37,33 @@ class System(Apex) gc := false. while (true) { -## TODO: exit from this loop when there are no other processes running except this finalizer process + while ((tmp := self _popCollectable) notError) { ## TODO: Do i have to protected this in an exception handler??? if (tmp respondsTo: #finalize) { tmp finalize }. }. - (* - if (Processor tally == 1 and: [Processor active == thisProcess]) + ##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? { - if (gc) { break }. + ## 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 + }. self collectGarbage. - 'GC GC GC GC' dump. - Processor tally dump. gc := true. - }.*) + } + else + { + gc := false. + }. ##System logNl: 'gc_waiting....'. - ##Processor sleepFor: 1. ## TODO: wait on semaphore instead.. + Processor sleepFor: 1. ## TODO: wait on semaphore instead.. } } diff --git a/moo/lib/Makefile.am b/moo/lib/Makefile.am index b019f54..ccea2aa 100644 --- a/moo/lib/Makefile.am +++ b/moo/lib/Makefile.am @@ -58,7 +58,6 @@ libmoo_la_SOURCES = \ heap.c \ moo.c \ obj.c \ - proc.c \ rbt.c \ sym.c \ utf8.c \ diff --git a/moo/lib/Makefile.in b/moo/lib/Makefile.in index 096a43b..dfcc33f 100644 --- a/moo/lib/Makefile.in +++ b/moo/lib/Makefile.in @@ -159,8 +159,8 @@ am_libmoo_la_OBJECTS = libmoo_la-bigint.lo libmoo_la-comp.lo \ libmoo_la-debug.lo libmoo_la-decode.lo libmoo_la-dic.lo \ libmoo_la-err.lo libmoo_la-exec.lo libmoo_la-logfmt.lo \ libmoo_la-gc.lo libmoo_la-heap.lo libmoo_la-moo.lo \ - libmoo_la-obj.lo libmoo_la-proc.lo libmoo_la-rbt.lo \ - libmoo_la-sym.lo libmoo_la-utf8.lo libmoo_la-utl.lo + libmoo_la-obj.lo libmoo_la-rbt.lo libmoo_la-sym.lo \ + libmoo_la-utf8.lo libmoo_la-utl.lo libmoo_la_OBJECTS = $(am_libmoo_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -443,7 +443,6 @@ libmoo_la_SOURCES = \ heap.c \ moo.c \ obj.c \ - proc.c \ rbt.c \ sym.c \ utf8.c \ @@ -619,7 +618,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-logfmt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-moo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-obj.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-proc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-rbt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-sym.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-utf8.Plo@am__quote@ @@ -734,13 +732,6 @@ libmoo_la-obj.lo: obj.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmoo_la-obj.lo `test -f 'obj.c' || echo '$(srcdir)/'`obj.c -libmoo_la-proc.lo: proc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmoo_la-proc.lo -MD -MP -MF $(DEPDIR)/libmoo_la-proc.Tpo -c -o libmoo_la-proc.lo `test -f 'proc.c' || echo '$(srcdir)/'`proc.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmoo_la-proc.Tpo $(DEPDIR)/libmoo_la-proc.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='proc.c' object='libmoo_la-proc.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmoo_la-proc.lo `test -f 'proc.c' || echo '$(srcdir)/'`proc.c - libmoo_la-rbt.lo: rbt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmoo_la-rbt.lo -MD -MP -MF $(DEPDIR)/libmoo_la-rbt.Tpo -c -o libmoo_la-rbt.lo `test -f 'rbt.c' || echo '$(srcdir)/'`rbt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmoo_la-rbt.Tpo $(DEPDIR)/libmoo_la-rbt.Plo diff --git a/moo/lib/exec.c b/moo/lib/exec.c index c42c4ff..5927b8b 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -153,6 +153,7 @@ 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_pushtmp (moo, (moo_oop_t*)&c); proc = (moo_oop_process_t)moo_instantiate (moo, moo->_process, MOO_NULL, moo->option.dfl_procstk_size); @@ -160,6 +161,14 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c) if (!proc) return MOO_NULL; proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); + +{ + static moo_ooi_t pid = 1; +/* TODO: chage this pid allocation scheme... */ + proc->id = MOO_SMOOI_TO_OOP(pid); + pid++; +} + proc->initial_context = c; proc->current_context = c; proc->sp = MOO_SMOOI_TO_OOP(-1); @@ -213,7 +222,7 @@ static void switch_to_process (moo_t* moo, moo_oop_process_t proc, int new_state /* the new process must be in the runnable state */ MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE) || - proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING)); + proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_WAITING)); sleep_active_process (moo, new_state_for_old_active); wake_new_process (moo, proc); @@ -223,12 +232,12 @@ static void switch_to_process (moo_t* moo, moo_oop_process_t proc, int new_state static MOO_INLINE moo_oop_process_t find_next_runnable_process (moo_t* moo) { - moo_oop_process_t npr; + moo_oop_process_t nrp; MOO_ASSERT (moo, moo->processor->active->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING)); - npr = moo->processor->active->next; - if ((moo_oop_t)npr == moo->_nil) npr = moo->processor->runnable_head; - return npr; + nrp = moo->processor->active->ps.next; + if ((moo_oop_t)nrp == moo->_nil) nrp = moo->processor->runnable.first; + return nrp; } static MOO_INLINE void switch_to_next_runnable_process (moo_t* moo) @@ -243,17 +252,17 @@ static MOO_INLINE int chain_into_processor (moo_t* moo, moo_oop_process_t proc) { /* the process is not scheduled at all. * link it to the processor's process list. */ - moo_ooi_t tally; + moo_ooi_t runnable_count; - MOO_ASSERT (moo, (moo_oop_t)proc->prev == moo->_nil); - MOO_ASSERT (moo, (moo_oop_t)proc->next == moo->_nil); + /*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)); - tally = MOO_OOP_TO_SMOOI(moo->processor->tally); + runnable_count = MOO_OOP_TO_SMOOI(moo->processor->runnable.count); - MOO_ASSERT (moo, tally >= 0); - if (tally >= MOO_SMOOI_MAX) + 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"); @@ -262,48 +271,64 @@ static MOO_INLINE int chain_into_processor (moo_t* moo, moo_oop_process_t proc) return -1; } - /* append to the runnable list */ - if (tally > 0) + if ((moo_oop_t)proc->ps.next != moo->_nil || (moo_oop_t)proc->ps.prev != moo->_nil || proc == moo->processor->suspended.first) { - proc->prev = moo->processor->runnable_tail; - moo->processor->runnable_tail->next = proc; - } - else - { - moo->processor->runnable_head = proc; - } - moo->processor->runnable_tail = proc; + moo_ooi_t suspended_count; - tally++; - moo->processor->tally = MOO_SMOOI_TO_OOP(tally); + 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); + + 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) { - moo_ooi_t tally; + moo_ooi_t runnable_count; /* the processor's process chain must be composed of running/runnable * processes only */ MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING) || - proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); + proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); - tally = MOO_OOP_TO_SMOOI(moo->processor->tally); - MOO_ASSERT (moo, tally > 0); + runnable_count = MOO_OOP_TO_SMOOI(moo->processor->runnable.count); + MOO_ASSERT (moo, runnable_count > 0); - if ((moo_oop_t)proc->prev != moo->_nil) proc->prev->next = proc->next; - else moo->processor->runnable_head = proc->next; - if ((moo_oop_t)proc->next != moo->_nil) proc->next->prev = proc->prev; - else moo->processor->runnable_tail = proc->prev; + MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->runnable, proc, ps); + + if (state != PROC_STATE_TERMINATED) + { + moo_ooi_t suspended_count; + + 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); + } + else + { + proc->ps.prev = (moo_oop_process_t)moo->_nil; + proc->ps.next = (moo_oop_process_t)moo->_nil; + } - proc->prev = (moo_oop_process_t)moo->_nil; - proc->next = (moo_oop_process_t)moo->_nil; proc->state = MOO_SMOOI_TO_OOP(state); - tally--; - if (tally == 0) moo->processor->active = moo->nil_process; - moo->processor->tally = MOO_SMOOI_TO_OOP(tally); + runnable_count--; + if (runnable_count == 0) moo->processor->active = moo->nil_process; + moo->processor->runnable.count = MOO_SMOOI_TO_OOP(runnable_count); } static MOO_INLINE void chain_into_semaphore (moo_t* moo, moo_oop_process_t proc, moo_oop_semaphore_t sem) @@ -311,20 +336,10 @@ static MOO_INLINE void chain_into_semaphore (moo_t* moo, moo_oop_process_t proc, /* append a process to the process list of a semaphore*/ MOO_ASSERT (moo, (moo_oop_t)proc->sem == moo->_nil); - MOO_ASSERT (moo, (moo_oop_t)proc->prev == moo->_nil); - MOO_ASSERT (moo, (moo_oop_t)proc->next == moo->_nil); + MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.prev == moo->_nil); + MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.next == moo->_nil); - if ((moo_oop_t)sem->waiting_head == moo->_nil) - { - MOO_ASSERT (moo, (moo_oop_t)sem->waiting_tail == moo->_nil); - sem->waiting_head = proc; - } - else - { - proc->prev = sem->waiting_tail; - sem->waiting_tail->next = proc; - } - sem->waiting_tail = proc; + MOO_APPEND_TO_OOP_LIST (moo, &sem->waiting, moo_oop_process_t, proc, sem_wait); proc->sem = sem; } @@ -336,14 +351,10 @@ static MOO_INLINE void unchain_from_semaphore (moo_t* moo, moo_oop_process_t pro MOO_ASSERT (moo, (moo_oop_t)proc->sem != moo->_nil); sem = proc->sem; - if ((moo_oop_t)proc->prev != moo->_nil) proc->prev->next = proc->next; - else sem->waiting_head = proc->next; - if ((moo_oop_t)proc->next != moo->_nil) proc->next->prev = proc->prev; - else sem->waiting_tail = proc->prev; - - proc->prev = (moo_oop_process_t)moo->_nil; - proc->next = (moo_oop_process_t)moo->_nil; + MOO_DELETE_FROM_OOP_LIST (moo, &sem->waiting, proc, sem_wait); + proc->sem_wait.prev = (moo_oop_process_t)moo->_nil; + proc->sem_wait.next = (moo_oop_process_t)moo->_nil; proc->sem = (moo_oop_semaphore_t)moo->_nil; } @@ -415,9 +426,9 @@ static void resume_process (moo_t* moo, moo_oop_process_t proc) { if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED)) { - /* SUSPENED ---> RUNNING */ - MOO_ASSERT (moo, (moo_oop_t)proc->prev == moo->_nil); - MOO_ASSERT (moo, (moo_oop_t)proc->next == moo->_nil); + /* SUSPENDED ---> RUNNING */ + /*MOO_ASSERT (moo, (moo_oop_t)proc->ps.prev == moo->_nil); + 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); @@ -479,7 +490,7 @@ static void suspend_process (moo_t* moo, moo_oop_process_t proc) * running/runnable process. so calling switch_to_process() * which expects the active process to be valid is safe */ MOO_ASSERT (moo, moo->processor->active != moo->nil_process); - switch_to_process (moo, nrp, PROC_STATE_SUSPENDED); + switch_to_process (moo, nrp, PROC_STATE_SUSPENDED); } } else @@ -543,7 +554,7 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem) moo_oop_process_t proc; moo_ooi_t count; - if ((moo_oop_t)sem->waiting_head == moo->_nil) + if ((moo_oop_t)sem->waiting.first == moo->_nil) { /* no process is waiting on this semaphore */ count = MOO_OOP_TO_SMOOI(sem->count); @@ -555,7 +566,7 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem) } else { - proc = sem->waiting_head; + proc = sem->waiting.first; /* [NOTE] no GC must occur as 'proc' isn't protected with moo_pushtmp(). */ @@ -594,7 +605,7 @@ static void await_semaphore (moo_t* moo, moo_oop_semaphore_t sem) /* link the suspended process to the semaphore's process list */ chain_into_semaphore (moo, proc, sem); - MOO_ASSERT (moo, sem->waiting_tail == proc); + MOO_ASSERT (moo, sem->waiting.last == proc); if (MOO_OOP_TO_SMOOI(sem->io_index) >= 0) moo->sem_io_wait_count++; @@ -797,7 +808,6 @@ static int add_to_sem_io (moo_t* moo, moo_oop_semaphore_t sem) moo->sem_io_count--; } -MOO_DEBUG3 (moo, "ADDED TO SEM IO => sem_io_count %d handle %d index %d\n", (int)moo->sem_io_count, (int)MOO_OOP_TO_SMOOI(sem->io_handle), (int)MOO_OOP_TO_SMOOI(sem->io_index)); return n; } @@ -887,7 +897,7 @@ static void signal_io_semaphore (moo_t* moo, moo_ooi_t mask, void* ctx) * 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_head); + MOO_ASSERT (moo, proc == moo->processor->runnable.first); wake_new_process (moo, proc); /* switch to running */ moo->proc_switched = 1; @@ -906,7 +916,7 @@ static moo_oop_process_t start_initial_process (moo_t* moo, moo_oop_context_t c) moo_oop_process_t proc; /* there must be no active process when this function is called */ - MOO_ASSERT (moo, moo->processor->tally == MOO_SMOOI_TO_OOP(0)); + 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); @@ -1253,7 +1263,7 @@ TODO: overcome this problem - accept parameters.... * is not NULL. at this poinst, moo->processor should point to * an instance of ProcessScheduler. */ MOO_ASSERT (moo, (moo_oop_t)moo->processor != moo->_nil); - MOO_ASSERT (moo, moo->processor->tally == MOO_SMOOI_TO_OOP(0)); + MOO_ASSERT (moo, moo->processor->runnable.count == MOO_SMOOI_TO_OOP(0)); /* start_initial_process() calls the SWITCH_ACTIVE_CONTEXT() macro. * the macro assumes a non-null value in moo->active_context. @@ -2075,13 +2085,7 @@ static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_ooi_t nargs) moo_oop_process_t proc; moo_ooi_t num_first_arg_elems = 0; - if (nargs > 1) - { - /* too many arguments */ -/* TODO: proper error handling */ - moo_seterrnum (moo, MOO_EINVAL); - return MOO_PF_FAILURE; - } + MOO_ASSERT (moo, nargs <= 1); if (nargs == 1) { @@ -2121,7 +2125,7 @@ static moo_pfrc_t pf_block_new_process (moo_t* moo, moo_ooi_t nargs) blkctx->sender = (moo_oop_context_t)moo->_nil; proc = make_process (moo, blkctx); - if (!proc) return MOO_PF_HARD_FAILURE; /* hard failure */ /* TOOD: can't this be treated as a soft failure? */ + if (!proc) return MOO_PF_HARD_FAILURE; /* hard failure */ /* TOOD: can't this be treated as a soft failure? throw an exception instead?? */ /* __block_value() has popped all arguments and the receiver. * PUSH the return value instead of changing the stack top */ @@ -2201,24 +2205,6 @@ static moo_pfrc_t pf_process_suspend (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } -static moo_pfrc_t pf_process_primerr_msg (moo_t* moo, moo_ooi_t nargs) -{ - moo_oop_t rcv, msg; - - rcv = MOO_STACK_GETRCV(moo, nargs); - if (MOO_CLASSOF(moo,rcv) != moo->_process) - { - moo_seterrnum (moo, MOO_EMSGRCV); - return MOO_PF_FAILURE; - } - - msg = moo_makestring (moo, (moo_ooch_t*)MOO_OBJ_GET_TRAILER_BYTE(rcv), moo_countoocstr((moo_ooch_t*)MOO_OBJ_GET_TRAILER_BYTE(rcv))); - if (!msg) return MOO_PF_FAILURE; - - MOO_STACK_SETRET (moo, nargs, msg); - return MOO_PF_SUCCESS; -} - /* ------------------------------------------------------------------ */ static moo_pfrc_t pf_semaphore_signal (moo_t* moo, moo_ooi_t nargs) { @@ -4477,7 +4463,7 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) * 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_head); + MOO_ASSERT (moo, proc == moo->processor->runnable.first); wake_new_process (moo, proc); /* switch to running */ moo->proc_switched = 1; @@ -4541,7 +4527,7 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) if (moo->processor->active == moo->nil_process) { /* no more waiting semaphore and no more process */ - MOO_ASSERT (moo, moo->processor->tally = MOO_SMOOI_TO_OOP(0)); + MOO_ASSERT (moo, moo->processor->runnable.count = MOO_SMOOI_TO_OOP(0)); MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No more runnable process\n"); return 0; } diff --git a/moo/lib/gc.c b/moo/lib/gc.c index cbf6a53..d198216 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -290,8 +290,9 @@ static int ignite_2 (moo_t* moo) tmp = (moo_oop_t)moo_instantiate (moo, moo->_process_scheduler, MOO_NULL, 0); if (!tmp) return -1; moo->processor = (moo_oop_process_scheduler_t)tmp; - moo->processor->tally = MOO_SMOOI_TO_OOP(0); moo->processor->active = moo->nil_process; + moo->processor->runnable.count = MOO_SMOOI_TO_OOP(0); + moo->processor->suspended.count = MOO_SMOOI_TO_OOP(0); return 0; } diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 27f1dbf..cca33a3 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -66,7 +66,7 @@ #define MOO_LIMIT_OBJ_SIZE -/* TODO: delete these header inclusion lines */ +/* TODO: delete these header inclusion lines after having revised MOO_MEMXXX macros. */ #include #if defined(__has_builtin) diff --git a/moo/lib/moo-utl.h b/moo/lib/moo-utl.h index b4082b9..3a741f6 100644 --- a/moo/lib/moo-utl.h +++ b/moo/lib/moo-utl.h @@ -57,6 +57,41 @@ } while(0) + + + + +#define MOO_APPEND_TO_OOP_LIST(moo, list, node_type, node, _link) do { \ + (node)->_link.next = (node_type)(moo)->_nil; \ + (node)->_link.prev = (list)->last; \ + if ((moo_oop_t)(list)->last != (moo)->_nil) (list)->last->_link.next = (node); \ + else (list)->first = (node); \ + (list)->last = (node); \ +} while(0) + +#define MOO_PREPPEND_TO_OOP_LIST(moo, list, node_type, node, _link) do { \ + (node)->_link.prev = (node_type)(moo)->_nil; \ + (node)->_link.next = (list)->first; \ + if ((moo_oop_t)(list)->first != (moo)->_nil) (list)->first->_link.prev = (node); \ + else (list)->last = (node); \ + (list)->first = (node); \ +} while(0) + +#define MOO_DELETE_FROM_OOP_LIST(moo, list, node, _link) do { \ + if ((moo_oop_t)(node)->_link.prev != (moo)->_nil) (node)->_link.prev->_link.next = (node)->_link.next; \ + else (list)->first = (node)->_link.next; \ + if ((moo_oop_t)(node)->_link.next != (moo)->_nil) (node)->_link.next->_link.prev = (node)->_link.prev; \ + else (list)->last = (node)->_link.prev; \ +} while(0) + +/* +#define MOO_CLEANUP_FROM_OOP_LIST(moo, list, node, _link) do { \ + MOO_DELETE_FROM_OOP_LIST (moo, list, node, _link); \ + (node)->link.prev = (node_type)(moo)->_nil; \ + (node)->link.next = (node_type)(moo)->_nil; \ +} while(0); +*/ + #if defined(__cplusplus) extern "C" { #endif diff --git a/moo/lib/moo.h b/moo/lib/moo.h index d73c872..8e88ed5 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -744,7 +744,7 @@ struct moo_context_t }; -#define MOO_PROCESS_NAMED_INSTVARS 9 +#define MOO_PROCESS_NAMED_INSTVARS 12 typedef struct moo_process_t moo_process_t; typedef struct moo_process_t* moo_oop_process_t; @@ -758,11 +758,21 @@ struct moo_process_t moo_oop_context_t initial_context; moo_oop_context_t current_context; + moo_oop_t id; /* SmallInteger */ moo_oop_t state; /* SmallInteger */ moo_oop_t sp; /* stack pointer. SmallInteger */ - moo_oop_process_t prev; - moo_oop_process_t next; + struct + { + moo_oop_process_t prev; + moo_oop_process_t next; + } ps; /* links to use with the process scheduler */ + + struct + { + moo_oop_process_t prev; + moo_oop_process_t next; + } sem_wait; /* links to use with a semaphore */ moo_oop_semaphore_t sem; moo_oop_t perr; /* last error set by a primitive function */ @@ -782,8 +792,12 @@ struct moo_semaphore_t MOO_OBJ_HEADER; moo_oop_t count; /* SmallInteger */ - moo_oop_process_t waiting_head; - moo_oop_process_t waiting_tail; + + struct + { + moo_oop_process_t first; + moo_oop_process_t last; + } waiting; /* list of processes waiting on this semaphore */ moo_oop_t heap_index; /* index to the heap */ moo_oop_t heap_ftime_sec; /* firing time */ @@ -794,17 +808,27 @@ struct moo_semaphore_t moo_oop_t io_mask; /* SmallInteger */ }; -#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 4 +#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 7 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_t tally; /* SmallInteger, the number of runnable processes */ moo_oop_process_t active; /* pointer to an active process in the runnable process list */ - moo_oop_process_t runnable_head; /* runnable process list */ - moo_oop_process_t runnable_tail; /* runnable process list */ - /*moo_oop_t sempq;*/ /* SemaphoreHeap */ + + struct + { + moo_oop_t count; /* SmallInteger, the number of runnable/running processes */ + moo_oop_process_t first; + moo_oop_process_t last; + } runnable; /* runnable process list */ + + struct + { + moo_oop_t count; /* SmallInteger */ + moo_oop_process_t first; + moo_oop_process_t last; + } suspended; }; /** diff --git a/moo/lib/proc.c b/moo/lib/proc.c deleted file mode 100644 index 3ecf1ea..0000000 --- a/moo/lib/proc.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * $Id$ - * - Copyright (c) 2014-2017 Chung, Hyung-Hwan. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "moo-prv.h" - -moo_oop_process_t moo_addnewproc (moo_t* moo) -{ - moo_oop_process_t proc; - - proc = (moo_oop_process_t)moo_instantiate (moo, moo->_process, MOO_NULL, moo->option.dfl_procstk_size); - if (!proc) return MOO_NULL; - - proc->state = MOO_SMOOI_TO_OOP(0); - - MOO_ASSERT (moo, MOO_OBJ_GET_SIZE(proc) == MOO_PROCESS_NAMED_INSTVARS + moo->option.dfl_procstk_size); - return proc; -} - -void moo_schedproc (moo_t* moo, moo_oop_process_t proc) -{ - /* TODO: if scheduled, don't add */ - /*proc->next = moo->_active_process; - proc->_active_process = proc;*/ -} - -void moo_unschedproc (moo_t* moo, moo_oop_process_t proc) -{ -}