enhanced the IO multiplexer code to utilize kqueue()/kevent() if available
This commit is contained in:
parent
5294db4d20
commit
9327c06745
@ -353,7 +353,7 @@ int hio_setoption (hio_t* hio, hio_option_t id, const void* value)
|
|||||||
{
|
{
|
||||||
hio_uch_t* v1;
|
hio_uch_t* v1;
|
||||||
hio_bch_t* v2;
|
hio_bch_t* v2;
|
||||||
hio_ucs_t* v = (hio_bcs_t*)value;
|
hio_ucs_t* v = (hio_ucs_t*)value;
|
||||||
|
|
||||||
v1 = hio_dupuchars(hio, v->ptr, v->len);
|
v1 = hio_dupuchars(hio, v->ptr, v->len);
|
||||||
if (HIO_UNLIKELY(!v1)) return -1;
|
if (HIO_UNLIKELY(!v1)) return -1;
|
||||||
@ -1243,7 +1243,7 @@ int hio_dev_watch (hio_dev_t* dev, hio_dev_watch_cmd_t cmd, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*ev.data.ptr = dev;*/
|
/*ev.data.ptr = dev;*/
|
||||||
dev_cap = dev->dev_cap & ~(DEV_CAP_ALL_WATCHED | HIO_DEV_CAP_WATCH_SUSPENDED); /* UGLY to use HIO_DEV_CAP_WATCH_SUSPENDED here */
|
dev_cap = dev->dev_cap & ~(DEV_CAP_ALL_WATCHED | HIO_DEV_CAP_WATCH_SUSPENDED | HIO_DEV_CAP_WATCH_REREG_REQUIRED); /* UGLY to use HIO_DEV_CAP_WATCH_SUSPENDED and HIO_DEV_CAP_WATCH_REREG_REQUIRED here */
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
@ -1314,7 +1314,7 @@ int hio_dev_watch (hio_dev_t* dev, hio_dev_watch_cmd_t cmd, int events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* UGLY. HIO_DEV_CAP_WATCH_SUSPENDED may be set/unset by hio_sys_ctrlmux. I need this to reflect it */
|
/* UGLY. HIO_DEV_CAP_WATCH_SUSPENDED may be set/unset by hio_sys_ctrlmux. I need this to reflect it */
|
||||||
dev->dev_cap = dev_cap | (dev->dev_cap & HIO_DEV_CAP_WATCH_SUSPENDED);
|
dev->dev_cap = dev_cap | (dev->dev_cap & (HIO_DEV_CAP_WATCH_SUSPENDED | HIO_DEV_CAP_WATCH_REREG_REQUIRED));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +431,8 @@ enum hio_dev_cap_t
|
|||||||
HIO_DEV_CAP_ZOMBIE = (1 << 17),
|
HIO_DEV_CAP_ZOMBIE = (1 << 17),
|
||||||
HIO_DEV_CAP_RENEW_REQUIRED = (1 << 18),
|
HIO_DEV_CAP_RENEW_REQUIRED = (1 << 18),
|
||||||
HIO_DEV_CAP_WATCH_STARTED = (1 << 19),
|
HIO_DEV_CAP_WATCH_STARTED = (1 << 19),
|
||||||
HIO_DEV_CAP_WATCH_SUSPENDED = (1 << 20)
|
HIO_DEV_CAP_WATCH_SUSPENDED = (1 << 20),
|
||||||
|
HIO_DEV_CAP_WATCH_REREG_REQUIRED = (1 << 21),
|
||||||
};
|
};
|
||||||
typedef enum hio_dev_cap_t hio_dev_cap_t;
|
typedef enum hio_dev_cap_t hio_dev_cap_t;
|
||||||
|
|
||||||
|
@ -1366,6 +1366,22 @@ fcntl (rdev->hnd, F_SETFL, flags | O_NONBLOCK);
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rdev->dev_cap & HIO_DEV_CAP_WATCH_REREG_REQUIRED)
|
||||||
|
{
|
||||||
|
/* On NetBSD, the listening socket added before listen()
|
||||||
|
* doesn't generate an event even if a new connection is ready
|
||||||
|
* to be accepted. */
|
||||||
|
|
||||||
|
/* TODO: need to keep the old watch flags before STOP and
|
||||||
|
* use the flags witn START */
|
||||||
|
if (hio_dev_watch(rdev, HIO_DEV_WATCH_STOP, 0) <= -1 ||
|
||||||
|
hio_dev_watch(rdev, HIO_DEV_WATCH_START, 0) <= -1)
|
||||||
|
{
|
||||||
|
hio_stop (hio, HIO_STOPREQ_WATCHER_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rdev->tmout = lstn->accept_tmout;
|
rdev->tmout = lstn->accept_tmout;
|
||||||
|
|
||||||
HIO_DEV_SCK_SET_PROGRESS (rdev, HIO_DEV_SCK_LISTENING);
|
HIO_DEV_SCK_SET_PROGRESS (rdev, HIO_DEV_SCK_LISTENING);
|
||||||
@ -1652,7 +1668,21 @@ static int accept_incoming_connection (hio_dev_sck_t* rdev)
|
|||||||
|
|
||||||
/* this is a server(lisening) socket */
|
/* this is a server(lisening) socket */
|
||||||
|
|
||||||
#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
|
#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_PACCEPT)
|
||||||
|
flags = SOCK_NONBLOCK | SOCK_CLOEXEC;
|
||||||
|
|
||||||
|
addrlen = HIO_SIZEOF(remoteaddr);
|
||||||
|
clisck = paccept(rdev->hnd, (struct sockaddr*)&remoteaddr, &addrlen, HIO_NULL, flags);
|
||||||
|
if (clisck <= -1)
|
||||||
|
{
|
||||||
|
if (errno != ENOSYS) goto accept_error;
|
||||||
|
/* go on for the normal 3-parameter accept */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto accept_done;
|
||||||
|
}
|
||||||
|
#elif defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
|
||||||
flags = SOCK_NONBLOCK | SOCK_CLOEXEC;
|
flags = SOCK_NONBLOCK | SOCK_CLOEXEC;
|
||||||
|
|
||||||
addrlen = HIO_SIZEOF(remoteaddr);
|
addrlen = HIO_SIZEOF(remoteaddr);
|
||||||
@ -2002,7 +2032,7 @@ static int dev_evcb_sck_on_read_qx (hio_dev_t* dev, const void* data, hio_iolen_
|
|||||||
{
|
{
|
||||||
if (make_accepted_client_connection(rdev, qxmsg->syshnd, &qxmsg->remoteaddr, qxmsg->scktype) <= -1)
|
if (make_accepted_client_connection(rdev, qxmsg->syshnd, &qxmsg->remoteaddr, qxmsg->scktype) <= -1)
|
||||||
{
|
{
|
||||||
printf ("unable to accept new client connection %d\n", qxmsg->syshnd);
|
/*printf ("unable to accept new client connection %d\n", qxmsg->syshnd);*/
|
||||||
return (rdev->state & HIO_DEV_SCK_LENIENT)? 0: -1;
|
return (rdev->state & HIO_DEV_SCK_LENIENT)? 0: -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,13 @@ int hio_sys_initmux (hio_t* hio)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(USE_EPOLL)
|
#elif defined(USE_EPOLL)
|
||||||
|
|
||||||
#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
|
#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
|
||||||
@ -186,7 +193,9 @@ void hio_sys_finimux (hio_t* hio)
|
|||||||
#elif defined(USE_KQUEUE)
|
#elif defined(USE_KQUEUE)
|
||||||
if (mux->ctrlp[0] != HIO_SYSHND_INVALID)
|
if (mux->ctrlp[0] != HIO_SYSHND_INVALID)
|
||||||
{
|
{
|
||||||
/* TODO: */
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
close (mux->kq);
|
close (mux->kq);
|
||||||
@ -291,7 +300,6 @@ int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_
|
|||||||
|
|
||||||
hnd = dev->dev_mth->getsyshnd(dev);
|
hnd = dev->dev_mth->getsyshnd(dev);
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (cmd == HIO_SYS_MUX_CMD_INSERT)
|
if (cmd == HIO_SYS_MUX_CMD_INSERT)
|
||||||
{
|
{
|
||||||
if (secure_poll_map_slot_for_hnd(hio, hnd) <= -1) return -1;
|
if (secure_poll_map_slot_for_hnd(hio, hnd) <= -1) return -1;
|
||||||
@ -304,30 +312,6 @@ int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (hnd >= mux->map.capa)
|
|
||||||
{
|
|
||||||
hio_oow_t new_capa;
|
|
||||||
hio_oow_t* tmp;
|
|
||||||
|
|
||||||
if (cmd != HIO_SYS_MUX_CMD_INSERT)
|
|
||||||
{
|
|
||||||
hio_seterrnum (hio, HIO_ENOENT);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_capa = HIO_ALIGN_POW2((hnd + 1), 256);
|
|
||||||
|
|
||||||
tmp = hio_reallocmem(hio, mux->map.ptr, new_capa * HIO_SIZEOF(*tmp));
|
|
||||||
if (HIO_UNLIKELY(!tmp)) return -1;
|
|
||||||
|
|
||||||
for (idx = mux->map.capa; idx < new_capa; idx++) tmp[idx] = MUX_INDEX_INVALID;
|
|
||||||
|
|
||||||
mux->map.ptr = tmp;
|
|
||||||
mux->map.capa = new_capa;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
idx = mux->map.ptr[hnd];
|
idx = mux->map.ptr[hnd];
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
@ -340,34 +324,7 @@ int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_
|
|||||||
}
|
}
|
||||||
|
|
||||||
do_insert:
|
do_insert:
|
||||||
#if 1
|
|
||||||
if (HIO_UNLIKELY(secure_poll_data_slot_for_insert(hio) <= -1)) return -1;
|
if (HIO_UNLIKELY(secure_poll_data_slot_for_insert(hio) <= -1)) return -1;
|
||||||
#else
|
|
||||||
|
|
||||||
if (mux->pd.size >= mux->pd.capa)
|
|
||||||
{
|
|
||||||
hio_oow_t new_capa;
|
|
||||||
struct pollfd* tmp1;
|
|
||||||
hio_dev_t** tmp2;
|
|
||||||
|
|
||||||
new_capa = HIO_ALIGN_POW2(mux->pd.size + 1, 256);
|
|
||||||
|
|
||||||
tmp1 = hio_reallocmem(hio, mux->pd.pfd, new_capa * HIO_SIZEOF(*tmp1));
|
|
||||||
if (HIO_UNLIKELY(!tmp1)) return -1;
|
|
||||||
|
|
||||||
tmp2 = hio_reallocmem(hio, mux->pd.dptr, new_capa * HIO_SIZEOF(*tmp2));
|
|
||||||
if (HIO_UNLIKELY(!tmp2))
|
|
||||||
{
|
|
||||||
hio_freemem (hio, tmp1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mux->pd.pfd = tmp1;
|
|
||||||
mux->pd.dptr = tmp2;
|
|
||||||
mux->pd.capa = new_capa;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
idx = mux->pd.size++;
|
idx = mux->pd.size++;
|
||||||
|
|
||||||
mux->pd.pfd[idx].fd = hnd;
|
mux->pd.pfd[idx].fd = hnd;
|
||||||
@ -453,6 +410,83 @@ int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_
|
|||||||
hio_seterrnum (hio, HIO_EINVAL);
|
hio_seterrnum (hio, HIO_EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
|
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;
|
||||||
|
|
||||||
|
EV_SET (&chlist[1], hnd, EVFILT_READ, EV_ADD | i_flag, 0, 0, dev);
|
||||||
|
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);
|
||||||
|
if (x >= 0) dev->dev_cap |= HIO_DEV_CAP_WATCH_REREG_REQUIRED; /* ugly hack for the listening sockets in NetBSD */
|
||||||
|
|
||||||
|
/* the CMD_INSERT comes with at MIO_DEV_CAP_IN_WATCHD set.
|
||||||
|
* skip checking to set WATCH_SUSPENDED */
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
EV_SET (&chlist[0], hnd, EVFILT_READ, EV_ADD | i_flag, 0, 0, dev);
|
||||||
|
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);
|
||||||
|
if (x >= 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
#elif defined(USE_EPOLL)
|
#elif defined(USE_EPOLL)
|
||||||
hio_sys_mux_t* mux = &hio->sysdep->mux;
|
hio_sys_mux_t* mux = &hio->sysdep->mux;
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
@ -586,6 +620,52 @@ int hio_sys_waitmux (hio_t* hio, const hio_ntime_t* tmout, hio_sys_mux_evtcb_t e
|
|||||||
event_handler (hio, dev, events, 0);
|
event_handler (hio, dev, events, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#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;
|
||||||
|
|
||||||
|
dev = mux->revs[i].udata;
|
||||||
|
|
||||||
|
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) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(USE_EPOLL)
|
#elif defined(USE_EPOLL)
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ struct hio_sys_mux_t
|
|||||||
|
|
||||||
#elif defined(USE_KQUEUE)
|
#elif defined(USE_KQUEUE)
|
||||||
|
|
||||||
struct hio_sys_mutx_t
|
struct hio_sys_mux_t
|
||||||
{
|
{
|
||||||
int kq;
|
int kq;
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ struct hio_sys_mutx_t
|
|||||||
|
|
||||||
int ctrlp[2];
|
int ctrlp[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(USE_EPOLL)
|
#elif defined(USE_EPOLL)
|
||||||
|
|
||||||
struct hio_sys_mux_t
|
struct hio_sys_mux_t
|
||||||
|
Loading…
Reference in New Issue
Block a user