cleaned up some code
This commit is contained in:
parent
19d39ca20a
commit
7f0428d288
@ -64,6 +64,7 @@ libhcl_la_SOURCES = \
|
|||||||
hcl-utl.h \
|
hcl-utl.h \
|
||||||
hcl-prv.h \
|
hcl-prv.h \
|
||||||
bigint.c \
|
bigint.c \
|
||||||
|
cb-impl.h \
|
||||||
comp.c \
|
comp.c \
|
||||||
debug.c \
|
debug.c \
|
||||||
decode.c \
|
decode.c \
|
||||||
|
@ -467,6 +467,7 @@ libhcl_la_SOURCES = \
|
|||||||
hcl-utl.h \
|
hcl-utl.h \
|
||||||
hcl-prv.h \
|
hcl-prv.h \
|
||||||
bigint.c \
|
bigint.c \
|
||||||
|
cb-impl.h \
|
||||||
comp.c \
|
comp.c \
|
||||||
debug.c \
|
debug.c \
|
||||||
decode.c \
|
decode.c \
|
||||||
|
794
lib/cb-impl.h
Normal file
794
lib/cb-impl.h
Normal file
@ -0,0 +1,794 @@
|
|||||||
|
/* this function contains commonly used callback functions for hcl */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------
|
||||||
|
* SYSTEM ERROR CONVERSION
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
static hcl_errnum_t errno_to_errnum (int errcode)
|
||||||
|
{
|
||||||
|
switch (errcode)
|
||||||
|
{
|
||||||
|
case ENOMEM: return HCL_ESYSMEM;
|
||||||
|
case EINVAL: return HCL_EINVAL;
|
||||||
|
|
||||||
|
#if defined(EBUSY)
|
||||||
|
case EBUSY: return HCL_EBUSY;
|
||||||
|
#endif
|
||||||
|
case EACCES: return HCL_EACCES;
|
||||||
|
#if defined(EPERM)
|
||||||
|
case EPERM: return HCL_EPERM;
|
||||||
|
#endif
|
||||||
|
#if defined(ENOTDIR)
|
||||||
|
case ENOTDIR: return HCL_ENOTDIR;
|
||||||
|
#endif
|
||||||
|
case ENOENT: return HCL_ENOENT;
|
||||||
|
#if defined(EEXIST)
|
||||||
|
case EEXIST: return HCL_EEXIST;
|
||||||
|
#endif
|
||||||
|
#if defined(EINTR)
|
||||||
|
case EINTR: return HCL_EINTR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(EPIPE)
|
||||||
|
case EPIPE: return HCL_EPIPE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK)
|
||||||
|
case EAGAIN:
|
||||||
|
case EWOULDBLOCK: return HCL_EAGAIN;
|
||||||
|
#elif defined(EAGAIN)
|
||||||
|
case EAGAIN: return HCL_EAGAIN;
|
||||||
|
#elif defined(EWOULDBLOCK)
|
||||||
|
case EWOULDBLOCK: return HCL_EAGAIN;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(EBADF)
|
||||||
|
case EBADF: return HCL_EBADHND;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(EIO)
|
||||||
|
case EIO: return HCL_EIOERR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: return HCL_ESYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
static hcl_errnum_t winerr_to_errnum (DWORD errcode)
|
||||||
|
{
|
||||||
|
switch (errcode)
|
||||||
|
{
|
||||||
|
case ERROR_NOT_ENOUGH_MEMORY:
|
||||||
|
case ERROR_OUTOFMEMORY:
|
||||||
|
return HCL_ESYSMEM;
|
||||||
|
|
||||||
|
case ERROR_INVALID_PARAMETER:
|
||||||
|
case ERROR_INVALID_NAME:
|
||||||
|
return HCL_EINVAL;
|
||||||
|
|
||||||
|
case ERROR_INVALID_HANDLE:
|
||||||
|
return HCL_EBADHND;
|
||||||
|
|
||||||
|
case ERROR_ACCESS_DENIED:
|
||||||
|
case ERROR_SHARING_VIOLATION:
|
||||||
|
return HCL_EACCES;
|
||||||
|
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
case ERROR_PATH_NOT_FOUND:
|
||||||
|
return HCL_ENOENT;
|
||||||
|
|
||||||
|
case ERROR_ALREADY_EXISTS:
|
||||||
|
case ERROR_FILE_EXISTS:
|
||||||
|
return HCL_EEXIST;
|
||||||
|
|
||||||
|
case ERROR_BROKEN_PIPE:
|
||||||
|
return HCL_EPIPE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return HCL_ESYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OS2__)
|
||||||
|
static hcl_errnum_t os2err_to_errnum (APIRET errcode)
|
||||||
|
{
|
||||||
|
/* APIRET e */
|
||||||
|
switch (errcode)
|
||||||
|
{
|
||||||
|
case ERROR_NOT_ENOUGH_MEMORY:
|
||||||
|
return HCL_ESYSMEM;
|
||||||
|
|
||||||
|
case ERROR_INVALID_PARAMETER:
|
||||||
|
case ERROR_INVALID_NAME:
|
||||||
|
return HCL_EINVAL;
|
||||||
|
|
||||||
|
case ERROR_INVALID_HANDLE:
|
||||||
|
return HCL_EBADHND;
|
||||||
|
|
||||||
|
case ERROR_ACCESS_DENIED:
|
||||||
|
case ERROR_SHARING_VIOLATION:
|
||||||
|
return HCL_EACCES;
|
||||||
|
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
case ERROR_PATH_NOT_FOUND:
|
||||||
|
return HCL_ENOENT;
|
||||||
|
|
||||||
|
case ERROR_ALREADY_EXISTS:
|
||||||
|
return HCL_EEXIST;
|
||||||
|
|
||||||
|
/*TODO: add more mappings */
|
||||||
|
default:
|
||||||
|
return HCL_ESYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(macintosh)
|
||||||
|
static hcl_errnum_t macerr_to_errnum (int errcode)
|
||||||
|
{
|
||||||
|
switch (e)
|
||||||
|
{
|
||||||
|
case notEnoughMemoryErr:
|
||||||
|
return HCL_ESYSMEM;
|
||||||
|
case paramErr:
|
||||||
|
return HCL_EINVAL;
|
||||||
|
|
||||||
|
case qErr: /* queue element not found during deletion */
|
||||||
|
case fnfErr: /* file not found */
|
||||||
|
case dirNFErr: /* direcotry not found */
|
||||||
|
case resNotFound: /* resource not found */
|
||||||
|
case resFNotFound: /* resource file not found */
|
||||||
|
case nbpNotFound: /* name not found on remove */
|
||||||
|
return HCL_ENOENT;
|
||||||
|
|
||||||
|
/*TODO: add more mappings */
|
||||||
|
default:
|
||||||
|
return HCL_ESYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static hcl_errnum_t syserrstrb (hcl_t* hcl, int syserr_type, int syserr_code, hcl_bch_t* buf, hcl_oow_t len)
|
||||||
|
{
|
||||||
|
switch (syserr_type)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
DWORD rc;
|
||||||
|
rc = FormatMessageA (
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, syserr_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
buf, len, HCL_NULL
|
||||||
|
);
|
||||||
|
while (rc > 0 && buf[rc - 1] == '\r' || buf[rc - 1] == '\n') buf[--rc] = '\0';
|
||||||
|
}
|
||||||
|
return winerr_to_errnum(syserr_code);
|
||||||
|
#elif defined(__OS2__)
|
||||||
|
/* TODO: convert code to string */
|
||||||
|
if (buf) hcl_copy_bcstr (buf, len, "system error");
|
||||||
|
return os2err_to_errnum(syserr_code);
|
||||||
|
#elif defined(macintosh)
|
||||||
|
/* TODO: convert code to string */
|
||||||
|
if (buf) hcl_copy_bcstr (buf, len, "system error");
|
||||||
|
return os2err_to_errnum(syserr_code);
|
||||||
|
#else
|
||||||
|
/* in other systems, errno is still the native system error code.
|
||||||
|
* fall thru */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
#if defined(HAVE_STRERROR_R)
|
||||||
|
if (buf) strerror_r (syserr_code, buf, len);
|
||||||
|
#else
|
||||||
|
/* this is not thread safe */
|
||||||
|
if (buf) hcl_copy_bcstr (buf, len, strerror(syserr_code));
|
||||||
|
#endif
|
||||||
|
return errno_to_errnum(syserr_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf) hcl_copy_bcstr (buf, len, "system error");
|
||||||
|
return HCL_ESYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------
|
||||||
|
* HEAP ALLOCATION
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------
|
||||||
|
* POSSIBLY MONOTONIC TIME
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void vm_gettime (hcl_t* hcl, hcl_ntime_t* now)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#if defined(_WIN64) || (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600))
|
||||||
|
hcl_uint64_t bigsec, bigmsec;
|
||||||
|
bigmsec = GetTickCount64();
|
||||||
|
#else
|
||||||
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||||
|
hcl_uint64_t bigsec, bigmsec;
|
||||||
|
DWORD msec;
|
||||||
|
|
||||||
|
msec = GetTickCount(); /* this can sustain for 49.7 days */
|
||||||
|
if (msec < xtn->tc_last)
|
||||||
|
{
|
||||||
|
/* i assume the difference is never bigger than 49.7 days */
|
||||||
|
/*diff = (HCL_TYPE_MAX(DWORD) - xtn->tc_last) + 1 + msec;*/
|
||||||
|
xtn->tc_overflow++;
|
||||||
|
bigmsec = ((hcl_uint64_t)HCL_TYPE_MAX(DWORD) * xtn->tc_overflow) + msec;
|
||||||
|
}
|
||||||
|
else bigmsec = msec;
|
||||||
|
xtn->tc_last = msec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bigsec = HCL_MSEC_TO_SEC(bigmsec);
|
||||||
|
bigmsec -= HCL_SEC_TO_MSEC(bigsec);
|
||||||
|
HCL_INIT_NTIME(now, bigsec, HCL_MSEC_TO_NSEC(bigmsec));
|
||||||
|
|
||||||
|
#elif defined(__OS2__)
|
||||||
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||||
|
hcl_uint64_t bigsec, bigmsec;
|
||||||
|
ULONG msec;
|
||||||
|
|
||||||
|
/* TODO: use DosTmrQueryTime() and DosTmrQueryFreq()? */
|
||||||
|
DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &msec, HCL_SIZEOF(msec)); /* milliseconds */
|
||||||
|
/* it must return NO_ERROR */
|
||||||
|
if (msec < xtn->tc_last)
|
||||||
|
{
|
||||||
|
xtn->tc_overflow++;
|
||||||
|
bigmsec = ((hcl_uint64_t)HCL_TYPE_MAX(ULONG) * xtn->tc_overflow) + msec;
|
||||||
|
}
|
||||||
|
else bigmsec = msec;
|
||||||
|
xtn->tc_last = msec;
|
||||||
|
|
||||||
|
bigsec = HCL_MSEC_TO_SEC(bigmsec);
|
||||||
|
bigmsec -= HCL_SEC_TO_MSEC(bigsec);
|
||||||
|
HCL_INIT_NTIME (now, bigsec, HCL_MSEC_TO_NSEC(bigmsec));
|
||||||
|
|
||||||
|
#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_INIT_NTIME (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_INIT_NTIME(now, ts.tv_sec, ts.tv_nsec);
|
||||||
|
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime (CLOCK_REALTIME, &ts);
|
||||||
|
HCL_INIT_NTIME(now, ts.tv_sec, ts.tv_nsec);
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday (&tv, HCL_NULL);
|
||||||
|
HCL_INIT_NTIME(now, tv.tv_sec, HCL_USEC_TO_NSEC(tv.tv_usec));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------
|
||||||
|
* SLEEPING
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#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 (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(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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------
|
||||||
|
* SHARED LIBRARY HANDLING
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(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(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(USE_WIN_DLL)
|
||||||
|
# define sys_dl_error() win_dlerror()
|
||||||
|
# define sys_dl_open(x) LoadLibraryExA(x, MOO_NULL, 0)
|
||||||
|
# define sys_dl_openext(x) LoadLibraryExA(x, MOO_NULL, 0)
|
||||||
|
# define sys_dl_close(x) FreeLibrary(x)
|
||||||
|
# define sys_dl_getsym(x,n) GetProcAddress(x,n)
|
||||||
|
|
||||||
|
#elif defined(USE_MACH_O_DYLD)
|
||||||
|
# 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)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_WIN_DLL)
|
||||||
|
|
||||||
|
static const char* win_dlerror (void)
|
||||||
|
{
|
||||||
|
/* TODO: handle wchar_t, moo_ooch_t etc? */
|
||||||
|
static char buf[256];
|
||||||
|
DWORD rc;
|
||||||
|
|
||||||
|
rc = FormatMessageA (
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
buf, MOO_COUNTOF(buf), MOO_NULL
|
||||||
|
);
|
||||||
|
while (rc > 0 && buf[rc - 1] == '\r' || buf[rc - 1] == '\n')
|
||||||
|
{
|
||||||
|
buf[--rc] = '\0';
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif 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
|
||||||
|
}
|
234
lib/err.c
234
lib/err.c
@ -163,167 +163,6 @@ static const hcl_bch_t* synerr_to_errstr (hcl_synerrnum_t errnum)
|
|||||||
return (errnum >= 0 && errnum < HCL_COUNTOF(synerrstr))? synerrstr[errnum]: e_unknown;
|
return (errnum >= 0 && errnum < HCL_COUNTOF(synerrstr))? synerrstr[errnum]: e_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
|
||||||
* SYSTEM DEPENDENT FUNCTIONS
|
|
||||||
* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#if defined(HAVE_EXECINFO_H)
|
|
||||||
# include <execinfo.h>
|
|
||||||
# include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# include <windows.h>
|
|
||||||
#elif defined(__OS2__)
|
|
||||||
# define INCL_DOSPROCESS
|
|
||||||
# define INCL_DOSFILEMGR
|
|
||||||
# define INCL_DOSERRORS
|
|
||||||
# include <os2.h>
|
|
||||||
#elif defined(__DOS__)
|
|
||||||
# include <dos.h>
|
|
||||||
# if defined(_INTELC32_)
|
|
||||||
# define DOS_EXIT 0x4C
|
|
||||||
# else
|
|
||||||
# include <dosfunc.h>
|
|
||||||
# endif
|
|
||||||
# include <errno.h>
|
|
||||||
#elif defined(vms) || defined(__vms)
|
|
||||||
# define __NEW_STARLET 1
|
|
||||||
# include <starlet.h> /* (SYS$...) */
|
|
||||||
# include <ssdef.h> /* (SS$...) */
|
|
||||||
# include <lib$routines.h> /* (lib$...) */
|
|
||||||
#elif defined(macintosh)
|
|
||||||
# include <MacErrors.h>
|
|
||||||
# include <Process.h>
|
|
||||||
# include <Dialogs.h>
|
|
||||||
# include <TextUtils.h>
|
|
||||||
#else
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <signal.h>
|
|
||||||
# include <errno.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hcl_errnum_t hcl_syserr_to_errnum (int e)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
switch (e)
|
|
||||||
{
|
|
||||||
case ERROR_NOT_ENOUGH_MEMORY:
|
|
||||||
case ERROR_OUTOFMEMORY:
|
|
||||||
return HCL_ESYSMEM;
|
|
||||||
case ERROR_INVALID_PARAMETER:
|
|
||||||
case ERROR_INVALID_HANDLE:
|
|
||||||
case ERROR_INVALID_NAME:
|
|
||||||
return HCL_EINVAL;
|
|
||||||
case ERROR_ACCESS_DENIED:
|
|
||||||
case ERROR_SHARING_VIOLATION:
|
|
||||||
return HCL_EACCES;
|
|
||||||
case ERROR_FILE_NOT_FOUND:
|
|
||||||
case ERROR_PATH_NOT_FOUND:
|
|
||||||
return HCL_ENOENT;
|
|
||||||
case ERROR_ALREADY_EXISTS:
|
|
||||||
case ERROR_FILE_EXISTS:
|
|
||||||
return HCL_EEXIST;
|
|
||||||
case ERROR_BROKEN_PIPE:
|
|
||||||
return HCL_EPIPE;
|
|
||||||
|
|
||||||
/*TODO: add more mappings */
|
|
||||||
default:
|
|
||||||
return HCL_ESYSERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__OS2__)
|
|
||||||
/* APIRET e */
|
|
||||||
switch (e)
|
|
||||||
{
|
|
||||||
case ERROR_NOT_ENOUGH_MEMORY: return HCL_ESYSMEM;
|
|
||||||
|
|
||||||
case ERROR_INVALID_PARAMETER:
|
|
||||||
case ERROR_INVALID_HANDLE:
|
|
||||||
case ERROR_INVALID_NAME: return HCL_EINVAL;
|
|
||||||
|
|
||||||
case ERROR_ACCESS_DENIED:
|
|
||||||
case ERROR_SHARING_VIOLATION: return HCL_EACCES;
|
|
||||||
|
|
||||||
case ERROR_FILE_NOT_FOUND:
|
|
||||||
case ERROR_PATH_NOT_FOUND: return HCL_ENOENT;
|
|
||||||
|
|
||||||
case ERROR_ALREADY_EXISTS: return HCL_EEXIST;
|
|
||||||
|
|
||||||
/*TODO: add more mappings */
|
|
||||||
default: return HCL_ESYSERR;
|
|
||||||
}
|
|
||||||
#elif defined(macintosh)
|
|
||||||
switch (e)
|
|
||||||
{
|
|
||||||
case notEnoughMemoryErr: return HCL_ESYSMEM;
|
|
||||||
case paramErr: return HCL_EINVAL;
|
|
||||||
|
|
||||||
case qErr: /* queue element not found during deletion */
|
|
||||||
case fnfErr: /* file not found */
|
|
||||||
case dirNFErr: /* direcotry not found */
|
|
||||||
case resNotFound: /* resource not found */
|
|
||||||
case resFNotFound: /* resource file not found */
|
|
||||||
case nbpNotFound: /* name not found on remove */
|
|
||||||
return HCL_ENOENT;
|
|
||||||
|
|
||||||
/*TODO: add more mappings */
|
|
||||||
default: return HCL_ESYSERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
switch (e)
|
|
||||||
{
|
|
||||||
case ENOMEM: return HCL_ESYSMEM;
|
|
||||||
case EINVAL: return HCL_EINVAL;
|
|
||||||
|
|
||||||
#if defined(EBUSY)
|
|
||||||
case EBUSY: return HCL_EBUSY;
|
|
||||||
#endif
|
|
||||||
case EACCES: return HCL_EACCES;
|
|
||||||
#if defined(EPERM)
|
|
||||||
case EPERM: return HCL_EPERM;
|
|
||||||
#endif
|
|
||||||
#if defined(ENOTDIR)
|
|
||||||
case ENOTDIR: return HCL_ENOTDIR;
|
|
||||||
#endif
|
|
||||||
case ENOENT: return HCL_ENOENT;
|
|
||||||
#if defined(EEXIST)
|
|
||||||
case EEXIST: return HCL_EEXIST;
|
|
||||||
#endif
|
|
||||||
#if defined(EINTR)
|
|
||||||
case EINTR: return HCL_EINTR;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EPIPE)
|
|
||||||
case EPIPE: return HCL_EPIPE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK)
|
|
||||||
case EAGAIN:
|
|
||||||
case EWOULDBLOCK: return HCL_EAGAIN;
|
|
||||||
#elif defined(EAGAIN)
|
|
||||||
case EAGAIN: return HCL_EAGAIN;
|
|
||||||
#elif defined(EWOULDBLOCK)
|
|
||||||
case EWOULDBLOCK: return HCL_EAGAIN;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(EBADF)
|
|
||||||
case EBADF: return HCL_EBADHND;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(EIO)
|
|
||||||
case EIO: return HCL_EIOERR;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default: return HCL_ESYSERR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* ERROR NUMBER/MESSAGE HANDLING
|
* ERROR NUMBER/MESSAGE HANDLING
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
@ -352,20 +191,22 @@ void hcl_seterrnum (hcl_t* hcl, hcl_errnum_t errnum)
|
|||||||
hcl->errmsg.len = 0;
|
hcl->errmsg.len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcl_seterrwithsyserr (hcl_t* hcl, int syserr)
|
void hcl_seterrwithsyserr (hcl_t* hcl, int syserr_type, int syserr_code)
|
||||||
{
|
{
|
||||||
|
hcl_errnum_t errnum;
|
||||||
|
|
||||||
if (hcl->shuterr) return;
|
if (hcl->shuterr) return;
|
||||||
|
|
||||||
if (hcl->vmprim.syserrstrb)
|
if (hcl->vmprim.syserrstrb)
|
||||||
{
|
{
|
||||||
hcl->vmprim.syserrstrb (hcl, syserr, hcl->errmsg.tmpbuf.bch, HCL_COUNTOF(hcl->errmsg.tmpbuf.bch));
|
errnum = hcl->vmprim.syserrstrb(hcl, syserr_type, syserr_code, hcl->errmsg.tmpbuf.bch, HCL_COUNTOF(hcl->errmsg.tmpbuf.bch));
|
||||||
hcl_seterrbfmt (hcl, hcl_syserr_to_errnum(syserr), "%hs", hcl->errmsg.tmpbuf.bch);
|
hcl_seterrbfmt (hcl, errnum, "%hs", hcl->errmsg.tmpbuf.bch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HCL_ASSERT (hcl, hcl->vmprim.syserrstru != HCL_NULL);
|
HCL_ASSERT (hcl, hcl->vmprim.syserrstru != HCL_NULL);
|
||||||
hcl->vmprim.syserrstru (hcl, syserr, hcl->errmsg.tmpbuf.uch, HCL_COUNTOF(hcl->errmsg.tmpbuf.uch));
|
errnum = hcl->vmprim.syserrstru(hcl, syserr_type, syserr_code, hcl->errmsg.tmpbuf.uch, HCL_COUNTOF(hcl->errmsg.tmpbuf.uch));
|
||||||
hcl_seterrbfmt (hcl, hcl_syserr_to_errnum(syserr), "%ls", hcl->errmsg.tmpbuf.uch);
|
hcl_seterrbfmt (hcl, errnum, "%ls", hcl->errmsg.tmpbuf.uch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,8 +325,61 @@ void hcl_setsynerrufmt (hcl_t* hcl, hcl_synerrnum_t num, const hcl_ioloc_t* loc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* STACK FRAME BACKTRACE
|
* ASSERTION SUPPORT
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(HCL_BUILD_RELEASE)
|
||||||
|
|
||||||
|
void hcl_assertfailed (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file, hcl_oow_t line)
|
||||||
|
{
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* defined(HCL_BUILD_RELEASE) */
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
* SYSTEM DEPENDENT HEADERS
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
#if defined(HCL_ENABLE_LIBUNWIND)
|
||||||
|
# include <libunwind.h>
|
||||||
|
#elif defined(HAVE_EXECINFO_H)
|
||||||
|
# include <execinfo.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
# include <errno.h>
|
||||||
|
#elif defined(__OS2__)
|
||||||
|
# define INCL_DOSPROCESS
|
||||||
|
# define INCL_DOSFILEMGR
|
||||||
|
# define INCL_DOSERRORS
|
||||||
|
# include <os2.h>
|
||||||
|
#elif defined(__DOS__)
|
||||||
|
# include <dos.h>
|
||||||
|
# if defined(_INTELC32_)
|
||||||
|
# define DOS_EXIT 0x4C
|
||||||
|
# else
|
||||||
|
# include <dosfunc.h>
|
||||||
|
# endif
|
||||||
|
# include <errno.h>
|
||||||
|
#elif defined(vms) || defined(__vms)
|
||||||
|
# define __NEW_STARLET 1
|
||||||
|
# include <starlet.h> /* (SYS$...) */
|
||||||
|
# include <ssdef.h> /* (SS$...) */
|
||||||
|
# include <lib$routines.h> /* (lib$...) */
|
||||||
|
#elif defined(macintosh)
|
||||||
|
# include <MacErrors.h>
|
||||||
|
# include <Process.h>
|
||||||
|
# include <Dialogs.h>
|
||||||
|
# include <TextUtils.h>
|
||||||
|
#else
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <signal.h>
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HCL_ENABLE_LIBUNWIND)
|
#if defined(HCL_ENABLE_LIBUNWIND)
|
||||||
static void backtrace_stack_frames (hcl_t* hcl)
|
static void backtrace_stack_frames (hcl_t* hcl)
|
||||||
{
|
{
|
||||||
@ -543,10 +437,6 @@ static void backtrace_stack_frames (hcl_t* hcl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
|
||||||
* ASSERTION FAILURE HANDLERsemaphore heap full
|
|
||||||
* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void hcl_assertfailed (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file, hcl_oow_t line)
|
void hcl_assertfailed (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file, hcl_oow_t line)
|
||||||
{
|
{
|
||||||
hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_FATAL, "ASSERTION FAILURE: %s at %s:%zu\n", expr, file, line);
|
hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_FATAL, "ASSERTION FAILURE: %s at %s:%zu\n", expr, file, line);
|
||||||
@ -578,3 +468,5 @@ void hcl_assertfailed (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file,
|
|||||||
_exit (1);
|
_exit (1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* defined(HCL_BUILD_RELEASE) */
|
||||||
|
@ -1288,12 +1288,12 @@ static int execute (hcl_t* hcl)
|
|||||||
HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(hcl->sem_heap[0]->heap_ftime_sec));
|
HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(hcl->sem_heap[0]->heap_ftime_sec));
|
||||||
HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(hcl->sem_heap[0]->heap_ftime_nsec));
|
HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(hcl->sem_heap[0]->heap_ftime_nsec));
|
||||||
|
|
||||||
HCL_INITNTIME (&ft,
|
HCL_INIT_NTIME (&ft,
|
||||||
HCL_OOP_TO_SMOOI(hcl->sem_heap[0]->heap_ftime_sec),
|
HCL_OOP_TO_SMOOI(hcl->sem_heap[0]->heap_ftime_sec),
|
||||||
HCL_OOP_TO_SMOOI(hcl->sem_heap[0]->heap_ftime_nsec)
|
HCL_OOP_TO_SMOOI(hcl->sem_heap[0]->heap_ftime_nsec)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (HCL_CMPNTIME(&ft, (hcl_ntime_t*)&now) <= 0)
|
if (HCL_CMP_NTIME(&ft, (hcl_ntime_t*)&now) <= 0)
|
||||||
{
|
{
|
||||||
hcl_oop_process_t proc;
|
hcl_oop_process_t proc;
|
||||||
|
|
||||||
@ -1324,7 +1324,7 @@ static int execute (hcl_t* hcl)
|
|||||||
}
|
}
|
||||||
else if (hcl->processor->active == hcl->nil_process)
|
else if (hcl->processor->active == hcl->nil_process)
|
||||||
{
|
{
|
||||||
HCL_SUBNTIME (&ft, &ft, (hcl_ntime_t*)&now);
|
HCL_SUB_NTIME (&ft, &ft, (hcl_ntime_t*)&now);
|
||||||
hcl->vmprim.vm_sleep (hcl, &ft); /* TODO: change this to i/o multiplexer??? */
|
hcl->vmprim.vm_sleep (hcl, &ft); /* TODO: change this to i/o multiplexer??? */
|
||||||
hcl->vmprim.vm_gettime (hcl, &now);
|
hcl->vmprim.vm_gettime (hcl, &now);
|
||||||
}
|
}
|
||||||
|
@ -393,31 +393,31 @@ struct hcl_ntime_t
|
|||||||
hcl_int32_t nsec; /* nanoseconds */
|
hcl_int32_t nsec; /* nanoseconds */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HCL_INITNTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns)))
|
#define HCL_INIT_NTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns)))
|
||||||
#define HCL_CLEARNTIME(c) HCL_INITNTIME(c, 0, 0)
|
#define HCL_CLEAR_NTIME(c) HCL_INIT_NTIME(c, 0, 0)
|
||||||
|
|
||||||
#define HCL_ADDNTIME(c,a,b) \
|
#define HCL_ADD_NTIME(c,a,b) \
|
||||||
do { \
|
do { \
|
||||||
(c)->sec = (a)->sec + (b)->sec; \
|
(c)->sec = (a)->sec + (b)->sec; \
|
||||||
(c)->nsec = (a)->nsec + (b)->nsec; \
|
(c)->nsec = (a)->nsec + (b)->nsec; \
|
||||||
while ((c)->nsec >= HCL_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= HCL_NSECS_PER_SEC; } \
|
while ((c)->nsec >= HCL_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= HCL_NSECS_PER_SEC; } \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define HCL_ADDNTIMESNS(c,a,s,ns) \
|
#define HCL_ADD_NTIME_SNS(c,a,s,ns) \
|
||||||
do { \
|
do { \
|
||||||
(c)->sec = (a)->sec + (s); \
|
(c)->sec = (a)->sec + (s); \
|
||||||
(c)->nsec = (a)->nsec + (ns); \
|
(c)->nsec = (a)->nsec + (ns); \
|
||||||
while ((c)->nsec >= HCL_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= HCL_NSECS_PER_SEC; } \
|
while ((c)->nsec >= HCL_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= HCL_NSECS_PER_SEC; } \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define HCL_SUBNTIME(c,a,b) \
|
#define HCL_SUB_NTIME(c,a,b) \
|
||||||
do { \
|
do { \
|
||||||
(c)->sec = (a)->sec - (b)->sec; \
|
(c)->sec = (a)->sec - (b)->sec; \
|
||||||
(c)->nsec = (a)->nsec - (b)->nsec; \
|
(c)->nsec = (a)->nsec - (b)->nsec; \
|
||||||
while ((c)->nsec < 0) { (c)->sec--; (c)->nsec += HCL_NSECS_PER_SEC; } \
|
while ((c)->nsec < 0) { (c)->sec--; (c)->nsec += HCL_NSECS_PER_SEC; } \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define HCL_SUBNTIMESNS(c,a,s,ns) \
|
#define HCL_SUB_NTIME_SNS(c,a,s,ns) \
|
||||||
do { \
|
do { \
|
||||||
(c)->sec = (a)->sec - s; \
|
(c)->sec = (a)->sec - s; \
|
||||||
(c)->nsec = (a)->nsec - ns; \
|
(c)->nsec = (a)->nsec - ns; \
|
||||||
@ -425,7 +425,7 @@ struct hcl_ntime_t
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
#define HCL_CMPNTIME(a,b) (((a)->sec == (b)->sec)? ((a)->nsec - (b)->nsec): ((a)->sec - (b)->sec))
|
#define HCL_CMP_NTIME(a,b) (((a)->sec == (b)->sec)? ((a)->nsec - (b)->nsec): ((a)->sec - (b)->sec))
|
||||||
|
|
||||||
/* =========================================================================
|
/* =========================================================================
|
||||||
* PRIMITIVE MACROS
|
* PRIMITIVE MACROS
|
||||||
|
466
lib/hcl-s.c
466
lib/hcl-s.c
@ -43,6 +43,8 @@
|
|||||||
# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
|
# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
|
||||||
# include <ltdl.h>
|
# include <ltdl.h>
|
||||||
# define USE_LTDL
|
# define USE_LTDL
|
||||||
|
# else
|
||||||
|
# define USE_WIN_DLL
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__OS2__)
|
#elif defined(__OS2__)
|
||||||
# define INCL_DOSMODULEMGR
|
# define INCL_DOSMODULEMGR
|
||||||
@ -59,27 +61,12 @@
|
|||||||
# if defined(HCL_ENABLE_LIBLTDL)
|
# if defined(HCL_ENABLE_LIBLTDL)
|
||||||
# include <ltdl.h>
|
# include <ltdl.h>
|
||||||
# define USE_LTDL
|
# 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)
|
# elif defined(HAVE_DLFCN_H)
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
# define USE_DLFCN
|
# 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__)
|
# elif defined(__APPLE__) || defined(__MACOSX__)
|
||||||
# define USE_MACH_O_DYLD
|
# define USE_MACH_O_DYLD
|
||||||
# include <mach-o/dyld.h>
|
# 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
|
# else
|
||||||
# error UNSUPPORTED DYNAMIC LINKER
|
# error UNSUPPORTED DYNAMIC LINKER
|
||||||
# endif
|
# endif
|
||||||
@ -542,7 +529,7 @@ static HCL_INLINE int read_input (hcl_t* hcl, hcl_ioinarg_t* arg)
|
|||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
if (errno == EINTR) goto start_over;
|
if (errno == EINTR) goto start_over;
|
||||||
hcl_seterrwithsyserr (hcl, errno);
|
hcl_seterrwithsyserr (hcl, 0, errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (n >= 1) break;
|
else if (n >= 1) break;
|
||||||
@ -559,7 +546,7 @@ static HCL_INLINE int read_input (hcl_t* hcl, hcl_ioinarg_t* arg)
|
|||||||
if (x <= -1)
|
if (x <= -1)
|
||||||
{
|
{
|
||||||
if (errno == EINTR) goto start_over;
|
if (errno == EINTR) goto start_over;
|
||||||
hcl_seterrwithsyserr (hcl, errno);
|
hcl_seterrwithsyserr (hcl, 0, errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,66 +643,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 void log_write (hcl_t* hcl, hcl_bitmask_t mask, const hcl_ooch_t* msg, hcl_oow_t len)
|
static void log_write (hcl_t* hcl, hcl_bitmask_t mask, const hcl_ooch_t* msg, hcl_oow_t len)
|
||||||
{
|
{
|
||||||
worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl);
|
worker_hcl_xtn_t* xtn = (worker_hcl_xtn_t*)hcl_getxtn(hcl);
|
||||||
@ -738,357 +665,7 @@ static void log_write_for_dummy (hcl_t* hcl, hcl_bitmask_t mask, const hcl_ooch_
|
|||||||
pthread_mutex_unlock (&server->log_mutex);
|
pthread_mutex_unlock (&server->log_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len)
|
#include "cb-impl.h"
|
||||||
{
|
|
||||||
#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_seterrnum (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(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(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
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
@ -1613,7 +1190,7 @@ static int insert_exec_timer (hcl_server_proto_t* proto, const hcl_ntime_t* tmou
|
|||||||
HCL_MEMSET (&event, 0, HCL_SIZEOF(event));
|
HCL_MEMSET (&event, 0, HCL_SIZEOF(event));
|
||||||
event.ctx = proto;
|
event.ctx = proto;
|
||||||
proto->hcl->vmprim.vm_gettime (proto->hcl, &event.when);
|
proto->hcl->vmprim.vm_gettime (proto->hcl, &event.when);
|
||||||
HCL_ADDNTIME (&event.when, &event.when, tmout);
|
HCL_ADD_NTIME (&event.when, &event.when, tmout);
|
||||||
event.handler = exec_runtime_handler;
|
event.handler = exec_runtime_handler;
|
||||||
event.updater = exec_runtime_updater;
|
event.updater = exec_runtime_updater;
|
||||||
|
|
||||||
@ -2027,7 +1604,7 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p
|
|||||||
|
|
||||||
if (pipe(pfd) <= -1)
|
if (pipe(pfd) <= -1)
|
||||||
{
|
{
|
||||||
if (errnum) *errnum = hcl_syserr_to_errnum(errno);
|
if (errnum) *errnum = syserrstrb(hcl, 0, errno, HCL_NULL, 0);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2071,8 +1648,8 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p
|
|||||||
server->cfg.worker_stack_size = 512000UL;
|
server->cfg.worker_stack_size = 512000UL;
|
||||||
server->cfg.actor_heap_size = 512000UL;
|
server->cfg.actor_heap_size = 512000UL;
|
||||||
|
|
||||||
HCL_INITNTIME (&server->cfg.worker_idle_timeout, 0, 0);
|
HCL_INIT_NTIME (&server->cfg.worker_idle_timeout, 0, 0);
|
||||||
HCL_INITNTIME (&server->cfg.actor_max_runtime, 0, 0);
|
HCL_INIT_NTIME (&server->cfg.actor_max_runtime, 0, 0);
|
||||||
|
|
||||||
server->mux_pipe[0] = pfd[0];
|
server->mux_pipe[0] = pfd[0];
|
||||||
server->mux_pipe[1] = pfd[1];
|
server->mux_pipe[1] = pfd[1];
|
||||||
@ -2407,7 +1984,7 @@ void hcl_server_logufmt (hcl_server_t* server, hcl_bitmask_t mask, const hcl_uch
|
|||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_err_with_syserr (hcl_server_t* server, int syserr, const char* bfmt, ...)
|
static void set_err_with_syserr (hcl_server_t* server, int syserr_type, int syserr_code, const char* bfmt, ...)
|
||||||
{
|
{
|
||||||
hcl_t* hcl = server->dummy_hcl;
|
hcl_t* hcl = server->dummy_hcl;
|
||||||
hcl_errnum_t errnum;
|
hcl_errnum_t errnum;
|
||||||
@ -2419,10 +1996,9 @@ static void set_err_with_syserr (hcl_server_t* server, int syserr, const char* b
|
|||||||
|
|
||||||
if (hcl->shuterr) return;
|
if (hcl->shuterr) return;
|
||||||
|
|
||||||
errnum = hcl_syserr_to_errnum(syserr);
|
|
||||||
if (hcl->vmprim.syserrstrb)
|
if (hcl->vmprim.syserrstrb)
|
||||||
{
|
{
|
||||||
hcl->vmprim.syserrstrb (hcl, syserr, hcl->errmsg.tmpbuf.bch, HCL_COUNTOF(hcl->errmsg.tmpbuf.bch));
|
errnum = hcl->vmprim.syserrstrb(hcl, syserr_type, syserr_code, hcl->errmsg.tmpbuf.bch, HCL_COUNTOF(hcl->errmsg.tmpbuf.bch));
|
||||||
|
|
||||||
va_start (ap, bfmt);
|
va_start (ap, bfmt);
|
||||||
hcl_seterrbfmtv (hcl, errnum, bfmt, ap);
|
hcl_seterrbfmtv (hcl, errnum, bfmt, ap);
|
||||||
@ -2443,7 +2019,7 @@ static void set_err_with_syserr (hcl_server_t* server, int syserr, const char* b
|
|||||||
{
|
{
|
||||||
HCL_ASSERT (hcl, hcl->vmprim.syserrstru != HCL_NULL);
|
HCL_ASSERT (hcl, hcl->vmprim.syserrstru != HCL_NULL);
|
||||||
|
|
||||||
hcl->vmprim.syserrstru (hcl, syserr, hcl->errmsg.tmpbuf.uch, HCL_COUNTOF(hcl->errmsg.tmpbuf.uch));
|
errnum = hcl->vmprim.syserrstru(hcl, syserr_type, syserr_code, hcl->errmsg.tmpbuf.uch, HCL_COUNTOF(hcl->errmsg.tmpbuf.uch));
|
||||||
|
|
||||||
va_start (ap, bfmt);
|
va_start (ap, bfmt);
|
||||||
hcl_seterrbfmtv (hcl, errnum, bfmt, ap);
|
hcl_seterrbfmtv (hcl, errnum, bfmt, ap);
|
||||||
@ -2497,7 +2073,7 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
ep_fd = epoll_create(1024);
|
ep_fd = epoll_create(1024);
|
||||||
if (ep_fd <= -1)
|
if (ep_fd <= -1)
|
||||||
{
|
{
|
||||||
set_err_with_syserr (server, errno, "unable to create multiplexer");
|
set_err_with_syserr (server, 0, errno, "unable to create multiplexer");
|
||||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2512,7 +2088,7 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
ev.data.fd = server->mux_pipe[0];
|
ev.data.fd = server->mux_pipe[0];
|
||||||
if (epoll_ctl(ep_fd, EPOLL_CTL_ADD, server->mux_pipe[0], &ev) <= -1)
|
if (epoll_ctl(ep_fd, EPOLL_CTL_ADD, server->mux_pipe[0], &ev) <= -1)
|
||||||
{
|
{
|
||||||
set_err_with_syserr (server, errno, "unable to register pipe %d to multiplexer", server->mux_pipe[0]);
|
set_err_with_syserr (server, 0, errno, "unable to register pipe %d to multiplexer", server->mux_pipe[0]);
|
||||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
||||||
close (ep_fd);
|
close (ep_fd);
|
||||||
return -1;
|
return -1;
|
||||||
@ -2543,7 +2119,7 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
srv_fd = socket(sck_fam, SOCK_STREAM, 0);
|
srv_fd = socket(sck_fam, SOCK_STREAM, 0);
|
||||||
if (srv_fd <= -1)
|
if (srv_fd <= -1)
|
||||||
{
|
{
|
||||||
set_err_with_syserr (server, errno, "unable to open server socket for %.*hs", addr_len, addr_ptr);
|
set_err_with_syserr (server, 0, errno, "unable to open server socket for %.*hs", addr_len, addr_ptr);
|
||||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
||||||
goto next_segment;
|
goto next_segment;
|
||||||
}
|
}
|
||||||
@ -2568,7 +2144,7 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
|
|
||||||
if (bind(srv_fd, (struct sockaddr*)&srv_addr, srv_len) == -1)
|
if (bind(srv_fd, (struct sockaddr*)&srv_addr, srv_len) == -1)
|
||||||
{
|
{
|
||||||
set_err_with_syserr (server, errno, "unable to bind server socket %d for %.*hs", srv_fd, addr_len, addr_ptr);
|
set_err_with_syserr (server, 0, errno, "unable to bind server socket %d for %.*hs", srv_fd, addr_len, addr_ptr);
|
||||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
||||||
close (srv_fd);
|
close (srv_fd);
|
||||||
goto next_segment;
|
goto next_segment;
|
||||||
@ -2576,7 +2152,7 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
|
|
||||||
if (listen(srv_fd, 128) <= -1)
|
if (listen(srv_fd, 128) <= -1)
|
||||||
{
|
{
|
||||||
set_err_with_syserr (server, errno, "unable to listen on server socket %d for %.*hs", srv_fd, addr_len, addr_ptr);
|
set_err_with_syserr (server, 0, errno, "unable to listen on server socket %d for %.*hs", srv_fd, addr_len, addr_ptr);
|
||||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
||||||
close (srv_fd);
|
close (srv_fd);
|
||||||
goto next_segment;
|
goto next_segment;
|
||||||
@ -2587,7 +2163,7 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
ev.data.fd = srv_fd;
|
ev.data.fd = srv_fd;
|
||||||
if (epoll_ctl(ep_fd, EPOLL_CTL_ADD, srv_fd, &ev) <= -1)
|
if (epoll_ctl(ep_fd, EPOLL_CTL_ADD, srv_fd, &ev) <= -1)
|
||||||
{
|
{
|
||||||
set_err_with_syserr (server, errno, "unable to register server socket %d to multiplexer for %.*hs", srv_fd, addr_len, addr_ptr);
|
set_err_with_syserr (server, 0, errno, "unable to register server socket %d to multiplexer for %.*hs", srv_fd, addr_len, addr_ptr);
|
||||||
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
HCL_LOG1 (server->dummy_hcl, SERVER_LOGMASK_ERROR, "%js\n", hcl_server_geterrmsg(server));
|
||||||
close (srv_fd);
|
close (srv_fd);
|
||||||
goto next_segment;
|
goto next_segment;
|
||||||
@ -2648,7 +2224,7 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
pthread_mutex_lock (&server->tmr_mutex);
|
pthread_mutex_lock (&server->tmr_mutex);
|
||||||
n = hcl_tmr_gettmout(server->tmr, HCL_NULL, &tmout);
|
n = hcl_tmr_gettmout(server->tmr, HCL_NULL, &tmout);
|
||||||
pthread_mutex_unlock (&server->tmr_mutex);
|
pthread_mutex_unlock (&server->tmr_mutex);
|
||||||
if (n <= -1) HCL_INITNTIME (&tmout, 10, 0);
|
if (n <= -1) HCL_INIT_NTIME (&tmout, 10, 0);
|
||||||
|
|
||||||
n = epoll_wait(server->listener.ep_fd, server->listener.ev_buf, HCL_COUNTOF(server->listener.ev_buf), HCL_SECNSEC_TO_MSEC(tmout.sec, tmout.nsec));
|
n = epoll_wait(server->listener.ep_fd, server->listener.ev_buf, HCL_COUNTOF(server->listener.ev_buf), HCL_SECNSEC_TO_MSEC(tmout.sec, tmout.nsec));
|
||||||
|
|
||||||
@ -2658,7 +2234,7 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
if (server->stopreq) break; /* normal termination requested */
|
if (server->stopreq) break; /* normal termination requested */
|
||||||
if (errno == EINTR) continue; /* interrupted but not termination requested */
|
if (errno == EINTR) continue; /* interrupted but not termination requested */
|
||||||
|
|
||||||
set_err_with_syserr (server, errno, "unable to poll for events in server");
|
set_err_with_syserr (server, 0, errno, "unable to poll for events in server");
|
||||||
xret = -1;
|
xret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2699,7 +2275,7 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs)
|
|||||||
if (errno == EAGAIN) continue;
|
if (errno == EAGAIN) continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
set_err_with_syserr (server, errno, "unable to accept worker on server socket %d", evp->data.fd);
|
set_err_with_syserr (server, 0, errno, "unable to accept worker on server socket %d", evp->data.fd);
|
||||||
xret = -1;
|
xret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
19
lib/hcl.h
19
lib/hcl.h
@ -266,7 +266,7 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t;
|
|||||||
* are set to 1 or 2.
|
* are set to 1 or 2.
|
||||||
*
|
*
|
||||||
* This scheme works because the object allocators aligns the object size to
|
* This scheme works because the object allocators aligns the object size to
|
||||||
* a multiple of sizeof(moo_oop_t). This way, the 2 least-significant bits
|
* a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits
|
||||||
* of a real OOP are always 0s.
|
* of a real OOP are always 0s.
|
||||||
*
|
*
|
||||||
* With 2 bits, i can encode only 3 special types except object pointers.
|
* With 2 bits, i can encode only 3 special types except object pointers.
|
||||||
@ -814,16 +814,18 @@ typedef void (*hcl_log_write_t) (
|
|||||||
hcl_oow_t len
|
hcl_oow_t len
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef void (*hcl_syserrstrb_t) (
|
typedef hcl_errnum_t (*hcl_syserrstrb_t) (
|
||||||
hcl_t* hcl,
|
hcl_t* hcl,
|
||||||
int syserr,
|
int syserr_type,
|
||||||
|
int syserr_code,
|
||||||
hcl_bch_t* buf,
|
hcl_bch_t* buf,
|
||||||
hcl_oow_t len
|
hcl_oow_t len
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef void (*hcl_syserrstru_t) (
|
typedef hcl_errnum_t (*hcl_syserrstru_t) (
|
||||||
hcl_t* hcl,
|
hcl_t* hcl,
|
||||||
int syserr,
|
int syserr_type,
|
||||||
|
int syserr_code,
|
||||||
hcl_uch_t* buf,
|
hcl_uch_t* buf,
|
||||||
hcl_oow_t len
|
hcl_oow_t len
|
||||||
);
|
);
|
||||||
@ -1525,7 +1527,8 @@ HCL_EXPORT void hcl_seterrnum (
|
|||||||
|
|
||||||
HCL_EXPORT void hcl_seterrwithsyserr (
|
HCL_EXPORT void hcl_seterrwithsyserr (
|
||||||
hcl_t* hcl,
|
hcl_t* hcl,
|
||||||
int syserr
|
int syserr_type,
|
||||||
|
int syserr_code
|
||||||
);
|
);
|
||||||
|
|
||||||
HCL_EXPORT void hcl_seterrbfmt (
|
HCL_EXPORT void hcl_seterrbfmt (
|
||||||
@ -1572,10 +1575,6 @@ HCL_EXPORT const hcl_ooch_t* hcl_errnum_to_errstr (
|
|||||||
hcl_errnum_t errnum
|
hcl_errnum_t errnum
|
||||||
);
|
);
|
||||||
|
|
||||||
HCL_EXPORT hcl_errnum_t hcl_syserr_to_errnum (
|
|
||||||
int syserr
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hcl_getoption() function gets the value of an option
|
* The hcl_getoption() function gets the value of an option
|
||||||
* specified by \a id into the buffer pointed to by \a value.
|
* specified by \a id into the buffer pointed to by \a value.
|
||||||
|
693
lib/main.c
693
lib/main.c
@ -44,6 +44,8 @@
|
|||||||
# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
|
# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
|
||||||
# include <ltdl.h>
|
# include <ltdl.h>
|
||||||
# define USE_LTDL
|
# define USE_LTDL
|
||||||
|
# else
|
||||||
|
# define USE_WIN_DLL
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__OS2__)
|
#elif defined(__OS2__)
|
||||||
# define INCL_DOSMODULEMGR
|
# define INCL_DOSMODULEMGR
|
||||||
@ -60,27 +62,12 @@
|
|||||||
# if defined(HCL_ENABLE_LIBLTDL)
|
# if defined(HCL_ENABLE_LIBLTDL)
|
||||||
# include <ltdl.h>
|
# include <ltdl.h>
|
||||||
# define USE_LTDL
|
# 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)
|
# elif defined(HAVE_DLFCN_H)
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
# define USE_DLFCN
|
# 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__)
|
# elif defined(__APPLE__) || defined(__MACOSX__)
|
||||||
# define USE_MACH_O_DYLD
|
# define USE_MACH_O_DYLD
|
||||||
# include <mach-o/dyld.h>
|
# 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
|
# else
|
||||||
# error UNSUPPORTED DYNAMIC LINKER
|
# error UNSUPPORTED DYNAMIC LINKER
|
||||||
# endif
|
# 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)
|
static int write_all (int fd, const hcl_bch_t* ptr, hcl_oow_t len)
|
||||||
{
|
{
|
||||||
while (len > 0)
|
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);
|
flush_log (hcl, logfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "cb-impl.h"
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
static int vm_startup (hcl_t* hcl)
|
static int vm_startup (hcl_t* hcl)
|
||||||
{
|
{
|
||||||
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
|
||||||
xtn->waitable_timer = CreateWaitableTimer(HCL_NULL, TRUE, HCL_NULL);
|
xtn->waitable_timer = CreateWaitableTimer(HCL_NULL, TRUE, HCL_NULL);
|
||||||
xtn->vm_running = 1;
|
#endif
|
||||||
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 */
|
|
||||||
|
|
||||||
xtn->vm_running = 1;
|
xtn->vm_running = 1;
|
||||||
return 0;
|
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)
|
static void vm_cleanup (hcl_t* hcl)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
|
||||||
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
|
||||||
|
|
||||||
|
xtn->vm_running = 0;
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
if (xtn->waitable_timer)
|
if (xtn->waitable_timer)
|
||||||
{
|
{
|
||||||
CloseHandle (xtn->waitable_timer);
|
CloseHandle (xtn->waitable_timer);
|
||||||
xtn->waitable_timer = HCL_NULL;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#define HEAP_LEFT(x) ((x) * 2 + 1)
|
#define HEAP_LEFT(x) ((x) * 2 + 1)
|
||||||
#define HEAP_RIGHT(x) ((x) * 2 + 2)
|
#define HEAP_RIGHT(x) ((x) * 2 + 2)
|
||||||
|
|
||||||
#define YOUNGER_THAN(x,y) (HCL_CMPNTIME(&(x)->when, &(y)->when) < 0)
|
#define YOUNGER_THAN(x,y) (HCL_CMP_NTIME(&(x)->when, &(y)->when) < 0)
|
||||||
|
|
||||||
hcl_tmr_t* hcl_tmr_open (hcl_t* hcl, hcl_oow_t xtnsize, hcl_oow_t capa)
|
hcl_tmr_t* hcl_tmr_open (hcl_t* hcl, hcl_oow_t xtnsize, hcl_oow_t capa)
|
||||||
{
|
{
|
||||||
@ -248,7 +248,7 @@ int hcl_tmr_fire (hcl_tmr_t* tmr, const hcl_ntime_t* tm, hcl_oow_t* firecnt)
|
|||||||
|
|
||||||
while (tmr->size > 0)
|
while (tmr->size > 0)
|
||||||
{
|
{
|
||||||
if (HCL_CMPNTIME(&tmr->event[0].when, &now) > 0) break;
|
if (HCL_CMP_NTIME(&tmr->event[0].when, &now) > 0) break;
|
||||||
|
|
||||||
event = tmr->event[0];
|
event = tmr->event[0];
|
||||||
hcl_tmr_delete (tmr, 0); /* remove the registered event structure */
|
hcl_tmr_delete (tmr, 0); /* remove the registered event structure */
|
||||||
@ -273,8 +273,8 @@ int hcl_tmr_gettmout (hcl_tmr_t* tmr, const hcl_ntime_t* tm, hcl_ntime_t* tmout)
|
|||||||
/*else if (hcl_gettime(&now) <= -1) return -1;*/
|
/*else if (hcl_gettime(&now) <= -1) return -1;*/
|
||||||
tmr->hcl->vmprim.vm_gettime (tmr->hcl, &now);
|
tmr->hcl->vmprim.vm_gettime (tmr->hcl, &now);
|
||||||
|
|
||||||
HCL_SUBNTIME (tmout, &tmr->event[0].when, &now);
|
HCL_SUB_NTIME (tmout, &tmr->event[0].when, &now);
|
||||||
if (tmout->sec < 0) HCL_CLEARNTIME (tmout);
|
if (tmout->sec < 0) HCL_CLEAR_NTIME (tmout);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user