added more code for process scheduling

This commit is contained in:
hyunghwan.chung 2015-10-18 15:06:17 +00:00
parent f52356e8c8
commit 3482c99ab7
8 changed files with 166 additions and 31 deletions

View File

@ -1,6 +1,5 @@
#class Boolean(Object) #class Boolean(Object)
{ {
"TODO: do i need to really define methods defined in True and False here? "TODO: do i need to really define methods defined in True and False here?
and call subclassResponsibiltiy?" and call subclassResponsibiltiy?"
} }
@ -75,7 +74,6 @@
^aBlock value ^aBlock value
} }
#method ifTrue: trueBlock ifFalse: falseBlock #method ifTrue: trueBlock ifFalse: falseBlock
{ {
^falseBlock value. ^falseBlock value.

View File

@ -42,13 +42,14 @@
#method fork #method fork
{ {
"crate a new process in the runnable state" "crate a new process in the runnable state"
## TODO ^self newProcess resume.
} }
#method newProcess #method newProcess
{ {
"create a new process in the suspended state" "create a new process in the suspended state"
## TODO <primitive: #_block_new_process>
self primitiveFailed.
} }
#method newProcessWith: anArray #method newProcessWith: anArray

View File

@ -1,6 +1,6 @@
#class(#pointer) Process(Object) #class(#pointer) Process(Object)
{ {
#dcl sp state prev next. #dcl context state prev next.
#method prev #method prev
{ {
@ -21,6 +21,12 @@
{ {
self.prev := aProcess. self.prev := aProcess.
} }
#method resume
{
^Scheduler resume: self.
}
} }
#class ProcessScheduler(Object) #class ProcessScheduler(Object)
@ -56,12 +62,22 @@
]. ].
} }
#method resume: aProcess
{
self add: aProcess.
self.active := aProcess.
}
#method remove: aProcess #method remove: aProcess
{ {
"<primitive: #_scheduler_remove>" "<primitive: #_scheduler_remove>"
"TODO: " "TODO: "
}
#method suspendActive
{
" TODO: .........."
} }
" "

View File

@ -241,9 +241,16 @@
ffi close. ffi close.
" "
self abc. | p |
self abc. '000000000000000000' dump.
self abc. p := [ 'xxxxxxxxxxxxxxxxx' dump. 'yyyyyyyyyyyyyyyyyyyyyyyyyy' dump. ] newProcess.
'999999999999999999' dump.
p resume.
'111111111111111111' dump.
'222222222222222222' dump.
'333333333333333333' dump.
'444444444444444444' dump.
" "
FFI isNil dump. FFI isNil dump.

View File

@ -100,6 +100,84 @@
# define DBGOUT_EXEC_3(fmt,a1,a2,a3) # define DBGOUT_EXEC_3(fmt,a1,a2,a3)
#endif #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) 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_context_t ctx;
stix_oop_association_t ass; stix_oop_association_t ass;
stix_oop_method_t mth; stix_oop_method_t mth;
stix_oop_process_t proc;
/* create a fake initial context */ /* create a fake initial context */
ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, 1); 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->origin = ctx;
ctx->method_or_nargs = (stix_oop_t)mth; /* fake. help SWITCH_ACTIVE_CONTEXT() not fail*/ 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); 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; stix->active_context = ctx;
ACTIVE_STACK_PUSH (stix, ass->value); /* push the receiver */ ACTIVE_STACK_PUSH (stix, ass->value); /* push the receiver */
STORE_ACTIVE_IP (stix); STORE_ACTIVE_IP (stix);
STORE_ACTIVE_SP (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); return activate_new_method (stix, mth);
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static int prim_dump (stix_t* stix, stix_ooi_t nargs) static int prim_dump (stix_t* stix, stix_ooi_t nargs)
{ {
@ -771,6 +860,27 @@ printf ("<<ENTERING BLOCK>>\n");
return 1; 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) static int prim_integer_add (stix_t* stix, stix_ooi_t nargs)
{ {
stix_ooi_t tmp; stix_ooi_t tmp;
@ -1319,6 +1429,7 @@ static prim_t primitives[] =
{ 2, prim_basic_at_put, "_basic_at_put" }, { 2, prim_basic_at_put, "_basic_at_put" },
{ -1, prim_block_value, "_block_value" }, { -1, prim_block_value, "_block_value" },
{ 0, prim_block_new_process, "_block_new_process" },
{ 1, prim_integer_add, "_integer_add" }, { 1, prim_integer_add, "_integer_add" },
{ 1, prim_integer_sub, "_integer_sub" }, { 1, prim_integer_sub, "_integer_sub" },
@ -1519,6 +1630,8 @@ int stix_execute (stix_t* stix)
while (1) while (1)
{ {
switch_to_next_process (stix);
#if 0 #if 0
printf ("IP => %d ", (int)stix->ip); printf ("IP => %d ", (int)stix->ip);
#endif #endif
@ -2498,11 +2611,8 @@ oops:
return -1; return -1;
} }
int stix_invoke (stix_t* stix, const stix_ucs_t* objname, const stix_ucs_t* mthname) 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; if (activate_initial_context (stix, objname, mthname) <= -1) return -1;
return stix_execute (stix); return stix_execute (stix);
} }

View File

@ -266,7 +266,7 @@ static int ignite_3 (stix_t* stix)
if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->sysdic)) return -1; if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->sysdic)) return -1;
/* Make the process scheduler avaialble as the global name 'Scheduler' */ /* 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 (!sym) return -1;
if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->scheduler)) return -1; if (!stix_putatsysdic(stix, sym, (stix_oop_t)stix->scheduler)) return -1;

View File

@ -27,6 +27,8 @@
#include "stix-prv.h" #include "stix-prv.h"
stix_oop_process_t stix_addnewproc (stix_t* stix) stix_oop_process_t stix_addnewproc (stix_t* stix)
{ {
stix_oop_process_t proc; stix_oop_process_t proc;

View File

@ -456,7 +456,7 @@ struct stix_context_t
* moment the block context was created. */ * moment the block context was created. */
stix_oop_t home; 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. * no change is made when the method context is activated.
* when a block context is created, it is set to nil. * when a block context is created, it is set to nil.
* when the block context is shallow-copied for activation, * when the block context is shallow-copied for activation,
@ -467,17 +467,6 @@ struct stix_context_t
stix_oop_t slot[1]; /* stack */ 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 #define STIX_PROCESS_NAMED_INSTVARS 4
typedef struct stix_process_t stix_process_t; 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 struct stix_process_t
{ {
STIX_OBJ_HEADER; STIX_OBJ_HEADER;
stix_oop_t sp; stix_oop_context_t context;
stix_oop_t state; stix_oop_t state;
stix_oop_t prev; stix_oop_process_t prev;
stix_oop_t next; stix_oop_process_t next;
/* == variable indexed part == */ /* == variable indexed part == */
stix_oop_t slot[1]; /* process stack */ 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 * The STIX_CLASSOF() macro return the class of an object including a numeric