From 3482c99ab774cccf0336a44d46a01e88fd19d510 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sun, 18 Oct 2015 15:06:17 +0000 Subject: [PATCH] added more code for process scheduling --- stix/kernel/Boolean.st | 2 - stix/kernel/Context.st | 5 +- stix/kernel/Process.st | 18 +++++- stix/kernel/test-005.st | 13 ++++- stix/lib/exec.c | 122 ++++++++++++++++++++++++++++++++++++++-- stix/lib/ignite.c | 2 +- stix/lib/proc.c | 2 + stix/lib/stix.h | 33 +++++------ 8 files changed, 166 insertions(+), 31 deletions(-) diff --git a/stix/kernel/Boolean.st b/stix/kernel/Boolean.st index aee3298..35c31f3 100644 --- a/stix/kernel/Boolean.st +++ b/stix/kernel/Boolean.st @@ -1,6 +1,5 @@ #class Boolean(Object) { - "TODO: do i need to really define methods defined in True and False here? and call subclassResponsibiltiy?" } @@ -75,7 +74,6 @@ ^aBlock value } - #method ifTrue: trueBlock ifFalse: falseBlock { ^falseBlock value. diff --git a/stix/kernel/Context.st b/stix/kernel/Context.st index 6cc6c39..3ee26e3 100644 --- a/stix/kernel/Context.st +++ b/stix/kernel/Context.st @@ -42,13 +42,14 @@ #method fork { "crate a new process in the runnable state" -## TODO + ^self newProcess resume. } #method newProcess { "create a new process in the suspended state" -## TODO + + self primitiveFailed. } #method newProcessWith: anArray diff --git a/stix/kernel/Process.st b/stix/kernel/Process.st index 4137802..e81a7d1 100644 --- a/stix/kernel/Process.st +++ b/stix/kernel/Process.st @@ -1,6 +1,6 @@ #class(#pointer) Process(Object) { - #dcl sp state prev next. + #dcl context state prev next. #method prev { @@ -21,6 +21,12 @@ { self.prev := aProcess. } + + #method resume + { + ^Scheduler resume: self. + } + } #class ProcessScheduler(Object) @@ -56,12 +62,22 @@ ]. } + #method resume: aProcess + { + self add: aProcess. + self.active := aProcess. + } + #method remove: aProcess { "" "TODO: " + } + #method suspendActive + { + " TODO: .........." } " diff --git a/stix/kernel/test-005.st b/stix/kernel/test-005.st index 41e72e7..c556f8f 100644 --- a/stix/kernel/test-005.st +++ b/stix/kernel/test-005.st @@ -241,9 +241,16 @@ ffi close. " - self abc. - self abc. - self abc. + | p | + '000000000000000000' dump. + p := [ 'xxxxxxxxxxxxxxxxx' dump. 'yyyyyyyyyyyyyyyyyyyyyyyyyy' dump. ] newProcess. + '999999999999999999' dump. + p resume. + + '111111111111111111' dump. + '222222222222222222' dump. + '333333333333333333' dump. + '444444444444444444' dump. " FFI isNil dump. diff --git a/stix/lib/exec.c b/stix/lib/exec.c index fced1ba..4e94c8f 100644 --- a/stix/lib/exec.c +++ b/stix/lib/exec.c @@ -100,6 +100,84 @@ # define DBGOUT_EXEC_3(fmt,a1,a2,a3) #endif +static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c) +{ + stix_oop_process_t proc; + +/* TODO: do something about the stack. */ + stix_pushtmp (stix, &c); + proc = (stix_oop_process_t)stix_instantiate (stix, stix->_process, STIX_NULL, stix->option.dfl_procstk_size); + stix_poptmp (stix); + if (!proc) return STIX_NULL; + + proc->state = STIX_OOP_FROM_SMINT(0); + proc->context = c; + + return proc; +} + +static void resume_process (stix_t* stix, stix_oop_process_t proc) +{ + if (proc->state == STIX_OOP_FROM_SMINT(0)) + { + stix_ooi_t tally; + STIX_ASSERT (proc->prev == stix->_nil); + STIX_ASSERT (proc->next == stix->_nil); + + tally = STIX_OOP_TO_SMINT(stix->scheduler->tally); + if (tally <= 0) + { + stix->scheduler->head = proc; + stix->scheduler->tail = proc; + stix->scheduler->tally = STIX_OOP_FROM_SMINT(1); + } + else + { + /* TODO: over flow check or maximum number of process check? */ + proc->next = stix->scheduler->head; + stix->scheduler->head->prev = proc; + stix->scheduler->head = proc; + stix->scheduler->tally = STIX_OOP_FROM_SMINT(tally + 1); + } + } + + stix->scheduler->active = proc; + proc->state = STIX_OOP_FROM_SMINT(1); /* TODO: change the code properly... changing state alone doesn't help */ +} + +static stix_oop_process_t start_new_process (stix_t* stix, stix_oop_context_t c) +{ + stix_oop_process_t proc; + + proc = make_process (stix, c); + if (!proc) return STIX_NULL; + + resume_process (stix, proc); + return proc; +} + +static void switch_process (stix_t* stix, stix_oop_process_t proc) +{ + if (stix->scheduler->active != proc) + { + SWITCH_ACTIVE_CONTEXT (stix, proc->context); + /*TODO: set the state to RUNNING */ + stix->scheduler->active = proc; + } +} + +static void switch_to_next_process (stix_t* stix) +{ +/* TODO: this is experimental. rewrite it */ + if (stix->scheduler->active->next == stix->_nil) + { + switch_process (stix, stix->scheduler->head); + } + else + { + switch_process (stix, stix->scheduler->active->next); + } +} static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth) { @@ -337,6 +415,7 @@ static int activate_initial_context (stix_t* stix, const stix_ucs_t* objname, co stix_oop_context_t ctx; stix_oop_association_t ass; stix_oop_method_t mth; + stix_oop_process_t proc; /* create a fake initial context */ ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, 1); @@ -369,20 +448,30 @@ TODO: overcome this problem ctx->origin = ctx; ctx->method_or_nargs = (stix_oop_t)mth; /* fake. help SWITCH_ACTIVE_CONTEXT() not fail*/ - /* receiver, sender of ctx are nils */ + + /* [NOTE] + * the receiver field and the sender field of ctx are nils. + * especially, the fact that the sender field is nil is used by + * the main execution loop for breaking out of the loop */ STIX_ASSERT (stix->active_context == STIX_NULL); - /* i can't use SWITCH_ACTIVE_CONTEXT() macro as there is no active context before switching */ + /* i can't use SWITCH_ACTIVE_CONTEXT() macro as there is no active + * context before switching. let's force set active_context to ctx + * directly. */ stix->active_context = ctx; ACTIVE_STACK_PUSH (stix, ass->value); /* push the receiver */ STORE_ACTIVE_IP (stix); STORE_ACTIVE_SP (stix); + stix_pushtmp (stix, (stix_oop_t*)&mth); + proc = start_new_process (stix, ctx); + stix_poptmp (stix); + if (!proc) return -1; + return activate_new_method (stix, mth); } - /* ------------------------------------------------------------------------- */ static int prim_dump (stix_t* stix, stix_ooi_t nargs) { @@ -771,6 +860,27 @@ printf ("<>\n"); return 1; } +static int prim_block_new_process (stix_t* stix, stix_ooi_t nargs) +{ + stix_oop_process_t proc; + stix_oop_context_t rcv; + + rcv = (stix_oop_context_t)ACTIVE_STACK_GETTOP(stix); + if (STIX_CLASSOF(stix, rcv) != stix->_block_context) + { +#if defined(STIX_DEBUG_EXEC) +printf ("PRIMITVE VALUE RECEIVER IS NOT A BLOCK CONTEXT\n"); +#endif + return 0; + } + + proc = make_process (stix, rcv); + if (!proc) return -1; /* hard failure */ /* TOOD: can't this be a soft failure? */ + + ACTIVE_STACK_SETTOP (stix, (stix_oop_t)proc); + return 1; +} + static int prim_integer_add (stix_t* stix, stix_ooi_t nargs) { stix_ooi_t tmp; @@ -1319,6 +1429,7 @@ static prim_t primitives[] = { 2, prim_basic_at_put, "_basic_at_put" }, { -1, prim_block_value, "_block_value" }, + { 0, prim_block_new_process, "_block_new_process" }, { 1, prim_integer_add, "_integer_add" }, { 1, prim_integer_sub, "_integer_sub" }, @@ -1519,6 +1630,8 @@ int stix_execute (stix_t* stix) while (1) { + +switch_to_next_process (stix); #if 0 printf ("IP => %d ", (int)stix->ip); #endif @@ -2498,11 +2611,8 @@ oops: return -1; } - int stix_invoke (stix_t* stix, const stix_ucs_t* objname, const stix_ucs_t* mthname) { - /*stix_oop_process_t proc;*/ - if (activate_initial_context (stix, objname, mthname) <= -1) return -1; return stix_execute (stix); } diff --git a/stix/lib/ignite.c b/stix/lib/ignite.c index f1253eb..5ed62fb 100644 --- a/stix/lib/ignite.c +++ b/stix/lib/ignite.c @@ -266,7 +266,7 @@ static int ignite_3 (stix_t* stix) if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->sysdic)) return -1; /* Make the process scheduler avaialble as the global name 'Scheduler' */ - sym = stix_makesymbol (stix, str_scheduler, 4); + sym = stix_makesymbol (stix, str_scheduler, 9); if (!sym) return -1; if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->scheduler)) return -1; diff --git a/stix/lib/proc.c b/stix/lib/proc.c index 63126b7..c947ba8 100644 --- a/stix/lib/proc.c +++ b/stix/lib/proc.c @@ -27,6 +27,8 @@ #include "stix-prv.h" + + stix_oop_process_t stix_addnewproc (stix_t* stix) { stix_oop_process_t proc; diff --git a/stix/lib/stix.h b/stix/lib/stix.h index ce5103a..d407db1 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -456,7 +456,7 @@ struct stix_context_t * moment the block context was created. */ stix_oop_t home; - /* when a method context is craeted, it is set to itself. + /* when a method context is created, it is set to itself. * no change is made when the method context is activated. * when a block context is created, it is set to nil. * when the block context is shallow-copied for activation, @@ -467,17 +467,6 @@ struct stix_context_t stix_oop_t slot[1]; /* stack */ }; -#define STIX_PROCESS_SCHEDULER_NAMED_INSTVARS 4 -typedef struct stix_process_scheduler_t stix_process_scheduler_t; -typedef struct stix_process_scheduler_t* stix_oop_process_scheduler_t; -struct stix_process_scheduler_t -{ - STIX_OBJ_HEADER; - stix_oop_t tally; - stix_oop_t head; - stix_oop_t tail; - stix_oop_t active; -}; #define STIX_PROCESS_NAMED_INSTVARS 4 typedef struct stix_process_t stix_process_t; @@ -485,15 +474,27 @@ typedef struct stix_process_t* stix_oop_process_t; struct stix_process_t { STIX_OBJ_HEADER; - stix_oop_t sp; - stix_oop_t state; - stix_oop_t prev; - stix_oop_t next; + stix_oop_context_t context; + stix_oop_t state; + stix_oop_process_t prev; + stix_oop_process_t next; /* == variable indexed part == */ stix_oop_t slot[1]; /* process stack */ }; +#define STIX_PROCESS_SCHEDULER_NAMED_INSTVARS 4 +typedef struct stix_process_scheduler_t stix_process_scheduler_t; +typedef struct stix_process_scheduler_t* stix_oop_process_scheduler_t; +struct stix_process_scheduler_t +{ + STIX_OBJ_HEADER; + stix_oop_t tally; + stix_oop_process_t head; + stix_oop_process_t tail; + stix_oop_process_t active; +}; + /** * The STIX_CLASSOF() macro return the class of an object including a numeric