diff options
Diffstat (limited to 'netio_posix.c')
-rw-r--r-- | netio_posix.c | 44 |
1 files changed, 19 insertions, 25 deletions
diff --git a/netio_posix.c b/netio_posix.c index 3cc00bb..46851f7 100644 --- a/netio_posix.c +++ b/netio_posix.c @@ -18,6 +18,7 @@ #include "netio.h" #include "coroutine.h" +#include "coroutine_sema.h" /* I found the following post to be very helpful when writing this: * http://davmac.org/davpage/linux/async-io.html */ @@ -29,16 +30,16 @@ static int sig_accept = 0; #endif struct netio_socket { - int fd; + int fd; #if CONFIG_NETIO_ISLINUX - cid_t accept_waiters[CONFIG_NETIO_NUM_CONNS]; + cr_sema_t accept_waiters; #endif }; static struct netio_socket socket_table[CONFIG_NETIO_NUM_PORTS] = {0}; static void handle_sig_io(int sig __attribute__ ((unused)), siginfo_t *info, void *ucontext __attribute__ ((unused))) { - cr_unpause((cid_t)info->si_value.sival_int); + cr_unpause_from_sighandler((cid_t)info->si_value.sival_int); } #if CONFIG_NETIO_ISLINUX @@ -49,12 +50,7 @@ static void handle_sig_accept(int sig __attribute__ ((unused)), siginfo_t *info, sock = &socket_table[i]; if (!sock) return; - for (int i = 0; i < CONFIG_NETIO_NUM_CONNS; i++) - if (sock->accept_waiters[i] > 0) { - cr_unpause(sock->accept_waiters[i]); - sock->accept_waiters[i] = 0; - return; - } + cr_sema_signal(&sock->accept_waiters); } #endif @@ -108,7 +104,7 @@ int netio_listen(uint16_t port) { memset(&addr, 0, sizeof addr); addr.in.sin_family = AF_INET; addr.in.sin_port = htons(port); - sock->fd = socket(AF_INET, SOCK_STREAM | (CONFIG_NETIO_ISLINUX ? 0 : SOCK_NONBLOCK), 0); + sock->fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); if (sock->fd < 0) error(1, errno, "socket"); if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) @@ -129,31 +125,29 @@ int netio_listen(uint16_t port) { } int netio_accept(int sock) { -#if CONFIG_NETIO_ISLINUX - int conn; - for (int i = 0; i < CONFIG_NETIO_NUM_CONNS; i++) - if (socket_table[sock].accept_waiters[i] == 0) { - socket_table[sock].accept_waiters[i] = cr_getcid(); - break; - } - cr_pause_and_yield(); - conn = accept(socket_table[sock].fd, NULL, NULL); - return conn < 0 ? -errno : conn; -#else /* AFAICT in pure POSIX there's no good way to do this that - * isn't just busy-polling. */ + * isn't just busy-polling. + * + * On Linux where we can get a signal to notify us when + * there's something to accept, we still do this non-blocking + * and check EAGAIN/EWOULDBLOCK in case the client timed out + * while waiting for us to accept(). */ for (;;) { +#if CONFIG_NETIO_ISLINUX + cr_sema_wait(&sock->accept_waiters); +#endif int conn = accept(socket_table[sock].fd, NULL, NULL); if (conn < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { +#if !CONFIG_NETIO_ISLINUX cr_yield(); +#endif continue; } return -errno; } return conn; } -#endif } ssize_t netio_read(int conn, void *buf, size_t count) { @@ -185,7 +179,7 @@ ssize_t netio_write(int conn, void *buf, size_t goal) { int r; struct aiocb ctl_block = { .aio_fildes = conn, - .aio_buf = &buf[done], + .aio_buf = &(((uint8_t *)buf)[done]), .aio_nbytes = goal-done, .aio_sigevent = { .sigev_notify = SIGEV_SIGNAL, @@ -201,7 +195,7 @@ ssize_t netio_write(int conn, void *buf, size_t goal) { while ((r = aio_error(&ctl_block)) == EINPROGRESS) cr_pause_and_yield(); - if ((r) < 0) + if (r < 0) return -abs(r); done += aio_return(&ctl_block); } |