changed process management code for gc finalization support. incompelete yet

This commit is contained in:
hyunghwan.chung 2017-07-24 13:25:25 +00:00
parent 7412ae0dac
commit 447012b214
10 changed files with 182 additions and 201 deletions

View File

@ -1,13 +1,9 @@
class(#pointer,#final,#limited) Process(Object) class(#pointer,#final,#limited) Process(Object)
{ {
var initial_context, current_context, state, sp, prev, next, sem, perr, perrmsg. var(#get) initialContext, currentContext, id, state.
var(#get) sp, ps_prev, ps_next, sem_wait_prev, sem_wait_next.
method prev { ^self.prev } var sem, perr, perrmsg.
method next { ^self.next }
method next: process { self.next := process }
method prev: process { self.prev := process }
method primError { ^self.perr } method primError { ^self.perr }
method primErrorMessage { ^self.perrmsg } method primErrorMessage { ^self.perrmsg }
@ -19,7 +15,7 @@ class(#pointer,#final,#limited) Process(Object)
method terminate 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, ## if a different process calls 'terminate' on a process,
## the ensureblock is not executed in the context of the ## the ensureblock is not executed in the context of the
## process being terminated, but in the context of terminatig process. ## 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 (Processor activeProcess ~~ self) { self _suspend }.
if (thisProcess ~~ 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 ^self _terminate
} }
method sp
{
^self.sp.
}
method initialContext
{
^self.initial_context
}
} }
class Semaphore(Object) class Semaphore(Object)
@ -304,8 +290,11 @@ class SemaphoreHeap(Object)
class(#final,#limited) ProcessScheduler(Object) class(#final,#limited) ProcessScheduler(Object)
{ {
var(#get) tally, active. var(#get) active.
var runnable_head, runnable_tail (*, sem_heap*). var(#get) runnable_count.
var runnable_head, runnable_tail.
var(#get) suspended_count.
var suspended_head, suspended_tail.
method activeProcess method activeProcess
{ {
@ -325,8 +314,8 @@ class(#final,#limited) ProcessScheduler(Object)
self.tally := 1. self.tally := 1.
] ]
ifFalse: [ ifFalse: [
process next: self.head. process ps_next: self.head.
self.head prev: process. self.head ps_prev: process.
self.head := process. self.head := process.
self.tally := self.tally + 1. self.tally := self.tally + 1.
]. ].

View File

@ -37,26 +37,33 @@ class System(Apex)
gc := false. gc := false.
while (true) while (true)
{ {
## TODO: exit from this loop when there are no other processes running except this finalizer process
while ((tmp := self _popCollectable) notError) while ((tmp := self _popCollectable) notError)
{ {
## TODO: Do i have to protected this in an exception handler??? ## TODO: Do i have to protected this in an exception handler???
if (tmp respondsTo: #finalize) { tmp finalize }. if (tmp respondsTo: #finalize) { tmp finalize }.
}. }.
(* ##if (Processor runnable_count == 1 and: [Processor active == thisProcess])
if (Processor tally == 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. self collectGarbage.
'GC GC GC GC' dump.
Processor tally dump.
gc := true. gc := true.
}.*) }
else
{
gc := false.
}.
##System logNl: 'gc_waiting....'. ##System logNl: 'gc_waiting....'.
##Processor sleepFor: 1. ## TODO: wait on semaphore instead.. Processor sleepFor: 1. ## TODO: wait on semaphore instead..
} }
} }

View File

@ -58,7 +58,6 @@ libmoo_la_SOURCES = \
heap.c \ heap.c \
moo.c \ moo.c \
obj.c \ obj.c \
proc.c \
rbt.c \ rbt.c \
sym.c \ sym.c \
utf8.c \ utf8.c \

View File

@ -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-debug.lo libmoo_la-decode.lo libmoo_la-dic.lo \
libmoo_la-err.lo libmoo_la-exec.lo libmoo_la-logfmt.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-gc.lo libmoo_la-heap.lo libmoo_la-moo.lo \
libmoo_la-obj.lo libmoo_la-proc.lo libmoo_la-rbt.lo \ libmoo_la-obj.lo libmoo_la-rbt.lo libmoo_la-sym.lo \
libmoo_la-sym.lo libmoo_la-utf8.lo libmoo_la-utl.lo libmoo_la-utf8.lo libmoo_la-utl.lo
libmoo_la_OBJECTS = $(am_libmoo_la_OBJECTS) libmoo_la_OBJECTS = $(am_libmoo_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -443,7 +443,6 @@ libmoo_la_SOURCES = \
heap.c \ heap.c \
moo.c \ moo.c \
obj.c \ obj.c \
proc.c \
rbt.c \ rbt.c \
sym.c \ sym.c \
utf8.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-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-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-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-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-sym.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_la-utf8.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@ @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 @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 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_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 @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmoo_la-rbt.Tpo $(DEPDIR)/libmoo_la-rbt.Plo

View File

@ -154,12 +154,21 @@ static moo_oop_process_t make_process (moo_t* moo, moo_oop_context_t c)
{ {
moo_oop_process_t proc; moo_oop_process_t proc;
moo_pushtmp (moo, (moo_oop_t*)&c); moo_pushtmp (moo, (moo_oop_t*)&c);
proc = (moo_oop_process_t)moo_instantiate (moo, moo->_process, MOO_NULL, moo->option.dfl_procstk_size); proc = (moo_oop_process_t)moo_instantiate (moo, moo->_process, MOO_NULL, moo->option.dfl_procstk_size);
moo_poptmp (moo); moo_poptmp (moo);
if (!proc) return MOO_NULL; if (!proc) return MOO_NULL;
proc->state = MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED); 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->initial_context = c;
proc->current_context = c; proc->current_context = c;
proc->sp = MOO_SMOOI_TO_OOP(-1); 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 */ /* the new process must be in the runnable state */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE) || 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); sleep_active_process (moo, new_state_for_old_active);
wake_new_process (moo, proc); 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) 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)); MOO_ASSERT (moo, moo->processor->active->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING));
npr = moo->processor->active->next; nrp = moo->processor->active->ps.next;
if ((moo_oop_t)npr == moo->_nil) npr = moo->processor->runnable_head; if ((moo_oop_t)nrp == moo->_nil) nrp = moo->processor->runnable.first;
return npr; return nrp;
} }
static MOO_INLINE void switch_to_next_runnable_process (moo_t* moo) 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. /* the process is not scheduled at all.
* link it to the processor's process list. */ * 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->ps.prev == moo->_nil);
MOO_ASSERT (moo, (moo_oop_t)proc->next == 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)); 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); MOO_ASSERT (moo, runnable_count >= 0);
if (tally >= MOO_SMOOI_MAX) if (runnable_count >= MOO_SMOOI_MAX)
{ {
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Processor - too many processes\n"); 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; return -1;
} }
/* append to the runnable list */ if ((moo_oop_t)proc->ps.next != moo->_nil || (moo_oop_t)proc->ps.prev != moo->_nil || proc == moo->processor->suspended.first)
if (tally > 0)
{ {
proc->prev = moo->processor->runnable_tail; moo_ooi_t suspended_count;
moo->processor->runnable_tail->next = proc;
}
else
{
moo->processor->runnable_head = proc;
}
moo->processor->runnable_tail = proc;
tally++; suspended_count = MOO_OOP_TO_SMOOI(moo->processor->suspended.count);
moo->processor->tally = MOO_SMOOI_TO_OOP(tally); 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; return 0;
} }
static MOO_INLINE void unchain_from_processor (moo_t* moo, moo_oop_process_t proc, int state) 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 /* the processor's process chain must be composed of running/runnable
* processes only */ * processes only */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNING) || 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); runnable_count = MOO_OOP_TO_SMOOI(moo->processor->runnable.count);
MOO_ASSERT (moo, tally > 0); MOO_ASSERT (moo, runnable_count > 0);
if ((moo_oop_t)proc->prev != moo->_nil) proc->prev->next = proc->next; MOO_DELETE_FROM_OOP_LIST (moo, &moo->processor->runnable, proc, ps);
else moo->processor->runnable_head = proc->next;
if ((moo_oop_t)proc->next != moo->_nil) proc->next->prev = proc->prev; if (state != PROC_STATE_TERMINATED)
else moo->processor->runnable_tail = proc->prev; {
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); proc->state = MOO_SMOOI_TO_OOP(state);
tally--; runnable_count--;
if (tally == 0) moo->processor->active = moo->nil_process; if (runnable_count == 0) moo->processor->active = moo->nil_process;
moo->processor->tally = MOO_SMOOI_TO_OOP(tally); 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) 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*/ /* 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->sem == moo->_nil);
MOO_ASSERT (moo, (moo_oop_t)proc->prev == moo->_nil); MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.prev == moo->_nil);
MOO_ASSERT (moo, (moo_oop_t)proc->next == moo->_nil); MOO_ASSERT (moo, (moo_oop_t)proc->sem_wait.next == moo->_nil);
if ((moo_oop_t)sem->waiting_head == moo->_nil) MOO_APPEND_TO_OOP_LIST (moo, &sem->waiting, moo_oop_process_t, proc, sem_wait);
{
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;
proc->sem = sem; 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); MOO_ASSERT (moo, (moo_oop_t)proc->sem != moo->_nil);
sem = proc->sem; sem = proc->sem;
if ((moo_oop_t)proc->prev != moo->_nil) proc->prev->next = proc->next; MOO_DELETE_FROM_OOP_LIST (moo, &sem->waiting, proc, sem_wait);
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;
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; 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)) if (proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_SUSPENDED))
{ {
/* SUSPENED ---> RUNNING */ /* SUSPENDED ---> RUNNING */
MOO_ASSERT (moo, (moo_oop_t)proc->prev == moo->_nil); /*MOO_ASSERT (moo, (moo_oop_t)proc->ps.prev == moo->_nil);
MOO_ASSERT (moo, (moo_oop_t)proc->next == moo->_nil); MOO_ASSERT (moo, (moo_oop_t)proc->ps.next == moo->_nil);*/
#if defined(MOO_DEBUG_VM_PROCESSOR) #if defined(MOO_DEBUG_VM_PROCESSOR)
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process %O SUSPENDED->RUNNING\n", proc); MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Processor - process %O SUSPENDED->RUNNING\n", proc);
@ -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_oop_process_t proc;
moo_ooi_t count; 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 */ /* no process is waiting on this semaphore */
count = MOO_OOP_TO_SMOOI(sem->count); 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 else
{ {
proc = sem->waiting_head; proc = sem->waiting.first;
/* [NOTE] no GC must occur as 'proc' isn't protected with moo_pushtmp(). */ /* [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 */ /* link the suspended process to the semaphore's process list */
chain_into_semaphore (moo, proc, sem); 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++; 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->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; 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 * switch_to_process() as there is no running
* process at this moment */ * process at this moment */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); 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 */ wake_new_process (moo, proc); /* switch to running */
moo->proc_switched = 1; 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; moo_oop_process_t proc;
/* there must be no active process when this function is called */ /* 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); MOO_ASSERT (moo, moo->processor->active == moo->nil_process);
proc = make_process (moo, c); 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 * is not NULL. at this poinst, moo->processor should point to
* an instance of ProcessScheduler. */ * an instance of ProcessScheduler. */
MOO_ASSERT (moo, (moo_oop_t)moo->processor != moo->_nil); 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. /* start_initial_process() calls the SWITCH_ACTIVE_CONTEXT() macro.
* the macro assumes a non-null value in moo->active_context. * 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_oop_process_t proc;
moo_ooi_t num_first_arg_elems = 0; moo_ooi_t num_first_arg_elems = 0;
if (nargs > 1) MOO_ASSERT (moo, nargs <= 1);
{
/* too many arguments */
/* TODO: proper error handling */
moo_seterrnum (moo, MOO_EINVAL);
return MOO_PF_FAILURE;
}
if (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; blkctx->sender = (moo_oop_context_t)moo->_nil;
proc = make_process (moo, blkctx); 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. /* __block_value() has popped all arguments and the receiver.
* PUSH the return value instead of changing the stack top */ * 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; 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) 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 * switch_to_process() as there is no running
* process at this moment */ * process at this moment */
MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); 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 */ wake_new_process (moo, proc); /* switch to running */
moo->proc_switched = 1; 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) if (moo->processor->active == moo->nil_process)
{ {
/* no more waiting semaphore and no more 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"); MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No more runnable process\n");
return 0; return 0;
} }

View File

@ -290,8 +290,9 @@ static int ignite_2 (moo_t* moo)
tmp = (moo_oop_t)moo_instantiate (moo, moo->_process_scheduler, MOO_NULL, 0); tmp = (moo_oop_t)moo_instantiate (moo, moo->_process_scheduler, MOO_NULL, 0);
if (!tmp) return -1; if (!tmp) return -1;
moo->processor = (moo_oop_process_scheduler_t)tmp; moo->processor = (moo_oop_process_scheduler_t)tmp;
moo->processor->tally = MOO_SMOOI_TO_OOP(0);
moo->processor->active = moo->nil_process; 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; return 0;
} }

View File

@ -66,7 +66,7 @@
#define MOO_LIMIT_OBJ_SIZE #define MOO_LIMIT_OBJ_SIZE
/* TODO: delete these header inclusion lines */ /* TODO: delete these header inclusion lines after having revised MOO_MEMXXX macros. */
#include <string.h> #include <string.h>
#if defined(__has_builtin) #if defined(__has_builtin)

View File

@ -57,6 +57,41 @@
} while(0) } 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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif

View File

@ -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_process_t;
typedef struct moo_process_t* moo_oop_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 initial_context;
moo_oop_context_t current_context; moo_oop_context_t current_context;
moo_oop_t id; /* SmallInteger */
moo_oop_t state; /* SmallInteger */ moo_oop_t state; /* SmallInteger */
moo_oop_t sp; /* stack pointer. SmallInteger */ moo_oop_t sp; /* stack pointer. SmallInteger */
moo_oop_process_t prev; struct
moo_oop_process_t next; {
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_semaphore_t sem;
moo_oop_t perr; /* last error set by a primitive function */ moo_oop_t perr; /* last error set by a primitive function */
@ -782,8 +792,12 @@ struct moo_semaphore_t
MOO_OBJ_HEADER; MOO_OBJ_HEADER;
moo_oop_t count; /* SmallInteger */ 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_index; /* index to the heap */
moo_oop_t heap_ftime_sec; /* firing time */ moo_oop_t heap_ftime_sec; /* firing time */
@ -794,17 +808,27 @@ struct moo_semaphore_t
moo_oop_t io_mask; /* SmallInteger */ 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_process_scheduler_t;
typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t; typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t;
struct moo_process_scheduler_t struct moo_process_scheduler_t
{ {
MOO_OBJ_HEADER; 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 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 */ struct
/*moo_oop_t sempq;*/ /* SemaphoreHeap */ {
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;
}; };
/** /**

View File

@ -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)
{
}