Skip to content

Instantly share code, notes, and snippets.

@saillinux
Created May 22, 2013 23:31
Show Gist options
  • Save saillinux/5631771 to your computer and use it in GitHub Desktop.
Save saillinux/5631771 to your computer and use it in GitHub Desktop.
BIRD patch for select() -> poll()
--- bird-1.3.9/sysdep/unix/io.c 2013-01-11 05:53:16.000000000 -0800
+++ /home/hkim/bird-1.3.9/sysdep/unix/io.c 2013-05-20 02:34:36.780698000 -0700
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
+#include <sys/poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -48,6 +49,10 @@
this to gen small latencies */
#define MAX_RX_STEPS 4
+/* Lets start simple with 8k fds for polling instead of dynamically
+ * allocate pollfds by the number of bird sockets */
+#define MAX_POLLPDFS 1024 * 8
+
/*
* Tracked Files
*/
@@ -1330,7 +1335,7 @@ sk_rx_ready(sock *s)
redo:
rv = select(s->fd+1, &rd, &wr, NULL, &timo);
-
+ debug("DEBUG: SK_RX_READY, SELECTOR FULL [%d]\n", rv);
if ((rv < 0) && (errno == EINTR || errno == EAGAIN))
goto redo;
@@ -1540,16 +1545,19 @@ static int short_loops = 0;
void
io_loop(void)
{
- fd_set rd, wr;
struct timeval timo;
time_t tout;
int hi, events;
sock *s;
node *n;
+ /* lets start simple using array for poll fds and use dynamic
+ * allocation by the number of available bird sockets later */
+ int nfds;
+ struct pollfd pollfds[MAX_POLLPDFS];
+
sock_recalc_fdsets_p = 1;
- for(;;)
- {
+ for(;;) {
events = ev_run_list(&global_event_list);
update_times();
tout = tm_first_shot();
@@ -1558,36 +1566,35 @@ io_loop(void)
tm_shot();
continue;
}
+
+ // TODO: poll uses milliseconds instead seconds
timo.tv_sec = events ? 0 : MIN(tout - now, 3);
timo.tv_usec = 0;
- if (sock_recalc_fdsets_p)
- {
+ // TODO: figure out whether we need to reset every file
+ // descriptors.
+ if (sock_recalc_fdsets_p) {
sock_recalc_fdsets_p = 0;
- FD_ZERO(&rd);
- FD_ZERO(&wr);
}
hi = 0;
- WALK_LIST(n, sock_list)
- {
+ nfds = 0;
+ WALK_LIST(n, sock_list) {
s = SKIP_BACK(sock, n, n);
- if (s->rx_hook)
- {
- FD_SET(s->fd, &rd);
- if (s->fd > hi)
- hi = s->fd;
+
+ if (s->rx_hook) {
+ pollfds[nfds].fd = s->fd;
+ pollfds[nfds].events = POLLIN;
}
- else
- FD_CLR(s->fd, &rd);
- if (s->tx_hook && s->ttx != s->tpos)
- {
- FD_SET(s->fd, &wr);
- if (s->fd > hi)
- hi = s->fd;
+
+ if (s->tx_hook && s->ttx != s->tpos) {
+ pollfds[nfds].fd = s->fd;
+ pollfds[nfds].events = POLLOUT;
}
- else
- FD_CLR(s->fd, &wr);
+
+ /* TODO: this is too naive approach, there might be a bird
+ * socket with no rx/tx hook. */
+ nfds++;
}
/*
@@ -1614,47 +1621,71 @@ io_loop(void)
continue;
}
- /* And finally enter select() to find active sockets */
- hi = select(hi+1, &rd, &wr, NULL, &timo);
+ // TODO: decide appropriate timeout value
+ hi = poll(pollfds, nfds + 1, 1000);
+ debug("DEBUG: # of poll events occured [%d] out of [%d] sockets\n", hi, nfds);
if (hi < 0)
- {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- die("select: %m");
- }
- if (hi)
- {
+ debug("DEBUG: POLL ERROR\n");
+
+ if (hi) {
/* guaranteed to be non-empty */
current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
- while (current_sock)
- {
+ while (current_sock) {
sock *s = current_sock;
- int e;
+ int i, e;
int steps;
+ // TODO: lets come up with better data structure so that we can avoid
+ // lookup fd for corresponding bird socket from the entire poll fds.
+ for (i = 0; i <= nfds; i++) {
+ if (s->fd == pollfds[i].fd) {
+ debug("DEBUG: unix socket type [%d] poll type [%d]\n", s->type,
+ pollfds[i].revents);
steps = MAX_STEPS;
- if ((s->type >= SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook)
- do
- {
+
+ if ((s->type >= SK_MAGIC) &&
+ pollfds[i].revents & POLLIN &&
+ s->rx_hook) {
+ debug("DEBUG: POLLIN event from fd [%d]\n", pollfds[i].fd);
+
+ do {
steps--;
e = sk_read(s);
- if (s != current_sock)
+ if (s != current_sock) {
+ // TODO: still don't get why we have this. But I've seen this debug output eventually.
+ debug("DEBUG: wtf POLLIN\n");
goto next;
}
- while (e && s->rx_hook && steps);
+ } while (e && s->rx_hook && steps);
+ }
steps = MAX_STEPS;
- if (FD_ISSET(s->fd, &wr))
- do
- {
+
+ if (pollfds[i].revents & POLLOUT) {
+ debug("DEBUG: POLLOUT event from fd [%d]\n", pollfds[i].fd);
+
+ do {
steps--;
e = sk_write(s);
- if (s != current_sock)
+ if (s != current_sock) {
+ // TODO: still don't get why we have this. But I've seen this debug output eventually.
+ debug("DEBUG: wtf POLLOUT\n");
goto next;
}
- while (e && steps);
+ } while (e && steps);
+ }
+
+ } else if (pollfds[i].revents & POLLNVAL) {
+ // once we allocate pollfds in dynamic manner we will free resource differently.
+ debug("DEBUG: POLLNVAL on socket [%d]. Freeing resource\n", pollfds[i].fd);
+ pollfds[i].fd = NULL;
+ pollfds[i].events = 0;
+ pollfds[i].revents = 0;
+ }
+ }
+
current_sock = sk_next(s);
next: ;
}
@@ -1669,18 +1700,27 @@ io_loop(void)
if (current_sock == NULL)
current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
- while (current_sock && count < MAX_RX_STEPS)
- {
+ while (current_sock && count < MAX_RX_STEPS) {
sock *s = current_sock;
- int e;
+ int i, e;
- if ((s->type < SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook)
- {
+ /* TODO: short loop */
+ for (i = 0; i <= nfds; i++) {
+ if (s->fd == pollfds[i].fd) {
+ debug("DEBUG: tcp/udp socket type [%d] poll event [%d]\n", s->type,
+ pollfds[i].revents);
+ if ((s->type < SK_MAGIC) &&
+ pollfds[i].revents & POLLIN &&
+ s->rx_hook) {
+ sk_dump_all();
+ debug("DEBUG: tcp/udp POLLIN event from fd [%d]\n", pollfds[i].fd);
count++;
e = sk_read(s);
if (s != current_sock)
goto next2;
}
+ }
+ }
current_sock = sk_next(s);
next2: ;
}
@saillinux
Copy link
Author

http://bird.network.cz/

patching io_loop located in sysdep/unix/io.c for bird-1.3.10.tar.gz

@saillinux
Copy link
Author

아고 bird-1.3.9.tar.gz이었음 죄송

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment