added more code for process scheduling
This commit is contained in:
parent
f52356e8c8
commit
3482c99ab7
@ -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.
|
||||
|
@ -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
|
||||
<primitive: #_block_new_process>
|
||||
self primitiveFailed.
|
||||
}
|
||||
|
||||
#method newProcessWith: anArray
|
||||
|
@ -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
|
||||
{
|
||||
"<primitive: #_scheduler_remove>"
|
||||
|
||||
"TODO: "
|
||||
}
|
||||
|
||||
#method suspendActive
|
||||
{
|
||||
" TODO: .........."
|
||||
}
|
||||
|
||||
"
|
||||
|
@ -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.
|
||||
|
122
stix/lib/exec.c
122
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 ("<<ENTERING BLOCK>>\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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "stix-prv.h"
|
||||
|
||||
|
||||
|
||||
stix_oop_process_t stix_addnewproc (stix_t* stix)
|
||||
{
|
||||
stix_oop_process_t proc;
|
||||
|
@ -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_context_t context;
|
||||
stix_oop_t state;
|
||||
stix_oop_t prev;
|
||||
stix_oop_t next;
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user