| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-02-20 15:35:16 +00:00
										 |  |  |     Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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 | 
					
						
							| 
									
										
										
										
											2022-06-11 05:32:01 +00:00
										 |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  |     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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | #define _GNU_SOURCE
 | 
					
						
							| 
									
										
										
										
											2020-04-30 02:28:09 +00:00
										 |  |  | #include "sys-prv.h"
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ========================================================================= */ | 
					
						
							|  |  |  | #if defined(USE_POLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | #	define MUX_INDEX_INVALID HIO_TYPE_MAX(hio_oow_t)
 | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | #	define MUX_INDEX_SUSPENDED (MUX_INDEX_INVALID - 1)
 | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | static int secure_poll_map_slot_for_hnd (hio_t* hio, hio_syshnd_t hnd); | 
					
						
							|  |  |  | static int secure_poll_data_slot_for_insert (hio_t* hio); | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | int hio_sys_initmux (hio_t* hio) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	/* create a pipe for internal signalling -  interrupt the multiplexer wait */ | 
					
						
							|  |  |  | #if defined(HAVE_PIPE2) && defined(O_CLOEXEC) && defined(O_NONBLOCK)
 | 
					
						
							|  |  |  | 	if (pipe2(mux->ctrlp, O_CLOEXEC | O_NONBLOCK) <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->ctrlp[0] = HIO_SYSHND_INVALID; | 
					
						
							|  |  |  | 		mux->ctrlp[1] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	if (pipe(mux->ctrlp) <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->ctrlp[0] = HIO_SYSHND_INVALID; | 
					
						
							|  |  |  | 		mux->ctrlp[1] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_makesyshndasync(hio, mux->ctrlp[0]); | 
					
						
							|  |  |  | 		hio_makesyshndcloexec(hio, mux->ctrlp[0]); | 
					
						
							|  |  |  | 		hio_makesyshndasync(hio, mux->ctrlp[1]); | 
					
						
							|  |  |  | 		hio_makesyshndcloexec(hio, mux->ctrlp[1]); | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | #if defined(USE_POLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (secure_poll_map_slot_for_hnd(hio, mux->ctrlp[0]) <= -1 || | 
					
						
							|  |  |  | 	    secure_poll_data_slot_for_insert(hio) <= -1) | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/* no control pipes if registration fails */ | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 		close (mux->ctrlp[1]); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->ctrlp[1] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		close (mux->ctrlp[0]); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->ctrlp[0] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_oow_t idx; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		idx = mux->pd.size++; | 
					
						
							|  |  |  | 		mux->pd.pfd[idx].fd = mux->ctrlp[0]; | 
					
						
							|  |  |  | 		mux->pd.pfd[idx].events = POLLIN; | 
					
						
							|  |  |  | 		mux->pd.pfd[idx].revents = 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->pd.dptr[idx] = HIO_NULL; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		mux->map.ptr[mux->ctrlp[0]] = idx; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | #elif defined(USE_SELECT)
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	FD_ZERO (&mux->rset); | 
					
						
							|  |  |  | 	FD_ZERO (&mux->wset); | 
					
						
							|  |  |  | 	mux->maxhnd = -1; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 15:23:55 +00:00
										 |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	#if defined(HAVE_KQUEUE1) && defined(O_CLOEXEC)
 | 
					
						
							|  |  |  | 	mux->kq = kqueue1(O_CLOEXEC); | 
					
						
							|  |  |  | 	if (mux->kq <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#else
 | 
					
						
							|  |  |  | 	mux->kq = kqueue(); | 
					
						
							|  |  |  | 	if (mux->kq <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		#if defined(FD_CLOEXEC)
 | 
					
						
							|  |  |  | 		int flags = fcntl(mux->kq, F_GETFD); | 
					
						
							| 
									
										
										
										
											2022-06-22 06:44:28 +00:00
										 |  |  | 		if (flags >= 0) fcntl (mux->kq, F_SETFD, flags | FD_CLOEXEC); | 
					
						
							| 
									
										
										
										
											2021-07-24 15:23:55 +00:00
										 |  |  | 		#endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 	/* register the control pipe */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		struct kevent chlist; | 
					
						
							|  |  |  | 		EV_SET(&chlist, mux->ctrlp[0], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); | 
					
						
							|  |  |  | 		kevent(mux->kq, &chlist, 1, HIO_NULL, 0, HIO_NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-15 03:40:15 +00:00
										 |  |  | #if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
 | 
					
						
							|  |  |  | 	mux->hnd = epoll_create1(EPOLL_CLOEXEC); | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | 	if (mux->hnd == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 		if (errno == ENOSYS) goto normal_epoll_create; /* kernel doesn't support it */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 	goto epoll_create_done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | normal_epoll_create: | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 	mux->hnd = epoll_create(16384); /* TODO: choose proper initial size? */ | 
					
						
							|  |  |  | 	if (mux->hnd == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #if defined(FD_CLOEXEC)
 | 
					
						
							| 
									
										
										
										
											2020-11-15 03:40:15 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		int flags = fcntl(mux->hnd, F_GETFD, 0); | 
					
						
							| 
									
										
										
										
											2020-11-15 03:40:15 +00:00
										 |  |  | 		if (flags >= 0 && !(flags & FD_CLOEXEC)) fcntl(mux->hnd, F_SETFD, flags | FD_CLOEXEC); | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #endif /* FD_CLOEXEC */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | epoll_create_done: | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (mux->ctrlp[0] != HIO_SYSHND_INVALID) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		struct epoll_event ev; | 
					
						
							|  |  |  | 		ev.events = EPOLLIN | EPOLLHUP | EPOLLERR; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		ev.data.ptr = HIO_NULL; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		if (epoll_ctl(mux->hnd, EPOLL_CTL_ADD, mux->ctrlp[0], &ev) == -1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* if ADD fails, close the control pipes and forget them */ | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			close (mux->ctrlp[1]); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			mux->ctrlp[1] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 			close (mux->ctrlp[0]); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			mux->ctrlp[0] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | #endif /* USE_EPOLL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | void hio_sys_finimux (hio_t* hio) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | #if defined(USE_POLL)
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 	if (mux->map.ptr) | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_freemem (hio, mux->map.ptr); | 
					
						
							|  |  |  | 		mux->map.ptr = HIO_NULL; | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | 		mux->map.capa = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 	if (mux->pd.pfd) | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_freemem (hio, mux->pd.pfd); | 
					
						
							|  |  |  | 		mux->pd.pfd = HIO_NULL; | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 	if (mux->pd.dptr) | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_freemem (hio, mux->pd.dptr); | 
					
						
							|  |  |  | 		mux->pd.dptr = HIO_NULL; | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	mux->pd.capa = 0; | 
					
						
							| 
									
										
										
										
											2020-05-24 09:38:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | #elif defined(USE_SELECT)
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	FD_ZERO (&mux->rset); | 
					
						
							|  |  |  | 	FD_ZERO (&mux->wset); | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	if (mux->me.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		for (i = 0; i < mux->me.ubound; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (mux->me.ptr[i]) hio_freemem (hio, mux->me.ptr[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hio_freemem (hio, mux->me.ptr); | 
					
						
							|  |  |  | 		mux->me.ubound = 0; | 
					
						
							|  |  |  | 		mux->me.ptr = HIO_NULL; | 
					
						
							|  |  |  | 		mux->maxhnd = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 15:23:55 +00:00
										 |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 	if (mux->ctrlp[0] != HIO_SYSHND_INVALID) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 		struct kevent chlist; | 
					
						
							|  |  |  | 		EV_SET(&chlist, mux->ctrlp[0], EVFILT_READ, EV_DELETE | EV_DISABLE, 0, 0, 0); | 
					
						
							|  |  |  | 		kevent(mux->kq, &chlist, 1, HIO_NULL, 0, HIO_NULL); | 
					
						
							| 
									
										
										
										
											2021-07-24 15:23:55 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	close (mux->kq); | 
					
						
							|  |  |  | 	mux->kq = HIO_SYSHND_INVALID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 02:27:54 +00:00
										 |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (mux->ctrlp[0] != HIO_SYSHND_INVALID) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		struct epoll_event ev; | 
					
						
							|  |  |  | 		ev.events = EPOLLIN | EPOLLHUP | EPOLLERR; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		ev.data.ptr = HIO_NULL; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 		epoll_ctl(mux->hnd, EPOLL_CTL_DEL, mux->ctrlp[0], &ev); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 16:57:16 +00:00
										 |  |  | 	close (mux->hnd); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	mux->hnd = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (mux->ctrlp[1] != HIO_SYSHND_INVALID) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 		close (mux->ctrlp[1]); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->ctrlp[1] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (mux->ctrlp[0] != HIO_SYSHND_INVALID) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		close (mux->ctrlp[0]); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		mux->ctrlp[0] = HIO_SYSHND_INVALID; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | void hio_sys_intrmux (hio_t* hio) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* for now, thie only use of the control pipe is to interrupt the multiplexer */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							|  |  |  | 	if (mux->ctrlp[1] != HIO_SYSHND_INVALID) write (mux->ctrlp[1], "Q", 1); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | #if defined(USE_POLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | static int secure_poll_map_slot_for_hnd (hio_t* hio, hio_syshnd_t hnd) | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (hnd >= mux->map.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_oow_t new_capa; | 
					
						
							|  |  |  | 		hio_oow_t* tmp; | 
					
						
							|  |  |  | 		hio_oow_t idx; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		new_capa = HIO_ALIGN_POW2((hnd + 1), 256); | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		tmp = hio_reallocmem(hio, mux->map.ptr, new_capa * HIO_SIZEOF(*tmp)); | 
					
						
							|  |  |  | 		if (HIO_UNLIKELY(!tmp)) return -1; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for (idx = mux->map.capa; idx < new_capa; idx++) tmp[idx] = MUX_INDEX_INVALID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mux->map.ptr = tmp; | 
					
						
							|  |  |  | 		mux->map.capa = new_capa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | static int secure_poll_data_slot_for_insert (hio_t* hio) | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (mux->pd.size >= mux->pd.capa) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_oow_t new_capa; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		struct pollfd* tmp1; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_dev_t** tmp2; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		new_capa = HIO_ALIGN_POW2(mux->pd.size + 1, 256); | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		tmp1 = hio_reallocmem(hio, mux->pd.pfd, new_capa * HIO_SIZEOF(*tmp1)); | 
					
						
							|  |  |  | 		if (HIO_UNLIKELY(!tmp1)) return -1; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		tmp2 = hio_reallocmem(hio, mux->pd.dptr, new_capa * HIO_SIZEOF(*tmp2)); | 
					
						
							|  |  |  | 		if (HIO_UNLIKELY(!tmp2)) | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			hio_freemem (hio, tmp1); | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mux->pd.pfd = tmp1; | 
					
						
							|  |  |  | 		mux->pd.dptr = tmp2; | 
					
						
							|  |  |  | 		mux->pd.capa = new_capa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_cap) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | #if defined(USE_POLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							|  |  |  | 	hio_oow_t idx; | 
					
						
							|  |  |  | 	hio_syshnd_t hnd; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 09:25:34 +00:00
										 |  |  | 	hnd = dev->dev_mth->getsyshnd(dev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (cmd == HIO_SYS_MUX_CMD_INSERT) | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		if (secure_poll_map_slot_for_hnd(hio, hnd) <=  -1) return -1; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (hnd >= mux->map.capa) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			hio_seterrnum (hio, HIO_ENOENT); | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	idx = mux->map.ptr[hnd]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		case HIO_SYS_MUX_CMD_INSERT: | 
					
						
							| 
									
										
										
										
											2020-05-24 17:40:47 +00:00
										 |  |  | 			if (idx != MUX_INDEX_INVALID) /* not valid index and not MUX_INDEX_SUSPENDED */ | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				hio_seterrnum (hio, HIO_EEXIST); | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 		do_insert: | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			if (HIO_UNLIKELY(secure_poll_data_slot_for_insert(hio) <=  -1)) return -1; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			idx = mux->pd.size++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mux->pd.pfd[idx].fd = hnd; | 
					
						
							|  |  |  | 			mux->pd.pfd[idx].events = 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			if (dev_cap & HIO_DEV_CAP_IN_WATCHED) mux->pd.pfd[idx].events |= POLLIN; | 
					
						
							|  |  |  | 			if (dev_cap & HIO_DEV_CAP_OUT_WATCHED) mux->pd.pfd[idx].events |= POLLOUT; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			mux->pd.pfd[idx].revents = 0; | 
					
						
							|  |  |  | 			mux->pd.dptr[idx] = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mux->map.ptr[hnd] = idx; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		case HIO_SYS_MUX_CMD_UPDATE: | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			int events = 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			if (dev_cap & HIO_DEV_CAP_IN_WATCHED) events |= POLLIN; | 
					
						
							|  |  |  | 			if (dev_cap & HIO_DEV_CAP_OUT_WATCHED) events |= POLLOUT; | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 17:40:47 +00:00
										 |  |  | 			if (idx == MUX_INDEX_INVALID) | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				hio_seterrnum (hio, HIO_ENOENT); | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			else if (idx == MUX_INDEX_SUSPENDED) | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				if (!events) return 0; /* no change. keep suspended */ | 
					
						
							|  |  |  | 				goto do_insert; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!events) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				mux->map.ptr[hnd] = MUX_INDEX_SUSPENDED; | 
					
						
							|  |  |  | 				goto do_delete; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-24 09:38:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			HIO_ASSERT (hio, mux->pd.dptr[idx] == dev); | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 			mux->pd.pfd[idx].events = events; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2020-05-24 17:40:47 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		case HIO_SYS_MUX_CMD_DELETE: | 
					
						
							| 
									
										
										
										
											2020-05-24 17:40:47 +00:00
										 |  |  | 			if (idx == MUX_INDEX_INVALID) | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				hio_seterrnum (hio, HIO_ENOENT); | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else if (idx == MUX_INDEX_SUSPENDED) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				mux->map.ptr[hnd] = MUX_INDEX_INVALID; | 
					
						
							|  |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			HIO_ASSERT (hio, mux->pd.dptr[idx] == dev); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			mux->map.ptr[hnd] = MUX_INDEX_INVALID; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 17:25:27 +00:00
										 |  |  | 		do_delete: | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			/* TODO: speed up deletion. allow a hole in the array.
 | 
					
						
							|  |  |  | 			 *       delay array compaction if there is a hole. | 
					
						
							|  |  |  | 			 *       set fd for the hole to -1 such that poll() | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			 *       ignores it. compact the array if another deletion | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			 *       is requested when there is an existing hole. */ | 
					
						
							|  |  |  | 			idx++; | 
					
						
							|  |  |  | 			while (idx < mux->pd.size) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				mux->pd.pfd[idx - 1] = mux->pd.pfd[idx]; | 
					
						
							|  |  |  | 				mux->pd.dptr[idx - 1] = mux->pd.dptr[idx]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				fd = mux->pd.pfd[idx].fd; | 
					
						
							|  |  |  | 				mux->map.ptr[fd] = idx - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				idx++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mux->pd.size--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			hio_seterrnum (hio, HIO_EINVAL); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | #elif defined(USE_SELECT)
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							|  |  |  | 	hio_syshnd_t hnd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hnd = dev->dev_mth->getsyshnd(dev); | 
					
						
							|  |  |  | 	if (hnd >= FD_SETSIZE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hio_seterrbfmt (hio, HIO_EINVAL, "device handle too hig"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case HIO_SYS_MUX_CMD_INSERT: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hio_mux_slct_evt_t* mevt; | 
					
						
							|  |  |  | 			int events = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* TODO: windows seems to return a pretty high file descriptors
 | 
					
						
							|  |  |  | 			 *       using an array to store information may not be so effcient. | 
					
						
							|  |  |  | 			 *       devise a different way to maintain information */ | 
					
						
							|  |  |  | 			if (hnd >= mux->me.ubound) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hio_mux_slct_evt_t** tmp; | 
					
						
							|  |  |  | 				int ubound; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ubound = hnd + 1; | 
					
						
							|  |  |  | 				ubound = HIO_ALIGN_POW2(ubound, 128); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				tmp = hio_reallocmem(hio, mux->me.ptr, HIO_SIZEOF(*mux->me.ptr) * ubound); | 
					
						
							|  |  |  | 				if (!tmp) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				HIO_MEMSET (&tmp[mux->me.ubound], 0, HIO_SIZEOF(*mux->me.ptr) * (ubound - mux->me.ubound)); | 
					
						
							|  |  |  | 				mux->me.ptr = tmp; | 
					
						
							|  |  |  | 				mux->me.ubound = ubound; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mevt = mux->me.ptr[hnd]; | 
					
						
							|  |  |  | 			if (!mevt) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				mevt = hio_allocmem(hio, HIO_SIZEOF(*mevt)); | 
					
						
							|  |  |  | 				if (!mevt) return -1; | 
					
						
							|  |  |  | 				mux->me.ptr[hnd] = mevt; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			HIO_MEMSET (mevt, 0, HIO_SIZEOF(*mevt)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (dev_cap & HIO_DEV_CAP_IN_WATCHED) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				FD_SET (hnd, &mux->rset); | 
					
						
							|  |  |  | 				mevt->mask |= HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (dev_cap & HIO_DEV_CAP_OUT_WATCHED) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				FD_SET (hnd, &mux->wset); | 
					
						
							|  |  |  | 				mevt->mask |= HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mevt->dev = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (hnd > mux->maxhnd) mux->maxhnd = hnd; | 
					
						
							|  |  |  | 			mux->size++; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HIO_SYS_MUX_CMD_UPDATE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hio_mux_slct_evt_t* mevt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (mux->size <= 0 || hnd < 0 || hnd >= mux->me.ubound) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hio_seterrbfmt (hio, HIO_EINVAL, "invalid multiplexer state"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mevt = mux->me.ptr[hnd]; | 
					
						
							|  |  |  | 			if (!mevt || mevt->dev != dev) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* already deleted??? */ | 
					
						
							|  |  |  | 				hio_seterrbfmt (hio, HIO_EINVAL, "invalid multiplexer state"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* the code doesn't care if the handle is set in the rset or wset already.
 | 
					
						
							|  |  |  | 			 * such a check doesn't really bring benefit. */ | 
					
						
							|  |  |  | 			if (dev_cap & HIO_DEV_CAP_IN_WATCHED) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				FD_SET (hnd, &mux->rset); | 
					
						
							|  |  |  | 				mevt->mask |= HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				FD_CLR (hnd, &mux->rset); | 
					
						
							|  |  |  | 				mevt->mask &= ~HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (dev_cap & HIO_DEV_CAP_OUT_WATCHED) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				FD_SET (hnd, &mux->wset); | 
					
						
							|  |  |  | 				mevt->mask |= HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				FD_CLR (hnd, &mux->wset); | 
					
						
							|  |  |  | 				mevt->mask &= ~HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HIO_SYS_MUX_CMD_DELETE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hio_mux_slct_evt_t* mevt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (mux->size <= 0 || hnd < 0 || hnd >= mux->me.ubound) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hio_seterrbfmt (hio, HIO_EINVAL, "invalid multiplexer state"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mevt = mux->me.ptr[hnd]; | 
					
						
							|  |  |  | 			if (!mevt || mevt->dev != dev) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* already deleted??? */ | 
					
						
							|  |  |  | 				hio_seterrbfmt (hio, HIO_EINVAL, "invalid multiplexer state"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (mevt->mask & HIO_DEV_EVENT_IN) FD_CLR (hnd, &mux->rset); | 
					
						
							|  |  |  | 			if (mevt->mask & HIO_DEV_EVENT_OUT) FD_CLR (hnd, &mux->wset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (hnd == mux->maxhnd) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hio_syshnd_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for (i = hnd; i > 0; ) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					hio_mux_slct_evt_t* xevt; | 
					
						
							|  |  |  | 					xevt = mux->me.ptr[--i]; | 
					
						
							|  |  |  | 					if (xevt && xevt->dev) | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						hio_syshnd_t xhnd = xevt->dev->dev_mth->getsyshnd(xevt->dev); | 
					
						
							|  |  |  | 						HIO_ASSERT (hio, i == xhnd); | 
					
						
							|  |  |  | 						mux->maxhnd = xhnd; | 
					
						
							|  |  |  | 						goto done; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				mux->maxhnd = -1; | 
					
						
							|  |  |  | 				HIO_ASSERT (hio, mux->size == 1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	done: | 
					
						
							|  |  |  | 			mevt->dev = HIO_NULL; | 
					
						
							|  |  |  | 			mevt->mask = 0; | 
					
						
							|  |  |  | 			mux->size--; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			hio_seterrnum (hio, HIO_EINVAL); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							|  |  |  | 	hio_syshnd_t hnd; | 
					
						
							|  |  |  | 	struct kevent chlist[2]; | 
					
						
							|  |  |  | 	int x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HIO_ASSERT (hio, hio == dev->hio); | 
					
						
							| 
									
										
										
										
											2021-07-26 15:19:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* no operation over a broken(closed) handle to prevent multiplexer from failing.
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 	 * close of the handle leads to auto-deletion from the kqueue multiplexer. | 
					
						
							| 
									
										
										
										
											2021-07-26 15:19:31 +00:00
										 |  |  | 	 * the closed handle must not be fed to the multiplexer */ | 
					
						
							|  |  |  | 	if (dev->dev_mth->issyshndbroken && dev->dev_mth->issyshndbroken(dev)) return 0; | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 	hnd = dev->dev_mth->getsyshnd(dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case HIO_SYS_MUX_CMD_INSERT: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			int i_flag, o_flag; | 
					
						
							|  |  |  | 			if (HIO_UNLIKELY(dev->dev_cap & HIO_DEV_CAP_WATCH_SUSPENDED)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hio_seterrnum (hio, HIO_EEXIST); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			i_flag = (dev_cap & HIO_DEV_CAP_IN_WATCHED)? EV_ENABLE: EV_DISABLE; | 
					
						
							|  |  |  | 			o_flag = (dev_cap & HIO_DEV_CAP_OUT_WATCHED)? EV_ENABLE: EV_DISABLE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			EV_SET (&chlist[1], hnd, EVFILT_READ, EV_ADD | i_flag, 0, 0, dev); | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 			EV_SET (&chlist[0], hnd, EVFILT_WRITE, EV_ADD | o_flag, 0, 0, dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			x = kevent(mux->kq, chlist, 2, HIO_NULL, 0, HIO_NULL); | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			if (x >= 0) dev->dev_cap |= HIO_DEV_CAP_WATCH_REREG_REQUIRED; /* ugly hack for the listening sockets in NetBSD */ | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			/* the CMD_INSERT comes with at MIO_DEV_CAP_IN_WATCHD set.
 | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 			 * skip checking to set WATCH_SUSPENDED */ | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HIO_SYS_MUX_CMD_UPDATE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			int i_flag, o_flag; | 
					
						
							|  |  |  | 			i_flag = (dev_cap & HIO_DEV_CAP_IN_WATCHED)? EV_ENABLE: EV_DISABLE; | 
					
						
							|  |  |  | 			o_flag = (dev_cap & HIO_DEV_CAP_OUT_WATCHED)? EV_ENABLE: EV_DISABLE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			EV_SET (&chlist[0], hnd, EVFILT_READ, EV_ADD | i_flag, 0, 0, dev); | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 			EV_SET (&chlist[1], hnd, EVFILT_WRITE, EV_ADD | o_flag, 0, 0, dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			x = kevent(mux->kq, chlist, 2, HIO_NULL, 0, HIO_NULL); | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			if (x >= 0) | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				if (i_flag == EV_DISABLE && o_flag == EV_DISABLE) | 
					
						
							|  |  |  | 					dev->dev_cap &= ~HIO_DEV_CAP_WATCH_SUSPENDED; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					dev->dev_cap |= HIO_DEV_CAP_WATCH_SUSPENDED; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HIO_SYS_MUX_CMD_DELETE: | 
					
						
							|  |  |  | 			EV_SET (&chlist[0], hnd, EVFILT_READ, EV_DELETE | EV_DISABLE, 0, 0, dev); | 
					
						
							|  |  |  | 			EV_SET (&chlist[1], hnd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, 0, 0, dev); | 
					
						
							|  |  |  | 			x = kevent(mux->kq, chlist, 2, HIO_NULL, 0, HIO_NULL); | 
					
						
							|  |  |  | 			if (x >= 0) dev->dev_cap &= ~HIO_DEV_CAP_WATCH_SUSPENDED; /* just clear this */ | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			hio_seterrnum (hio, HIO_EINVAL); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (x <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	struct epoll_event ev; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_syshnd_t hnd; | 
					
						
							|  |  |  | 	hio_uint32_t events; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 	int x; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	HIO_ASSERT (hio, hio == dev->hio); | 
					
						
							| 
									
										
										
										
											2021-07-26 15:19:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* no operation over a broken(closed) handle to prevent multiplexer from failing.
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 	 * close() of the handle leads to auto-deletion from the epoll multiplexer. | 
					
						
							| 
									
										
										
										
											2021-07-26 15:19:31 +00:00
										 |  |  | 	 * the closed handle must not be fed to the multiplexer */ | 
					
						
							|  |  |  | 	if (dev->dev_mth->issyshndbroken && dev->dev_mth->issyshndbroken(dev)) return 0; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 	hnd = dev->dev_mth->getsyshnd(dev); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 	events = 0; | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 	if (dev_cap & HIO_DEV_CAP_IN_WATCHED) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 		events |= EPOLLIN; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	#if defined(EPOLLRDHUP)
 | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 		events |= EPOLLRDHUP; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		if (dev_cap & HIO_DEV_CAP_PRI_WATCHED) events |= EPOLLPRI; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (dev_cap & HIO_DEV_CAP_OUT_WATCHED) events |= EPOLLOUT; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 17:29:52 +00:00
										 |  |  | 	ev.events = events | EPOLLHUP | EPOLLERR /*| EPOLLET*/; /* TODO: ready to support edge-trigger? */ | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 	ev.data.ptr = dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		case HIO_SYS_MUX_CMD_INSERT: | 
					
						
							|  |  |  | 			if (HIO_UNLIKELY(dev->dev_cap & HIO_DEV_CAP_WATCH_SUSPENDED)) | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				hio_seterrnum (hio, HIO_EEXIST); | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			x = epoll_ctl(mux->hnd, EPOLL_CTL_ADD, hnd, &ev); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		case HIO_SYS_MUX_CMD_UPDATE: | 
					
						
							|  |  |  | 			if (HIO_UNLIKELY(!events)) | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				if (dev->dev_cap & HIO_DEV_CAP_WATCH_SUSPENDED) | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					/* no change. keep suspended */ | 
					
						
							|  |  |  | 					return 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					x = epoll_ctl(mux->hnd, EPOLL_CTL_DEL, hnd, &ev); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 					if (x >= 0) dev->dev_cap |= HIO_DEV_CAP_WATCH_SUSPENDED; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				if (dev->dev_cap & HIO_DEV_CAP_WATCH_SUSPENDED) | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					x = epoll_ctl(mux->hnd, EPOLL_CTL_ADD, hnd, &ev); | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 					if (x >= 0) dev->dev_cap &= ~HIO_DEV_CAP_WATCH_SUSPENDED; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					x = epoll_ctl(mux->hnd, EPOLL_CTL_MOD, hnd, &ev); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		case HIO_SYS_MUX_CMD_DELETE: | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 			if (dev->dev_cap & HIO_DEV_CAP_WATCH_SUSPENDED) | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				/* clear the SUSPENDED bit because it's a normal deletion */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 				dev->dev_cap &= ~HIO_DEV_CAP_WATCH_SUSPENDED; | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 				return 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			x = epoll_ctl(mux->hnd, EPOLL_CTL_DEL, hnd, &ev); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			hio_seterrnum (hio, HIO_EINVAL); | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 19:29:35 +00:00
										 |  |  | 	if (x == -1) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #	error NO SUPPORTED MULTIPLEXER
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | int hio_sys_waitmux (hio_t* hio, const hio_ntime_t* tmout, hio_sys_mux_evtcb_t event_handler) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-01-29 08:38:12 +00:00
										 |  |  | #if defined(USE_POLL)
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2019-04-10 09:25:34 +00:00
										 |  |  | 	int nentries, i; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	nentries = poll(mux->pd.pfd, mux->pd.size, HIO_SECNSEC_TO_MSEC(tmout->sec, tmout->nsec)); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	if (nentries == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (errno == EINTR) return 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < mux->pd.size; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		if (HIO_UNLIKELY(mux->ctrlp[0] != HIO_SYSHND_INVALID && mux->pd.pfd[i].fd == mux->ctrlp[0])) | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* internal pipe for signaling */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			/* mux->pd.dptr[i] must be HIO_NULL */ | 
					
						
							|  |  |  | 			hio_uint8_t tmp[16]; | 
					
						
							|  |  |  | 			while (read(mux->ctrlp[0], tmp, HIO_SIZEOF(tmp)) > 0) ; | 
					
						
							| 
									
										
										
										
											2021-07-21 13:43:10 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (mux->pd.pfd[i].fd >= 0 && mux->pd.pfd[i].revents) | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			int events = 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			hio_dev_t* dev; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			dev = mux->pd.dptr[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			/*HIO_ASSERT (hio, !(mux->pd.pfd[i].revents & POLLNVAL));*/ | 
					
						
							|  |  |  | 			if (mux->pd.pfd[i].revents & POLLIN) events |= HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			if (mux->pd.pfd[i].revents & POLLOUT) events |= HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 			if (mux->pd.pfd[i].revents & POLLPRI) events |= HIO_DEV_EVENT_PRI; | 
					
						
							|  |  |  | 			if (mux->pd.pfd[i].revents & POLLERR) events |= HIO_DEV_EVENT_ERR; | 
					
						
							|  |  |  | 			if (mux->pd.pfd[i].revents & POLLHUP) events |= HIO_DEV_EVENT_HUP; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			event_handler (hio, dev, events, 0); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_SELECT)
 | 
					
						
							|  |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							|  |  |  | 	struct timeval tv; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tv.tv_sec = tmout->sec; | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	tv.tv_usec = tmout->nsec / HIO_NSECS_PER_USEC; | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	mux->tmprset = mux->rset; | 
					
						
							|  |  |  | 	mux->tmpwset = mux->wset; | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | /* TODO: call select with exceptset? */ | 
					
						
							|  |  |  | 	n = select(mux->maxhnd + 1, &mux->tmprset, &mux->tmpwset, NULL, &tv); | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 	if (n <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (errno == EINTR) return 0; /* it's actually ok */ | 
					
						
							|  |  |  | 		/* other errors are critical - EBADF, EFAULT, EINVAL */ | 
					
						
							|  |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 	if (n > 0) | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-11-20 13:43:52 +09:00
										 |  |  | 		hio_syshnd_t i; | 
					
						
							|  |  |  | 		hio_mux_slct_evt_t* evt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (i = 0; i <= mux->maxhnd; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			int events = 0; | 
					
						
							|  |  |  | 			hio_syshnd_t hnd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			evt = mux->me.ptr[i]; | 
					
						
							|  |  |  | 			if (!evt || !evt->dev) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hnd = evt->dev->dev_mth->getsyshnd(evt->dev); | 
					
						
							|  |  |  | 			if ((evt->mask & HIO_DEV_EVENT_IN) && FD_ISSET(hnd, &mux->tmprset)) events |= HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			if ((evt->mask & HIO_DEV_EVENT_OUT) && FD_ISSET(hnd, &mux->tmpwset)) events |= HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			event_handler (hio, evt->dev, events, 0); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-11-20 02:30:38 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | #elif defined(USE_KQUEUE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							|  |  |  | 	struct timespec ts; | 
					
						
							|  |  |  | 	int nentries, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ts.tv_sec = tmout->sec; | 
					
						
							|  |  |  | 	ts.tv_nsec = tmout->nsec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nentries = kevent(mux->kq, HIO_NULL, 0, mux->revs, HIO_COUNTOF(mux->revs), &ts); | 
					
						
							|  |  |  | 	if (nentries <= -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (errno == EINTR) return 0; /* it's actually ok */ | 
					
						
							|  |  |  | 		/* other errors are critical - EBADF, EFAULT, EINVAL */ | 
					
						
							|  |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < nentries; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int events = 0; | 
					
						
							|  |  |  | 		hio_dev_t* dev; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 		dev = mux->revs[i].udata; | 
					
						
							| 
									
										
										
										
											2021-07-25 17:52:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (HIO_LIKELY(dev)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			HIO_ASSERT (hio, mux->revs[i].ident == dev->dev_mth->getsyshnd(dev)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (mux->revs[i].flags & EV_ERROR) events |= HIO_DEV_EVENT_ERR; | 
					
						
							|  |  |  | 			if (mux->revs[i].flags & EV_EOF) events |= HIO_DEV_EVENT_HUP; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (mux->revs[i].filter == EVFILT_READ) events |= HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			else if (mux->revs[i].filter == EVFILT_WRITE) events |= HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (HIO_LIKELY(events)) event_handler (hio, dev, events, 0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (mux->ctrlp[0] != HIO_SYSHND_INVALID) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* internal pipe for signaling */ | 
					
						
							|  |  |  | 			hio_uint8_t tmp[16]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			HIO_ASSERT (hio, mux->revs[i].ident == mux->ctrlp[0]); | 
					
						
							|  |  |  | 			while (read(mux->ctrlp[0], tmp, HIO_SIZEOF(tmp)) > 0) ; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #elif defined(USE_EPOLL)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_sys_mux_t* mux = &hio->sysdep->mux; | 
					
						
							| 
									
										
										
										
											2019-01-27 16:22:55 +00:00
										 |  |  | 	int nentries, i; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	nentries = epoll_wait(mux->hnd, mux->revs, HIO_COUNTOF(mux->revs), HIO_SECNSEC_TO_MSEC(tmout->sec, tmout->nsec)); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	if (nentries == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (errno == EINTR) return 0; /* it's actually ok */ | 
					
						
							|  |  |  | 		/* other errors are critical - EBADF, EFAULT, EINVAL */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_seterrwithsyserr (hio, 0, errno); | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: merge events??? for the same descriptor */ | 
					
						
							| 
									
										
										
										
											2023-01-11 23:59:41 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	for (i = 0; i < nentries; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int events = 0, rdhup = 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_dev_t* dev; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		dev = mux->revs[i].data.ptr; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		if (HIO_LIKELY(dev)) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			if (mux->revs[i].events & EPOLLIN) events |= HIO_DEV_EVENT_IN; | 
					
						
							|  |  |  | 			if (mux->revs[i].events & EPOLLOUT) events |= HIO_DEV_EVENT_OUT; | 
					
						
							|  |  |  | 			if (mux->revs[i].events & EPOLLPRI) events |= HIO_DEV_EVENT_PRI; | 
					
						
							|  |  |  | 			if (mux->revs[i].events & EPOLLERR) events |= HIO_DEV_EVENT_ERR; | 
					
						
							|  |  |  | 			if (mux->revs[i].events & EPOLLHUP) events |= HIO_DEV_EVENT_HUP; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 		#if defined(EPOLLRDHUP)
 | 
					
						
							|  |  |  | 			else if (mux->revs[i].events & EPOLLRDHUP) rdhup = 1; | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			event_handler (hio, dev, events, rdhup); | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		else if (mux->ctrlp[0] != HIO_SYSHND_INVALID) | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* internal pipe for signaling */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			hio_uint8_t tmp[16]; | 
					
						
							|  |  |  | 			while (read(mux->ctrlp[0], tmp, HIO_SIZEOF(tmp)) > 0) ; | 
					
						
							| 
									
										
										
										
											2021-07-17 17:21:38 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #	error NO SUPPORTED MULTIPLEXER
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-01-28 08:13:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2019-01-27 02:09:22 +00:00
										 |  |  | } |