From 37d072c26a58e8b4dbaf5bc399edd683bfd4e8eb Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 20 Nov 2023 13:43:52 +0900 Subject: [PATCH] have added the select support --- configure | 6 ++ configure.ac | 2 +- lib/hio-cfg.h.in | 3 + lib/http-svr.c | 2 +- lib/sys-mux.c | 212 ++++++++++++++++++++++++++++++++++++++++++++--- lib/sys-prv.h | 33 ++++++-- 6 files changed, 237 insertions(+), 21 deletions(-) diff --git a/configure b/configure index d2204b4..3098403 100755 --- a/configure +++ b/configure @@ -14949,6 +14949,12 @@ if test "x$ac_cv_header_sys_poll_h" = xyes then : printf "%s\n" "#define HAVE_SYS_POLL_H 1" >>confdefs.h +fi +ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_select_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h + fi ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "$ac_includes_default" diff --git a/configure.ac b/configure.ac index 15483ca..cff443f 100644 --- a/configure.ac +++ b/configure.ac @@ -114,7 +114,7 @@ AC_PROG_EGREP AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h]) AC_CHECK_HEADERS([time.h sys/time.h utime.h spawn.h execinfo.h ucontext.h]) AC_CHECK_HEADERS([sys/resource.h sys/wait.h sys/syscall.h sys/ioctl.h]) -AC_CHECK_HEADERS([sys/sendfile.h sys/epoll.h sys/event.h sys/poll.h]) +AC_CHECK_HEADERS([sys/sendfile.h sys/epoll.h sys/event.h sys/poll.h sys/select.h]) AC_CHECK_HEADERS([sys/sysctl.h sys/socket.h sys/sockio.h sys/un.h]) AC_CHECK_HEADERS([ifaddrs.h tiuser.h linux/netfilter_ipv4.h netinet/in.h netinet/sctp.h]) AC_CHECK_HEADERS([net/if.h net/if_dl.h netinet/if_ether.h netpacket/packet.h net/bpf.h], [], [], [ diff --git a/lib/hio-cfg.h.in b/lib/hio-cfg.h.in index 8d52e08..d77b05a 100644 --- a/lib/hio-cfg.h.in +++ b/lib/hio-cfg.h.in @@ -441,6 +441,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SENDFILE_H diff --git a/lib/http-svr.c b/lib/http-svr.c index 1982598..de6731f 100644 --- a/lib/http-svr.c +++ b/lib/http-svr.c @@ -439,7 +439,7 @@ static void client_on_disconnect (hio_dev_sck_t* sck) /* ------------------------------------------------------------------------ */ -#define MAX_CLIENT_IDLE 10 +#define MAX_CLIENT_IDLE 10 /*TODO: make this configurable... */ static void halt_idle_clients (hio_t* hio, const hio_ntime_t* now, hio_tmrjob_t* job) { diff --git a/lib/sys-mux.c b/lib/sys-mux.c index 7c75a89..2be7533 100644 --- a/lib/sys-mux.c +++ b/lib/sys-mux.c @@ -86,8 +86,9 @@ int hio_sys_initmux (hio_t* hio) mux->map.ptr[mux->ctrlp[0]] = idx; } #elif defined(USE_SELECT) - FD_ZERO (&mux->rfds); - FD_ZERO (&mux->wfds); + FD_ZERO (&mux->rset); + FD_ZERO (&mux->wset); + mux->maxhnd = -1; #elif defined(USE_KQUEUE) #if defined(HAVE_KQUEUE1) && defined(O_CLOEXEC) @@ -193,8 +194,21 @@ void hio_sys_finimux (hio_t* hio) mux->pd.capa = 0; #elif defined(USE_SELECT) + FD_ZERO (&mux->rset); + FD_ZERO (&mux->wset); - /* nothing to do */ + 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; + } #elif defined(USE_KQUEUE) if (mux->ctrlp[0] != HIO_SYSHND_INVALID) @@ -341,7 +355,6 @@ int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_ mux->pd.dptr[idx] = dev; mux->map.ptr[hnd] = idx; - return 0; case HIO_SYS_MUX_CMD_UPDATE: @@ -418,6 +431,166 @@ int hio_sys_ctrlmux (hio_t* hio, hio_sys_mux_cmd_t cmd, hio_dev_t* dev, int dev_ } #elif defined(USE_SELECT) + 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; + } #elif defined(USE_KQUEUE) @@ -640,20 +813,18 @@ int hio_sys_waitmux (hio_t* hio, const hio_ntime_t* tmout, hio_sys_mux_evtcb_t e } #elif defined(USE_SELECT) - -/* TODO: not complete */ hio_sys_mux_t* mux = &hio->sysdep->mux; struct timeval tv; - struct rfds, wfds; int n; tv.tv_sec = tmout->sec; - tv.tv_usec = tmout->nsec / HIO_NSEC_PER_USEC; + tv.tv_usec = tmout->nsec / HIO_NSECS_PER_USEC; - rfds = mux->rfds; - wfds = mux->wfds; + mux->tmprset = mux->rset; + mux->tmpwset = mux->wset; - n = select(mux->maxfd + 1, rfds, wfds, NULL, &tv); +/* TODO: call select with exceptset? */ + n = select(mux->maxhnd + 1, &mux->tmprset, &mux->tmpwset, NULL, &tv); if (n <= -1) { if (errno == EINTR) return 0; /* it's actually ok */ @@ -662,8 +833,25 @@ int hio_sys_waitmux (hio_t* hio, const hio_ntime_t* tmout, hio_sys_mux_evtcb_t e return -1; } - if (FD_ISSET(rfds, xxx)) + if (n > 0) { + 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); + } } diff --git a/lib/sys-prv.h b/lib/sys-prv.h index c212191..7bac031 100644 --- a/lib/sys-prv.h +++ b/lib/sys-prv.h @@ -33,12 +33,17 @@ # include # include # define USE_KQUEUE +/* #elif defined(HAVE_SYS_EPOLL_H) # include # define USE_EPOLL #elif defined(HAVE_SYS_POLL_H) # include -# define USE_POLL +# define USE_POLL*/ +#elif defined(HAVE_SYS_SELECT_H) +/*# define FD_SETSIZE 4096*/ +# include +# define USE_SELECT #else # error NO SUPPORTED MULTIPLEXER #endif @@ -70,21 +75,36 @@ struct hio_sys_mux_t }; #elif defined(USE_SELECT) + +struct hio_mux_slct_evt_t +{ + hio_dev_t* dev; + int mask; +}; +typedef struct hio_mux_slct_evt_t hio_mux_slct_evt_t; + struct hio_sys_mux_t { - fd_set rfds; - fd_set wfds; + fd_set rset; + fd_set wset; + fd_set tmprset; + fd_set tmpwset; + int size; + hio_syshnd_t maxhnd; + struct + { + hio_mux_slct_evt_t** ptr; + int ubound; + } me; + int ctrlp[2]; }; - #elif defined(USE_KQUEUE) struct hio_sys_mux_t { int kq; - struct kevent revs[1024]; /* TODO: is it a good size? */ - int ctrlp[2]; }; @@ -94,7 +114,6 @@ struct hio_sys_mux_t { int hnd; struct epoll_event revs[1024]; /* TODO: is it a good size? */ - int ctrlp[2]; };