refactored moo_execute() by taking process switcher out to a separate inline function
This commit is contained in:
214
moo/lib/exec.c
214
moo/lib/exec.c
@ -2914,6 +2914,106 @@ static int send_private_message (moo_t* moo, const moo_ooch_t* nameptr, moo_oow_
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static MOO_INLINE int switch_process_if_needed (moo_t* moo)
|
||||
{
|
||||
if (moo->sem_heap_count > 0)
|
||||
{
|
||||
moo_ntime_t ft, now;
|
||||
vm_gettime (moo, &now);
|
||||
|
||||
do
|
||||
{
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_sec));
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_nsec));
|
||||
|
||||
MOO_INITNTIME (&ft,
|
||||
MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_sec),
|
||||
MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_nsec)
|
||||
);
|
||||
|
||||
if (MOO_CMPNTIME(&ft, (moo_ntime_t*)&now) <= 0)
|
||||
{
|
||||
moo_oop_process_t proc;
|
||||
|
||||
/* waited long enough. signal the semaphore */
|
||||
|
||||
proc = signal_semaphore (moo, moo->sem_heap[0]);
|
||||
/* [NOTE] no moo_pushtmp() on proc. no GC must occur
|
||||
* in the following line until it's used for
|
||||
* wake_new_process() below. */
|
||||
delete_from_sem_heap (moo, 0);
|
||||
|
||||
/* if no process is waiting on the semaphore,
|
||||
* signal_semaphore() returns moo->_nil. */
|
||||
|
||||
if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil)
|
||||
{
|
||||
/* this is the only runnable process.
|
||||
* switch the process to the running state.
|
||||
* it uses wake_new_process() instead of
|
||||
* 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);
|
||||
|
||||
wake_new_process (moo, proc);
|
||||
moo->proc_switched = 1;
|
||||
}
|
||||
}
|
||||
else if (moo->processor->active == moo->nil_process)
|
||||
{
|
||||
MOO_SUBNTIME (&ft, &ft, (moo_ntime_t*)&now);
|
||||
vm_sleep (moo, &ft); /* TODO: change this to i/o multiplexer??? */
|
||||
vm_gettime (moo, &now);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (moo->sem_heap_count > 0);
|
||||
}
|
||||
|
||||
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_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No more runnable process\n");
|
||||
|
||||
#if 0
|
||||
if (there is semaphore awaited.... )
|
||||
{
|
||||
/* DO SOMETHING */
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (moo->sem_list_count > 0)
|
||||
{
|
||||
/* handle async signals */
|
||||
--moo->sem_list_count;
|
||||
signal_semaphore (moo, moo->sem_list[moo->sem_list_count]);
|
||||
}
|
||||
/*
|
||||
if (semaphore heap has pending request)
|
||||
{
|
||||
signal them...
|
||||
}*/
|
||||
|
||||
/* TODO: implement different process switching scheme - time-slice or clock based??? */
|
||||
#if defined(MOO_EXTERNAL_PROCESS_SWITCH)
|
||||
if (!moo->proc_switched && moo->switch_proc) { switch_to_next_runnable_process (moo); }
|
||||
moo->switch_proc = 0;
|
||||
#else
|
||||
if (!moo->proc_switched) { switch_to_next_runnable_process (moo); }
|
||||
#endif
|
||||
|
||||
moo->proc_switched = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int moo_execute (moo_t* moo)
|
||||
{
|
||||
moo_oob_t bcode;
|
||||
@ -2922,6 +3022,7 @@ int moo_execute (moo_t* moo)
|
||||
int unwind_protect;
|
||||
moo_oop_context_t unwind_start;
|
||||
moo_oop_context_t unwind_stop;
|
||||
int vm_startup_called = 0;
|
||||
|
||||
#if defined(MOO_PROFILE_VM)
|
||||
moo_uintmax_t inst_counter = 0;
|
||||
@ -2934,105 +3035,12 @@ int moo_execute (moo_t* moo)
|
||||
MOO_ASSERT (moo, moo->active_context != MOO_NULL);
|
||||
|
||||
vm_startup (moo);
|
||||
vm_startup_called = 1;
|
||||
moo->proc_switched = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (moo->sem_heap_count > 0)
|
||||
{
|
||||
moo_ntime_t ft, now;
|
||||
vm_gettime (moo, &now);
|
||||
|
||||
do
|
||||
{
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_sec));
|
||||
MOO_ASSERT (moo, MOO_OOP_IS_SMOOI(moo->sem_heap[0]->heap_ftime_nsec));
|
||||
|
||||
MOO_INITNTIME (&ft,
|
||||
MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_sec),
|
||||
MOO_OOP_TO_SMOOI(moo->sem_heap[0]->heap_ftime_nsec)
|
||||
);
|
||||
|
||||
if (MOO_CMPNTIME(&ft, (moo_ntime_t*)&now) <= 0)
|
||||
{
|
||||
moo_oop_process_t proc;
|
||||
|
||||
/* waited long enough. signal the semaphore */
|
||||
|
||||
proc = signal_semaphore (moo, moo->sem_heap[0]);
|
||||
/* [NOTE] no moo_pushtmp() on proc. no GC must occur
|
||||
* in the following line until it's used for
|
||||
* wake_new_process() below. */
|
||||
delete_from_sem_heap (moo, 0);
|
||||
|
||||
/* if no process is waiting on the semaphore,
|
||||
* signal_semaphore() returns moo->_nil. */
|
||||
|
||||
if (moo->processor->active == moo->nil_process && (moo_oop_t)proc != moo->_nil)
|
||||
{
|
||||
/* this is the only runnable process.
|
||||
* switch the process to the running state.
|
||||
* it uses wake_new_process() instead of
|
||||
* 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);
|
||||
|
||||
wake_new_process (moo, proc);
|
||||
moo->proc_switched = 1;
|
||||
}
|
||||
}
|
||||
else if (moo->processor->active == moo->nil_process)
|
||||
{
|
||||
MOO_SUBNTIME (&ft, &ft, (moo_ntime_t*)&now);
|
||||
vm_sleep (moo, &ft); /* TODO: change this to i/o multiplexer??? */
|
||||
vm_gettime (moo, &now);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (moo->sem_heap_count > 0);
|
||||
}
|
||||
|
||||
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_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "No more runnable process\n");
|
||||
|
||||
#if 0
|
||||
if (there is semaphore awaited.... )
|
||||
{
|
||||
/* DO SOMETHING */
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
while (moo->sem_list_count > 0)
|
||||
{
|
||||
/* handle async signals */
|
||||
--moo->sem_list_count;
|
||||
signal_semaphore (moo, moo->sem_list[moo->sem_list_count]);
|
||||
}
|
||||
/*
|
||||
if (semaphore heap has pending request)
|
||||
{
|
||||
signal them...
|
||||
}*/
|
||||
|
||||
/* TODO: implement different process switching scheme - time-slice or clock based??? */
|
||||
#if defined(MOO_EXTERNAL_PROCESS_SWITCH)
|
||||
if (!moo->proc_switched && moo->switch_proc) { switch_to_next_runnable_process (moo); }
|
||||
moo->switch_proc = 0;
|
||||
#else
|
||||
if (!moo->proc_switched) { switch_to_next_runnable_process (moo); }
|
||||
#endif
|
||||
|
||||
moo->proc_switched = 0;
|
||||
if (switch_process_if_needed(moo) == 0) break; /* no more runnable process */
|
||||
|
||||
#if defined(MOO_DEBUG_VM_EXEC)
|
||||
fetched_instruction_pointer = moo->ip;
|
||||
@ -3804,7 +3812,7 @@ int moo_execute (moo_t* moo)
|
||||
*/
|
||||
moo->ip--;
|
||||
#else
|
||||
if (moo->active_context->origin == moo->processor->active->initial_context->origin)
|
||||
if (MOO_UNLIKELY(moo->active_context->origin == moo->processor->active->initial_context->origin))
|
||||
{
|
||||
/* method return from a processified block
|
||||
*
|
||||
@ -4141,7 +4149,6 @@ int moo_execute (moo_t* moo)
|
||||
LOG_INST_0 (moo, "noop");
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_FATAL, "Fatal error - unknown byte code 0x%zx\n", bcode);
|
||||
moo->errnum = MOO_EINTERN;
|
||||
@ -4158,7 +4165,7 @@ done:
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* TODO: anything to do here? */
|
||||
if (vm_startup_called) vm_cleanup (moo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -4182,3 +4189,14 @@ int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname
|
||||
return n;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname)
|
||||
{
|
||||
/* TODO: .... */
|
||||
/* call
|
||||
* System initializeClasses
|
||||
* and invoke
|
||||
* objname mthname
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
@ -116,6 +116,9 @@ typedef struct xtn_t xtn_t;
|
||||
struct xtn_t
|
||||
{
|
||||
const char* source_path; /* main source file */
|
||||
#if defined(_WIN32)
|
||||
HANDLE waitable_timer;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ========================================================================= */
|
||||
@ -675,7 +678,8 @@ static void vm_gettime (moo_t* moo, moo_ntime_t* now)
|
||||
static void vm_sleep (moo_t* moo, const moo_ntime_t* dur)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (moo->waitable_timer)
|
||||
xtn_t* xtn = moo_getxtn(moo);
|
||||
if (xtn->waitable_timer)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -MOO_SECNSEC_TO_NSEC(dur->sec, dur->nsec);
|
||||
@ -735,17 +739,19 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur)
|
||||
static void vm_startup (moo_t* moo)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
moo->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL);
|
||||
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
||||
xtn->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vm_cleanup (moo_t* moo)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (moo->waitable_timer)
|
||||
xtn_t* xtn = (xtn_t*)moo_getxtn(moo);
|
||||
if (xtn->waitable_timer)
|
||||
{
|
||||
CloseHandle (moo->waitable_timer);
|
||||
moo->waitable_timer = MOO_NULL;
|
||||
CloseHandle (xtn->waitable_timer);
|
||||
xtn->waitable_timer = MOO_NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -57,6 +57,9 @@
|
||||
/* Define to 1 if you have the `closedir' function. */
|
||||
#undef HAVE_CLOSEDIR
|
||||
|
||||
/* computed gotos */
|
||||
#undef HAVE_COMPUTED_GOTO
|
||||
|
||||
/* Define to 1 if you have the `coshq' function. */
|
||||
#undef HAVE_COSHQ
|
||||
|
||||
|
@ -720,11 +720,12 @@ typedef struct moo_t moo_t;
|
||||
#endif
|
||||
|
||||
#if defined(MOO_HAVE_BUILTIN_EXPECT)
|
||||
# define MOO_LIKELY(x) (__builtin_expect(!!x,1))
|
||||
# define MOO_UNLIKELY(x) (__builtin_expect(!!x,0))
|
||||
# define MOO_LIKELY(x) (__builtin_expect(!!(x),1))
|
||||
# define MOO_UNLIKELY(x) (__builtin_expect(!!(x),0))
|
||||
#else
|
||||
# define MOO_LIKELY(x) (x)
|
||||
# define MOO_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -873,17 +873,17 @@ enum moo_bcode_t
|
||||
|
||||
/* -------------------------------------- */
|
||||
|
||||
BCODE_MAKE_ARRAY = 0xF5, /* 245 */
|
||||
BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */
|
||||
BCODE_DUP_STACKTOP = 0xF7,
|
||||
BCODE_POP_STACKTOP = 0xF8,
|
||||
BCODE_RETURN_STACKTOP = 0xF9, /* ^something */
|
||||
BCODE_RETURN_RECEIVER = 0xFA, /* ^self */
|
||||
BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */
|
||||
BCODE_LOCAL_RETURN = 0xFC,
|
||||
BCODE_MAKE_BLOCK = 0xFD,
|
||||
BCODE_SEND_BLOCK_COPY = 0xFE,
|
||||
BCODE_NOOP = 0xFF
|
||||
BCODE_MAKE_ARRAY = 0xF5, /* 245 */
|
||||
BCODE_POP_INTO_ARRAY = 0xF6, /* 246 */
|
||||
BCODE_DUP_STACKTOP = 0xF7,
|
||||
BCODE_POP_STACKTOP = 0xF8,
|
||||
BCODE_RETURN_STACKTOP = 0xF9, /* ^something */
|
||||
BCODE_RETURN_RECEIVER = 0xFA, /* ^self */
|
||||
BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */
|
||||
BCODE_LOCAL_RETURN = 0xFC,
|
||||
BCODE_MAKE_BLOCK = 0xFD,
|
||||
BCODE_SEND_BLOCK_COPY = 0xFE,
|
||||
BCODE_NOOP = 0xFF
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@ -1181,7 +1181,7 @@ moo_oop_t moo_strtoint (
|
||||
moo_oop_t moo_inttostr (
|
||||
moo_t* moo,
|
||||
moo_oop_t num,
|
||||
int radix
|
||||
int radix
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
|
Reference in New Issue
Block a user