summaryrefslogtreecommitdiff
path: root/sysdep/unix/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/unix/io.c')
-rw-r--r--sysdep/unix/io.c96
1 files changed, 73 insertions, 23 deletions
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 5cc80dcd..3eb2e03c 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -30,12 +30,17 @@
#include "lib/unix.h"
#include "lib/sysio.h"
-/* Maximum number of calls of rx/tx handler for one socket in one
+/* Maximum number of calls of tx handler for one socket in one
* select iteration. Should be small enough to not monopolize CPU by
* one protocol instance.
*/
#define MAX_STEPS 4
+/* Maximum number of calls of rx handler for all sockets in one select
+ iteration. RX callbacks are often much more costly so we limit
+ this to gen small latencies */
+#define MAX_RX_STEPS 4
+
/*
* Tracked Files
*/
@@ -205,10 +210,6 @@ timer *
tm_new(pool *p)
{
timer *t = ralloc(p, &tm_class);
- t->hook = NULL;
- t->data = NULL;
- t->randomize = 0;
- t->expires = 0;
return t;
}
@@ -497,6 +498,7 @@ tm_format_reltime(char *x, bird_clock_t t)
static list sock_list;
static struct birdsock *current_sock;
+static struct birdsock *stored_sock;
static int sock_recalc_fdsets_p;
static inline sock *
@@ -545,6 +547,8 @@ sk_free(resource *r)
close(s->fd);
if (s == current_sock)
current_sock = sk_next(s);
+ if (s == stored_sock)
+ stored_sock = sk_next(s);
rem_node(&s->n);
sock_recalc_fdsets_p = 1;
}
@@ -595,22 +599,9 @@ sk_new(pool *p)
{
sock *s = ralloc(p, &sk_class);
s->pool = p;
- s->data = NULL;
- s->saddr = s->daddr = IPA_NONE;
- s->sport = s->dport = 0;
+ // s->saddr = s->daddr = IPA_NONE;
s->tos = s->ttl = -1;
- s->flags = 0;
- s->iface = NULL;
- s->rbuf = NULL;
- s->rx_hook = NULL;
- s->rbsize = 0;
- s->tbuf = NULL;
- s->tx_hook = NULL;
- s->tbsize = 0;
- s->err_hook = NULL;
s->fd = -1;
- s->rbuf_alloc = s->tbuf_alloc = NULL;
- s->password = NULL;
return s;
}
@@ -1169,6 +1160,29 @@ sk_maybe_write(sock *s)
}
}
+int
+sk_rx_ready(sock *s)
+{
+ fd_set rd, wr;
+ struct timeval timo;
+ int rv;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_SET(s->fd, &rd);
+
+ timo.tv_sec = 0;
+ timo.tv_usec = 0;
+
+ redo:
+ rv = select(s->fd+1, &rd, &wr, NULL, &timo);
+
+ if ((rv < 0) && (errno == EINTR || errno == EAGAIN))
+ goto redo;
+
+ return rv;
+}
+
/**
* sk_send - send data to a socket
* @s: socket
@@ -1337,6 +1351,9 @@ io_init(void)
srandom((int) now_real);
}
+static int short_loops = 0;
+#define SHORT_LOOP_MAX 10
+
void
io_loop(void)
{
@@ -1415,8 +1432,8 @@ io_loop(void)
}
/* And finally enter select() to find active sockets */
-
hi = select(hi+1, &rd, &wr, NULL, &timo);
+
if (hi < 0)
{
if (errno == EINTR || errno == EAGAIN)
@@ -1425,13 +1442,17 @@ io_loop(void)
}
if (hi)
{
- current_sock = SKIP_BACK(sock, n, HEAD(sock_list)); /* guaranteed to be non-empty */
+ /* guaranteed to be non-empty */
+ current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
+
while (current_sock)
{
sock *s = current_sock;
int e;
- int steps = MAX_STEPS;
- if (FD_ISSET(s->fd, &rd) && s->rx_hook)
+ int steps;
+
+ steps = MAX_STEPS;
+ if ((s->type >= SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook)
do
{
steps--;
@@ -1454,6 +1475,35 @@ io_loop(void)
current_sock = sk_next(s);
next: ;
}
+
+ short_loops++;
+ if (events && (short_loops < SHORT_LOOP_MAX))
+ continue;
+ short_loops = 0;
+
+ int count = 0;
+ current_sock = stored_sock;
+ if (current_sock == NULL)
+ current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
+
+ while (current_sock && count < MAX_RX_STEPS)
+ {
+ sock *s = current_sock;
+ int e;
+ int steps;
+
+ if ((s->type < SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook)
+ {
+ count++;
+ e = sk_read(s);
+ if (s != current_sock)
+ goto next2;
+ }
+ current_sock = sk_next(s);
+ next2: ;
+ }
+
+ stored_sock = current_sock;
}
}
}