added more vm primitives
This commit is contained in:
parent
49363231a1
commit
95b4c5e0d7
@ -134,6 +134,7 @@ dnl check functions
|
||||
AC_CHECK_FUNCS([gettimeofday settimeofday clock_gettime clock_settime getitimer setitimer])
|
||||
AC_CHECK_FUNCS([backtrace backtrace_symbols])
|
||||
AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext])
|
||||
AC_CHECK_FUNCS([clock_nanosleep nanosleep usleep])
|
||||
AC_CHECK_FUNCS([snprintf _vsnprintf _vsnwprintf])
|
||||
AC_CHECK_FUNCS([isatty])
|
||||
|
||||
|
179
lib/exec.c
179
lib/exec.c
@ -27,30 +27,6 @@
|
||||
|
||||
#include "hcl-prv.h"
|
||||
|
||||
/* TODO: remove these headers after having migrated system-dependent functions of of this file */
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSMISC
|
||||
# define INCL_DOSDATETIME
|
||||
# define INCL_DOSERRORS
|
||||
# include <os2.h>
|
||||
# include <time.h>
|
||||
#elif defined(__MSDOS__)
|
||||
# include <time.h>
|
||||
#elif defined(macintosh)
|
||||
# include <Types.h>
|
||||
# include <OSUtils.h>
|
||||
# include <Timer.h>
|
||||
#else
|
||||
# if defined(HAVE_TIME_H)
|
||||
# include <time.h>
|
||||
# endif
|
||||
# if defined(HAVE_SYS_TIME_H)
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define PROC_STATE_RUNNING 3
|
||||
#define PROC_STATE_WAITING 2
|
||||
#define PROC_STATE_RUNNABLE 1
|
||||
@ -139,147 +115,21 @@ static HCL_INLINE const char* proc_state_to_string (int state)
|
||||
# define LOG_INST_3(hcl,fmt,a1,a2,a3)
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static HCL_INLINE void vm_gettime (hcl_t* hcl, hcl_ntime_t* now)
|
||||
static int vm_startup (hcl_t* hcl)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
HCL_DEBUG0 (hcl, "VM started up\n");
|
||||
|
||||
/* TODO: */
|
||||
if (hcl->vmprim.vm_startup(hcl) <= -1) return -1;
|
||||
hcl->vmprim.vm_gettime (hcl, &hcl->exec_start_time); /* raw time. no adjustment */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
ULONG out;
|
||||
|
||||
/* TODO: handle overflow?? */
|
||||
/* TODO: use DosTmrQueryTime() and DosTmrQueryFreq()? */
|
||||
DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &out, HCL_SIZEOF(out)); /* milliseconds */
|
||||
/* it must return NO_ERROR */
|
||||
|
||||
HCL_INITNTIME (now, HCL_MSEC_TO_SEC(out), HCL_MSEC_TO_NSEC(out));
|
||||
#elif defined(__MSDOS__) && defined(_INTELC32_)
|
||||
clock_t c;
|
||||
|
||||
/* TODO: handle overflow?? */
|
||||
c = clock ();
|
||||
now->sec = c / CLOCKS_PER_SEC;
|
||||
#if (CLOCKS_PER_SEC == 1000)
|
||||
now->nsec = HCL_MSEC_TO_NSEC(c % CLOCKS_PER_SEC);
|
||||
#elif (CLOCKS_PER_SEC == 1000000L)
|
||||
now->nsec = HCL_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;
|
||||
hcl_uint64_t tick64;
|
||||
|
||||
Microseconds (&tick);
|
||||
|
||||
tick64 = *(hcl_uint64_t*)&tick;
|
||||
HCL_INITNTIME (now, HCL_USEC_TO_SEC(tick64), HCL_USEC_TO_NSEC(tick64));
|
||||
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
clock_gettime (CLOCK_MONOTONIC, &ts);
|
||||
HCL_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
|
||||
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
||||
struct timespec ts;
|
||||
clock_gettime (CLOCK_REALTIME, &ts);
|
||||
HCL_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
|
||||
HCL_SUBNTIME (now, now, &hcl->vm_time_offset); /* offset */
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, HCL_NULL);
|
||||
HCL_INITNTIME(now, tv.tv_sec, HCL_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 */
|
||||
HCL_SUBNTIME (now, now, &hcl->vm_time_offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
static HCL_INLINE void vm_sleep (hcl_t* hcl, const hcl_ntime_t* dur)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (hcl->waitable_timer)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -HCL_SECNSEC_TO_NSEC(dur->sec, dur->nsec);
|
||||
if(SetWaitableTimer(timer, &li, 0, HCL_NULL, HCL_NULL, FALSE) == FALSE) goto normal_sleep;
|
||||
WaitForSingleObject(timer, INFINITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
normal_sleep:
|
||||
/* fallback to normal Sleep() */
|
||||
Sleep (HCL_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 (HCL_SECNSEC_TO_MSEC(dur->sec,dur->nsec));
|
||||
|
||||
#elif defined(macintosh)
|
||||
|
||||
/* TODO: ... */
|
||||
|
||||
#elif defined(__MSDOS__) && defined(_INTELC32_)
|
||||
|
||||
clock_t c;
|
||||
|
||||
c = clock ();
|
||||
c += dur->sec * CLOCKS_PER_SEC;
|
||||
#if (CLOCKS_PER_SEC == 1000)
|
||||
c += HCL_NSEC_TO_MSEC(dur->nsec);
|
||||
#elif (CLOCKS_PER_SEC == 1000000L)
|
||||
c += HCL_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()) ;
|
||||
|
||||
#else
|
||||
struct timespec ts;
|
||||
ts.tv_sec = dur->sec;
|
||||
ts.tv_nsec = dur->nsec;
|
||||
nanosleep (&ts, HCL_NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void vm_startup (hcl_t* hcl)
|
||||
{
|
||||
hcl_ntime_t now;
|
||||
|
||||
#if defined(_WIN32)
|
||||
hcl->waitable_timer = CreateWaitableTimer(HCL_NULL, TRUE, HCL_NULL);
|
||||
#endif
|
||||
|
||||
/* reset hcl->vm_time_offset so that vm_gettime is not affected */
|
||||
HCL_INITNTIME(&hcl->vm_time_offset, 0, 0);
|
||||
vm_gettime (hcl, &now);
|
||||
hcl->vm_time_offset = now;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vm_cleanup (hcl_t* hcl)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (hcl->waitable_timer)
|
||||
{
|
||||
CloseHandle (hcl->waitable_timer);
|
||||
hcl->waitable_timer = HCL_NULL;
|
||||
}
|
||||
#endif
|
||||
hcl->vmprim.vm_gettime (hcl, &hcl->exec_end_time); /* raw time. no adjustment */
|
||||
hcl->vmprim.vm_cleanup (hcl);
|
||||
HCL_DEBUG0 (hcl, "VM started up\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@ -1224,7 +1074,7 @@ static int execute (hcl_t* hcl)
|
||||
|
||||
HCL_ASSERT (hcl, hcl->active_context != HCL_NULL);
|
||||
|
||||
vm_startup (hcl);
|
||||
if (vm_startup (hcl) <= -1) return -1;
|
||||
hcl->proc_switched = 0;
|
||||
|
||||
while (1)
|
||||
@ -1232,7 +1082,7 @@ static int execute (hcl_t* hcl)
|
||||
if (hcl->sem_heap_count > 0)
|
||||
{
|
||||
hcl_ntime_t ft, now;
|
||||
vm_gettime (hcl, &now);
|
||||
hcl->vmprim.vm_gettime (hcl, &now);
|
||||
|
||||
do
|
||||
{
|
||||
@ -1276,8 +1126,8 @@ static int execute (hcl_t* hcl)
|
||||
else if (hcl->processor->active == hcl->nil_process)
|
||||
{
|
||||
HCL_SUBNTIME (&ft, &ft, (hcl_ntime_t*)&now);
|
||||
vm_sleep (hcl, &ft); /* TODO: change this to i/o multiplexer??? */
|
||||
vm_gettime (hcl, &now);
|
||||
hcl->vmprim.vm_sleep (hcl, &ft); /* TODO: change this to i/o multiplexer??? */
|
||||
hcl->vmprim.vm_gettime (hcl, &now);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1327,8 +1177,9 @@ static int execute (hcl_t* hcl)
|
||||
|
||||
if (hcl->ip >= hcl->code.bc.len)
|
||||
{
|
||||
HCL_DEBUG2 (hcl, "IP(%zd) reached the end of bytecode(%zu). Stopping execution\n", hcl->ip, hcl->code.bc.len);
|
||||
break;
|
||||
HCL_DEBUG1 (hcl, "IP reached the end of bytecode(%zu). Stopping execution\n", hcl->code.bc.len);
|
||||
return_value = hcl->_nil;
|
||||
goto handle_return;
|
||||
}
|
||||
|
||||
#if defined(HCL_DEBUG_VM_EXEC)
|
||||
|
@ -61,7 +61,8 @@
|
||||
#if !defined(NDEBUG)
|
||||
#define HCL_DEBUG_VM_PROCESSOR 1
|
||||
#define HCL_DEBUG_VM_EXEC 1
|
||||
#define MOO_DEBUG_BIGINT 1
|
||||
#define HCL_DEBUG_BIGINT 1
|
||||
#define HCL_PROFILE_VM 1
|
||||
#endif
|
||||
|
||||
/* allow the caller to drive process switching by calling
|
||||
|
18
lib/hcl.h
18
lib/hcl.h
@ -700,14 +700,28 @@ typedef void (*hcl_log_write_t) (hcl_t* hcl, hcl_oow_t mask, const hcl_ooch_t* m
|
||||
typedef void (*hcl_syserrstrb_t) (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len);
|
||||
typedef void (*hcl_syserrstru_t) (hcl_t* hcl, int syserr, hcl_uch_t* buf, hcl_oow_t len);
|
||||
|
||||
typedef int (*hcl_vmprim_startup_t) (hcl_t* hcl);
|
||||
typedef void (*hcl_vmprim_cleanup_t) (hcl_t* hcl);
|
||||
typedef void (*hcl_vmprim_gettime_t) (hcl_t* hcl, hcl_ntime_t* now);
|
||||
|
||||
|
||||
typedef void (*hcl_vmprim_sleep_t) (hcl_t* hcl, const hcl_ntime_t* duration);
|
||||
|
||||
struct hcl_vmprim_t
|
||||
{
|
||||
hcl_vmprim_dlopen_t dl_open;
|
||||
hcl_vmprim_dlclose_t dl_close;
|
||||
hcl_vmprim_dlsym_t dl_getsym;
|
||||
|
||||
hcl_log_write_t log_write;
|
||||
hcl_syserrstrb_t syserrstrb;
|
||||
hcl_syserrstru_t syserrstru;
|
||||
|
||||
hcl_vmprim_startup_t vm_startup;
|
||||
hcl_vmprim_cleanup_t vm_cleanup;
|
||||
hcl_vmprim_gettime_t vm_gettime;
|
||||
|
||||
hcl_vmprim_sleep_t vm_sleep;
|
||||
};
|
||||
|
||||
typedef struct hcl_vmprim_t hcl_vmprim_t;
|
||||
@ -992,7 +1006,9 @@ struct hcl_t
|
||||
hcl_ooi_t ip;
|
||||
int proc_switched; /* TODO: this is temporary. implement something else to skip immediate context switching */
|
||||
int switch_proc;
|
||||
hcl_ntime_t vm_time_offset;
|
||||
|
||||
hcl_ntime_t exec_start_time;
|
||||
hcl_ntime_t exec_end_time;
|
||||
/* == END EXECUTION REGISTERS == */
|
||||
|
||||
/* == BIGINT CONVERSION == */
|
||||
|
318
lib/main.c
318
lib/main.c
@ -88,6 +88,8 @@ struct xtn_t
|
||||
const char* read_path; /* main source file */
|
||||
const char* print_path;
|
||||
|
||||
int vm_running;
|
||||
|
||||
int logfd;
|
||||
int logmask;
|
||||
int logfd_istty;
|
||||
@ -548,6 +550,316 @@ static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int vm_startup (hcl_t* hcl)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||
xtn->waitable_timer = CreateWaitableTimer(HCL_NULL, TRUE, HCL_NULL);
|
||||
|
||||
#else
|
||||
|
||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||
int pcount = 0, flag;
|
||||
|
||||
#if defined(USE_DEVPOLL)
|
||||
xtn->ep = open ("/dev/poll", O_RDWR);
|
||||
if (xtn->ep == -1)
|
||||
{
|
||||
hcl_syserr_to_errnum (errno);
|
||||
HCL_DEBUG1 (hcl, "Cannot create devpoll - %hs\n", strerror(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
flag = fcntl (xtn->ep, F_GETFD);
|
||||
if (flag >= 0) fcntl (xtn->ep, F_SETFD, flag | FD_CLOEXEC);
|
||||
|
||||
#elif defined(USE_EPOLL)
|
||||
#if defined(EPOLL_CLOEXEC)
|
||||
xtn->ep = epoll_create1 (EPOLL_CLOEXEC);
|
||||
#else
|
||||
xtn->ep = epoll_create (1024);
|
||||
#endif
|
||||
if (xtn->ep == -1)
|
||||
{
|
||||
hcl_syserr_to_errnum (errno);
|
||||
HCL_DEBUG1 (hcl, "Cannot create epoll - %hs\n", strerror(errno));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#if defined(EPOLL_CLOEXEC)
|
||||
/* do nothing */
|
||||
#else
|
||||
flag = fcntl (xtn->ep, F_GETFD);
|
||||
if (flag >= 0) fcntl (xtn->ep, F_SETFD, flag | FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
#elif defined(USE_POLL)
|
||||
|
||||
MUTEX_INIT (&xtn->ev.reg.pmtx);
|
||||
|
||||
#elif defined(USE_SELECT)
|
||||
FD_ZERO (&xtn->ev.reg.rfds);
|
||||
FD_ZERO (&xtn->ev.reg.wfds);
|
||||
xtn->ev.reg.maxfd = -1;
|
||||
MUTEX_INIT (&xtn->ev.reg.smtx);
|
||||
#endif /* USE_DEVPOLL */
|
||||
|
||||
#if defined(USE_THREAD)
|
||||
if (pipe(xtn->p) == -1)
|
||||
{
|
||||
hcl_syserr_to_errnum (errno);
|
||||
HCL_DEBUG1 (hcl, "Cannot create pipes - %hs\n", strerror(errno));
|
||||
goto oops;
|
||||
}
|
||||
pcount = 2;
|
||||
|
||||
#if defined(O_CLOEXEC)
|
||||
flag = fcntl (xtn->p[0], F_GETFD);
|
||||
if (flag >= 0) fcntl (xtn->p[0], F_SETFD, flag | FD_CLOEXEC);
|
||||
flag = fcntl (xtn->p[1], F_GETFD);
|
||||
if (flag >= 0) fcntl (xtn->p[1], F_SETFD, flag | FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
#if defined(O_NONBLOCK)
|
||||
flag = fcntl (xtn->p[0], F_GETFL);
|
||||
if (flag >= 0) fcntl (xtn->p[0], F_SETFL, flag | O_NONBLOCK);
|
||||
flag = fcntl (xtn->p[1], F_GETFL);
|
||||
if (flag >= 0) fcntl (xtn->p[1], F_SETFL, flag | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
if (_add_poll_fd(hcl, xtn->p[0], XPOLLIN) <= -1) goto oops;
|
||||
|
||||
pthread_mutex_init (&xtn->ev.mtx, HCL_NULL);
|
||||
pthread_cond_init (&xtn->ev.cnd, HCL_NULL);
|
||||
pthread_cond_init (&xtn->ev.cnd2, HCL_NULL);
|
||||
|
||||
xtn->iothr_abort = 0;
|
||||
xtn->iothr_up = 0;
|
||||
/*pthread_create (&xtn->iothr, HCL_NULL, iothr_main, hcl);*/
|
||||
|
||||
|
||||
#endif /* USE_THREAD */
|
||||
|
||||
xtn->vm_running = 1;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
|
||||
#if defined(USE_THREAD)
|
||||
if (pcount > 0)
|
||||
{
|
||||
close (xtn->p[0]);
|
||||
close (xtn->p[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_DEVPOLL) || defined(USE_EPOLL)
|
||||
if (xtn->ep >= 0)
|
||||
{
|
||||
close (xtn->ep);
|
||||
xtn->ep = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vm_cleanup (hcl_t* hcl)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
xtn_t* xtn = (xatn_t*)hcl_getxtn(hcl);
|
||||
if (xtn->waitable_timer)
|
||||
{
|
||||
CloseHandle (xtn->waitable_timer);
|
||||
xtn->waitable_timer = HCL_NULL;
|
||||
}
|
||||
#else
|
||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||
|
||||
xtn->vm_running = 0;
|
||||
|
||||
#if defined(USE_THREAD)
|
||||
if (xtn->iothr_up)
|
||||
{
|
||||
xtn->iothr_abort = 1;
|
||||
write (xtn->p[1], "Q", 1);
|
||||
pthread_cond_signal (&xtn->ev.cnd);
|
||||
pthread_join (xtn->iothr, HCL_NULL);
|
||||
xtn->iothr_up = 0;
|
||||
}
|
||||
pthread_cond_destroy (&xtn->ev.cnd);
|
||||
pthread_cond_destroy (&xtn->ev.cnd2);
|
||||
pthread_mutex_destroy (&xtn->ev.mtx);
|
||||
|
||||
_del_poll_fd (hcl, xtn->p[0]);
|
||||
close (xtn->p[1]);
|
||||
close (xtn->p[0]);
|
||||
#endif /* USE_THREAD */
|
||||
|
||||
#if defined(USE_DEVPOLL)
|
||||
if (xtn->ep >= 0)
|
||||
{
|
||||
close (xtn->ep);
|
||||
xtn->ep = -1;
|
||||
}
|
||||
/*destroy_poll_data_space (hcl);*/
|
||||
#elif defined(USE_EPOLL)
|
||||
if (xtn->ep >= 0)
|
||||
{
|
||||
close (xtn->ep);
|
||||
xtn->ep = -1;
|
||||
}
|
||||
#elif defined(USE_POLL)
|
||||
if (xtn->ev.reg.ptr)
|
||||
{
|
||||
hcl_freemem (hcl, xtn->ev.reg.ptr);
|
||||
xtn->ev.reg.ptr = HCL_NULL;
|
||||
xtn->ev.reg.len = 0;
|
||||
xtn->ev.reg.capa = 0;
|
||||
}
|
||||
if (xtn->ev.buf)
|
||||
{
|
||||
hcl_freemem (hcl, xtn->ev.buf);
|
||||
xtn->ev.buf = HCL_NULL;
|
||||
}
|
||||
/*destroy_poll_data_space (hcl);*/
|
||||
MUTEX_DESTROY (&xtn->ev.reg.pmtx);
|
||||
#elif defined(USE_SELECT)
|
||||
FD_ZERO (&xtn->ev.reg.rfds);
|
||||
FD_ZERO (&xtn->ev.reg.wfds);
|
||||
xtn->ev.reg.maxfd = -1;
|
||||
MUTEX_DESTROY (&xtn->ev.reg.smtx);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vm_gettime (hcl_t* hcl, hcl_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, HCL_SIZEOF(out)); /* milliseconds */
|
||||
/* it must return NO_ERROR */
|
||||
HCL_INITNTIME (now, HCL_MSEC_TO_SEC(out), HCL_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 = HCL_MSEC_TO_NSEC((c % CLOCKS_PER_SEC) * 10);
|
||||
#elif (CLOCKS_PER_SEC == 1000)
|
||||
now->nsec = HCL_MSEC_TO_NSEC(c % CLOCKS_PER_SEC);
|
||||
#elif (CLOCKS_PER_SEC == 1000000L)
|
||||
now->nsec = HCL_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;
|
||||
hcl_uint64_t tick64;
|
||||
Microseconds (&tick);
|
||||
tick64 = *(hcl_uint64_t*)&tick;
|
||||
HCL_INITNTIME (now, HCL_USEC_TO_SEC(tick64), HCL_USEC_TO_NSEC(tick64));
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
clock_gettime (CLOCK_MONOTONIC, &ts);
|
||||
HCL_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
||||
struct timespec ts;
|
||||
clock_gettime (CLOCK_REALTIME, &ts);
|
||||
HCL_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, HCL_NULL);
|
||||
HCL_INITNTIME(now, tv.tv_sec, HCL_USEC_TO_NSEC(tv.tv_usec));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vm_sleep (hcl_t* hcl, const hcl_ntime_t* dur)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
xtn_t* xtn = hcl_getxtn(hcl);
|
||||
if (xtn->waitable_timer)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -HCL_SECNSEC_TO_NSEC(dur->sec, dur->nsec);
|
||||
if(SetWaitableTimer(timer, &li, 0, HCL_NULL, HCL_NULL, FALSE) == FALSE) goto normal_sleep;
|
||||
WaitForSingleObject(timer, INFINITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
normal_sleep:
|
||||
/* fallback to normal Sleep() */
|
||||
Sleep (HCL_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 (HCL_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 += HCL_NSEC_TO_MSEC(dur->nsec) / 10;
|
||||
#elif (CLOCKS_PER_SEC == 1000)
|
||||
c += HCL_NSEC_TO_MSEC(dur->nsec);
|
||||
#elif (CLOCKS_PER_SEC == 1000000L)
|
||||
c += HCL_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
|
||||
#if defined(USE_THREAD)
|
||||
/* the sleep callback is called only if there is no IO semaphore
|
||||
* waiting. so i can safely call vm_muxwait() without a muxwait callback
|
||||
* when USE_THREAD is true */
|
||||
vm_muxwait (hcl, dur, HCL_NULL);
|
||||
#elif defined(HAVE_NANOSLEEP)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = dur->sec;
|
||||
ts.tv_nsec = dur->nsec;
|
||||
nanosleep (&ts, HCL_NULL);
|
||||
#elif defined(HAVE_USLEEP)
|
||||
usleep (HCL_SECNSEC_TO_USEC(dur->sec, dur->nsec));
|
||||
#else
|
||||
# error UNSUPPORT SLEEP
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static void fini_hcl (hcl_t* hcl)
|
||||
{
|
||||
xtn_t* xtn = hcl_getxtn(hcl);
|
||||
@ -906,8 +1218,12 @@ int main (int argc, char* argv[])
|
||||
|
||||
|
||||
memset (&vmprim, 0, HCL_SIZEOF(vmprim));
|
||||
vmprim.log_write = log_write;
|
||||
vmprim.log_write = log_write;
|
||||
vmprim.syserrstrb = syserrstrb;
|
||||
vmprim.vm_startup = vm_startup;
|
||||
vmprim.vm_cleanup = vm_cleanup;
|
||||
vmprim.vm_gettime = vm_gettime;
|
||||
vmprim.vm_sleep = vm_sleep;
|
||||
|
||||
hcl = hcl_open (&sys_mmgr, HCL_SIZEOF(xtn_t), 2048000lu, &vmprim, HCL_NULL);
|
||||
if (!hcl)
|
||||
|
Loading…
Reference in New Issue
Block a user