Created
May 22, 2013 23:31
-
-
Save saillinux/5631771 to your computer and use it in GitHub Desktop.
BIRD patch for select() -> poll()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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: ; | |
} |
아고 bird-1.3.9.tar.gz이었음 죄송
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://bird.network.cz/
patching io_loop located in sysdep/unix/io.c for bird-1.3.10.tar.gz