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-19 17:30:38 +00: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 14:59:41 +00: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-19 17:30:38 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2023-11-20 04:43:52 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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-19 17:30:38 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2023-11-20 04:43:52 +00:00
|
|
|
FD_ZERO (&mux->rset);
|
|
|
|
FD_ZERO (&mux->wset);
|
2023-11-19 17:30:38 +00:00
|
|
|
|
2023-11-20 04:43:52 +00: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-19 17:30:38 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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-19 17:30:38 +00:00
|
|
|
#elif defined(USE_SELECT)
|
2023-11-20 04:43:52 +00: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-19 17:30:38 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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 14:59:41 +00: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-19 17:30:38 +00: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 04:43:52 +00:00
|
|
|
tv.tv_usec = tmout->nsec / HIO_NSECS_PER_USEC;
|
2023-11-19 17:30:38 +00:00
|
|
|
|
2023-11-20 04:43:52 +00:00
|
|
|
mux->tmprset = mux->rset;
|
|
|
|
mux->tmpwset = mux->wset;
|
2023-11-19 17:30:38 +00:00
|
|
|
|
2023-11-20 04:43:52 +00:00
|
|
|
/* TODO: call select with exceptset? */
|
|
|
|
n = select(mux->maxhnd + 1, &mux->tmprset, &mux->tmpwset, NULL, &tv);
|
2023-11-19 17:30:38 +00: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 04:43:52 +00:00
|
|
|
if (n > 0)
|
2023-11-19 17:30:38 +00:00
|
|
|
{
|
2023-11-20 04:43:52 +00: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-19 17:30:38 +00: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 14:59:41 +00: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 14:59:41 +00: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
|
|
|
}
|