diff --git a/include/proto/fd.h b/include/proto/fd.h index 72b2c6be8..287c8bd80 100644 --- a/include/proto/fd.h +++ b/include/proto/fd.h @@ -35,15 +35,13 @@ */ void fd_delete(int fd); -/* registers all known pollers */ -void register_pollers(); - /* disable the specified poller */ void disable_poller(const char *poller_name); /* * Initialize the pollers till the best one is found. * If none works, returns 0, otherwise 1. + * The pollers register themselves just before main() is called. */ int init_pollers(); diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 403e71c3c..b4844998a 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -220,7 +220,7 @@ REGPRM1 static void __fd_clo(int fd) /* * epoll() poller */ -REGPRM2 static void epoll_poll(struct poller *p, int wait_time) +REGPRM2 static void _do_poll(struct poller *p, int wait_time) { int status; int fd; @@ -257,7 +257,7 @@ REGPRM2 static void epoll_poll(struct poller *p, int wait_time) * Returns 0 in case of failure, non-zero in case of success. If it fails, it * disables the poller by setting its pref to 0. */ -REGPRM1 static int epoll_init(struct poller *p) +REGPRM1 static int _do_init(struct poller *p) { __label__ fail_chg_ptr, fail_chg_list, fail_fdevt, fail_ee, fail_fd; int fd_set_bytes; @@ -306,7 +306,7 @@ REGPRM1 static int epoll_init(struct poller *p) * Termination of the epoll() poller. * Memory is released and the poller is marked as unselectable. */ -REGPRM1 static void epoll_term(struct poller *p) +REGPRM1 static void _do_term(struct poller *p) { fd_flush_changes(); @@ -335,7 +335,7 @@ REGPRM1 static void epoll_term(struct poller *p) * Check that the poller works. * Returns 1 if OK, otherwise 0. */ -REGPRM1 static int epoll_test(struct poller *p) +REGPRM1 static int _do_test(struct poller *p) { int fd; @@ -347,26 +347,33 @@ REGPRM1 static int epoll_test(struct poller *p) } /* - * The only exported function. Returns 1. + * It is a constructor, which means that it will automatically be called before + * main(). This is GCC-specific but it works at least since 2.95. + * Special care must be taken so that it does not need any uninitialized data. */ -int epoll_register(struct poller *p) +__attribute__((constructor)) +static void _do_register(void) { + struct poller *p; + + if (nbpollers >= MAX_POLLERS) + return; + p = &pollers[nbpollers++]; + p->name = "epoll"; p->pref = 300; p->private = NULL; - p->test = epoll_test; - p->init = epoll_init; - p->term = epoll_term; - p->poll = epoll_poll; + p->test = _do_test; + p->init = _do_init; + p->term = _do_term; + p->poll = _do_poll; p->is_set = __fd_is_set; p->cond_s = p->set = __fd_set; p->cond_c = p->clr = __fd_clr; p->rem = __fd_rem; p->clo = __fd_clo; - - return 1; } diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index dd990e470..55419f6f0 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -98,7 +98,7 @@ REGPRM1 static void __fd_clo(int fd) /* * kqueue() poller */ -REGPRM2 static void kqueue_poll(struct poller *p, int wait_time) +REGPRM2 static void _do_poll(struct poller *p, int wait_time) { int status; int count, fd; @@ -142,7 +142,7 @@ REGPRM2 static void kqueue_poll(struct poller *p, int wait_time) * Returns 0 in case of failure, non-zero in case of success. If it fails, it * disables the poller by setting its pref to 0. */ -REGPRM1 static int kqueue_init(struct poller *p) +REGPRM1 static int _do_init(struct poller *p) { __label__ fail_wevt, fail_revt, fail_fd; int fd_set_bytes; @@ -183,7 +183,7 @@ REGPRM1 static int kqueue_init(struct poller *p) * Termination of the kqueue() poller. * Memory is released and the poller is marked as unselectable. */ -REGPRM1 static void kqueue_term(struct poller *p) +REGPRM1 static void _do_term(struct poller *p) { if (fd_evts[DIR_WR]) free(fd_evts[DIR_WR]); @@ -202,7 +202,7 @@ REGPRM1 static void kqueue_term(struct poller *p) * Check that the poller works. * Returns 1 if OK, otherwise 0. */ -REGPRM1 static int kqueue_test(struct poller *p) +REGPRM1 static int _do_test(struct poller *p) { int fd; @@ -218,7 +218,7 @@ REGPRM1 static int kqueue_test(struct poller *p) * otherwise 0. Note that some pollers need to be reopened after a fork() * (such as kqueue), and some others may fail to do so in a chroot. */ -REGPRM1 static int kqueue_fork(struct poller *p) +REGPRM1 static int _do_fork(struct poller *p) { close(kqueue_fd); kqueue_fd = kqueue(); @@ -228,27 +228,34 @@ REGPRM1 static int kqueue_fork(struct poller *p) } /* - * The only exported function. Returns 1. + * It is a constructor, which means that it will automatically be called before + * main(). This is GCC-specific but it works at least since 2.95. + * Special care must be taken so that it does not need any uninitialized data. */ -int kqueue_register(struct poller *p) +__attribute__((constructor)) +static void _do_register(void) { + struct poller *p; + + if (nbpollers >= MAX_POLLERS) + return; + p = &pollers[nbpollers++]; + p->name = "kqueue"; p->pref = 300; p->private = NULL; - p->test = kqueue_test; - p->init = kqueue_init; - p->term = kqueue_term; - p->poll = kqueue_poll; - p->fork = kqueue_fork; + p->test = _do_test; + p->init = _do_init; + p->term = _do_term; + p->poll = _do_poll; + p->fork = _do_fork; p->is_set = __fd_is_set; p->cond_s = p->set = __fd_set; p->cond_c = p->clr = __fd_clr; p->rem = __fd_rem; p->clo = __fd_clo; - - return 1; } diff --git a/src/ev_poll.c b/src/ev_poll.c index 1dbf22889..c48f50215 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -81,7 +81,7 @@ REGPRM1 static void __fd_rem(const int fd) /* * Poll() poller */ -REGPRM2 static void poll_poll(struct poller *p, int wait_time) +REGPRM2 static void _do_poll(struct poller *p, int wait_time) { int status; int fd, nbfd; @@ -157,7 +157,7 @@ REGPRM2 static void poll_poll(struct poller *p, int wait_time) * Returns 0 in case of failure, non-zero in case of success. If it fails, it * disables the poller by setting its pref to 0. */ -REGPRM1 static int poll_init(struct poller *p) +REGPRM1 static int _do_init(struct poller *p) { __label__ fail_swevt, fail_srevt, fail_pe; int fd_set_bytes; @@ -192,7 +192,7 @@ REGPRM1 static int poll_init(struct poller *p) * Termination of the poll() poller. * Memory is released and the poller is marked as unselectable. */ -REGPRM1 static void poll_term(struct poller *p) +REGPRM1 static void _do_term(struct poller *p) { if (fd_evts[DIR_WR]) free(fd_evts[DIR_WR]); @@ -208,31 +208,39 @@ REGPRM1 static void poll_term(struct poller *p) * Check that the poller works. * Returns 1 if OK, otherwise 0. */ -REGPRM1 static int poll_test(struct poller *p) +REGPRM1 static int _do_test(struct poller *p) { return 1; } /* - * The only exported function. Returns 1. + * It is a constructor, which means that it will automatically be called before + * main(). This is GCC-specific but it works at least since 2.95. + * Special care must be taken so that it does not need any uninitialized data. */ -int poll_register(struct poller *p) +__attribute__((constructor)) +static void _do_register(void) { + struct poller *p; + + if (nbpollers >= MAX_POLLERS) + return; + p = &pollers[nbpollers++]; + p->name = "poll"; p->pref = 200; p->private = NULL; - p->test = poll_test; - p->init = poll_init; - p->term = poll_term; - p->poll = poll_poll; + p->test = _do_test; + p->init = _do_init; + p->term = _do_term; + p->poll = _do_poll; p->is_set = __fd_is_set; p->set = __fd_set; p->clr = __fd_clr; p->clo = p->rem = __fd_rem; p->cond_s = __fd_cond_s; p->cond_c = __fd_cond_c; - return 1; } diff --git a/src/ev_select.c b/src/ev_select.c index 6c1a13294..ed79abf01 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -78,7 +78,7 @@ REGPRM1 static void __fd_rem(int fd) /* * Select() poller */ -REGPRM2 static void select_poll(struct poller *p, int wait_time) +REGPRM2 static void _do_poll(struct poller *p, int wait_time) { int status; int fd, i; @@ -153,7 +153,7 @@ REGPRM2 static void select_poll(struct poller *p, int wait_time) * Returns 0 in case of failure, non-zero in case of success. If it fails, it * disables the poller by setting its pref to 0. */ -REGPRM1 static int select_init(struct poller *p) +REGPRM1 static int _do_init(struct poller *p) { __label__ fail_swevt, fail_srevt, fail_wevt, fail_revt; int fd_set_bytes; @@ -190,7 +190,7 @@ REGPRM1 static int select_init(struct poller *p) * Termination of the select() poller. * Memory is released and the poller is marked as unselectable. */ -REGPRM1 static void select_term(struct poller *p) +REGPRM1 static void _do_term(struct poller *p) { if (fd_evts[DIR_WR]) free(fd_evts[DIR_WR]); @@ -208,31 +208,39 @@ REGPRM1 static void select_term(struct poller *p) * Check that the poller works. * Returns 1 if OK, otherwise 0. */ -REGPRM1 static int select_test(struct poller *p) +REGPRM1 static int _do_test(struct poller *p) { return 1; } /* - * The only exported function. Returns 1. + * It is a constructor, which means that it will automatically be called before + * main(). This is GCC-specific but it works at least since 2.95. + * Special care must be taken so that it does not need any uninitialized data. */ -int select_register(struct poller *p) +__attribute__((constructor)) +static void _do_register(void) { + struct poller *p; + + if (nbpollers >= MAX_POLLERS) + return; + p = &pollers[nbpollers++]; + p->name = "select"; p->pref = 150; p->private = NULL; - p->test = select_test; - p->init = select_init; - p->term = select_term; - p->poll = select_poll; + p->test = _do_test; + p->init = _do_init; + p->term = _do_term; + p->poll = _do_poll; p->is_set = __fd_is_set; p->set = __fd_set; p->clr = __fd_clr; p->clo = p->rem = __fd_rem; p->cond_s = __fd_cond_s; p->cond_c = __fd_cond_c; - return 1; } diff --git a/src/fd.c b/src/fd.c index 5ddfebdd0..9c370faf9 100644 --- a/src/fd.c +++ b/src/fd.c @@ -35,22 +35,6 @@ struct poller cur_poller; int nbpollers = 0; -/********************* - * generic functions - *********************/ - -extern int select_register(struct poller *p); -#if defined(ENABLE_POLL) -extern int poll_register(struct poller *p); -#endif -#if defined(ENABLE_EPOLL) -extern int epoll_register(struct poller *p); -#endif -#if defined(ENABLE_KQUEUE) -extern int kqueue_register(struct poller *p); -#endif - - /* Deletes an FD from the fdsets, and recomputes the maxfd limit. * The file descriptor is also closed. */ @@ -65,27 +49,6 @@ void fd_delete(int fd) } -/* registers all known pollers */ -void register_pollers() -{ - if (select_register(&pollers[nbpollers])) - nbpollers++; -#if defined(ENABLE_POLL) - poll_register(&pollers[nbpollers]); - nbpollers++; -#endif - -#if defined(ENABLE_EPOLL) - epoll_register(&pollers[nbpollers]); - nbpollers++; -#endif - -#if defined(ENABLE_KQUEUE) - kqueue_register(&pollers[nbpollers]); - nbpollers++; -#endif -} - /* disable the specified poller */ void disable_poller(const char *poller_name) { diff --git a/src/haproxy.c b/src/haproxy.c index 785bd740f..f1e5cc3b7 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -523,8 +523,10 @@ void init(int argc, char **argv) fdtab[i].state = FD_STCLOSE; } - register_pollers(); - /* Note: we could register external pollers here */ + /* + * Note: we could register external pollers here. + * Built-in pollers have been registered before main(). + */ if (!(cfg_polling_mechanism & POLL_USE_KQUEUE)) disable_poller("kqueue");