| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |     Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |     are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |        documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | 
					
						
							|  |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							|  |  |  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
					
						
							|  |  |  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
					
						
							|  |  |  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
					
						
							|  |  |  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
					
						
							|  |  |  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
					
						
							|  |  |  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "hcl-prv.h"
 | 
					
						
							|  |  |  | #include <hcl-utl.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | #	include <windows.h>
 | 
					
						
							|  |  |  | #	include <tchar.h>
 | 
					
						
							|  |  |  | #	include <time.h>
 | 
					
						
							|  |  |  | #	include <io.h>
 | 
					
						
							|  |  |  | #	include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
 | 
					
						
							|  |  |  | #		include <ltdl.h>
 | 
					
						
							|  |  |  | #		define USE_LTDL
 | 
					
						
							|  |  |  | #	else
 | 
					
						
							|  |  |  | #		define USE_WIN_DLL
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	include "poll-msw.h"
 | 
					
						
							|  |  |  | #	define USE_POLL
 | 
					
						
							|  |  |  | #	define XPOLLIN POLLIN
 | 
					
						
							|  |  |  | #	define XPOLLOUT POLLOUT
 | 
					
						
							|  |  |  | #	define XPOLLERR POLLERR
 | 
					
						
							|  |  |  | #	define XPOLLHUP POLLHUP
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(SIZE_T)
 | 
					
						
							|  |  |  | #	define SIZE_T unsigned long int
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | #	define INCL_DOSMODULEMGR
 | 
					
						
							|  |  |  | #	define INCL_DOSPROCESS
 | 
					
						
							|  |  |  | #	define INCL_DOSSEMAPHORES
 | 
					
						
							|  |  |  | #	define INCL_DOSEXCEPTIONS
 | 
					
						
							|  |  |  | #	define INCL_DOSMISC
 | 
					
						
							|  |  |  | #	define INCL_DOSDATETIME
 | 
					
						
							|  |  |  | #	define INCL_DOSFILEMGR
 | 
					
						
							|  |  |  | #	define INCL_DOSERRORS
 | 
					
						
							|  |  |  | #	include <os2.h>
 | 
					
						
							|  |  |  | #	include <time.h>
 | 
					
						
							|  |  |  | #	include <fcntl.h>
 | 
					
						
							|  |  |  | #	include <io.h>
 | 
					
						
							|  |  |  | #	include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #	include <types.h> /* some types for socket.h */
 | 
					
						
							|  |  |  | #	include <sys/socket.h> /* for socketpair */
 | 
					
						
							|  |  |  | #	include <sys/time.h>
 | 
					
						
							|  |  |  | #	include <sys/ioctl.h> /* FIONBIO */
 | 
					
						
							|  |  |  | #   include <nerrno.h> /* for SOCEXXX error codes */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	define BSD_SELECT
 | 
					
						
							|  |  |  | #	if defined(TCPV40HDRS)
 | 
					
						
							|  |  |  | #	include <sys/select.h>
 | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | #	include <sys/un.h> /* for sockaddr_un */
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #	else
 | 
					
						
							|  |  |  | #	include <unistd.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	define USE_SELECT
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	/* fake XPOLLXXX values */ | 
					
						
							|  |  |  | #	define XPOLLIN  (1 << 0)
 | 
					
						
							|  |  |  | #	define XPOLLOUT (1 << 1)
 | 
					
						
							|  |  |  | #	define XPOLLERR (1 << 2)
 | 
					
						
							|  |  |  | #	define XPOLLHUP (1 << 3)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | #	include <dos.h>
 | 
					
						
							|  |  |  | #	include <time.h>
 | 
					
						
							|  |  |  | #	include <io.h>
 | 
					
						
							|  |  |  | #	include <signal.h>
 | 
					
						
							|  |  |  | #	include <errno.h>
 | 
					
						
							|  |  |  | #	include <fcntl.h>
 | 
					
						
							|  |  |  | #	include <conio.h> /* inp, outp */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(_INTELC32_)
 | 
					
						
							|  |  |  | #		define DOS_EXIT 0x4C
 | 
					
						
							|  |  |  | #		include <i32.h>
 | 
					
						
							|  |  |  | #		include <stk.h>
 | 
					
						
							|  |  |  | #	else
 | 
					
						
							|  |  |  | #		include <dosfunc.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* fake XPOLLXXX values */ | 
					
						
							|  |  |  | #	define XPOLLIN  (1 << 0)
 | 
					
						
							|  |  |  | #	define XPOLLOUT (1 << 1)
 | 
					
						
							|  |  |  | #	define XPOLLERR (1 << 2)
 | 
					
						
							|  |  |  | #	define XPOLLHUP (1 << 3)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(macintosh)
 | 
					
						
							|  |  |  | #	include <Types.h>
 | 
					
						
							|  |  |  | #	include <OSUtils.h>
 | 
					
						
							|  |  |  | #	include <Timer.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	include <MacErrors.h>
 | 
					
						
							|  |  |  | #	include <Process.h>
 | 
					
						
							|  |  |  | #	include <Dialogs.h>
 | 
					
						
							|  |  |  | #	include <TextUtils.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	include <sys/types.h>
 | 
					
						
							|  |  |  | #	include <unistd.h>
 | 
					
						
							|  |  |  | #	include <fcntl.h>
 | 
					
						
							|  |  |  | #	include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(HAVE_TIME_H)
 | 
					
						
							|  |  |  | #		include <time.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #	if defined(HAVE_SYS_TIME_H)
 | 
					
						
							|  |  |  | #		include <sys/time.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #	if defined(HAVE_SIGNAL_H)
 | 
					
						
							|  |  |  | #		include <signal.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #	if defined(HAVE_SYS_MMAN_H)
 | 
					
						
							|  |  |  | #		include <sys/mman.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(HCL_ENABLE_LIBLTDL)
 | 
					
						
							|  |  |  | #		include <ltdl.h>
 | 
					
						
							|  |  |  | #		define USE_LTDL
 | 
					
						
							|  |  |  | #	elif defined(HAVE_DLFCN_H)
 | 
					
						
							|  |  |  | #		include <dlfcn.h>
 | 
					
						
							|  |  |  | #		define USE_DLFCN
 | 
					
						
							|  |  |  | #	elif defined(__APPLE__) || defined(__MACOSX__)
 | 
					
						
							|  |  |  | #		define USE_MACH_O_DYLD
 | 
					
						
							|  |  |  | #		include <mach-o/dyld.h>
 | 
					
						
							|  |  |  | #	else
 | 
					
						
							|  |  |  | #		error UNSUPPORTED DYNAMIC LINKER
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(HAVE_TIME_H)
 | 
					
						
							|  |  |  | #		include <time.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #	if defined(HAVE_SYS_TIME_H)
 | 
					
						
							|  |  |  | #		include <sys/time.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #	if defined(HAVE_SIGNAL_H)
 | 
					
						
							|  |  |  | #		include <signal.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #	if defined(HAVE_SYS_MMAN_H)
 | 
					
						
							|  |  |  | #		include <sys/mman.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(USE_THREAD)
 | 
					
						
							|  |  |  | #		include <pthread.h>
 | 
					
						
							|  |  |  | #		include <sched.h>
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	if defined(HAVE_SYS_DEVPOLL_H)
 | 
					
						
							|  |  |  | 		/* solaris */ | 
					
						
							|  |  |  | #		include <sys/devpoll.h>
 | 
					
						
							|  |  |  | #		define USE_DEVPOLL
 | 
					
						
							|  |  |  | #		define XPOLLIN POLLIN
 | 
					
						
							|  |  |  | #		define XPOLLOUT POLLOUT
 | 
					
						
							|  |  |  | #		define XPOLLERR POLLERR
 | 
					
						
							|  |  |  | #		define XPOLLHUP POLLHUP
 | 
					
						
							|  |  |  | #	elif defined(HAVE_SYS_EVENT_H) && defined(HAVE_KQUEUE)
 | 
					
						
							|  |  |  | 		/* netbsd, openbsd, etc */ | 
					
						
							|  |  |  | #		include <sys/event.h>
 | 
					
						
							|  |  |  | #		define USE_KQUEUE
 | 
					
						
							|  |  |  | 		/* fake XPOLLXXX values */ | 
					
						
							|  |  |  | #		define XPOLLIN  (1 << 0)
 | 
					
						
							|  |  |  | #		define XPOLLOUT (1 << 1)
 | 
					
						
							|  |  |  | #		define XPOLLERR (1 << 2)
 | 
					
						
							|  |  |  | #		define XPOLLHUP (1 << 3)
 | 
					
						
							|  |  |  | #	elif defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE)
 | 
					
						
							|  |  |  | 		/* linux */ | 
					
						
							|  |  |  | #		include <sys/epoll.h>
 | 
					
						
							|  |  |  | #		define USE_EPOLL
 | 
					
						
							|  |  |  | #		define XPOLLIN EPOLLIN
 | 
					
						
							|  |  |  | #		define XPOLLOUT EPOLLOUT
 | 
					
						
							|  |  |  | #		define XPOLLERR EPOLLERR
 | 
					
						
							|  |  |  | #		define XPOLLHUP EPOLLHUP
 | 
					
						
							|  |  |  | #	elif defined(HAVE_POLL_H)
 | 
					
						
							|  |  |  | #		include <poll.h>
 | 
					
						
							|  |  |  | #		define USE_POLL
 | 
					
						
							|  |  |  | #		define XPOLLIN POLLIN
 | 
					
						
							|  |  |  | #		define XPOLLOUT POLLOUT
 | 
					
						
							|  |  |  | #		define XPOLLERR POLLERR
 | 
					
						
							|  |  |  | #		define XPOLLHUP POLLHUP
 | 
					
						
							|  |  |  | #	else
 | 
					
						
							|  |  |  | #		define USE_SELECT
 | 
					
						
							|  |  |  | 		/* fake XPOLLXXX values */ | 
					
						
							|  |  |  | #		define XPOLLIN  (1 << 0)
 | 
					
						
							|  |  |  | #		define XPOLLOUT (1 << 1)
 | 
					
						
							|  |  |  | #		define XPOLLERR (1 << 2)
 | 
					
						
							|  |  |  | #		define XPOLLHUP (1 << 3)
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(HCL_DEFAULT_PFMODDIR)
 | 
					
						
							|  |  |  | #	define HCL_DEFAULT_PFMODDIR ""
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(HCL_DEFAULT_PFMODPREFIX)
 | 
					
						
							|  |  |  | #	if defined(_WIN32)
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPREFIX "hcl-"
 | 
					
						
							|  |  |  | #	elif defined(__OS2__)
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPREFIX "hcl"
 | 
					
						
							|  |  |  | #	elif defined(__DOS__)
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPREFIX "hcl"
 | 
					
						
							|  |  |  | #	else
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPREFIX "libhcl-"
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(HCL_DEFAULT_PFMODPOSTFIX)
 | 
					
						
							|  |  |  | #	if defined(_WIN32)
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPOSTFIX ""
 | 
					
						
							|  |  |  | #	elif defined(__OS2__)
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPOSTFIX ""
 | 
					
						
							|  |  |  | #	elif defined(__DOS__)
 | 
					
						
							|  |  |  | #		define HCL_DEFAULT_PFMODPOSTFIX ""
 | 
					
						
							|  |  |  | #	else
 | 
					
						
							|  |  |  | #		if defined(USE_DLFCN)
 | 
					
						
							|  |  |  | #			define HCL_DEFAULT_PFMODPOSTFIX ".so"
 | 
					
						
							|  |  |  | #		elif defined(USE_MACH_O_DYLD)
 | 
					
						
							|  |  |  | #			define HCL_DEFAULT_PFMODPOSTFIX ".dylib"
 | 
					
						
							|  |  |  | #		else
 | 
					
						
							|  |  |  | #			define HCL_DEFAULT_PFMODPOSTFIX ""
 | 
					
						
							|  |  |  | #		endif
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 15:06:41 +00:00
										 |  |  | #if defined(USE_THREAD)
 | 
					
						
							|  |  |  | #	define MUTEX_INIT(x) pthread_mutex_init((x), MOO_NULL)
 | 
					
						
							|  |  |  | #	define MUTEX_DESTROY(x) pthread_mutex_destroy(x)
 | 
					
						
							|  |  |  | #	define MUTEX_LOCK(x) pthread_mutex_lock(x)
 | 
					
						
							|  |  |  | #	define MUTEX_UNLOCK(x) pthread_mutex_unlock(x)
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-02-09 15:06:41 +00:00
										 |  |  | #	define MUTEX_INIT(x)
 | 
					
						
							|  |  |  | #	define MUTEX_DESTROY(x)
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | #	define MUTEX_LOCK(x)
 | 
					
						
							|  |  |  | #	define MUTEX_UNLOCK(x)
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #if defined(USE_SELECT)
 | 
					
						
							|  |  |  | struct select_fd_t | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int fd; | 
					
						
							|  |  |  | 	int events; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct xtn_t xtn_t; | 
					
						
							|  |  |  | struct xtn_t | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_t* next; | 
					
						
							|  |  |  | 	hcl_t* prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int vm_running; | 
					
						
							|  |  |  | 	int rcv_tick; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl_cmgr_t* input_cmgr; | 
					
						
							|  |  |  | 	hcl_cmgr_t* log_cmgr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int fd; | 
					
						
							|  |  |  | 		int fd_flag; /* bitwise OR'ed fo logfd_flag_t bits */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		struct | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_bch_t buf[4096]; | 
					
						
							|  |  |  | 			hcl_oow_t len; | 
					
						
							|  |  |  | 		} out; | 
					
						
							|  |  |  | 	} log; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(_WIN32)
 | 
					
						
							|  |  |  | 	HANDLE waitable_timer; | 
					
						
							|  |  |  | 	DWORD tc_last; | 
					
						
							|  |  |  | 	DWORD tc_overflow; | 
					
						
							|  |  |  | 	#elif defined(__OS2__)
 | 
					
						
							|  |  |  | 	ULONG tc_last; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	ULONG tc_overflow; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	hcl_ntime_t tc_last_ret; | 
					
						
							|  |  |  | 	#elif defined(__DOS__)
 | 
					
						
							|  |  |  | 	clock_t tc_last; | 
					
						
							|  |  |  | 	hcl_ntime_t tc_last_ret; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 	int ep; /* /dev/poll */ | 
					
						
							|  |  |  | 	#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	int ep; /* kqueue */ | 
					
						
							|  |  |  | 	#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	int ep; /* epoll */ | 
					
						
							|  |  |  | 	#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 	/* nothing */ | 
					
						
							|  |  |  | 	#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 	/* nothing */ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 	struct | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int p[2]; /* pipe for signaling */ | 
					
						
							|  |  |  | 		pthread_t thr; | 
					
						
							|  |  |  | 		int up; | 
					
						
							|  |  |  | 		int abort; | 
					
						
							|  |  |  | 	} iothr; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int p[2]; /* pipe for signaling */ | 
					
						
							|  |  |  | 	} sigfd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 		/*TODO: make it dynamically changeable depending on the number of
 | 
					
						
							|  |  |  | 		 *      file descriptors added */ | 
					
						
							|  |  |  | 		struct pollfd buf[64]; /* buffer for reading events */ | 
					
						
							|  |  |  | 	#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 		struct | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t* ptr; | 
					
						
							|  |  |  | 			hcl_oow_t capa; | 
					
						
							|  |  |  | 		} reg; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		struct kevent buf[64]; | 
					
						
							|  |  |  | 	#elif defined(USE_EPOLL)
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		/*TODO: make it dynamically changeable depending on the number of
 | 
					
						
							|  |  |  | 		 *      file descriptors added */ | 
					
						
							|  |  |  | 		struct epoll_event buf[64]; /* buffer for reading events */ | 
					
						
							|  |  |  | 	#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 		struct | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			struct pollfd* ptr; | 
					
						
							|  |  |  | 			hcl_oow_t capa; | 
					
						
							|  |  |  | 			hcl_oow_t len; | 
					
						
							|  |  |  | 		#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 			pthread_mutex_t pmtx; | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 		} reg; /* registry */ | 
					
						
							|  |  |  | 		struct pollfd* buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 		struct | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			fd_set rfds; | 
					
						
							|  |  |  | 			fd_set wfds; | 
					
						
							|  |  |  | 			int maxfd; | 
					
						
							|  |  |  | 		#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 			pthread_mutex_t smtx; | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 		} reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		struct select_fd_t buf[FD_SETSIZE]; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hcl_oow_t len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 		pthread_mutex_t mtx; | 
					
						
							|  |  |  | 		pthread_cond_t cnd; | 
					
						
							|  |  |  | 		pthread_cond_t cnd2; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int halting; | 
					
						
							|  |  |  | 	} ev; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_XTN(hcl) ((xtn_t*)((hcl_uint8_t*)hcl_getxtn(hcl) - HCL_SIZEOF(xtn_t)))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * BASIC MEMORY MANAGER | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void* sys_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return malloc(size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void* sys_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return realloc(ptr, size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sys_free (hcl_mmgr_t* mmgr, void* ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	free (ptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static hcl_mmgr_t sys_mmgr = | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	sys_alloc, | 
					
						
							|  |  |  | 	sys_realloc, | 
					
						
							|  |  |  | 	sys_free, | 
					
						
							|  |  |  | 	HCL_NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * LOGGING SUPPORT | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum logfd_flag_t | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	LOGFD_TTY = (1 << 0), | 
					
						
							|  |  |  | 	LOGFD_OPENED_HERE = (1 << 1) | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int write_all (int fd, const hcl_bch_t* ptr, hcl_oow_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	while (len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_ooi_t wr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		wr = write(fd, ptr, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (wr <= -1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK)
 | 
					
						
							|  |  |  | 			if (errno == EAGAIN) continue; | 
					
						
							|  |  |  | 		#else
 | 
					
						
							|  |  |  | 			#if defined(EAGAIN)
 | 
					
						
							|  |  |  | 			if (errno == EAGAIN) continue; | 
					
						
							|  |  |  | 			#elif defined(EWOULDBLOCK)
 | 
					
						
							|  |  |  | 			if (errno == EWOULDBLOCK) continue; | 
					
						
							|  |  |  | 			#endif
 | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		#if defined(EINTR)
 | 
					
						
							|  |  |  | 			/* TODO: would this interfere with non-blocking nature of this VM? */ | 
					
						
							|  |  |  | 			if (errno == EINTR) continue; | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ptr += wr; | 
					
						
							|  |  |  | 		len -= wr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int write_log (hcl_t* hcl, int fd, const hcl_bch_t* ptr, hcl_oow_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (xtn->log.out.len > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t rcapa, cplen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rcapa = HCL_COUNTOF(xtn->log.out.buf) - xtn->log.out.len; | 
					
						
							|  |  |  | 			cplen = (len >= rcapa)? rcapa: len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			HCL_MEMCPY (&xtn->log.out.buf[xtn->log.out.len], ptr, cplen); | 
					
						
							|  |  |  | 			xtn->log.out.len += cplen; | 
					
						
							|  |  |  | 			ptr += cplen; | 
					
						
							|  |  |  | 			len -= cplen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (xtn->log.out.len >= HCL_COUNTOF(xtn->log.out.buf)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int n; | 
					
						
							|  |  |  | 				n = write_all(fd, xtn->log.out.buf, xtn->log.out.len); | 
					
						
							|  |  |  | 				xtn->log.out.len = 0; | 
					
						
							|  |  |  | 				if (n <= -1) return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t rcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rcapa = HCL_COUNTOF(xtn->log.out.buf); | 
					
						
							|  |  |  | 			if (len >= rcapa) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (write_all(fd, ptr, rcapa) <= -1) return -1; | 
					
						
							|  |  |  | 				ptr += rcapa; | 
					
						
							|  |  |  | 				len -= rcapa; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				HCL_MEMCPY (xtn->log.out.buf, ptr, len); | 
					
						
							|  |  |  | 				xtn->log.out.len += len; | 
					
						
							|  |  |  | 				ptr += len; | 
					
						
							|  |  |  | 				len -= len; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void flush_log (hcl_t* hcl, int fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	if (xtn->log.out.len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		write_all (fd, xtn->log.out.buf, xtn->log.out.len); | 
					
						
							|  |  |  | 		xtn->log.out.len = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void log_write (hcl_t* hcl, hcl_bitmask_t mask, const hcl_ooch_t* msg, hcl_oow_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_bch_t buf[256]; | 
					
						
							|  |  |  | 	hcl_oow_t ucslen, bcslen, msgidx; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	int logfd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mask & HCL_LOG_STDERR) logfd = 2; | 
					
						
							|  |  |  | 	else if (mask & HCL_LOG_STDOUT) logfd = 1; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		logfd = xtn->log.fd; | 
					
						
							|  |  |  | 		if (logfd <= -1) return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* TODO: beautify the log message.
 | 
					
						
							|  |  |  |  *       do classification based on mask. */ | 
					
						
							|  |  |  | 	if (!(mask & (HCL_LOG_STDOUT | HCL_LOG_STDERR))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		time_t now; | 
					
						
							|  |  |  | 		char ts[32]; | 
					
						
							|  |  |  | 		size_t tslen; | 
					
						
							|  |  |  | 		struct tm tm, *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		now = time(HCL_NULL); | 
					
						
							|  |  |  | 	#if defined(_WIN32)
 | 
					
						
							|  |  |  | 		tmp = localtime(&now); | 
					
						
							|  |  |  | 		tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		if (tslen == 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#elif defined(__OS2__)
 | 
					
						
							|  |  |  | 		#if defined(__WATCOMC__)
 | 
					
						
							|  |  |  | 		tmp = _localtime(&now, &tm); | 
					
						
							|  |  |  | 		#else
 | 
					
						
							|  |  |  | 		tmp = localtime(&now); | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 		#if defined(__BORLANDC__) || defined(__IBMC__)
 | 
					
						
							|  |  |  | 		/* the borland compiler doesn't handle %z properly - it showed 00 all the time.
 | 
					
						
							|  |  |  | 		 * the visualage compiler 3.0 doesn't support %z */ | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); | 
					
						
							|  |  |  | 		#else
 | 
					
						
							|  |  |  | 		tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		if (tslen == 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#elif defined(__DOS__)
 | 
					
						
							|  |  |  | 		tmp = localtime(&now); | 
					
						
							|  |  |  | 		/* since i know that %z/%Z is not available in strftime, i switch to sprintf immediately */ | 
					
						
							|  |  |  | 		tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		#if defined(HAVE_LOCALTIME_R)
 | 
					
						
							|  |  |  | 		tmp = localtime_r(&now, &tm); | 
					
						
							|  |  |  | 		#else
 | 
					
						
							|  |  |  | 		tmp = localtime(&now); | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		#if defined(HAVE_STRFTIME_SMALL_Z)
 | 
					
						
							|  |  |  | 		tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); | 
					
						
							|  |  |  | 		#else
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		#endif
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		if (tslen == 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		write_log (hcl, logfd, ts, tslen); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (logfd == xtn->log.fd && (xtn->log.fd_flag & LOGFD_TTY)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (mask & HCL_LOG_FATAL) write_log (hcl, logfd, "\x1B[1;31m", 7); | 
					
						
							|  |  |  | 		else if (mask & HCL_LOG_ERROR) write_log (hcl, logfd, "\x1B[1;32m", 7); | 
					
						
							|  |  |  | 		else if (mask & HCL_LOG_WARN) write_log (hcl, logfd, "\x1B[1;33m", 7); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(HCL_OOCH_IS_UCH)
 | 
					
						
							|  |  |  | 	msgidx = 0; | 
					
						
							|  |  |  | 	while (len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ucslen = len; | 
					
						
							|  |  |  | 		bcslen = HCL_COUNTOF(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		n = hcl_convootobchars(hcl, &msg[msgidx], &ucslen, buf, &bcslen); | 
					
						
							|  |  |  | 		if (n == 0 || n == -2) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			/* n = 0:
 | 
					
						
							|  |  |  | 			 *   converted all successfully | 
					
						
							|  |  |  | 			 * n == -2: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			 *    buffer not sufficient. not all got converted yet. | 
					
						
							|  |  |  | 			 *    write what have been converted this round. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			HCL_ASSERT (hcl, ucslen > 0); /* if this fails, the buffer size must be increased */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* attempt to write all converted characters */ | 
					
						
							|  |  |  | 			if (write_log(hcl, logfd, buf, bcslen) <= -1) break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (n == 0) break; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				msgidx += ucslen; | 
					
						
							|  |  |  | 				len -= ucslen; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (n <= -1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* conversion error */ | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	write_log (hcl, logfd, msg, len); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (logfd == xtn->log.fd && (xtn->log.fd_flag & LOGFD_TTY)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_log (hcl, logfd, "\x1B[0m", 4); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	flush_log (hcl, logfd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * 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)
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		case EAGAIN: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		case ERROR_INVALID_PARAMETER: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		case ERROR_INVALID_NAME: | 
					
						
							|  |  |  | 			return HCL_EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		case ERROR_INVALID_HANDLE: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			return HCL_EBADHND; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		case ERROR_ACCESS_DENIED: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if !defined(TCPV40HDRS)
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | static hcl_errnum_t os2sockerr_to_errnum (int errcode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (errcode) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case SOCEPERM:  return HCL_EPERM; | 
					
						
							|  |  |  | 		case SOCENOENT: return HCL_ENOENT; | 
					
						
							|  |  |  | 		case SOCEINTR:  return HCL_EINTR; | 
					
						
							|  |  |  | 		case SOCEACCES: return HCL_EACCES; | 
					
						
							|  |  |  | 		case SOCEINVAL: return HCL_EINVAL; | 
					
						
							|  |  |  | 		case SOCENOMEM: return HCL_ESYSMEM; | 
					
						
							|  |  |  | 		case SOCEPIPE:  return HCL_EPIPE; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 		default: return HCL_ESYSERR; | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | #endif /* TCPV40HDRS */
 | 
					
						
							|  |  |  | #endif /* __OS2__ */
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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 */ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			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) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 		case 2: | 
					
						
							|  |  |  | 		#if defined(__OS2__)
 | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 			#if defined(TCPV40HDRS)
 | 
					
						
							|  |  |  | 			if (buf)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				char tmp[64]; | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 				sprintf (tmp, "socket error %d", (int)syserr_code); | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 				hcl_copy_bcstr (buf, len, tmp); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return HCL_ESYSERR; | 
					
						
							|  |  |  | 			#else
 | 
					
						
							|  |  |  | 			/* sock_strerror() available in tcpip32.dll only */ | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 			if (buf) hcl_copy_bcstr (buf, len, sock_strerror(syserr_code)); | 
					
						
							|  |  |  | 			return os2sockerr_to_errnum(syserr_code); | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 			#endif
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 		#endif
 | 
					
						
							|  |  |  | 			/* fall thru for other platforms */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		case 1: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		#if defined(_WIN32)
 | 
					
						
							|  |  |  | 			if (buf) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DWORD rc; | 
					
						
							|  |  |  | 				rc = FormatMessageA ( | 
					
						
							|  |  |  | 					FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 					NULL, syserr_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 					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__)
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 			if (buf) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				char tmp[64]; | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 				sprintf (tmp, "system error %d", (int)syserr_code); | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 				hcl_copy_bcstr (buf, len, tmp); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			return os2err_to_errnum(syserr_code); | 
					
						
							|  |  |  | 		#elif defined(macintosh)
 | 
					
						
							|  |  |  | 			/* TODO: convert code to string */ | 
					
						
							|  |  |  | 			if (buf) hcl_copy_bcstr (buf, len, "system error"); | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 			return macerr_to_errnum(syserr_code); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		#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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* --------------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * ASSERTION SUPPORT | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(HCL_BUILD_RELEASE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void _assertfail (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file, hcl_oow_t line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* do nothing */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else /* defined(HCL_BUILD_RELEASE) */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* --------------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * SYSTEM DEPENDENT HEADERS | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | #	include <windows.h>
 | 
					
						
							|  |  |  | #	include <errno.h>
 | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	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)
 | 
					
						
							|  |  |  | #include <libunwind.h>
 | 
					
						
							|  |  |  | static void backtrace_stack_frames (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unw_cursor_t cursor; | 
					
						
							|  |  |  | 	unw_context_t context; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unw_getcontext(&context); | 
					
						
							|  |  |  | 	unw_init_local(&cursor, &context); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_DEBUG, "[BACKTRACE]\n"); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	for (n = 0; unw_step(&cursor) > 0; n++) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		unw_word_t ip, sp, off; | 
					
						
							|  |  |  | 		char symbol[256]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		unw_get_reg (&cursor, UNW_REG_IP, &ip); | 
					
						
							|  |  |  | 		unw_get_reg (&cursor, UNW_REG_SP, &sp); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		if (unw_get_proc_name(&cursor, symbol, HCL_COUNTOF(symbol), &off)) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_copy_bcstr (symbol, HCL_COUNTOF(symbol), "<unknown>"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_DEBUG, | 
					
						
							|  |  |  | 			"#%02d ip=0x%*p sp=0x%*p %hs+0x%zu\n", | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			n, HCL_SIZEOF(void*) * 2, (void*)ip, HCL_SIZEOF(void*) * 2, (void*)sp, symbol, (hcl_oow_t)off); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #elif defined(HAVE_BACKTRACE)
 | 
					
						
							|  |  |  | #include <execinfo.h>
 | 
					
						
							|  |  |  | static void backtrace_stack_frames (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void* btarray[128]; | 
					
						
							|  |  |  | 	hcl_oow_t btsize; | 
					
						
							|  |  |  | 	char** btsyms; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	btsize = backtrace (btarray, HCL_COUNTOF(btarray)); | 
					
						
							|  |  |  | 	btsyms = backtrace_symbols (btarray, btsize); | 
					
						
							|  |  |  | 	if (btsyms) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t i; | 
					
						
							|  |  |  | 		hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_DEBUG, "[BACKTRACE]\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (i = 0; i < btsize; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-02-11 14:14:49 +00:00
										 |  |  | 			hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_DEBUG, "  %hs\n", btsyms[i]); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		free (btsyms); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | static void backtrace_stack_frames (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* do nothing. not supported */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void _assertfail (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file, hcl_oow_t line) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-11 14:14:49 +00:00
										 |  |  | 	hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_FATAL, "ASSERTION FAILURE: %hs at %hs:%zu\n", expr, file, line); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	backtrace_stack_frames (hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	ExitProcess (249); | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 	DosExit (EXIT_PROCESS, 249); | 
					
						
							|  |  |  | #elif defined(__DOS__)
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		union REGS regs; | 
					
						
							|  |  |  | 		regs.h.ah = DOS_EXIT; | 
					
						
							|  |  |  | 		regs.h.al = 249; | 
					
						
							|  |  |  | 		intdos (®s, ®s); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #elif defined(vms) || defined(__vms)
 | 
					
						
							|  |  |  | 	lib$stop (SS$_ABORT); /* use SS$_OPCCUS instead? */ | 
					
						
							|  |  |  | 	/* this won't be reached since lib$stop() terminates the process */ | 
					
						
							|  |  |  | 	sys$exit (SS$_ABORT); /* this condition code can be shown with
 | 
					
						
							|  |  |  | 	                       * 'show symbol $status' from the command-line. */ | 
					
						
							|  |  |  | #elif defined(macintosh)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ExitToShell (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	kill (getpid(), SIGABRT); | 
					
						
							|  |  |  | 	_exit (1); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* defined(HCL_BUILD_RELEASE) */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * HEAP ALLOCATION | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | static int get_huge_page_size (hcl_t* hcl, hcl_oow_t* page_size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	FILE* fp; | 
					
						
							|  |  |  | 	char buf[256]; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	fp = fopen("/proc/meminfo", "r"); | 
					
						
							|  |  |  | 	if (!fp) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (!feof(fp)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (fgets(buf, sizeof(buf) - 1, fp) == NULL) goto oops; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (strncmp(buf, "Hugepagesize: ", 13) == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			unsigned long int tmp; | 
					
						
							|  |  |  | 			tmp = strtoul(&buf[13], NULL, 10); | 
					
						
							|  |  |  | 			if (tmp == HCL_TYPE_MAX(unsigned long int) && errno == ERANGE) goto oops; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			*page_size = tmp * 1024; /* KBytes to Bytes */ | 
					
						
							|  |  |  | 			fclose (fp); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | oops: | 
					
						
							|  |  |  | 	fclose (fp); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void* alloc_heap (hcl_t* hcl, hcl_oow_t* size) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | { | 
					
						
							|  |  |  | #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; | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	hcl_oow_t req_size, align, aligned_size; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	req_size = HCL_SIZEOF(hcl_oow_t) + *size; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	flags = MAP_PRIVATE | MAP_ANONYMOUS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(MAP_UNINITIALIZED)
 | 
					
						
							|  |  |  | 	flags |= MAP_UNINITIALIZED; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	#if defined(MAP_HUGETLB)
 | 
					
						
							|  |  |  | 	if (get_huge_page_size(hcl, &align) <= -1) align = 2 * 1024 * 1024; /* default to 2MB */ | 
					
						
							|  |  |  | 	if (req_size > align / 2) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 		/* if the requested size is large enough, attempt HUGETLB */ | 
					
						
							|  |  |  | 		flags |= MAP_HUGETLB; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		align = sysconf(_SC_PAGESIZE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 	align = sysconf(_SC_PAGESIZE); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	aligned_size = HCL_ALIGN_POW2(req_size, align); | 
					
						
							|  |  |  | 	ptr = (hcl_oow_t*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, flags, -1, 0); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	#if defined(MAP_HUGETLB)
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (ptr == MAP_FAILED && (flags & MAP_HUGETLB)) | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		flags &= ~MAP_HUGETLB; | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 		align = sysconf(_SC_PAGESIZE); | 
					
						
							|  |  |  | 		aligned_size = HCL_ALIGN_POW2(req_size, align); | 
					
						
							|  |  |  | 		ptr = (hcl_oow_t*)mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, flags, -1, 0); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		if (ptr == MAP_FAILED) | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 			return HCL_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (ptr == MAP_FAILED) | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*ptr = aligned_size; | 
					
						
							|  |  |  | 	*size = aligned_size - HCL_SIZEOF(hcl_oow_t); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return (void*)(ptr + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	return HCL_MMGR_ALLOC(hcl->_mmgr, *size); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | #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
 | 
					
						
							| 
									
										
										
										
											2021-03-25 16:53:05 +00:00
										 |  |  | 	HCL_MMGR_FREE(hcl->_mmgr, ptr); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * POSSIBLY MONOTONIC TIME | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 = GET_XTN(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 = GET_XTN(hcl); | 
					
						
							|  |  |  | 	ULONG msec; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	#if (HCL_SIZEOF_UINT64_T > 0)
 | 
					
						
							|  |  |  | 	hcl_uint64_t bigsec, bigmsec; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | /* 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)); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	#else
 | 
					
						
							|  |  |  |     hcl_uint32_t bigsec, bigmsec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &msec, HCL_SIZEOF(msec)); | 
					
						
							|  |  |  | 	bigsec = HCL_MSEC_TO_SEC(msec); | 
					
						
							|  |  |  | 	bigmsec = msec - HCL_SEC_TO_MSEC(bigsec); | 
					
						
							|  |  |  | 	if (msec < xtn->tc_last) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ULONG i; | 
					
						
							|  |  |  | 		hcl_uint32_t inc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		xtn->tc_overflow++; | 
					
						
							|  |  |  | 		inc = HCL_MSEC_TO_SEC(HCL_TYPE_MAX(hcl_uint32_t)); | 
					
						
							|  |  |  | 		for (i = 0; i < xtn->tc_overflow; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ULONG max = HCL_TYPE_MAX(hcl_uint32_t) - bigsec; | 
					
						
							|  |  |  | 			if (max > inc) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				bigsec = HCL_TYPE_MAX(hcl_uint32_t); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			bigsec += inc; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	HCL_INIT_NTIME (now, bigsec, HCL_MSEC_TO_NSEC(bigmsec)); | 
					
						
							|  |  |  |     #endif
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -----------------------------------------------------------------
 | 
					
						
							|  |  |  |  * IO MULTIPLEXING | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int _add_poll_fd (hcl_t* hcl, int fd, int event_mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	struct pollfd ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, xtn->ep >= 0); | 
					
						
							|  |  |  | 	ev.fd = fd; | 
					
						
							|  |  |  | 	ev.events = event_mask; | 
					
						
							|  |  |  | 	ev.revents = 0; | 
					
						
							|  |  |  | 	if (write(xtn->ep, &ev, HCL_SIZEOF(ev)) != HCL_SIZEOF(ev)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot add file descriptor %d to devpoll - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	struct kevent ev; | 
					
						
							|  |  |  | 	hcl_oow_t rindex, roffset; | 
					
						
							|  |  |  | 	hcl_oow_t rv = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rindex = (hcl_oow_t)fd / (HCL_BITSOF(hcl_oow_t) >> 1); | 
					
						
							|  |  |  | 	roffset = ((hcl_oow_t)fd << 1) % HCL_BITSOF(hcl_oow_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rindex >= xtn->ev.reg.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_oow_t* tmp; | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HCL_STATIC_ASSERT (HCL_SIZEOF(*tmp) == HCL_SIZEOF(*xtn->ev.reg.ptr)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newcapa = rindex + 1; | 
					
						
							|  |  |  | 		newcapa = HCL_ALIGN_POW2(newcapa, 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp = (hcl_oow_t*)hcl_reallocmem(hcl, xtn->ev.reg.ptr, newcapa * HCL_SIZEOF(*tmp)); | 
					
						
							|  |  |  | 		if (!tmp) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			const hcl_ooch_t* oldmsg = hcl_backuperrmsg(hcl); | 
					
						
							|  |  |  | 			hcl_seterrbfmt (hcl, HCL_ESYSERR, "unable to add file descriptor %d to kqueue - %js", fd, oldmsg); | 
					
						
							|  |  |  | 			HCL_DEBUG1 (hcl, "%js", hcl_geterrmsg(hcl)); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HCL_MEMSET (&tmp[xtn->ev.reg.capa], 0, newcapa - xtn->ev.reg.capa); | 
					
						
							|  |  |  | 		xtn->ev.reg.ptr = tmp; | 
					
						
							|  |  |  | 		xtn->ev.reg.capa = newcapa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (event_mask & XPOLLIN) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/*EV_SET (&ev, fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);*/ | 
					
						
							|  |  |  | 		HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 		ev.ident = fd; | 
					
						
							|  |  |  | 		ev.flags = EV_ADD; | 
					
						
							|  |  |  | 	#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 		ev.flags |= EV_CLEAR; /* EV_CLEAR for edge trigger? */ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		ev.filter = EVFILT_READ; | 
					
						
							|  |  |  | 		if (kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL) == -1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 			HCL_DEBUG2 (hcl, "Cannot add file descriptor %d to kqueue for read - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		rv |= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (event_mask & XPOLLOUT) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/*EV_SET (&ev, fd, EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);*/ | 
					
						
							|  |  |  | 		HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 		ev.ident = fd; | 
					
						
							|  |  |  | 		ev.flags = EV_ADD; | 
					
						
							|  |  |  | 	#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 		ev.flags |= EV_CLEAR; /* EV_CLEAR for edge trigger? */ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		ev.filter = EVFILT_WRITE; | 
					
						
							|  |  |  | 		if (kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL) == -1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 			HCL_DEBUG2 (hcl, "Cannot add file descriptor %d to kqueue for write - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (event_mask & XPOLLIN) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 				ev.ident = fd; | 
					
						
							|  |  |  | 				ev.flags = EV_DELETE; | 
					
						
							|  |  |  | 				ev.filter = EVFILT_READ; | 
					
						
							|  |  |  | 				kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		rv |= 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_SETBITS (hcl_oow_t, xtn->ev.reg.ptr[rindex], roffset, 2, rv); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	struct epoll_event ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, xtn->ep >= 0); | 
					
						
							|  |  |  | 	HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 	ev.events = event_mask; | 
					
						
							|  |  |  | 	#if defined(USE_THREAD) && defined(EPOLLET)
 | 
					
						
							|  |  |  | 	/* epoll_wait may return again if the worker thread consumes events.
 | 
					
						
							|  |  |  | 	 * switch to level-trigger. */ | 
					
						
							|  |  |  | 	/* TODO: verify if EPOLLLET is desired */ | 
					
						
							|  |  |  | 	ev.events |= EPOLLET/*  | EPOLLRDHUP | EPOLLHUP */; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	/*ev.data.ptr = (void*)event_data;*/ | 
					
						
							|  |  |  | 	ev.data.fd = fd; | 
					
						
							|  |  |  | 	if (epoll_ctl(xtn->ep, EPOLL_CTL_ADD, fd, &ev) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot add file descriptor %d to epoll - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MUTEX_LOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 	if (xtn->ev.reg.len >= xtn->ev.reg.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		struct pollfd* tmp, * tmp2; | 
					
						
							|  |  |  | 		hcl_oow_t newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newcapa = HCL_ALIGN_POW2 (xtn->ev.reg.len + 1, 256); | 
					
						
							|  |  |  | 		tmp = (struct pollfd*)hcl_reallocmem(hcl, xtn->ev.reg.ptr, newcapa * HCL_SIZEOF(*tmp)); | 
					
						
							|  |  |  | 		tmp2 = (struct pollfd*)hcl_reallocmem(hcl, xtn->ev.buf, newcapa * HCL_SIZEOF(*tmp2)); | 
					
						
							|  |  |  | 		if (!tmp || !tmp2) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_DEBUG2 (hcl, "Cannot add file descriptor %d to poll - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 			MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 			if (tmp) hcl_freemem (hcl, tmp); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		xtn->ev.reg.ptr = tmp; | 
					
						
							|  |  |  | 		xtn->ev.reg.capa = newcapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		xtn->ev.buf = tmp2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn->ev.reg.ptr[xtn->ev.reg.len].fd = fd; | 
					
						
							|  |  |  | 	xtn->ev.reg.ptr[xtn->ev.reg.len].events = event_mask; | 
					
						
							|  |  |  | 	xtn->ev.reg.ptr[xtn->ev.reg.len].revents = 0; | 
					
						
							|  |  |  | 	xtn->ev.reg.len++; | 
					
						
							|  |  |  | 	MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MUTEX_LOCK (&xtn->ev.reg.smtx); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (event_mask & XPOLLIN) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		FD_SET (fd, &xtn->ev.reg.rfds); | 
					
						
							|  |  |  | 		if (fd > xtn->ev.reg.maxfd) xtn->ev.reg.maxfd = fd; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (event_mask & XPOLLOUT) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		FD_SET (fd, &xtn->ev.reg.wfds); | 
					
						
							|  |  |  | 		if (fd > xtn->ev.reg.maxfd) xtn->ev.reg.maxfd = fd; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	MUTEX_UNLOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_DEBUG1 (hcl, "Cannot add file descriptor %d to poll - not implemented\n", fd); | 
					
						
							|  |  |  | 	hcl_seterrnum (hcl, HCL_ENOIMPL); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int _del_poll_fd (hcl_t* hcl, int fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	struct pollfd ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, xtn->ep >= 0); | 
					
						
							|  |  |  | 	ev.fd = fd; | 
					
						
							|  |  |  | 	ev.events = POLLREMOVE; | 
					
						
							|  |  |  | 	ev.revents = 0; | 
					
						
							|  |  |  | 	if (write(xtn->ep, &ev, HCL_SIZEOF(ev)) != HCL_SIZEOF(ev)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot remove file descriptor %d from devpoll - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	hcl_oow_t rindex, roffset; | 
					
						
							|  |  |  | 	int rv; | 
					
						
							|  |  |  | 	struct kevent ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rindex = (hcl_oow_t)fd / (HCL_BITSOF(hcl_oow_t) >> 1); | 
					
						
							|  |  |  | 	roffset = ((hcl_oow_t)fd << 1) % HCL_BITSOF(hcl_oow_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rindex >= xtn->ev.reg.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, HCL_EINVAL, "unknown file descriptor %d", fd); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot remove file descriptor %d from kqueue - %js\n", fd, hcl_geterrmsg(hcl)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rv = HCL_GETBITS (hcl_oow_t, xtn->ev.reg.ptr[rindex], roffset, 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rv & 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/*EV_SET (&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);*/ | 
					
						
							|  |  |  | 		HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 		ev.ident = fd; | 
					
						
							|  |  |  | 		ev.flags = EV_DELETE; | 
					
						
							|  |  |  | 		ev.filter = EVFILT_READ; | 
					
						
							|  |  |  | 		kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL); | 
					
						
							|  |  |  | 		/* no error check for now */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rv & 2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/*EV_SET (&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);*/ | 
					
						
							|  |  |  | 		HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 		ev.ident = fd; | 
					
						
							|  |  |  | 		ev.flags = EV_DELETE; | 
					
						
							|  |  |  | 		ev.filter = EVFILT_WRITE; | 
					
						
							|  |  |  | 		kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL); | 
					
						
							|  |  |  | 		/* no error check for now */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_SETBITS (hcl_oow_t, xtn->ev.reg.ptr[rindex], roffset, 2, 0); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	struct epoll_event ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, xtn->ep >= 0); | 
					
						
							|  |  |  | 	HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 	if (epoll_ctl(xtn->ep, EPOLL_CTL_DEL, fd, &ev) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot remove file descriptor %d from epoll - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	hcl_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: performance boost. no linear search */ | 
					
						
							|  |  |  | 	MUTEX_LOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 	for (i = 0; i < xtn->ev.reg.len; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (xtn->ev.reg.ptr[i].fd == fd) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			xtn->ev.reg.len--; | 
					
						
							|  |  |  | 			HCL_MEMMOVE (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i) * HCL_SIZEOF(*xtn->ev.reg.ptr)); | 
					
						
							|  |  |  | 			MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_DEBUG1 (hcl, "Cannot remove file descriptor %d from poll - not found\n", fd); | 
					
						
							|  |  |  | 	hcl_seterrnum (hcl, HCL_ENOENT); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MUTEX_LOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 	FD_CLR (fd, &xtn->ev.reg.rfds); | 
					
						
							|  |  |  | 	FD_CLR (fd, &xtn->ev.reg.wfds); | 
					
						
							|  |  |  | 	if (fd >= xtn->ev.reg.maxfd) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		/* TODO: any way to make this search faster or to do without the search like this */ | 
					
						
							|  |  |  | 		for (i = fd - 1; i >= 0; i--) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (FD_ISSET(i, &xtn->ev.reg.rfds) || FD_ISSET(i, &xtn->ev.reg.wfds)) break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		xtn->ev.reg.maxfd = i; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	MUTEX_UNLOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_DEBUG1 (hcl, "Cannot remove file descriptor %d from poll - not implemented\n", fd); | 
					
						
							|  |  |  | 	hcl_seterrnum (hcl, HCL_ENOIMPL); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int _mod_poll_fd (hcl_t* hcl, int fd, int event_mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (_del_poll_fd (hcl, fd) <= -1) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (_add_poll_fd (hcl, fd, event_mask) <= -1) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/* TODO: any good way to rollback successful deletion? */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	hcl_oow_t rindex, roffset; | 
					
						
							|  |  |  | 	int rv, newrv = 0; | 
					
						
							|  |  |  | 	struct kevent ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rindex = (hcl_oow_t)fd / (HCL_BITSOF(hcl_oow_t) >> 1); | 
					
						
							|  |  |  | 	roffset = ((hcl_oow_t)fd << 1) % HCL_BITSOF(hcl_oow_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rindex >= xtn->ev.reg.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, HCL_EINVAL, "unknown file descriptor %d", fd); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot modify file descriptor %d in kqueue - %js\n", fd, hcl_geterrmsg(hcl)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rv = HCL_GETBITS(hcl_oow_t, xtn->ev.reg.ptr[rindex], roffset, 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rv & 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!(event_mask & XPOLLIN)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 			ev.ident = fd; | 
					
						
							|  |  |  | 			ev.flags = EV_DELETE; | 
					
						
							|  |  |  | 			ev.filter = EVFILT_READ; | 
					
						
							|  |  |  | 			if (kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL) == -1) goto kqueue_syserr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			newrv &= ~1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (event_mask & XPOLLIN) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 			ev.ident = fd; | 
					
						
							|  |  |  | 			ev.flags = EV_ADD; | 
					
						
							|  |  |  | 		#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 			ev.flags |= EV_CLEAR; /* EV_CLEAR for edge trigger? */ | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 			ev.filter = EVFILT_READ; | 
					
						
							|  |  |  | 			if (kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL) == -1) goto kqueue_syserr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			newrv |= 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (rv & 2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!(event_mask & XPOLLOUT)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 			ev.ident = fd; | 
					
						
							|  |  |  | 			ev.flags = EV_DELETE; | 
					
						
							|  |  |  | 			ev.filter = EVFILT_WRITE; | 
					
						
							|  |  |  | 			/* there is no operation rollback for the (rv & 1) case.
 | 
					
						
							|  |  |  | 			 * the rollback action may fail again even if i try it */ | 
					
						
							|  |  |  | 			if (kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL) == -1) goto kqueue_syserr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			newrv &= ~2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (event_mask & XPOLLOUT) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 			ev.ident = fd; | 
					
						
							|  |  |  | 			ev.flags = EV_ADD; | 
					
						
							|  |  |  | 		#if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 			ev.flags |= EV_CLEAR; /* EV_CLEAR for edge trigger? */ | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 			ev.filter = EVFILT_WRITE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* there is no operation rollback for the (rv & 1) case.
 | 
					
						
							|  |  |  | 			 * the rollback action may fail again even if i try it */ | 
					
						
							|  |  |  | 			if (kevent(xtn->ep, &ev, 1, HCL_NULL, 0, HCL_NULL) == -1) goto kqueue_syserr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			newrv |= 2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_SETBITS (hcl_oow_t, xtn->ev.reg.ptr[rindex], roffset, 2, newrv); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | kqueue_syserr: | 
					
						
							|  |  |  | 	hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 	HCL_DEBUG2 (hcl, "Cannot modify file descriptor %d in kqueue - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	struct epoll_event ev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, xtn->ep >= 0); | 
					
						
							|  |  |  | 	HCL_MEMSET (&ev, 0, HCL_SIZEOF(ev)); | 
					
						
							|  |  |  | 	ev.events = event_mask; | 
					
						
							|  |  |  | 	#if defined(USE_THREAD) && defined(EPOLLET)
 | 
					
						
							|  |  |  | 	/* epoll_wait may return again if the worker thread consumes events.
 | 
					
						
							|  |  |  | 	 * switch to level-trigger. */ | 
					
						
							|  |  |  | 	/* TODO: verify if EPOLLLET is desired */ | 
					
						
							|  |  |  | 	ev.events |= EPOLLET; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	ev.data.fd = fd; | 
					
						
							|  |  |  | 	if (epoll_ctl(xtn->ep, EPOLL_CTL_MOD, fd, &ev) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot modify file descriptor %d in epoll - %hs\n", fd, strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	hcl_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MUTEX_LOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 	for (i = 0; i < xtn->ev.reg.len; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (xtn->ev.reg.ptr[i].fd == fd) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_MEMMOVE (&xtn->ev.reg.ptr[i], &xtn->ev.reg.ptr[i+1], (xtn->ev.reg.len - i - 1) * HCL_SIZEOF(*xtn->ev.reg.ptr)); | 
					
						
							|  |  |  | 			xtn->ev.reg.ptr[i].fd = fd; | 
					
						
							|  |  |  | 			xtn->ev.reg.ptr[i].events = event_mask; | 
					
						
							|  |  |  | 			xtn->ev.reg.ptr[i].revents = 0; | 
					
						
							|  |  |  | 			MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_DEBUG1 (hcl, "Cannot modify file descriptor %d in poll - not found\n", fd); | 
					
						
							|  |  |  | 	hcl_seterrnum (hcl, HCL_ENOENT); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MUTEX_LOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, fd <= xtn->ev.reg.maxfd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (event_mask & XPOLLIN) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		FD_SET (fd, &xtn->ev.reg.rfds); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		FD_CLR (fd, &xtn->ev.reg.rfds); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (event_mask & XPOLLOUT) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		FD_SET (fd, &xtn->ev.reg.wfds); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		FD_CLR (fd, &xtn->ev.reg.wfds); | 
					
						
							|  |  |  | 	MUTEX_UNLOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	HCL_DEBUG1 (hcl, "Cannot modify file descriptor %d in poll - not implemented\n", fd); | 
					
						
							|  |  |  | 	hcl_seterrnum (hcl, HCL_ENOIMPL); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vm_muxadd (hcl_t* hcl, hcl_ooi_t io_handle, hcl_ooi_t mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int event_mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	event_mask = 0; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (mask & HCL_SEMAPHORE_IO_MASK_INPUT) event_mask |= XPOLLIN; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	if (mask & HCL_SEMAPHORE_IO_MASK_OUTPUT) event_mask |= XPOLLOUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (event_mask == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, io_handle); | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, HCL_EINVAL, "invalid semaphore mask %zd on handle %zd", mask, io_handle); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _add_poll_fd(hcl, io_handle, event_mask); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vm_muxmod (hcl_t* hcl, hcl_ooi_t io_handle, hcl_ooi_t mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int event_mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	event_mask = 0; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (mask & HCL_SEMAPHORE_IO_MASK_INPUT) event_mask |= XPOLLIN; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	if (mask & HCL_SEMAPHORE_IO_MASK_OUTPUT) event_mask |= XPOLLOUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (event_mask == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "<vm_muxadd> Invalid semaphore mask %zd on handle %zd\n", mask, io_handle); | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, HCL_EINVAL, "invalid semaphore mask %zd on handle %zd", mask, io_handle); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _mod_poll_fd(hcl, io_handle, event_mask); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vm_muxdel (hcl_t* hcl, hcl_ooi_t io_handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return _del_poll_fd(hcl, io_handle); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(USE_THREAD)
 | 
					
						
							|  |  |  | static void* iothr_main (void* arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_t* hcl = (hcl_t*)arg; | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*while (!hcl->abort_req)*/ | 
					
						
							|  |  |  | 	while (!xtn->iothr.abort) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (xtn->ev.len <= 0) /* TODO: no mutex needed for this check? */ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			int n; | 
					
						
							|  |  |  | 		#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 			struct dvpoll dvp; | 
					
						
							|  |  |  | 		#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 			struct timespec ts; | 
					
						
							|  |  |  | 		#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 			hcl_oow_t nfds; | 
					
						
							|  |  |  | 		#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 			struct timeval tv; | 
					
						
							|  |  |  | 			fd_set rfds; | 
					
						
							|  |  |  | 			fd_set wfds; | 
					
						
							|  |  |  | 			int maxfd; | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		poll_for_event: | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 			dvp.dp_timeout = 10000; /* milliseconds */ | 
					
						
							|  |  |  | 			dvp.dp_fds = xtn->ev.buf; | 
					
						
							|  |  |  | 			dvp.dp_nfds = HCL_COUNTOF(xtn->ev.buf); | 
					
						
							|  |  |  | 			n = ioctl (xtn->ep, DP_POLL, &dvp); | 
					
						
							|  |  |  | 		#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 			ts.tv_sec = 10; | 
					
						
							|  |  |  | 			ts.tv_nsec = 0; | 
					
						
							|  |  |  | 			n = kevent(xtn->ep, HCL_NULL, 0, xtn->ev.buf, HCL_COUNTOF(xtn->ev.buf), &ts); | 
					
						
							|  |  |  | 			/* n == 0: timeout
 | 
					
						
							|  |  |  | 			 * n == -1: error */ | 
					
						
							|  |  |  | 		#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 			n = epoll_wait(xtn->ep, xtn->ev.buf, HCL_COUNTOF(xtn->ev.buf), 10000); /* TODO: make this timeout value in the io thread */ | 
					
						
							|  |  |  | 		#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 			MUTEX_LOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 			HCL_MEMCPY (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * HCL_SIZEOF(*xtn->ev.buf)); | 
					
						
							|  |  |  | 			nfds = xtn->ev.reg.len; | 
					
						
							|  |  |  | 			MUTEX_UNLOCK (&xtn->ev.reg.pmtx); | 
					
						
							|  |  |  | 			n = poll(xtn->ev.buf, nfds, 10000); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			if (n > 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				/* compact the return buffer as poll() doesn't */ | 
					
						
							|  |  |  | 				hcl_oow_t i, j; | 
					
						
							|  |  |  | 				for (i = 0, j = 0; i < nfds && j < n; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if (xtn->ev.buf[i].revents) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						if (j != i) xtn->ev.buf[j] = xtn->ev.buf[i]; | 
					
						
							|  |  |  | 						j++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				n = j; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 			tv.tv_sec = 10; | 
					
						
							|  |  |  | 			tv.tv_usec = 0; | 
					
						
							|  |  |  | 			MUTEX_LOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 			maxfd = xtn->ev.reg.maxfd; | 
					
						
							|  |  |  | 			HCL_MEMCPY (&rfds, &xtn->ev.reg.rfds, HCL_SIZEOF(rfds)); | 
					
						
							|  |  |  | 			HCL_MEMCPY (&wfds, &xtn->ev.reg.wfds, HCL_SIZEOF(wfds)); | 
					
						
							|  |  |  | 			MUTEX_UNLOCK (&xtn->ev.reg.smtx); | 
					
						
							|  |  |  | 			n = select (maxfd + 1, &rfds, &wfds, HCL_NULL, &tv); | 
					
						
							|  |  |  | 			if (n > 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int fd, count = 0; | 
					
						
							|  |  |  | 				for (fd = 0;  fd <= maxfd; fd++) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					int events = 0; | 
					
						
							|  |  |  | 					if (FD_ISSET(fd, &rfds)) events |= XPOLLIN; | 
					
						
							|  |  |  | 					if (FD_ISSET(fd, &wfds)) events |= XPOLLOUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (events) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						HCL_ASSERT (hcl, count < HCL_COUNTOF(xtn->ev.buf)); | 
					
						
							|  |  |  | 						xtn->ev.buf[count].fd = fd; | 
					
						
							|  |  |  | 						xtn->ev.buf[count].events = events; | 
					
						
							|  |  |  | 						count++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				n = count; | 
					
						
							|  |  |  | 				HCL_ASSERT (hcl, n > 0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			pthread_mutex_lock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 			if (n <= -1) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* TODO: don't use HCL_DEBUG2. it's not thread safe... */ | 
					
						
							|  |  |  | 				/* the following call has a race-condition issue when called in this separate thread */ | 
					
						
							|  |  |  | 				/*HCL_DEBUG2 (hcl, "Warning: multiplexer wait failure - %d, %hs\n", errno, strerror(errno));*/ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else if (n > 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				xtn->ev.len = n; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			pthread_cond_signal (&xtn->ev.cnd2); | 
					
						
							|  |  |  | 			pthread_mutex_unlock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* the event buffer has not been emptied yet */ | 
					
						
							|  |  |  | 			struct timespec ts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			pthread_mutex_lock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 			if (xtn->ev.len <= 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* it got emptied between the if check and pthread_mutex_lock() above */ | 
					
						
							|  |  |  | 				pthread_mutex_unlock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 				goto poll_for_event; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
 | 
					
						
							|  |  |  | 			clock_gettime (CLOCK_REALTIME, &ts); | 
					
						
							|  |  |  | 		#else
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				struct timeval tv; | 
					
						
							|  |  |  | 				gettimeofday (&tv, HCL_NULL); | 
					
						
							|  |  |  | 				ts.tv_sec = tv.tv_sec; | 
					
						
							|  |  |  | 				ts.tv_nsec = HCL_USEC_TO_NSEC(tv.tv_usec); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 			ts.tv_sec += 10; | 
					
						
							|  |  |  | 			pthread_cond_timedwait (&xtn->ev.cnd, &xtn->ev.mtx, &ts); | 
					
						
							|  |  |  | 			pthread_mutex_unlock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*sched_yield ();*/ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return HCL_NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void vm_muxwait (hcl_t* hcl, const hcl_ntime_t* dur, hcl_vmprim_muxwait_cb_t muxwcb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* create a thread if mux wait is started at least once. */ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (!xtn->iothr.up) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		xtn->iothr.up = 1; | 
					
						
							|  |  |  | 		if (pthread_create(&xtn->iothr.thr, HCL_NULL, iothr_main, hcl) != 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HCL_LOG2 (hcl, HCL_LOG_WARN, "Warning: pthread_create failure - %d, %hs\n", errno, strerror(errno)); | 
					
						
							|  |  |  | 			xtn->iothr.up = 0; | 
					
						
							|  |  |  | /* TODO: switch to the non-threaded mode? */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (xtn->iothr.abort) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (xtn->ev.len <= 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		struct timespec ts; | 
					
						
							|  |  |  | 		hcl_ntime_t ns; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!dur) return; /* immediate check is requested. and there is no event */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
 | 
					
						
							|  |  |  | 		clock_gettime (CLOCK_REALTIME, &ts); | 
					
						
							|  |  |  | 		ns.sec = ts.tv_sec; | 
					
						
							|  |  |  | 		ns.nsec = ts.tv_nsec; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			struct timeval tv; | 
					
						
							|  |  |  | 			gettimeofday (&tv, HCL_NULL); | 
					
						
							|  |  |  | 			ns.sec = tv.tv_sec; | 
					
						
							|  |  |  | 			ns.nsec = HCL_USEC_TO_NSEC(tv.tv_usec); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 		HCL_ADD_NTIME (&ns, &ns, dur); | 
					
						
							|  |  |  | 		ts.tv_sec = ns.sec; | 
					
						
							|  |  |  | 		ts.tv_nsec = ns.nsec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pthread_mutex_lock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 		if (xtn->ev.len <= 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* the event buffer is still empty */ | 
					
						
							|  |  |  | 			pthread_cond_timedwait (&xtn->ev.cnd2, &xtn->ev.mtx, &ts); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pthread_mutex_unlock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = xtn->ev.len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (n > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		do | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			--n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 			if (xtn->ev.buf[n].fd == xtn->iothr.p[0]) | 
					
						
							|  |  |  | 		#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 			if (xtn->ev.buf[n].ident == xtn->iothr.p[0]) | 
					
						
							|  |  |  | 		#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 			/*if (xtn->ev.buf[n].data.ptr == (void*)HCL_TYPE_MAX(hcl_oow_t))*/ | 
					
						
							|  |  |  | 			if (xtn->ev.buf[n].data.fd == xtn->iothr.p[0]) | 
					
						
							|  |  |  | 		#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 			if (xtn->ev.buf[n].fd == xtn->iothr.p[0]) | 
					
						
							|  |  |  | 		#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 			if (xtn->ev.buf[n].fd == xtn->iothr.p[0]) | 
					
						
							|  |  |  | 		#else
 | 
					
						
							|  |  |  | 		#	error UNSUPPORTED
 | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl_uint8_t u8; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 				while (read(xtn->iothr.p[0], &u8, HCL_SIZEOF(u8)) > 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					/* consume as much as possible */; | 
					
						
							|  |  |  | 					if (u8 == 'Q') xtn->iothr.abort = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else if (muxwcb) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int revents; | 
					
						
							|  |  |  | 				hcl_ooi_t mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 				revents = xtn->ev.buf[n].revents; | 
					
						
							|  |  |  | 			#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 				if (xtn->ev.buf[n].filter == EVFILT_READ) mask = HCL_SEMAPHORE_IO_MASK_INPUT; | 
					
						
							|  |  |  | 				else if (xtn->ev.buf[n].filter == EVFILT_WRITE) mask = HCL_SEMAPHORE_IO_MASK_OUTPUT; | 
					
						
							|  |  |  | 				else mask = 0; | 
					
						
							|  |  |  | 				goto call_muxwcb_kqueue; | 
					
						
							|  |  |  | 			#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 				revents = xtn->ev.buf[n].events; | 
					
						
							|  |  |  | 			#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 				revents = xtn->ev.buf[n].revents; | 
					
						
							|  |  |  | 			#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 				revents = xtn->ev.buf[n].events; | 
					
						
							|  |  |  | 			#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				mask = 0; | 
					
						
							|  |  |  | 				if (revents & XPOLLIN) mask |= HCL_SEMAPHORE_IO_MASK_INPUT; | 
					
						
							|  |  |  | 				if (revents & XPOLLOUT) mask |= HCL_SEMAPHORE_IO_MASK_OUTPUT; | 
					
						
							|  |  |  | 				if (revents & XPOLLERR) mask |= HCL_SEMAPHORE_IO_MASK_ERROR; | 
					
						
							|  |  |  | 				if (revents & XPOLLHUP) mask |= HCL_SEMAPHORE_IO_MASK_HANGUP; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 				muxwcb (hcl, xtn->ev.buf[n].fd, mask); | 
					
						
							|  |  |  | 			#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 			call_muxwcb_kqueue: | 
					
						
							|  |  |  | 				muxwcb (hcl, xtn->ev.buf[n].ident, mask); | 
					
						
							|  |  |  | 			#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 				muxwcb (hcl, xtn->ev.buf[n].data.fd, mask); | 
					
						
							|  |  |  | 			#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 				muxwcb (hcl, xtn->ev.buf[n].fd, mask); | 
					
						
							|  |  |  | 			#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 				muxwcb (hcl, xtn->ev.buf[n].fd, mask); | 
					
						
							|  |  |  | 			#else
 | 
					
						
							|  |  |  | 			#	error UNSUPPORTED
 | 
					
						
							|  |  |  | 			#endif
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		while (n > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pthread_mutex_lock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 		xtn->ev.len = 0; | 
					
						
							|  |  |  | 		pthread_cond_signal (&xtn->ev.cnd); | 
					
						
							|  |  |  | 		pthread_mutex_unlock (&xtn->ev.mtx); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else /* USE_THREAD */
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 	int tmout; | 
					
						
							|  |  |  | 	struct dvpoll dvp; | 
					
						
							|  |  |  | 	#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	struct timespec ts; | 
					
						
							|  |  |  | 	#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	int tmout; | 
					
						
							|  |  |  | 	#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 	int tmout; | 
					
						
							|  |  |  | 	#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 	struct timeval tv; | 
					
						
							|  |  |  | 	fd_set rfds, wfds; | 
					
						
							|  |  |  | 	int maxfd; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 	tmout = dur? HCL_SECNSEC_TO_MSEC(dur->sec, dur->nsec): 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dvp.dp_timeout = tmout; /* milliseconds */ | 
					
						
							|  |  |  | 	dvp.dp_fds = xtn->ev.buf; | 
					
						
							|  |  |  | 	dvp.dp_nfds = HCL_COUNTOF(xtn->ev.buf); | 
					
						
							|  |  |  | 	n = ioctl(xtn->ep, DP_POLL, &dvp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#elif defined(USE_KQUEUE)
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	if (dur) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ts.tv_sec = dur->sec; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		ts.tv_nsec = dur->nsec; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ts.tv_sec = 0; | 
					
						
							|  |  |  | 		ts.tv_nsec = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n = kevent(xtn->ep, HCL_NULL, 0, xtn->ev.buf, HCL_COUNTOF(xtn->ev.buf), &ts); | 
					
						
							|  |  |  | 	/* n == 0: timeout
 | 
					
						
							|  |  |  | 	 * n == -1: error */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	tmout = dur? HCL_SECNSEC_TO_MSEC(dur->sec, dur->nsec): 0; | 
					
						
							|  |  |  | 	n = epoll_wait(xtn->ep, xtn->ev.buf, HCL_COUNTOF(xtn->ev.buf), tmout); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 	tmout = dur? HCL_SECNSEC_TO_MSEC(dur->sec, dur->nsec): 0; | 
					
						
							|  |  |  | 	HCL_MEMCPY (xtn->ev.buf, xtn->ev.reg.ptr, xtn->ev.reg.len * HCL_SIZEOF(*xtn->ev.buf)); | 
					
						
							|  |  |  | 	n = poll(xtn->ev.buf, xtn->ev.reg.len, tmout); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (n > 0) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/* compact the return buffer as poll() doesn't */ | 
					
						
							|  |  |  | 		hcl_oow_t i, j; | 
					
						
							|  |  |  | 		for (i = 0, j = 0; i < xtn->ev.reg.len && j < n; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (xtn->ev.buf[i].revents) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (j != i) xtn->ev.buf[j] = xtn->ev.buf[i]; | 
					
						
							|  |  |  | 				j++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		n = j; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 	if (dur) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		tv.tv_sec = dur->sec; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		tv.tv_usec = HCL_NSEC_TO_USEC(dur->nsec); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		tv.tv_sec = 0; | 
					
						
							|  |  |  | 		tv.tv_usec = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	maxfd = xtn->ev.reg.maxfd; | 
					
						
							|  |  |  | 	HCL_MEMCPY (&rfds, &xtn->ev.reg.rfds, HCL_SIZEOF(rfds)); | 
					
						
							|  |  |  | 	HCL_MEMCPY (&wfds, &xtn->ev.reg.wfds, HCL_SIZEOF(wfds)); | 
					
						
							|  |  |  | 	n = select(maxfd + 1, &rfds, &wfds, HCL_NULL, &tv); | 
					
						
							|  |  |  | 	if (n > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int fd, count = 0; | 
					
						
							|  |  |  | 		for (fd = 0; fd <= maxfd; fd++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			int events = 0; | 
					
						
							|  |  |  | 			if (FD_ISSET(fd, &rfds)) events |= XPOLLIN; | 
					
						
							|  |  |  | 			if (FD_ISSET(fd, &wfds)) events |= XPOLLOUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (events) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				HCL_ASSERT (hcl, count < HCL_COUNTOF(xtn->ev.buf)); | 
					
						
							|  |  |  | 				xtn->ev.buf[count].fd = fd; | 
					
						
							|  |  |  | 				xtn->ev.buf[count].events = events; | 
					
						
							|  |  |  | 				count++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		n = count; | 
					
						
							|  |  |  | 		HCL_ASSERT (hcl, n > 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (n <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 	#if defined(__OS2__)
 | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 2, sock_errno()); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Warning: multiplexer wait failure - %d, %js\n", sock_errno(), hcl_geterrmsg(hcl)); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							| 
									
										
										
										
											2021-02-11 14:14:49 +00:00
										 |  |  | 		HCL_DEBUG2 (hcl, "Warning: multiplexer wait failure - %d, %js\n", errno, hcl_geterrmsg(hcl)); | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		xtn->ev.len = n; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the muxwcb must be valid all the time in a non-threaded mode */ | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, muxwcb != HCL_NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (n > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int revents; | 
					
						
							|  |  |  | 		hcl_ooi_t mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		--n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 		revents = xtn->ev.buf[n].revents; | 
					
						
							|  |  |  | 	#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 		if (xtn->ev.buf[n].filter == EVFILT_READ) mask = HCL_SEMAPHORE_IO_MASK_INPUT; | 
					
						
							|  |  |  | 		else if (xtn->ev.buf[n].filter == EVFILT_WRITE) mask = HCL_SEMAPHORE_IO_MASK_OUTPUT; | 
					
						
							|  |  |  | 		else mask = 0; | 
					
						
							|  |  |  | 		goto call_muxwcb_kqueue; | 
					
						
							|  |  |  | 	#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 		revents = xtn->ev.buf[n].events; | 
					
						
							|  |  |  | 	#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 		revents = xtn->ev.buf[n].revents; | 
					
						
							|  |  |  | 	#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 		revents = xtn->ev.buf[n].events; | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 		revents = 0; /* TODO: fake. unsupported but to compile on such an unsupported system.*/ | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mask = 0; | 
					
						
							|  |  |  | 		if (revents & XPOLLIN) mask |= HCL_SEMAPHORE_IO_MASK_INPUT; | 
					
						
							|  |  |  | 		if (revents & XPOLLOUT) mask |= HCL_SEMAPHORE_IO_MASK_OUTPUT; | 
					
						
							|  |  |  | 		if (revents & XPOLLERR) mask |= HCL_SEMAPHORE_IO_MASK_ERROR; | 
					
						
							|  |  |  | 		if (revents & XPOLLHUP) mask |= HCL_SEMAPHORE_IO_MASK_HANGUP; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 		muxwcb (hcl, xtn->ev.buf[n].fd, mask); | 
					
						
							|  |  |  | 	#elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	call_muxwcb_kqueue: | 
					
						
							|  |  |  | 		muxwcb (hcl, xtn->ev.buf[n].ident, mask); | 
					
						
							|  |  |  | 	#elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 		muxwcb (hcl, xtn->ev.buf[n].data.fd, mask); | 
					
						
							|  |  |  | 	#elif defined(USE_POLL)
 | 
					
						
							|  |  |  | 		muxwcb (hcl, xtn->ev.buf[n].fd, mask); | 
					
						
							|  |  |  | 	#elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 		muxwcb (hcl, xtn->ev.buf[n].fd, mask); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn->ev.len = 0; | 
					
						
							|  |  |  | #endif  /* USE_THREAD */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * SLEEPING | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | #if defined(__DOS__)
 | 
					
						
							|  |  |  | #	if defined(_INTELC32_)
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	void _halt_cpu (void); | 
					
						
							|  |  |  | #	elif defined(__WATCOMC__)
 | 
					
						
							|  |  |  | 	void _halt_cpu (void); | 
					
						
							|  |  |  | #	pragma aux _halt_cpu = "hlt"
 | 
					
						
							|  |  |  | #	endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vm_sleep (hcl_t* hcl, const hcl_ntime_t* dur) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	if (xtn->waitable_timer) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		LARGE_INTEGER li; | 
					
						
							|  |  |  | 		li.QuadPart = -(HCL_SECNSEC_TO_NSEC(dur->sec, dur->nsec) / 100); /* in 100 nanoseconds */ | 
					
						
							|  |  |  | 		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__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	/* TODO: in gui mode, this is not a desirable method???
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	 *       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 */ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	while (c > clock()) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		_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
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * SHARED LIBRARY HANDLING | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | #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, HCL_NULL, 0)
 | 
					
						
							|  |  |  | #	define sys_dl_openext(x) LoadLibraryExA(x, HCL_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, hcl_ooch_t etc? */ | 
					
						
							|  |  |  | 	static char buf[256]; | 
					
						
							|  |  |  | 	DWORD rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = FormatMessageA ( | 
					
						
							|  |  |  | 		FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		buf, HCL_COUNTOF(buf), HCL_NULL | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	while (rc > 0 && buf[rc - 1] == '\r' || buf[rc - 1] == '\n') | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		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 = ""; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if ((rc = NSCreateObjectFileImageFromFile(path, &image)) != NSObjectFileImageSuccess) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			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_startup (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(USE_LTDL)
 | 
					
						
							|  |  |  | 	lt_dlinit (); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void dl_cleanup (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(USE_LTDL)
 | 
					
						
							|  |  |  | 	lt_dlexit (); | 
					
						
							|  |  |  | #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
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	bufcapa += HCL_COUNTOF(HCL_DEFAULT_PFMODDIR) + HCL_COUNTOF(HCL_DEFAULT_PFMODPREFIX) + HCL_COUNTOF(HCL_DEFAULT_PFMODPOSTFIX) + 1; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		dlen = HCL_IS_PATH_ABSOLUTE(HCL_DEFAULT_PFMODPREFIX)? | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			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 */ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		xlen  = len + bcslen; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		for (i = len; i < xlen; i++) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* convert a period(.) to a dash(-) */ | 
					
						
							|  |  |  | 			if (bufptr[i] == '.') bufptr[i] = '-'; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 		if (!handle) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			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]); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			if (!handle) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				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), '-'); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 				if (dash) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 					/* remove a segment at the back.
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 					 * [NOTE] a dash contained in the original name before | 
					
						
							|  |  |  | 					 *        period-to-dash transformation may cause extraneous/wrong | 
					
						
							|  |  |  | 					 *        loading reattempts. */ | 
					
						
							|  |  |  | 					xlen = dash - bufptr; | 
					
						
							|  |  |  | 					goto retry; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				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); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			if (!handle) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				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); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			if (!handle) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				const hcl_bch_t* dl_errstr; | 
					
						
							|  |  |  | 				dl_errstr = sys_dl_error(); | 
					
						
							| 
									
										
										
										
											2021-02-11 14:14:49 +00:00
										 |  |  | 				HCL_DEBUG2 (hcl, "Unable to open(ext) DL %hs - %hs\n", bufptr, dl_errstr); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 				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) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 			bufptr[bcslen + 1] = '_'; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 			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); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * EVENT CALLBACKS | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 15:48:44 +00:00
										 |  |  | /*#define ENABLE_LOG_INITIALLY*/ | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static HCL_INLINE void reset_log_to_default (xtn_t* xtn) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(ENABLE_LOG_INITIALLY)
 | 
					
						
							|  |  |  | 	xtn->log.fd = 2; | 
					
						
							|  |  |  | 	xtn->log.fd_flag = 0; | 
					
						
							|  |  |  | 	#if defined(HAVE_ISATTY)
 | 
					
						
							|  |  |  | 	if (isatty(xtn->log.fd)) xtn->log.fd_flag |= LOGFD_TTY; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	xtn->log.fd = -1; | 
					
						
							|  |  |  | 	xtn->log.fd_flag = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void cb_fini (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	if ((xtn->log.fd_flag & LOGFD_OPENED_HERE) && xtn->log.fd >= 0) close (xtn->log.fd); | 
					
						
							|  |  |  | 	reset_log_to_default (xtn); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void cb_opt_set (hcl_t* hcl, hcl_option_t id, const void* value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 	int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (id != HCL_LOG_TARGET) return; /* return success. not interested */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	fd = _open(hcl->option.log_target, _O_CREAT | _O_WRONLY | _O_APPEND | _O_BINARY , 0644); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	#if defined(HCL_OOCH_IS_UCH)
 | 
					
						
							|  |  |  | 	fd = open(hcl->option.log_targetx, O_CREAT | O_WRONLY | O_APPEND , 0644); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 	fd = open(hcl->option.log_target, O_CREAT | O_WRONLY | O_APPEND , 0644); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (fd == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* TODO: any warning that log file not changed? */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if ((xtn->log.fd_flag & LOGFD_OPENED_HERE) && xtn->log.fd >= 0) close (xtn->log.fd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		xtn->log.fd = fd; | 
					
						
							|  |  |  | 		xtn->log.fd_flag = LOGFD_OPENED_HERE; | 
					
						
							|  |  |  | 	#if defined(HAVE_ISATTY)
 | 
					
						
							|  |  |  | 		if (isatty(xtn->log.fd)) xtn->log.fd_flag |= LOGFD_TTY; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | #if defined(__OS2__) && defined(TCPV40HDRS)
 | 
					
						
							|  |  |  | static int os2_socket_pair (int p[2]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	int x = -1, y = -1, z; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 	struct sockaddr_un sa; | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	PTIB tib; | 
					
						
							|  |  |  | 	PPIB pib; | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	ULONG msec, idx; | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	DosGetInfoBlocks(&tib, &pib); | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &msec, HCL_SIZEOF(msec)); | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	x = socket(PF_OS2, SOCK_STREAM, 0); | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	if (x <= -1) goto oops; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	idx = msec; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | attempt_to_bind: | 
					
						
							|  |  |  | 	HCL_MEMSET (&sa, 0, HCL_SIZEOF(sa)); | 
					
						
							|  |  |  | 	sa.sun_family = AF_OS2; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	/* OS/2 mandates the socket name should begin with \socket\ */ | 
					
						
							|  |  |  | 	sprintf (sa.sun_path, "\\socket\\hcl-%08lx-%08lx-%08lx", (unsigned long int)pib->pib_ulpid, (unsigned long int)tib->tib_ptib2->tib2_ultid, (unsigned long int)idx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bind(x, (struct sockaddr*)&sa, HCL_SIZEOF(sa)) <= -1)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (sock_errno() != SOCEADDRINUSE) goto oops; | 
					
						
							|  |  |  | 		if (idx - msec > 9999) goto oops; /* failure after many attempts */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		idx++; | 
					
						
							|  |  |  | 		goto attempt_to_bind; | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	if (listen(x, 1) <= -1) goto oops; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	y = socket(PF_OS2, SOCK_STREAM, 0); | 
					
						
							|  |  |  | 	if (y <= -1) goto oops; | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	if (connect(y, (struct sockaddr*)&sa, HCL_SIZEOF(sa)) <= -1) goto oops; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 	z = accept(x, HCL_NULL, HCL_NULL); | 
					
						
							| 
									
										
										
										
											2021-03-30 05:37:00 +00:00
										 |  |  | 	if (z <= -1) goto oops; | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	soclose (x); | 
					
						
							|  |  |  | 	p[0] = z; | 
					
						
							|  |  |  | 	p[1] = y; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | oops: | 
					
						
							|  |  |  | 	if (y >= 0) soclose (y); | 
					
						
							|  |  |  | 	if (x >= 0) soclose (x); | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | static int open_pipes (hcl_t* hcl, int p[2]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	u_long flags; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 	int flags; | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	if (_pipe(p, 256, _O_BINARY | _O_NOINHERIT) == -1) | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrbfmtwithsyserr (hcl, 0, errno, "unable to create pipes"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | #elif defined(__OS2__)
 | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 	#if defined(TCPV40HDRS)
 | 
					
						
							|  |  |  | 	/* neither pipe nor socketpair available */ | 
					
						
							|  |  |  | 	if (os2_socket_pair(p) == -1) | 
					
						
							|  |  |  | 	#else
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | 	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, p) == -1) | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrbfmtwithsyserr (hcl, 2, sock_errno(), "unable to create pipes"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | #elif defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK)
 | 
					
						
							|  |  |  | 	if (pipe2(p, O_CLOEXEC | O_NONBLOCK) == -1) | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrbfmtwithsyserr (hcl, 0, errno, "unable to create pipes"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	if (pipe(p) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 		hcl_seterrbfmtwithsyserr (hcl, 0, errno, "unable to create pipes"); | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-30 06:13:46 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	flags = 1; | 
					
						
							|  |  |  | 	ioctl (p[0], FIONBIO, &flags); | 
					
						
							|  |  |  | 	ioctl (p[1], FIONBIO, &flags); | 
					
						
							|  |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 	flags = 1; /* don't block */ | 
					
						
							| 
									
										
										
										
											2021-03-30 01:37:36 +00:00
										 |  |  | 	ioctl (p[0], FIONBIO, (char*)&flags, HCL_SIZEOF(flags)); | 
					
						
							|  |  |  | 	ioctl (p[1], FIONBIO, (char*)&flags, HCL_SIZEOF(flags)); | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #elif defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK)
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 		/* do nothing */ | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	#if defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  | 	flags = fcntl(p[0], F_GETFD); | 
					
						
							|  |  |  | 	if (flags >= 0) fcntl (p[0], F_SETFD, flags | FD_CLOEXEC); | 
					
						
							|  |  |  | 	flags = fcntl(p[1], F_GETFD); | 
					
						
							|  |  |  | 	if (flags >= 0) fcntl (p[1], F_SETFD, flags | FD_CLOEXEC); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	#if defined(O_NONBLOCK)
 | 
					
						
							|  |  |  | 	flags = fcntl(p[0], F_GETFL); | 
					
						
							|  |  |  | 	if (flags >= 0) fcntl (p[0], F_SETFL, flags | O_NONBLOCK); | 
					
						
							|  |  |  | 	flags = fcntl(p[1], F_GETFL); | 
					
						
							|  |  |  | 	if (flags >= 0) fcntl (p[1], F_SETFL, flags | O_NONBLOCK); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | static void close_pipes (hcl_t* hcl, int p[2]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	_close (p[0]); | 
					
						
							|  |  |  | 	_close (p[1]); | 
					
						
							| 
									
										
										
										
											2021-03-28 18:12:07 +00:00
										 |  |  | #elif defined(__OS2__)
 | 
					
						
							|  |  |  | 	soclose (p[0]); | 
					
						
							|  |  |  | 	soclose (p[1]); | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	close (p[0]); | 
					
						
							|  |  |  | 	close (p[1]); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	p[0] = -1; | 
					
						
							|  |  |  | 	p[1] = -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | static int cb_vm_startup (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 	int sigfd_pcount = 0; | 
					
						
							|  |  |  | 	int iothr_pcount = 0, flags; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	xtn->waitable_timer = CreateWaitableTimer(HCL_NULL, TRUE, HCL_NULL); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | #if defined(USE_DEVPOLL)
 | 
					
						
							|  |  |  | 	xtn->ep = open("/dev/poll", O_RDWR); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (xtn->ep == -1) | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Cannot create devpoll - %hs\n", strerror(errno)); | 
					
						
							|  |  |  | 		goto oops; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  | 	flags = fcntl(xtn->ep, F_GETFD); | 
					
						
							|  |  |  | 	if (flags >= 0) fcntl (xtn->ep, F_SETFD, flags | FD_CLOEXEC); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	#if defined(HAVE_KQUEUE1) && defined(O_CLOEXEC)
 | 
					
						
							|  |  |  | 	xtn->ep = kqueue1(O_CLOEXEC); | 
					
						
							|  |  |  | 	if (xtn->ep == -1) xtn->ep = kqueue(); | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 	xtn->ep = kqueue(); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	if (xtn->ep == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Cannot create kqueue - %hs\n", strerror(errno)); | 
					
						
							|  |  |  | 		goto oops; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  | 	flags = fcntl(xtn->ep, F_GETFD); | 
					
						
							|  |  |  | 	if (flags >= 0 && !(flags & FD_CLOEXEC)) fcntl (xtn->ep, F_SETFD, flags | FD_CLOEXEC); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
 | 
					
						
							|  |  |  | 	xtn->ep = epoll_create1(EPOLL_CLOEXEC); | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (xtn->ep == -1) xtn->ep = epoll_create(1024); | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 	#else
 | 
					
						
							|  |  |  | 	xtn->ep = epoll_create(1024); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | 	if (xtn->ep == -1) | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrwithsyserr (hcl, 0, errno); | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Cannot create epoll - %hs\n", strerror(errno)); | 
					
						
							|  |  |  | 		goto oops; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  | 	flags = fcntl(xtn->ep, F_GETFD); | 
					
						
							|  |  |  | 	if (flags >= 0 && !(flags & FD_CLOEXEC)) fcntl (xtn->ep, F_SETFD, flags | 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 (open_pipes(hcl, xtn->sigfd.p) <= -1) goto oops; | 
					
						
							|  |  |  | 	sigfd_pcount = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 	if (open_pipes(hcl, xtn->iothr.p) <= -1) goto oops; | 
					
						
							|  |  |  | 	iothr_pcount = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (_add_poll_fd(hcl, xtn->iothr.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->ev.halting = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn->iothr.abort = 0; | 
					
						
							|  |  |  | 	xtn->iothr.up = 0; | 
					
						
							|  |  |  | 	/*pthread_create (&xtn->iothr, HCL_NULL, iothr_main, hcl);*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* USE_THREAD */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn->vm_running = 1; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | oops: | 
					
						
							|  |  |  | #if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 	if (iothr_pcount > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		close (xtn->iothr.p[0]); | 
					
						
							|  |  |  | 		close (xtn->iothr.p[1]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (sigfd_pcount > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		close (xtn->sigfd.p[0]); | 
					
						
							|  |  |  | 		close (xtn->sigfd.p[1]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(USE_DEVPOLL) || defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 	if (xtn->ep >= 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		close (xtn->ep); | 
					
						
							|  |  |  | 		xtn->ep = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void cb_vm_cleanup (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xtn_t* xtn = GET_XTN(hcl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xtn->vm_running = 0; | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | #if defined(_WIN32)
 | 
					
						
							|  |  |  | 	if (xtn->waitable_timer) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		CloseHandle (xtn->waitable_timer); | 
					
						
							|  |  |  | 		xtn->waitable_timer = HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | #if defined(USE_THREAD)
 | 
					
						
							|  |  |  | 	if (xtn->iothr.up) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		xtn->iothr.abort = 1; | 
					
						
							|  |  |  | 		write (xtn->iothr.p[1], "Q", 1); | 
					
						
							|  |  |  | 		pthread_cond_signal (&xtn->ev.cnd); | 
					
						
							|  |  |  | 		pthread_join (xtn->iothr.thr, 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->iothr.p[0]); | 
					
						
							|  |  |  | 	close_pipes (hcl, xtn->iothr.p); | 
					
						
							|  |  |  | #endif /* USE_THREAD */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	close_pipes (hcl, xtn->sigfd.p); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | #if defined(USE_DEVPOLL)
 | 
					
						
							| 
									
										
										
										
											2021-02-08 09:16:53 +00:00
										 |  |  | 	if (xtn->ep >= 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		close (xtn->ep); | 
					
						
							|  |  |  | 		xtn->ep = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/*destroy_poll_data_space (hcl);*/ | 
					
						
							|  |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	if (xtn->ep >= 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		close (xtn->ep); | 
					
						
							|  |  |  | 		xtn->ep = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #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
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-28 03:44:27 +00:00
										 |  |  | /* -----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  |  * STANDARD HCL | 
					
						
							|  |  |  |  * ----------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | hcl_t* hcl_openstdwithmmgr (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_errnum_t* errnum) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hcl_t* hcl; | 
					
						
							|  |  |  | 	hcl_vmprim_t vmprim; | 
					
						
							|  |  |  | 	hcl_cb_t cb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim)); | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	vmprim.alloc_heap = alloc_heap; | 
					
						
							|  |  |  | 	vmprim.free_heap = free_heap; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	vmprim.log_write = log_write; | 
					
						
							|  |  |  | 	vmprim.syserrstrb = _syserrstrb; | 
					
						
							|  |  |  | 	vmprim.assertfail = _assertfail; | 
					
						
							|  |  |  | 	vmprim.dl_startup = dl_startup; | 
					
						
							|  |  |  | 	vmprim.dl_cleanup = dl_cleanup; | 
					
						
							|  |  |  | 	vmprim.dl_open = dl_open; | 
					
						
							|  |  |  | 	vmprim.dl_close = dl_close; | 
					
						
							|  |  |  | 	vmprim.dl_getsym = dl_getsym; | 
					
						
							|  |  |  | 	vmprim.vm_gettime = vm_gettime; | 
					
						
							|  |  |  | 	vmprim.vm_muxadd = vm_muxadd; | 
					
						
							|  |  |  | 	vmprim.vm_muxdel = vm_muxdel; | 
					
						
							|  |  |  | 	vmprim.vm_muxmod = vm_muxmod; | 
					
						
							|  |  |  | 	vmprim.vm_muxwait = vm_muxwait; | 
					
						
							|  |  |  | 	vmprim.vm_sleep = vm_sleep; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | 	hcl = hcl_open(mmgr, HCL_SIZEOF(xtn_t) + xtnsize, &vmprim, errnum); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:58:23 +00:00
										 |  |  | 	if (HCL_UNLIKELY(!hcl)) return HCL_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* adjust the object size by the sizeof xtn_t so that moo_getxtn() returns the right pointer. */ | 
					
						
							|  |  |  | 	hcl->_instsize += HCL_SIZEOF(xtn_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	reset_log_to_default (GET_XTN(hcl)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_MEMSET (&cb, 0, HCL_SIZEOF(cb)); | 
					
						
							|  |  |  | 	cb.fini = cb_fini; | 
					
						
							|  |  |  | 	cb.opt_set = cb_opt_set; | 
					
						
							|  |  |  | 	cb.vm_startup = cb_vm_startup; | 
					
						
							|  |  |  | 	cb.vm_cleanup = cb_vm_cleanup; | 
					
						
							|  |  |  | 	if (hcl_regcb(hcl, &cb) == HCL_NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (errnum) *errnum = hcl_geterrnum(hcl); | 
					
						
							|  |  |  | 		hcl_close (hcl); | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return hcl; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-02-08 09:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | hcl_t* hcl_openstd (hcl_oow_t xtnsize, hcl_errnum_t* errnum) | 
					
						
							| 
									
										
										
										
											2021-02-08 09:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | 	return hcl_openstdwithmmgr(&sys_mmgr, xtnsize, errnum); | 
					
						
							| 
									
										
										
										
											2021-02-08 09:41:40 +00:00
										 |  |  | } |