From 7384777b5995b4a6e05a1aa358c3503c9ad41754 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Fri, 10 Feb 2017 09:06:53 +0000 Subject: [PATCH] introduced vm_getttime, vm_sleep, vm_startup, vm_cleanup callbacks --- moo/kernel/Mill.moo | 5 +- moo/lib/exec.c | 188 ++++---------------------------------------- moo/lib/main.c | 161 +++++++++++++++++++++++++++++++++++-- moo/lib/moo.h | 19 ++++- 4 files changed, 187 insertions(+), 186 deletions(-) diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index bb49ee2..37903b8 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -315,9 +315,8 @@ class MyObject(Object) '------------' dump. ]. - - (a associationAt: :(#aaa)) dump. + (a associationAt: :(#aaa)) dump. (* while (true) { @@ -327,6 +326,8 @@ class MyObject(Object) (1 + (if (false) {} else { break })) dump. } }*) + + Processor sleepFor: 20. } } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 56ad5ce..dff140e 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -26,31 +26,6 @@ #include "moo-prv.h" -/* TODO: remove these headers after having migrated system-dependent functions of of this file */ -#if defined(_WIN32) -# include -#elif defined(__OS2__) -# define INCL_DOSMISC -# define INCL_DOSDATETIME -# define INCL_DOSERRORS -# include -# include -#elif defined(__DOS__) -# include -#elif defined(macintosh) -# include -# include -# include -#else -# if defined(HAVE_TIME_H) -# include -# endif -# if defined(HAVE_SYS_TIME_H) -# include -# endif -#endif - - #define PROC_STATE_RUNNING 3 #define PROC_STATE_WAITING 2 #define PROC_STATE_RUNNABLE 1 @@ -132,161 +107,28 @@ /* ------------------------------------------------------------------------- */ static MOO_INLINE void vm_gettime (moo_t* moo, moo_ntime_t* now) { -#if defined(_WIN32) - - /* TODO: */ - -#elif defined(__OS2__) - ULONG out; - -/* TODO: handle overflow?? */ -/* TODO: use DosTmrQueryTime() and DosTmrQueryFreq()? */ - DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &out, MOO_SIZEOF(out)); /* milliseconds */ - /* it must return NO_ERROR */ - - MOO_INITNTIME (now, MOO_MSEC_TO_SEC(out), MOO_MSEC_TO_NSEC(out)); -#elif defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__)) - clock_t c; - -/* TODO: handle overflow?? */ - c = clock (); - now->sec = c / CLOCKS_PER_SEC; - #if (CLOCKS_PER_SEC == 100) - now->nsec = MOO_MSEC_TO_NSEC((c % CLOCKS_PER_SEC) * 10); - #elif (CLOCKS_PER_SEC == 1000) - now->nsec = MOO_MSEC_TO_NSEC(c % CLOCKS_PER_SEC); - #elif (CLOCKS_PER_SEC == 1000000L) - now->nsec = MOO_USEC_TO_NSEC(c % CLOCKS_PER_SEC); - #elif (CLOCKS_PER_SEC == 1000000000L) - now->nsec = (c % CLOCKS_PER_SEC); - #else - # error UNSUPPORTED CLOCKS_PER_SEC - #endif -#elif defined(macintosh) - UnsignedWide tick; - moo_uint64_t tick64; - - Microseconds (&tick); - - tick64 = *(moo_uint64_t*)&tick; - MOO_INITNTIME (now, MOO_USEC_TO_SEC(tick64), MOO_USEC_TO_NSEC(tick64)); - -#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) - struct timespec ts; - clock_gettime (CLOCK_MONOTONIC, &ts); - MOO_INITNTIME(now, ts.tv_sec, ts.tv_nsec); - -#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) - struct timespec ts; - clock_gettime (CLOCK_REALTIME, &ts); - MOO_INITNTIME(now, ts.tv_sec, ts.tv_nsec); - MOO_SUBNTIME (now, now, &moo->vm_time_offset); /* offset */ -#else - struct timeval tv; - gettimeofday (&tv, MOO_NULL); - MOO_INITNTIME(now, tv.tv_sec, MOO_USEC_TO_NSEC(tv.tv_usec)); - - /* at the first call, vm_time_offset should be 0. so subtraction takes - * no effect. once it becomes non-zero, it offsets the actual time. - * this is to keep the returned time small enough to be held in a - * small integer on platforms where the small integer is not large enough */ - MOO_SUBNTIME (now, now, &moo->vm_time_offset); -#endif + moo->vmprim.vm_gettime (moo, now); + /* in vm_startup(), moo->exec_start_time has been set to the time of + * that moment. time returned here becomes relative to moo->exec_start_time + * and is kept small such that it can get reprensed in a small integer */ + MOO_SUBNTIME (now, now, &moo->exec_start_time); /* now = now - exec_start_time */ } -#if defined(__DOS__) -# if defined(_INTELC32_) - void _halt_cpu (void); -# elif defined(__WATCOMC__) - void _halt_cpu (void); -# pragma aux _halt_cpu = "hlt" -# endif -#endif - static MOO_INLINE void vm_sleep (moo_t* moo, const moo_ntime_t* dur) { -#if defined(_WIN32) - if (moo->waitable_timer) - { - LARGE_INTEGER li; - li.QuadPart = -MOO_SECNSEC_TO_NSEC(dur->sec, dur->nsec); - if(SetWaitableTimer(timer, &li, 0, MOO_NULL, MOO_NULL, FALSE) == FALSE) goto normal_sleep; - WaitForSingleObject(timer, INFINITE); - } - else - { - normal_sleep: - /* fallback to normal Sleep() */ - Sleep (MOO_SECNSEC_TO_MSEC(dur->sec,dur->nsec)); - } -#elif defined(__OS2__) - - /* TODO: in gui mode, this is not a desirable method??? - * this must be made event-driven coupled with the main event loop */ - DosSleep (MOO_SECNSEC_TO_MSEC(dur->sec,dur->nsec)); - -#elif defined(macintosh) - - /* TODO: ... */ - -#elif defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__)) - - clock_t c; - - c = clock (); - c += dur->sec * CLOCKS_PER_SEC; - - #if (CLOCKS_PER_SEC == 100) - c += MOO_NSEC_TO_MSEC(dur->nsec) / 10; - #elif (CLOCKS_PER_SEC == 1000) - c += MOO_NSEC_TO_MSEC(dur->nsec); - #elif (CLOCKS_PER_SEC == 1000000L) - c += MOO_NSEC_TO_USEC(dur->nsec); - #elif (CLOCKS_PER_SEC == 1000000000L) - c += dur->nsec; - #else - # error UNSUPPORTED CLOCKS_PER_SEC - #endif - -/* TODO: handle clock overvlow */ -/* TODO: check if there is abortion request or interrupt */ - while (c > clock()) - { - _halt_cpu(); - } - -#else - struct timespec ts; - ts.tv_sec = dur->sec; - ts.tv_nsec = dur->nsec; - nanosleep (&ts, MOO_NULL); -#endif + moo->vmprim.vm_sleep (moo, dur); } - -static void vm_startup (moo_t* moo) +static MOO_INLINE void vm_startup (moo_t* moo) { - moo_ntime_t now; - -#if defined(_WIN32) - moo->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); -#endif - - /* reset moo->vm_time_offset so that vm_gettime is not affected */ - MOO_INITNTIME(&moo->vm_time_offset, 0, 0); - vm_gettime (moo, &now); - moo->vm_time_offset = now; + moo->vmprim.vm_startup (moo); + moo->vmprim.vm_gettime (moo, &moo->exec_start_time); } -static void vm_cleanup (moo_t* moo) +static MOO_INLINE void vm_cleanup (moo_t* moo) { -#if defined(_WIN32) - if (moo->waitable_timer) - { - CloseHandle (moo->waitable_timer); - moo->waitable_timer = MOO_NULL; - } -#endif + vm_gettime (moo, &moo->exec_end_time); + moo->vmprim.vm_cleanup (moo); } /* ------------------------------------------------------------------------- */ @@ -2159,10 +2001,8 @@ static moo_pfrc_t pf_processor_add_timed_semaphore (moo_t* moo, moo_ooi_t nargs) */ } -/* TODO: make clock_gettime to be platform independent - * - * this code assumes that the monotonic clock returns a small value - * that can fit into a SmallInteger, even after some additions... */ + /* this code assumes that the monotonic clock returns a small value + * that can fit into a SmallInteger, even after some additions... */ vm_gettime (moo, &now); MOO_ADDNTIMESNS (&ft, &now, MOO_OOP_TO_SMOOI(sec), MOO_OOP_TO_SMOOI(nsec)); if (ft.sec < 0 || ft.sec > MOO_SMOOI_MAX) diff --git a/moo/lib/main.c b/moo/lib/main.c index 3e0d5d3..a2adf4a 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -43,13 +43,18 @@ #elif defined(__OS2__) # define INCL_DOSMODULEMGR # define INCL_DOSPROCESS +# define INCL_DOSMISC +# define INCL_DOSDATETIME # define INCL_DOSERRORS # include +# include #elif defined(__DOS__) # include # include # include #elif defined(macintosh) +# include +# include # include #else # include @@ -482,10 +487,10 @@ static void* dl_getsym (moo_t* moo, void* handle, const moo_ooch_t* name) /* ========================================================================= */ #if defined(_WIN32) -# error NOT IMPLEMENTED - + /* nothing to do */ + #elif defined(macintosh) -# error NOT IMPLEMENTED + /* nothing to do */ #else static int write_all (int fd, const char* ptr, moo_oow_t len) @@ -605,10 +610,148 @@ if (mask & MOO_LOG_GC) return; /* don't show gc logs */ #endif } + +/* ========================================================================= */ + +static void vm_gettime (moo_t* moo, moo_ntime_t* now) +{ +#if defined(_WIN32) + /* TODO: */ +#elif defined(__OS2__) + ULONG out; + +/* TODO: handle overflow?? */ +/* TODO: use DosTmrQueryTime() and DosTmrQueryFreq()? */ + DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &out, MOO_SIZEOF(out)); /* milliseconds */ + /* it must return NO_ERROR */ + MOO_INITNTIME (now, MOO_MSEC_TO_SEC(out), MOO_MSEC_TO_NSEC(out)); +#elif defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__)) + clock_t c; + +/* TODO: handle overflow?? */ + c = clock (); + now->sec = c / CLOCKS_PER_SEC; + #if (CLOCKS_PER_SEC == 100) + now->nsec = MOO_MSEC_TO_NSEC((c % CLOCKS_PER_SEC) * 10); + #elif (CLOCKS_PER_SEC == 1000) + now->nsec = MOO_MSEC_TO_NSEC(c % CLOCKS_PER_SEC); + #elif (CLOCKS_PER_SEC == 1000000L) + now->nsec = MOO_USEC_TO_NSEC(c % CLOCKS_PER_SEC); + #elif (CLOCKS_PER_SEC == 1000000000L) + now->nsec = (c % CLOCKS_PER_SEC); + #else + # error UNSUPPORTED CLOCKS_PER_SEC + #endif +#elif defined(macintosh) + UnsignedWide tick; + moo_uint64_t tick64; + Microseconds (&tick); + tick64 = *(moo_uint64_t*)&tick; + MOO_INITNTIME (now, MOO_USEC_TO_SEC(tick64), MOO_USEC_TO_NSEC(tick64)); +#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + struct timespec ts; + clock_gettime (CLOCK_MONOTONIC, &ts); + MOO_INITNTIME(now, ts.tv_sec, ts.tv_nsec); +#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + struct timespec ts; + clock_gettime (CLOCK_REALTIME, &ts); + MOO_INITNTIME(now, ts.tv_sec, ts.tv_nsec); +#else + struct timeval tv; + gettimeofday (&tv, MOO_NULL); + MOO_INITNTIME(now, tv.tv_sec, MOO_USEC_TO_NSEC(tv.tv_usec)); +#endif +} + +#if defined(__DOS__) +# if defined(_INTELC32_) + void _halt_cpu (void); +# elif defined(__WATCOMC__) + void _halt_cpu (void); +# pragma aux _halt_cpu = "hlt" +# endif +#endif + +static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) +{ +#if defined(_WIN32) + if (moo->waitable_timer) + { + LARGE_INTEGER li; + li.QuadPart = -MOO_SECNSEC_TO_NSEC(dur->sec, dur->nsec); + if(SetWaitableTimer(timer, &li, 0, MOO_NULL, MOO_NULL, FALSE) == FALSE) goto normal_sleep; + WaitForSingleObject(timer, INFINITE); + } + else + { + normal_sleep: + /* fallback to normal Sleep() */ + Sleep (MOO_SECNSEC_TO_MSEC(dur->sec,dur->nsec)); + } +#elif defined(__OS2__) + + /* TODO: in gui mode, this is not a desirable method??? + * this must be made event-driven coupled with the main event loop */ + DosSleep (MOO_SECNSEC_TO_MSEC(dur->sec,dur->nsec)); + +#elif defined(macintosh) + + /* TODO: ... */ + +#elif defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__)) + + clock_t c; + + c = clock (); + c += dur->sec * CLOCKS_PER_SEC; + + #if (CLOCKS_PER_SEC == 100) + c += MOO_NSEC_TO_MSEC(dur->nsec) / 10; + #elif (CLOCKS_PER_SEC == 1000) + c += MOO_NSEC_TO_MSEC(dur->nsec); + #elif (CLOCKS_PER_SEC == 1000000L) + c += MOO_NSEC_TO_USEC(dur->nsec); + #elif (CLOCKS_PER_SEC == 1000000000L) + c += dur->nsec; + #else + # error UNSUPPORTED CLOCKS_PER_SEC + #endif + +/* TODO: handle clock overvlow */ +/* TODO: check if there is abortion request or interrupt */ + while (c > clock()) + { + _halt_cpu(); + } + +#else + struct timespec ts; + ts.tv_sec = dur->sec; + ts.tv_nsec = dur->nsec; + nanosleep (&ts, MOO_NULL); +#endif +} + +static void vm_startup (moo_t* moo) +{ +#if defined(_WIN32) + moo->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); +#endif +} + +static void vm_cleanup (moo_t* moo) +{ +#if defined(_WIN32) + if (moo->waitable_timer) + { + CloseHandle (moo->waitable_timer); + moo->waitable_timer = MOO_NULL; + } +#endif +} + /* ========================================================================= */ -static moo_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' }; -static moo_ooch_t str_main[] = { 'm', 'a', 'i', 'n' }; static moo_t* g_moo = MOO_NULL; /* ========================================================================= */ @@ -731,6 +874,9 @@ static void cancel_tick (void) int main (int argc, char* argv[]) { + static moo_ooch_t str_my_object[] = { 'M', 'y', 'O', 'b','j','e','c','t' }; /*TODO: make this an argument */ + static moo_ooch_t str_main[] = { 'm', 'a', 'i', 'n' }; + moo_t* moo; xtn_t* xtn; moo_oocs_t objname; @@ -750,7 +896,10 @@ int main (int argc, char* argv[]) vmprim.dl_close = dl_close; vmprim.dl_getsym = dl_getsym; vmprim.log_write = log_write; - + vmprim.vm_gettime = vm_gettime; + vmprim.vm_sleep = vm_sleep; + vmprim.vm_startup = vm_startup; + vmprim.vm_cleanup = vm_cleanup; #if defined(USE_LTDL) lt_dlinit (); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 605cfa5..8283edc 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -739,12 +739,22 @@ typedef void* (*moo_vmprim_getdlsym_t) (moo_t* moo, void* handle, const moo_ooch typedef void (*moo_log_write_t) (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len); +typedef void (*moo_vmprim_sleep_t) (moo_t* moo, const moo_ntime_t* duration); +typedef void (*moo_vmprim_gettime_t) (moo_t* moo, moo_ntime_t* now); +typedef void (*moo_vmprim_startup_t) (moo_t* moo); +typedef void (*moo_vmprim_cleanup_t) (moo_t* moo); + struct moo_vmprim_t { - moo_vmprim_opendl_t dl_open; - moo_vmprim_closedl_t dl_close; + moo_vmprim_opendl_t dl_open; + moo_vmprim_closedl_t dl_close; moo_vmprim_getdlsym_t dl_getsym; - moo_log_write_t log_write; + moo_log_write_t log_write; + + moo_vmprim_gettime_t vm_gettime; + moo_vmprim_sleep_t vm_sleep; + moo_vmprim_startup_t vm_startup; + moo_vmprim_cleanup_t vm_cleanup; }; typedef struct moo_vmprim_t moo_vmprim_t; @@ -967,7 +977,8 @@ struct moo_t moo_ooi_t ip; int proc_switched; /* TODO: this is temporary. implement something else to skip immediate context switching */ int switch_proc; - moo_ntime_t vm_time_offset; + moo_ntime_t exec_start_time; + moo_ntime_t exec_end_time; /* ============================================================= * END EXECUTION REGISTERS * ============================================================= */