more code to add standard callbacks

This commit is contained in:
hyunghwan.chung 2018-11-11 16:53:21 +00:00
parent d32394cdef
commit cd6c6d994c
7 changed files with 507 additions and 2707 deletions

View File

@ -185,15 +185,21 @@ static const moo_ooch_t* synerr_to_errstr (moo_synerrnum_t errnum)
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
const moo_ooch_t* moo_geterrstr (moo_t* moo) const moo_ooch_t* moo_geterrstr (moo_t* moo)
{ {
return moo_errnum_to_errstr (moo->errnum); return moo_errnum_to_errstr(moo->errnum);
} }
const moo_ooch_t* moo_geterrmsg (moo_t* moo) const moo_ooch_t* moo_geterrmsg (moo_t* moo)
{ {
if (moo->errmsg.len <= 0) return moo_errnum_to_errstr (moo->errnum); if (moo->errmsg.len <= 0) return moo_errnum_to_errstr(moo->errnum);
return moo->errmsg.buf; return moo->errmsg.buf;
} }
void moo_geterrinf (moo_t* moo, moo_errinf_t* info)
{
info->num = moo_geterrnum(moo);
moo_copy_oocstr (info->msg, MOO_COUNTOF(info->msg), moo_geterrmsg(moo));
}
const moo_ooch_t* moo_backuperrmsg (moo_t* moo) const moo_ooch_t* moo_backuperrmsg (moo_t* moo)
{ {
moo_copy_oocstr (moo->errmsg.tmpbuf.ooch, MOO_COUNTOF(moo->errmsg.tmpbuf.ooch), moo_geterrmsg(moo)); moo_copy_oocstr (moo->errmsg.tmpbuf.ooch, MOO_COUNTOF(moo->errmsg.tmpbuf.ooch), moo_geterrmsg(moo));

View File

@ -644,7 +644,7 @@ moo_ooi_t moo_logbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...
fo.putcs = put_oocs; fo.putcs = put_oocs;
va_start (ap, fmt); va_start (ap, fmt);
x = _logbfmtv (moo, fmt, &fo, ap); x = _logbfmtv(moo, fmt, &fo, ap);
va_end (ap); va_end (ap);
if (moo->log.len > 0 && moo->log.ptr[moo->log.len - 1] == '\n') if (moo->log.len > 0 && moo->log.ptr[moo->log.len - 1] == '\n')
@ -672,7 +672,7 @@ moo_ooi_t moo_logufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...
fo.putcs = put_oocs; fo.putcs = put_oocs;
va_start (ap, fmt); va_start (ap, fmt);
x = _logufmtv (moo, fmt, &fo, ap); x = _logufmtv(moo, fmt, &fo, ap);
va_end (ap); va_end (ap);
if (moo->log.len > 0 && moo->log.ptr[moo->log.len - 1] == '\n') if (moo->log.len > 0 && moo->log.ptr[moo->log.len - 1] == '\n')

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,33 @@
#include <moo.h> #include <moo.h>
enum moo_cfg_type_t
{
MOO_CFG_TYPE_B,
MOO_CFG_TYPE_U
};
typedef enum moo_cfg_type_t moo_cfg_type_t;
struct moo_cfg_t
{
moo_cfg_type_t type;
moo_oow_t memsize;
int large_pages;
const void* logopt;
const void* dbgopt;
};
typedef struct moo_cfg_t moo_cfg_t;
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
MOO_EXPORT moo_t* moo_openstd ( MOO_EXPORT moo_t* moo_openstd (
moo_oow_t xtnsize, moo_oow_t xtnsize,
moo_oow_t memsize, const moo_cfg_t* cfg,
moo_errnum_t* errnum moo_errinf_t* errinfo
); );
MOO_EXPORT void* moo_getxtnstd ( MOO_EXPORT void* moo_getxtnstd (

View File

@ -26,7 +26,7 @@
#include "moo-prv.h" #include "moo-prv.h"
moo_t* moo_open (moo_mmgr_t* mmgr, moo_oow_t xtnsize, moo_oow_t heapsize, const moo_vmprim_t* vmprim, moo_errnum_t* errnum) moo_t* moo_open (moo_mmgr_t* mmgr, moo_oow_t xtnsize, moo_oow_t heapsize, const moo_vmprim_t* vmprim, moo_errinf_t* errinfo)
{ {
moo_t* moo; moo_t* moo;
@ -38,13 +38,17 @@ moo_t* moo_open (moo_mmgr_t* mmgr, moo_oow_t xtnsize, moo_oow_t heapsize, const
{ {
if (moo_init(moo, mmgr, heapsize, vmprim) <= -1) if (moo_init(moo, mmgr, heapsize, vmprim) <= -1)
{ {
if (errnum) *errnum = moo->errnum; if (errinfo) moo_geterrinf (moo, errinfo);
MOO_MMGR_FREE (mmgr, moo); MOO_MMGR_FREE (mmgr, moo);
moo = MOO_NULL; moo = MOO_NULL;
} }
else MOO_MEMSET (moo + 1, 0, xtnsize); else MOO_MEMSET (moo + 1, 0, xtnsize);
} }
else if (errnum) *errnum = MOO_ESYSMEM; else if (errinfo)
{
errinfo->num = MOO_ESYSMEM;
moo_copy_oocstr (errinfo->msg, MOO_COUNTOF(errinfo->msg), moo_errnum_to_errstr(MOO_ESYSMEM));
}
return moo; return moo;
} }
@ -109,7 +113,8 @@ int moo_init (moo_t* moo, moo_mmgr_t* mmgr, moo_oow_t heapsz, const moo_vmprim_t
if (!moo->vmprim.alloc_heap) moo->vmprim.alloc_heap = alloc_heap; if (!moo->vmprim.alloc_heap) moo->vmprim.alloc_heap = alloc_heap;
if (!moo->vmprim.free_heap) moo->vmprim.free_heap = free_heap; if (!moo->vmprim.free_heap) moo->vmprim.free_heap = free_heap;
moo->option.log_mask = ~0u; /*moo->option.log_mask = ~0u;*/
moo->option.log_mask = MOO_LOG_ALL_LEVELS | MOO_LOG_ALL_TYPES;
moo->option.log_maxcapa = MOO_DFL_LOG_MAXCAPA; moo->option.log_maxcapa = MOO_DFL_LOG_MAXCAPA;
moo->option.dfl_symtab_size = MOO_DFL_SYMTAB_SIZE; moo->option.dfl_symtab_size = MOO_DFL_SYMTAB_SIZE;
moo->option.dfl_sysdic_size = MOO_DFL_SYSDIC_SIZE; moo->option.dfl_sysdic_size = MOO_DFL_SYSDIC_SIZE;

View File

@ -999,10 +999,8 @@ enum moo_log_mask_t
MOO_LOG_ALL_LEVELS = (MOO_LOG_DEBUG | MOO_LOG_INFO | MOO_LOG_WARN | MOO_LOG_ERROR | MOO_LOG_FATAL), MOO_LOG_ALL_LEVELS = (MOO_LOG_DEBUG | MOO_LOG_INFO | MOO_LOG_WARN | MOO_LOG_ERROR | MOO_LOG_FATAL),
MOO_LOG_ALL_TYPES = (MOO_LOG_UNTYPED | MOO_LOG_COMPILER | MOO_LOG_VM | MOO_LOG_MNEMONIC | MOO_LOG_GC | MOO_LOG_IC | MOO_LOG_PRIMITIVE | MOO_LOG_APP), MOO_LOG_ALL_TYPES = (MOO_LOG_UNTYPED | MOO_LOG_COMPILER | MOO_LOG_VM | MOO_LOG_MNEMONIC | MOO_LOG_GC | MOO_LOG_IC | MOO_LOG_PRIMITIVE | MOO_LOG_APP),
MOO_LOG_STDOUT = (1u << 14), /* write log messages to stdout without timestamp. MOO_LOG_STDOUT wins over MOO_LOG_STDERR. */ MOO_LOG_STDOUT = (1u << 14), /* write log messages to stdout without timestamp. MOO_LOG_STDOUT wins over MOO_LOG_STDERR. */
MOO_LOG_STDERR = (1u << 15) /* write log messages to stderr without timestamp. */ MOO_LOG_STDERR = (1u << 15) /* write log messages to stderr without timestamp. */
}; };
typedef enum moo_log_mask_t moo_log_mask_t; typedef enum moo_log_mask_t moo_log_mask_t;
@ -1373,6 +1371,12 @@ enum moo_sbuf_id_t
/* more? */ /* more? */
}; };
struct moo_errinf_t
{
moo_errnum_t num;
moo_ooch_t msg[MOO_ERRMSG_CAPA];
};
typedef struct moo_errinf_t moo_errinf_t;
struct moo_t struct moo_t
{ {
@ -1771,7 +1775,7 @@ MOO_EXPORT moo_t* moo_open (
moo_oow_t xtnsize, moo_oow_t xtnsize,
moo_oow_t heapsize, moo_oow_t heapsize,
const moo_vmprim_t* vmprim, const moo_vmprim_t* vmprim,
moo_errnum_t* errnum moo_errinf_t* errinfo
); );
MOO_EXPORT void moo_close ( MOO_EXPORT void moo_close (
@ -1840,6 +1844,11 @@ MOO_EXPORT const moo_ooch_t* moo_geterrmsg (
moo_t* moo moo_t* moo
); );
MOO_EXPORT void moo_geterrinf (
moo_t* moo,
moo_errinf_t* info
);
MOO_EXPORT const moo_ooch_t* moo_backuperrmsg ( MOO_EXPORT const moo_ooch_t* moo_backuperrmsg (
moo_t* moo moo_t* moo
); );

View File

@ -1,4 +1,3 @@
/* /*
* $Id$ * $Id$
* *
@ -25,18 +24,11 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <moo-std.h>
#include "moo-prv.h" #include "moo-prv.h"
#include "moo-opt.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <locale.h>
*/
#if !defined(__DOS__) && defined(HAVE_PTHREAD) && defined(HAVE_STRERROR_R) #if !defined(__DOS__) && defined(HAVE_PTHREAD) && defined(HAVE_STRERROR_R)
# define USE_THREAD # define USE_THREAD
@ -259,15 +251,24 @@ struct select_fd_t
}; };
#endif #endif
enum logfd_trait_t
{
LOGFD_TTY = (1 << 0),
LOGFD_OPENED = (1 << 1)
};
typedef struct std_xtn_t std_xtn_t; typedef struct std_xtn_t std_xtn_t;
struct std_xtn_t struct std_xtn_t
{ {
moo_t* next;
moo_t* prev;
const char* source_path; /* main source file */ const char* source_path; /* main source file */
int vm_running; int vm_running;
moo_bitmask_t logmask; moo_bitmask_t logmask;
int logfd; int logfd;
int logfd_istty; int logfd_trait; /* bitwise OR'ed fo logfd_trait_t bits */
struct struct
{ {
@ -275,6 +276,7 @@ struct std_xtn_t
moo_oow_t len; moo_oow_t len;
} logbuf; } logbuf;
#if defined(_WIN32) #if defined(_WIN32)
HANDLE waitable_timer; HANDLE waitable_timer;
DWORD tc_last; DWORD tc_last;
@ -347,6 +349,10 @@ struct std_xtn_t
} ev; } ev;
}; };
#define GETXTNSTD(moo) ((std_xtn_t*)((moo_uint8_t*)moo_getxtn(moo) + MOO_SIZEOF(std_xtn_t)))
static moo_t* g_moo = MOO_NULL;
/* ========================================================================= */ /* ========================================================================= */
static void* sys_alloc (moo_mmgr_t* mmgr, moo_oow_t size) static void* sys_alloc (moo_mmgr_t* mmgr, moo_oow_t size)
@ -481,7 +487,6 @@ static MOO_INLINE moo_ooi_t close_input (moo_t* moo, moo_ioarg_t* arg)
return 0; return 0;
} }
static MOO_INLINE moo_ooi_t read_input (moo_t* moo, moo_ioarg_t* arg) static MOO_INLINE moo_ooi_t read_input (moo_t* moo, moo_ioarg_t* arg)
{ {
/*std_xtn_t* xtn = moo_getxtn(moo);*/ /*std_xtn_t* xtn = moo_getxtn(moo);*/
@ -522,7 +527,7 @@ static MOO_INLINE moo_ooi_t read_input (moo_t* moo, moo_ioarg_t* arg)
#endif #endif
remlen = bb->len - bcslen; remlen = bb->len - bcslen;
if (remlen > 0) memmove (bb->buf, &bb->buf[bcslen], remlen); if (remlen > 0) MOO_MEMMOVE (bb->buf, &bb->buf[bcslen], remlen);
bb->len = remlen; bb->len = remlen;
return ucslen; return ucslen;
} }
@ -532,13 +537,13 @@ static moo_ooi_t input_handler (moo_t* moo, moo_iocmd_t cmd, moo_ioarg_t* arg)
switch (cmd) switch (cmd)
{ {
case MOO_IO_OPEN: case MOO_IO_OPEN:
return open_input (moo, arg); return open_input(moo, arg);
case MOO_IO_CLOSE: case MOO_IO_CLOSE:
return close_input (moo, arg); return close_input(moo, arg);
case MOO_IO_READ: case MOO_IO_READ:
return read_input (moo, arg); return read_input(moo, arg);
default: default:
moo_seterrnum (moo, MOO_EINTERN); moo_seterrnum (moo, MOO_EINTERN);
@ -657,7 +662,7 @@ static int write_log (moo_t* moo, int fd, const moo_bch_t* ptr, moo_oow_t len)
rcapa = MOO_COUNTOF(xtn->logbuf.buf) - xtn->logbuf.len; rcapa = MOO_COUNTOF(xtn->logbuf.buf) - xtn->logbuf.len;
cplen = (len >= rcapa)? rcapa: len; cplen = (len >= rcapa)? rcapa: len;
memcpy (&xtn->logbuf.buf[xtn->logbuf.len], ptr, cplen); MOO_MEMCPY (&xtn->logbuf.buf[xtn->logbuf.len], ptr, cplen);
xtn->logbuf.len += cplen; xtn->logbuf.len += cplen;
ptr += cplen; ptr += cplen;
len -= cplen; len -= cplen;
@ -683,7 +688,7 @@ static int write_log (moo_t* moo, int fd, const moo_bch_t* ptr, moo_oow_t len)
} }
else else
{ {
memcpy (xtn->logbuf.buf, ptr, len); MOO_MEMCPY (xtn->logbuf.buf, ptr, len);
xtn->logbuf.len += len; xtn->logbuf.len += len;
ptr += len; ptr += len;
len -= len; len -= len;
@ -785,7 +790,7 @@ static void log_write (moo_t* moo, moo_bitmask_t mask, const moo_ooch_t* msg, mo
write_log (moo, logfd, ts, tslen); write_log (moo, logfd, ts, tslen);
} }
if (logfd == xtn->logfd && xtn->logfd_istty) if (logfd == xtn->logfd && (xtn->logfd_trait & LOGFD_TTY))
{ {
if (mask & MOO_LOG_FATAL) write_log (moo, logfd, "\x1B[1;31m", 7); if (mask & MOO_LOG_FATAL) write_log (moo, logfd, "\x1B[1;31m", 7);
else if (mask & MOO_LOG_ERROR) write_log (moo, logfd, "\x1B[1;32m", 7); else if (mask & MOO_LOG_ERROR) write_log (moo, logfd, "\x1B[1;32m", 7);
@ -830,7 +835,7 @@ static void log_write (moo_t* moo, moo_bitmask_t mask, const moo_ooch_t* msg, mo
write_log (moo, logfd, msg, len); write_log (moo, logfd, msg, len);
#endif #endif
if (logfd == xtn->logfd && xtn->logfd_istty) if (logfd == xtn->logfd && (xtn->logfd_trait & LOGFD_TTY))
{ {
if (mask & (MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN)) write_log (moo, logfd, "\x1B[0m", 4); if (mask & (MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN)) write_log (moo, logfd, "\x1B[0m", 4);
} }
@ -1527,7 +1532,7 @@ static int _add_poll_fd (moo_t* moo, int fd, int event_mask)
struct epoll_event ev; struct epoll_event ev;
MOO_ASSERT (moo, xtn->ep >= 0); MOO_ASSERT (moo, xtn->ep >= 0);
memset (&ev, 0, MOO_SIZEOF(ev)); MOO_MEMSET (&ev, 0, MOO_SIZEOF(ev));
ev.events = event_mask; ev.events = event_mask;
#if defined(USE_THREAD) && defined(EPOLLET) #if defined(USE_THREAD) && defined(EPOLLET)
/* epoll_wait may return again if the worker thread consumes events. /* epoll_wait may return again if the worker thread consumes events.
@ -1631,7 +1636,7 @@ static int _del_poll_fd (moo_t* moo, int fd)
struct epoll_event ev; struct epoll_event ev;
MOO_ASSERT (moo, xtn->ep >= 0); MOO_ASSERT (moo, xtn->ep >= 0);
memset (&ev, 0, MOO_SIZEOF(ev)); MOO_MEMSET (&ev, 0, MOO_SIZEOF(ev));
if (epoll_ctl (xtn->ep, EPOLL_CTL_DEL, fd, &ev) == -1) if (epoll_ctl (xtn->ep, EPOLL_CTL_DEL, fd, &ev) == -1)
{ {
moo_seterrwithsyserr (moo, 0, errno); moo_seterrwithsyserr (moo, 0, errno);
@ -1651,7 +1656,7 @@ static int _del_poll_fd (moo_t* moo, int fd)
if (xtn->ev.reg.ptr[i].fd == fd) if (xtn->ev.reg.ptr[i].fd == fd)
{ {
xtn->ev.reg.len--; xtn->ev.reg.len--;
memmove (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i) * MOO_SIZEOF(*xtn->ev.reg.ptr)); MOO_MEMMOVE (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i) * MOO_SIZEOF(*xtn->ev.reg.ptr));
MUTEX_UNLOCK (&xtn->ev.reg.pmtx); MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
return 0; return 0;
} }
@ -1711,7 +1716,7 @@ static int _mod_poll_fd (moo_t* moo, int fd, int event_mask)
struct epoll_event ev; struct epoll_event ev;
MOO_ASSERT (moo, xtn->ep >= 0); MOO_ASSERT (moo, xtn->ep >= 0);
memset (&ev, 0, MOO_SIZEOF(ev)); MOO_MEMSET (&ev, 0, MOO_SIZEOF(ev));
ev.events = event_mask; ev.events = event_mask;
#if defined(USE_THREAD) && defined(EPOLLET) #if defined(USE_THREAD) && defined(EPOLLET)
/* epoll_wait may return again if the worker thread consumes events. /* epoll_wait may return again if the worker thread consumes events.
@ -1739,7 +1744,7 @@ static int _mod_poll_fd (moo_t* moo, int fd, int event_mask)
{ {
if (xtn->ev.reg.ptr[i].fd == fd) if (xtn->ev.reg.ptr[i].fd == fd)
{ {
memmove (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i - 1) * MOO_SIZEOF(*xtn->ev.reg.ptr)); MOO_MEMMOVE (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i - 1) * MOO_SIZEOF(*xtn->ev.reg.ptr));
xtn->ev.reg.ptr[i].fd = fd; xtn->ev.reg.ptr[i].fd = fd;
xtn->ev.reg.ptr[i].events = event_mask; xtn->ev.reg.ptr[i].events = event_mask;
xtn->ev.reg.ptr[i].revents = 0; xtn->ev.reg.ptr[i].revents = 0;
@ -2124,7 +2129,7 @@ static void* iothr_main (void* arg)
n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), 10000); /* TODO: make this timeout value in the io thread */ n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), 10000); /* TODO: make this timeout value in the io thread */
#elif defined(USE_POLL) #elif defined(USE_POLL)
MUTEX_LOCK (&xtn->ev.reg.pmtx); MUTEX_LOCK (&xtn->ev.reg.pmtx);
memcpy (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf)); MOO_MEMCPY (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf));
nfds = xtn->ev.reg.len; nfds = xtn->ev.reg.len;
MUTEX_UNLOCK (&xtn->ev.reg.pmtx); MUTEX_UNLOCK (&xtn->ev.reg.pmtx);
n = poll(xtn->ev.buf, nfds, 10000); n = poll(xtn->ev.buf, nfds, 10000);
@ -2366,7 +2371,7 @@ static void vm_muxwait (moo_t* moo, const moo_ntime_t* dur, moo_vmprim_muxwait_c
#elif defined(USE_EPOLL) #elif defined(USE_EPOLL)
n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), tmout); n = epoll_wait (xtn->ep, xtn->ev.buf, MOO_COUNTOF(xtn->ev.buf), tmout);
#elif defined(USE_POLL) #elif defined(USE_POLL)
memcpy (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf)); MOO_MEMCPY (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * MOO_SIZEOF(*xtn->ev.buf));
n = poll(xtn->ev.buf, xtn->ev.reg.len, tmout); n = poll(xtn->ev.buf, xtn->ev.reg.len, tmout);
if (n > 0) if (n > 0)
{ {
@ -2553,27 +2558,386 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur)
#endif #endif
#endif #endif
} }
/* ========================================================================= */
static MOO_INLINE void swproc_all (void)
{
/* TODO: make this atomic */
if (g_moo)
{
moo_t* moo = g_moo;
do
{
moo_switchprocess (moo);
moo = GETXTNSTD(moo)->next;
}
while (moo);
}
/* TODO: make this atomic */
}
#if defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
#if defined(_INTELC32_)
static void (*prev_timer_intr_handler) (void);
#else
static void (__interrupt *prev_timer_intr_handler) (void);
#endif
#if defined(_INTELC32_)
#pragma interrupt(timer_intr_handler)
static void timer_intr_handler (void)
#else
static void __interrupt timer_intr_handler (void)
#endif
{
/*
_XSTACK *stk;
int r;
stk = (_XSTACK *)_get_stk_frame();
r = (unsigned short)stk_ptr->eax;
*/
/* The timer interrupt (normally) occurs 18.2 times per second. */
if (g_moo) moo_switchprocess (g_moo);
_chain_intr (prev_timer_intr_handler);
}
#elif defined(_WIN32)
static HANDLE g_tick_timer = MOO_NULL; /*INVALID_HANDLE_VALUE;*/
static VOID CALLBACK arrange_process_switching (LPVOID arg, DWORD timeLow, DWORD timeHigh)
{
swproc_all ();
}
#elif defined(__OS2__)
static TID g_tick_tid;
static HEV g_tick_sem;
static HTIMER g_tick_timer;
static int g_tick_done = 0;
static void EXPENTRY os2_wait_for_timer_event (ULONG x)
{
APIRET rc;
ULONG count;
rc = DosCreateEventSem (NULL, &g_tick_sem, DC_SEM_SHARED, FALSE);
if (rc != NO_ERROR)
{
/* xxxx */
}
rc = DosStartTimer (1L, (HSEM)g_tick_sem, &g_tick_timer);
if (rc != NO_ERROR)
{
}
while (!g_tick_done)
{
rc = DosWaitEventSem((HSEM)g_tick_sem, 5000L);
DosResetEventSem((HSEM)g_tick_sem, &count);
swproc_all ();
}
DosStopTimer (g_tick_timer);
DosCloseEventSem ((HSEM)g_tick_sem);
g_tick_timer = NULL;
g_tick_sem = NULL;
DosExit (EXIT_THREAD, 0);
}
#elif defined(macintosh)
static TMTask g_tmtask;
static ProcessSerialNumber g_psn;
#define TMTASK_DELAY 50 /* milliseconds if positive, microseconds(after negation) if negative */
static pascal void timer_intr_handler (TMTask* task)
{
swproc_all ();
WakeUpProcess (&g_psn);
PrimeTime ((QElem*)&g_tmtask, TMTASK_DELAY);
}
#else
static void arrange_process_switching (int sig)
{
swproc_all ();
}
#endif
static void setup_tick (void)
{
#if defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
prev_timer_intr_handler = _dos_getvect (0x1C);
_dos_setvect (0x1C, timer_intr_handler);
#elif defined(_WIN32)
LARGE_INTEGER li;
g_tick_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL);
if (g_tick_timer)
{
li.QuadPart = -MOO_SECNSEC_TO_NSEC(0, 20000); /* 20000 microseconds. 0.02 seconds */
SetWaitableTimer (g_tick_timer, &li, 0, arrange_process_switching, MOO_NULL, FALSE);
}
#elif defined(__OS2__)
/* TODO: Error check */
DosCreateThread (&g_tick_tid, os2_wait_for_timer_event, 0, 0, 4096);
#elif defined(macintosh)
GetCurrentProcess (&g_psn);
memset (&g_tmtask, 0, MOO_SIZEOF(g_tmtask));
g_tmtask.tmAddr = NewTimerProc (timer_intr_handler);
InsXTime ((QElem*)&g_tmtask);
PrimeTime ((QElem*)&g_tmtask, TMTASK_DELAY);
#elif defined(HAVE_SETITIMER) && defined(SIGVTALRM) && defined(ITIMER_VIRTUAL)
struct itimerval itv;
struct sigaction act;
memset (&act, 0, sizeof(act));
sigemptyset (&act.sa_mask);
act.sa_handler = arrange_process_switching;
act.sa_flags = SA_RESTART;
sigaction (SIGVTALRM, &act, MOO_NULL);
/*#define MOO_ITIMER_TICK 10000*/ /* microseconds. 0.01 seconds */
#define MOO_ITIMER_TICK 20000 /* microseconds. 0.02 seconds. */
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = MOO_ITIMER_TICK;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = MOO_ITIMER_TICK;
setitimer (ITIMER_VIRTUAL, &itv, MOO_NULL);
#else
# error UNSUPPORTED
#endif
}
static void cancel_tick (void)
{
#if defined(__DOS__) && (defined(_INTELC32_) || defined(__WATCOMC__))
_dos_setvect (0x1C, prev_timer_intr_handler);
#elif defined(_WIN32)
if (g_tick_timer)
{
CancelWaitableTimer (g_tick_timer);
CloseHandle (g_tick_timer);
g_tick_timer = MOO_NULL;
}
#elif defined(__OS2__)
if (g_tick_sem) DosPostEventSem (g_tick_sem);
g_tick_done = 1;
#elif defined(macintosh)
RmvTime ((QElem*)&g_tmtask);
/*DisposeTimerProc (g_tmtask.tmAddr);*/
#elif defined(HAVE_SETITIMER) && defined(SIGVTALRM) && defined(ITIMER_VIRTUAL)
struct itimerval itv;
struct sigaction act;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0; /* make setitimer() one-shot only */
itv.it_value.tv_usec = 0;
setitimer (ITIMER_VIRTUAL, &itv, MOO_NULL);
sigemptyset (&act.sa_mask);
act.sa_handler = SIG_IGN; /* ignore the signal potentially fired by the one-shot arrange above */
act.sa_flags = 0;
sigaction (SIGVTALRM, &act, MOO_NULL);
#else
# error UNSUPPORTED
#endif
}
/* ========================================================================= */
static struct
{
const char* name;
moo_bitmask_t mask;
} log_mask_table[] =
{
{ "app", MOO_LOG_APP },
{ "compiler", MOO_LOG_COMPILER },
{ "vm", MOO_LOG_VM },
{ "mnemonic", MOO_LOG_MNEMONIC },
{ "gc", MOO_LOG_GC },
{ "ic", MOO_LOG_IC },
{ "primitive", MOO_LOG_PRIMITIVE },
{ "fatal", MOO_LOG_FATAL },
{ "error", MOO_LOG_ERROR },
{ "warn", MOO_LOG_WARN },
{ "info", MOO_LOG_INFO },
{ "debug", MOO_LOG_DEBUG },
{ "fatal+", MOO_LOG_FATAL },
{ "error+", MOO_LOG_FATAL | MOO_LOG_ERROR },
{ "warn+", MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN },
{ "info+", MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN | MOO_LOG_INFO },
{ "debug+", MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN | MOO_LOG_INFO | MOO_LOG_DEBUG }
};
static int handle_logopt (moo_t* moo, const moo_bch_t* str)
{
std_xtn_t* xtn = moo_getxtn (moo);
moo_bch_t* xstr = (moo_bch_t*)str;
moo_bch_t* cm, * flt;
moo_bitmask_t logmask;
moo_oow_t i;
cm = moo_find_bchar_in_bcstr(xstr, ',');
if (cm)
{
/* i duplicate this string for open() below as open() doesn't
* accept a length-bounded string */
xstr = moo_dupbchars(moo, str, moo_count_bcstr(str));
if (!xstr)
{
moo_seterrbfmt (moo, MOO_ESYSERR, "out of memory in duplicating %hs", str);
return -1;
}
cm = moo_find_bchar_in_bcstr(xstr, ',');
*cm = '\0';
logmask = xtn->logmask;
do
{
flt = cm + 1;
cm = moo_find_bchar_in_bcstr(flt, ',');
if (cm) *cm = '\0';
for (i = 0; i < MOO_COUNTOF(log_mask_table); i++)
{
if (moo_comp_bcstr(flt, log_mask_table[i].name) == 0)
{
logmask |= log_mask_table[i].mask;
break;
}
}
if (i >= MOO_COUNTOF(log_mask_table))
{
moo_seterrbfmt (moo, MOO_EINVAL, "unknown log option value %hs", flt);
if (str != xstr) moo_freemem (moo, xstr);
return -1;
}
}
while (cm);
if (!(logmask & MOO_LOG_ALL_TYPES)) logmask |= MOO_LOG_ALL_TYPES; /* no types specified. force to all types */
if (!(logmask & MOO_LOG_ALL_LEVELS)) logmask |= MOO_LOG_ALL_LEVELS; /* no levels specified. force to all levels */
}
else
{
logmask = MOO_LOG_ALL_LEVELS | MOO_LOG_ALL_TYPES;
}
xtn->logfd = open(xstr, O_CREAT | O_WRONLY | O_APPEND , 0644);
if (xtn->logfd == -1)
{
moo_seterrbfmt (moo, MOO_ESYSERR, "cannot open log file %hs", xstr); /* TODO: use syserrb/u??? */
if (str != xstr) moo_freemem (moo, xstr);
return -1;
}
xtn->logmask = logmask;
xtn->logfd_trait |= LOGFD_OPENED;
#if defined(HAVE_ISATTY)
if (isatty(xtn->logfd)) xtn->logfd_trait |= LOGFD_TTY;
#endif
if (str != xstr) moo_freemem (moo, xstr);
return 0;
}
static int handle_dbgopt (moo_t* moo, const moo_bch_t* str)
{
const moo_bch_t* cm, * flt;
moo_oow_t len;
moo_bitmask_t trait, dbgopt = 0;
cm = str - 1;
do
{
flt = cm + 1;
cm = moo_find_bchar_in_bcstr(flt, ',');
len = cm? (cm - flt): moo_count_bcstr(flt);
if (moo_comp_bchars_bcstr(flt, len, "gc") == 0) dbgopt |= MOO_DEBUG_GC;
else if (moo_comp_bchars_bcstr(flt, len, "bigint") == 0) dbgopt |= MOO_DEBUG_BIGINT;
else
{
moo_seterrbfmt (moo, MOO_EINVAL, "unknown log option value %.*hs", len, flt);
return -1;
}
}
while (cm);
moo_getoption (moo, MOO_TRAIT, &trait);
trait |= dbgopt;
moo_setoption (moo, MOO_TRAIT, &trait);
return 0;
}
/* ========================================================================= */ /* ========================================================================= */
static void fini_moo (moo_t* moo) static void fini_moo (moo_t* moo)
{ {
std_xtn_t* xtn = moo_getxtn(moo); std_xtn_t* xtn = GETXTNSTD(moo);
if (xtn->logfd >= 0) if ((xtn->logfd_trait & LOGFD_OPENED) && xtn->logfd >= 0)
{ {
close (xtn->logfd); close (xtn->logfd);
xtn->logfd = -1;
xtn->logfd_istty = 0; /* back to the default */
xtn->logfd = -2;
xtn->logfd_trait = 0;
#if defined(HAVE_ISATTY)
if (isatty(xtn->logfd)) xtn->logfd_trait |= LOGFD_TTY;
#endif
} }
/* TODO: make this atomic */
if (xtn->prev) GETXTNSTD(xtn->prev)->next = xtn->next;
else g_moo = xtn->next;
if (xtn->next) GETXTNSTD(xtn->next)->prev = xtn->prev;
/* TODO: make this atomic */
xtn->prev = MOO_NULL;
xtn->prev = MOO_NULL;
} }
moo_t* moo_openstd (moo_oow_t xtnsize, moo_oow_t memsize, moo_errnum_t* errnum) moo_t* moo_openstd (moo_oow_t xtnsize, const moo_cfg_t* cfg, moo_errinf_t* errinfo)
{ {
moo_t* moo; moo_t* moo;
moo_vmprim_t vmprim; moo_vmprim_t vmprim;
moo_cb_t cb;
std_xtn_t* xtn;
MOO_MEMSET(&vmprim, 0, MOO_SIZEOF(vmprim)); MOO_MEMSET(&vmprim, 0, MOO_SIZEOF(vmprim));
if (1) /* TOOD: */ if (cfg->large_pages)
{ {
vmprim.alloc_heap = alloc_heap; vmprim.alloc_heap = alloc_heap;
vmprim.free_heap = free_heap; vmprim.free_heap = free_heap;
@ -2595,14 +2959,41 @@ moo_t* moo_openstd (moo_oow_t xtnsize, moo_oow_t memsize, moo_errnum_t* errnum)
vmprim.vm_muxwait = vm_muxwait; vmprim.vm_muxwait = vm_muxwait;
vmprim.vm_sleep = vm_sleep; vmprim.vm_sleep = vm_sleep;
moo = moo_open(&sys_mmgr, MOO_SIZEOF(std_xtn_t) + xtnsize, memsize, &vmprim, errnum); moo = moo_open(&sys_mmgr, MOO_SIZEOF(std_xtn_t) + xtnsize, cfg->memsize, &vmprim, errinfo);
if (!moo) return MOO_NULL; if (!moo) return MOO_NULL;
xtn = (std_xtn_t*)GETXTNSTD(moo);
/* initial log goes to stderr */
xtn->logfd = -2;
xtn->logfd_trait = 0;
#if defined(HAVE_ISATTY)
if (isatty(xtn->logfd)) xtn->logfd_trait |= LOGFD_TTY;
#endif
MOO_MEMSET (&cb, 0, MOO_SIZEOF(cb));
cb.fini = fini_moo;
moo_regcb (moo, &cb);
/* TODO: cfg->logopt, dbgopt => bch uch differentation */
if (handle_logopt(moo, cfg->logopt) <= -1 ||
handle_dbgopt(moo, cfg->dbgopt) <= -1)
{
if (errinfo) moo_geterrinf (moo, errinfo);
moo_close (moo);
return MOO_NULL;
}
/* TODO: make this atomic */
if (g_moo) GETXTNSTD(g_moo)->prev = moo;
else g_moo = moo;
xtn->next = g_moo;
/* TODO: make this atomic */
return moo; return moo;
} }
void* moo_getxtnstd (moo_t* moo) void* moo_getxtnstd (moo_t* moo)
{ {
return (void*)((moo_uint8_t*)moo_getxtn(moo) + MOO_SIZEOF(std_xtn_t)); return GETXTNSTD(moo);
} }