cleaned up some code
This commit is contained in:
693
lib/main.c
693
lib/main.c
@ -44,6 +44,8 @@
|
||||
# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
|
||||
# include <ltdl.h>
|
||||
# define USE_LTDL
|
||||
# else
|
||||
# define USE_WIN_DLL
|
||||
# endif
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSMODULEMGR
|
||||
@ -60,27 +62,12 @@
|
||||
# if defined(HCL_ENABLE_LIBLTDL)
|
||||
# include <ltdl.h>
|
||||
# define USE_LTDL
|
||||
# define sys_dl_error() lt_dlerror()
|
||||
# define sys_dl_open(x) lt_dlopen(x)
|
||||
# define sys_dl_openext(x) lt_dlopenext(x)
|
||||
# define sys_dl_close(x) lt_dlclose(x)
|
||||
# define sys_dl_getsym(x,n) lt_dlsym(x,n)
|
||||
# elif defined(HAVE_DLFCN_H)
|
||||
# include <dlfcn.h>
|
||||
# define USE_DLFCN
|
||||
# define sys_dl_error() dlerror()
|
||||
# define sys_dl_open(x) dlopen(x,RTLD_NOW)
|
||||
# define sys_dl_openext(x) dlopen(x,RTLD_NOW)
|
||||
# define sys_dl_close(x) dlclose(x)
|
||||
# define sys_dl_getsym(x,n) dlsym(x,n)
|
||||
# elif defined(__APPLE__) || defined(__MACOSX__)
|
||||
# define USE_MACH_O_DYLD
|
||||
# include <mach-o/dyld.h>
|
||||
# define sys_dl_error() mach_dlerror()
|
||||
# define sys_dl_open(x) mach_dlopen(x)
|
||||
# define sys_dl_openext(x) mach_dlopen(x)
|
||||
# define sys_dl_close(x) mach_dlclose(x)
|
||||
# define sys_dl_getsym(x,n) mach_dlsym(x,n)
|
||||
# else
|
||||
# error UNSUPPORTED DYNAMIC LINKER
|
||||
# endif
|
||||
@ -480,66 +467,6 @@ static int print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg)
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static void* alloc_heap (hcl_t* hcl, hcl_oow_t size)
|
||||
{
|
||||
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) && defined(MAP_ANONYMOUS)
|
||||
/* It's called via hcl_makeheap() when HCL creates a GC heap.
|
||||
* The heap is large in size. I can use a different memory allocation
|
||||
* function instead of an ordinary malloc.
|
||||
* upon failure, it doesn't require to set error information as hcl_makeheap()
|
||||
* set the error number to HCL_EOOMEM. */
|
||||
|
||||
#if !defined(MAP_HUGETLB) && (defined(__amd64__) || defined(__x86_64__))
|
||||
# define MAP_HUGETLB 0x40000
|
||||
#endif
|
||||
|
||||
hcl_oow_t* ptr;
|
||||
int flags;
|
||||
hcl_oow_t actual_size;
|
||||
|
||||
flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
|
||||
#if defined(MAP_HUGETLB)
|
||||
flags |= MAP_HUGETLB;
|
||||
#endif
|
||||
|
||||
#if defined(MAP_UNINITIALIZED)
|
||||
flags |= MAP_UNINITIALIZED;
|
||||
#endif
|
||||
|
||||
actual_size = HCL_SIZEOF(hcl_oow_t) + size;
|
||||
actual_size = HCL_ALIGN_POW2(actual_size, 2 * 1024 * 1024);
|
||||
ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
#if defined(MAP_HUGETLB)
|
||||
flags &= ~MAP_HUGETLB;
|
||||
ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
if (ptr == MAP_FAILED) return HCL_NULL;
|
||||
#else
|
||||
return HCL_NULL;
|
||||
#endif
|
||||
}
|
||||
*ptr = actual_size;
|
||||
|
||||
return (void*)(ptr + 1);
|
||||
|
||||
#else
|
||||
return HCL_MMGR_ALLOC(hcl->mmgr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void free_heap (hcl_t* hcl, void* ptr)
|
||||
{
|
||||
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
|
||||
hcl_oow_t* actual_ptr;
|
||||
actual_ptr = (hcl_oow_t*)ptr - 1;
|
||||
munmap (actual_ptr, *actual_ptr);
|
||||
#else
|
||||
return HCL_MMGR_FREE(hcl->mmgr, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int write_all (int fd, const hcl_bch_t* ptr, hcl_oow_t len)
|
||||
{
|
||||
while (len > 0)
|
||||
@ -772,634 +699,34 @@ static void log_write (hcl_t* hcl, hcl_bitmask_t mask, const hcl_ooch_t* msg, hc
|
||||
flush_log (hcl, logfd);
|
||||
}
|
||||
|
||||
|
||||
static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len)
|
||||
{
|
||||
#if defined(HAVE_STRERROR_R)
|
||||
strerror_r (syserr, buf, len);
|
||||
#else
|
||||
/* this may not be thread safe */
|
||||
hcl_copy_bcstr (buf, len, strerror(syserr));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#if defined(USE_MACH_O_DYLD)
|
||||
static const char* mach_dlerror_str = "";
|
||||
|
||||
static void* mach_dlopen (const char* path)
|
||||
{
|
||||
NSObjectFileImage image;
|
||||
NSObjectFileImageReturnCode rc;
|
||||
void* handle;
|
||||
|
||||
mach_dlerror_str = "";
|
||||
if ((rc = NSCreateObjectFileImageFromFile(path, &image)) != NSObjectFileImageSuccess)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case NSObjectFileImageFailure:
|
||||
case NSObjectFileImageFormat:
|
||||
mach_dlerror_str = "unable to crate object file image";
|
||||
break;
|
||||
|
||||
case NSObjectFileImageInappropriateFile:
|
||||
mach_dlerror_str = "inappropriate file";
|
||||
break;
|
||||
|
||||
case NSObjectFileImageArch:
|
||||
mach_dlerror_str = "incompatible architecture";
|
||||
break;
|
||||
|
||||
case NSObjectFileImageAccess:
|
||||
mach_dlerror_str = "inaccessible file";
|
||||
break;
|
||||
|
||||
default:
|
||||
mach_dlerror_str = "unknown error";
|
||||
break;
|
||||
}
|
||||
return HCL_NULL;
|
||||
}
|
||||
handle = (void*)NSLinkModule(image, path, NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
|
||||
NSDestroyObjectFileImage (image);
|
||||
return handle;
|
||||
}
|
||||
|
||||
static HCL_INLINE void mach_dlclose (void* handle)
|
||||
{
|
||||
mach_dlerror_str = "";
|
||||
NSUnLinkModule (handle, NSUNLINKMODULE_OPTION_NONE);
|
||||
}
|
||||
|
||||
static HCL_INLINE void* mach_dlsym (void* handle, const char* name)
|
||||
{
|
||||
mach_dlerror_str = "";
|
||||
return (void*)NSAddressOfSymbol(NSLookupSymbolInModule(handle, name));
|
||||
}
|
||||
|
||||
static const char* mach_dlerror (void)
|
||||
{
|
||||
int err_no;
|
||||
const char* err_file;
|
||||
NSLinkEditErrors err;
|
||||
|
||||
if (mach_dlerror_str[0] == '\0')
|
||||
NSLinkEditError (&err, &err_no, &err_file, &mach_dlerror_str);
|
||||
|
||||
return mach_dlerror_str;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void* dl_open (hcl_t* hcl, const hcl_ooch_t* name, int flags)
|
||||
{
|
||||
#if defined(USE_LTDL) || defined(USE_DLFCN) || defined(USE_MACH_O_DYLD)
|
||||
hcl_bch_t stabuf[128], * bufptr;
|
||||
hcl_oow_t ucslen, bcslen, bufcapa;
|
||||
void* handle;
|
||||
|
||||
#if defined(HCL_OOCH_IS_UCH)
|
||||
if (hcl_convootobcstr(hcl, name, &ucslen, HCL_NULL, &bufcapa) <= -1) return HCL_NULL;
|
||||
/* +1 for terminating null. but it's not needed because HCL_COUNTOF(HCL_DEFAULT_PFMODPREFIX)
|
||||
* and HCL_COUNTOF(HCL_DEFAULT_PFMODPOSTIFX) include the terminating nulls. Never mind about
|
||||
* the extra 2 characters. */
|
||||
#else
|
||||
bufcapa = hcl_count_bcstr(name);
|
||||
#endif
|
||||
bufcapa += HCL_COUNTOF(HCL_DEFAULT_PFMODDIR) + HCL_COUNTOF(HCL_DEFAULT_PFMODPREFIX) + HCL_COUNTOF(HCL_DEFAULT_PFMODPOSTFIX) + 1;
|
||||
|
||||
if (bufcapa <= HCL_COUNTOF(stabuf)) bufptr = stabuf;
|
||||
else
|
||||
{
|
||||
bufptr = (hcl_bch_t*)hcl_allocmem(hcl, bufcapa * HCL_SIZEOF(*bufptr));
|
||||
if (!bufptr) return HCL_NULL;
|
||||
}
|
||||
|
||||
if (flags & HCL_VMPRIM_DLOPEN_PFMOD)
|
||||
{
|
||||
hcl_oow_t len, i, xlen, dlen;
|
||||
|
||||
/* opening a primitive function module - mostly libhcl-xxxx.
|
||||
* if PFMODPREFIX is absolute, never use PFMODDIR */
|
||||
dlen = IS_PATH_ABSOLUTE(HCL_DEFAULT_PFMODPREFIX)?
|
||||
0: hcl_copy_bcstr(bufptr, bufcapa, HCL_DEFAULT_PFMODDIR);
|
||||
len = hcl_copy_bcstr(bufptr, bufcapa, HCL_DEFAULT_PFMODPREFIX);
|
||||
len += dlen;
|
||||
|
||||
bcslen = bufcapa - len;
|
||||
#if defined(HCL_OOCH_IS_UCH)
|
||||
hcl_convootobcstr(hcl, name, &ucslen, &bufptr[len], &bcslen);
|
||||
#else
|
||||
bcslen = hcl_copy_bcstr(&bufptr[len], bcslen, name);
|
||||
#endif
|
||||
|
||||
/* length including the directory, the prefix and the name. but excluding the postfix */
|
||||
xlen = len + bcslen;
|
||||
|
||||
for (i = len; i < xlen; i++)
|
||||
{
|
||||
/* convert a period(.) to a dash(-) */
|
||||
if (bufptr[i] == '.') bufptr[i] = '-';
|
||||
}
|
||||
|
||||
retry:
|
||||
hcl_copy_bcstr (&bufptr[xlen], bufcapa - xlen, HCL_DEFAULT_PFMODPOSTFIX);
|
||||
|
||||
/* both prefix and postfix attached. for instance, libhcl-xxx */
|
||||
handle = sys_dl_openext(bufptr);
|
||||
if (!handle)
|
||||
{
|
||||
HCL_DEBUG3 (hcl, "Unable to open(ext) PFMOD %hs[%js] - %hs\n", &bufptr[dlen], name, sys_dl_error());
|
||||
|
||||
if (dlen > 0)
|
||||
{
|
||||
handle = sys_dl_openext(&bufptr[0]);
|
||||
if (handle) goto pfmod_open_ok;
|
||||
HCL_DEBUG3 (hcl, "Unable to open(ext) PFMOD %hs[%js] - %hs\n", &bufptr[0], name, sys_dl_error());
|
||||
}
|
||||
|
||||
/* try without prefix and postfix */
|
||||
bufptr[xlen] = '\0';
|
||||
handle = sys_dl_openext(&bufptr[len]);
|
||||
if (!handle)
|
||||
{
|
||||
hcl_bch_t* dash;
|
||||
const hcl_bch_t* dl_errstr;
|
||||
dl_errstr = sys_dl_error();
|
||||
HCL_DEBUG3 (hcl, "Unable to open(ext) PFMOD %hs[%js] - %hs\n", &bufptr[len], name, dl_errstr);
|
||||
hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to open(ext) PFMOD %js - %hs", name, dl_errstr);
|
||||
|
||||
dash = hcl_rfind_bchar(bufptr, hcl_count_bcstr(bufptr), '-');
|
||||
if (dash)
|
||||
{
|
||||
/* remove a segment at the back.
|
||||
* [NOTE] a dash contained in the original name before
|
||||
* period-to-dash transformation may cause extraneous/wrong
|
||||
* loading reattempts. */
|
||||
xlen = dash - bufptr;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HCL_DEBUG3 (hcl, "Opened(ext) PFMOD %hs[%js] handle %p\n", &bufptr[len], name, handle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pfmod_open_ok:
|
||||
HCL_DEBUG3 (hcl, "Opened(ext) PFMOD %hs[%js] handle %p\n", &bufptr[dlen], name, handle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* opening a raw shared object without a prefix and/or a postfix */
|
||||
#if defined(HCL_OOCH_IS_UCH)
|
||||
bcslen = bufcapa;
|
||||
hcl_convootobcstr(hcl, name, &ucslen, bufptr, &bcslen);
|
||||
#else
|
||||
bcslen = hcl_copy_bcstr(bufptr, bufcapa, name);
|
||||
#endif
|
||||
|
||||
if (hcl_find_bchar(bufptr, bcslen, '.'))
|
||||
{
|
||||
handle = sys_dl_open(bufptr);
|
||||
if (!handle)
|
||||
{
|
||||
const hcl_bch_t* dl_errstr;
|
||||
dl_errstr = sys_dl_error();
|
||||
HCL_DEBUG2 (hcl, "Unable to open DL %hs - %hs\n", bufptr, dl_errstr);
|
||||
hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to open DL %js - %hs", name, dl_errstr);
|
||||
}
|
||||
else HCL_DEBUG2 (hcl, "Opened DL %hs handle %p\n", bufptr, handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = sys_dl_openext(bufptr);
|
||||
if (!handle)
|
||||
{
|
||||
const hcl_bch_t* dl_errstr;
|
||||
dl_errstr = sys_dl_error();
|
||||
HCL_DEBUG2 (hcl, "Unable to open(ext) DL %hs - %s\n", bufptr, dl_errstr);
|
||||
hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to open(ext) DL %js - %hs", name, dl_errstr);
|
||||
}
|
||||
else HCL_DEBUG2 (hcl, "Opened(ext) DL %hs handle %p\n", bufptr, handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (bufptr != stabuf) hcl_freemem (hcl, bufptr);
|
||||
return handle;
|
||||
|
||||
#else
|
||||
|
||||
/* TODO: support various platforms */
|
||||
/* TODO: implemenent this */
|
||||
HCL_DEBUG1 (hcl, "Dynamic loading not implemented - cannot open %js\n", name);
|
||||
hcl_seterrbfmt (hcl, HCL_ENOIMPL, "dynamic loading not implemented - cannot open %js", name);
|
||||
return HCL_NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dl_close (hcl_t* hcl, void* handle)
|
||||
{
|
||||
#if defined(USE_LTDL) || defined(USE_DLFCN) || defined(USE_MACH_O_DYLD)
|
||||
HCL_DEBUG1 (hcl, "Closed DL handle %p\n", handle);
|
||||
sys_dl_close (handle);
|
||||
|
||||
#else
|
||||
/* TODO: implemenent this */
|
||||
HCL_DEBUG1 (hcl, "Dynamic loading not implemented - cannot close handle %p\n", handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void* dl_getsym (hcl_t* hcl, void* handle, const hcl_ooch_t* name)
|
||||
{
|
||||
#if defined(USE_LTDL) || defined(USE_DLFCN) || defined(USE_MACH_O_DYLD)
|
||||
hcl_bch_t stabuf[64], * bufptr;
|
||||
hcl_oow_t bufcapa, ucslen, bcslen, i;
|
||||
const hcl_bch_t* symname;
|
||||
void* sym;
|
||||
|
||||
#if defined(HCL_OOCH_IS_UCH)
|
||||
if (hcl_convootobcstr(hcl, name, &ucslen, HCL_NULL, &bcslen) <= -1) return HCL_NULL;
|
||||
#else
|
||||
bcslen = hcl_count_bcstr (name);
|
||||
#endif
|
||||
|
||||
if (bcslen >= HCL_COUNTOF(stabuf) - 2)
|
||||
{
|
||||
bufcapa = bcslen + 3;
|
||||
bufptr = (hcl_bch_t*)hcl_allocmem(hcl, bufcapa * HCL_SIZEOF(*bufptr));
|
||||
if (!bufptr) return HCL_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufcapa = HCL_COUNTOF(stabuf);
|
||||
bufptr = stabuf;
|
||||
}
|
||||
|
||||
bcslen = bufcapa - 1;
|
||||
#if defined(HCL_OOCH_IS_UCH)
|
||||
hcl_convootobcstr (hcl, name, &ucslen, &bufptr[1], &bcslen);
|
||||
#else
|
||||
bcslen = hcl_copy_bcstr(&bufptr[1], bcslen, name);
|
||||
#endif
|
||||
|
||||
/* convert a period(.) to an underscore(_) */
|
||||
for (i = 1; i <= bcslen; i++) if (bufptr[i] == '.') bufptr[i] = '_';
|
||||
|
||||
symname = &bufptr[1]; /* try the name as it is */
|
||||
|
||||
sym = sys_dl_getsym(handle, symname);
|
||||
if (!sym)
|
||||
{
|
||||
bufptr[0] = '_';
|
||||
symname = &bufptr[0]; /* try _name */
|
||||
sym = sys_dl_getsym(handle, symname);
|
||||
if (!sym)
|
||||
{
|
||||
bufptr[bcslen + 1] = '_';
|
||||
bufptr[bcslen + 2] = '\0';
|
||||
|
||||
symname = &bufptr[1]; /* try name_ */
|
||||
sym = sys_dl_getsym(handle, symname);
|
||||
|
||||
if (!sym)
|
||||
{
|
||||
symname = &bufptr[0]; /* try _name_ */
|
||||
sym = sys_dl_getsym(handle, symname);
|
||||
if (!sym)
|
||||
{
|
||||
const hcl_bch_t* dl_errstr;
|
||||
dl_errstr = sys_dl_error();
|
||||
HCL_DEBUG3 (hcl, "Failed to get module symbol %js from handle %p - %hs\n", name, handle, dl_errstr);
|
||||
hcl_seterrbfmt (hcl, HCL_ENOENT, "unable to get module symbol %hs - %hs", symname, dl_errstr);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sym) HCL_DEBUG3 (hcl, "Loaded module symbol %js from handle %p - %hs\n", name, handle, symname);
|
||||
if (bufptr != stabuf) hcl_freemem (hcl, bufptr);
|
||||
return sym;
|
||||
|
||||
#else
|
||||
/* TODO: IMPLEMENT THIS */
|
||||
HCL_DEBUG2 (hcl, "Dynamic loading not implemented - Cannot load module symbol %js from handle %p\n", name, handle);
|
||||
hcl_seterrbfmt (hcl, HCL_ENOIMPL, "dynamic loading not implemented - Cannot load module symbol %js from handle %p", name, handle);
|
||||
return HCL_NULL;
|
||||
#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 = (xtn_t*)hcl_getxtn(hcl);
|
||||
if (xtn->waitable_timer)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -HCL_SECNSEC_TO_NSEC(dur->sec, dur->nsec);
|
||||
if(SetWaitableTimer(xtn->waitable_timer, &li, 0, HCL_NULL, HCL_NULL, FALSE) == FALSE) goto normal_sleep;
|
||||
WaitForSingleObject(xtn->waitable_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
|
||||
}
|
||||
#include "cb-impl.h"
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static int vm_startup (hcl_t* hcl)
|
||||
{
|
||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||
|
||||
#if defined(_WIN32)
|
||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||
xtn->waitable_timer = CreateWaitableTimer(HCL_NULL, TRUE, HCL_NULL);
|
||||
xtn->vm_running = 1;
|
||||
return 0;
|
||||
#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 */
|
||||
#endif
|
||||
|
||||
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 = (xtn_t*)hcl_getxtn(hcl);
|
||||
|
||||
xtn->vm_running = 0;
|
||||
|
||||
#if defined(_WIN32)
|
||||
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
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user