summaryrefslogtreecommitdiff
path: root/netio_posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'netio_posix.c')
-rw-r--r--netio_posix.c44
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);
}