[MAJOR] auto-registering of pollers at load time
Gcc provides __attribute__((constructor)) which is very convenient
to execute functions at startup right before main(). All the pollers
have been converted to have their register() function declared like
this, so that it is not necessary anymore to call them from a centralized
file.
diff --git a/include/proto/fd.h b/include/proto/fd.h
index 72b2c6b..287c8bd 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 403e71c..b484499 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -220,7 +220,7 @@
/*
* 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 @@
* 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 @@
* 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 @@
* 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 @@
}
/*
- * 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 dd990e4..55419f6 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -98,7 +98,7 @@
/*
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
}
/*
- * 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 1dbf228..c48f502 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -81,7 +81,7 @@
/*
* 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 @@
* 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 @@
* 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 @@
* 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 6c1a132..ed79abf 100644
--- a/src/ev_select.c
+++ b/src/ev_select.c
@@ -78,7 +78,7 @@
/*
* 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 @@
* 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 @@
* 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 @@
* 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 5ddfebd..9c370fa 100644
--- a/src/fd.c
+++ b/src/fd.c
@@ -35,22 +35,6 @@
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.
*/
@@ -64,27 +48,6 @@
maxfd--;
}
-
-/* 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 785bd74..f1e5cc3 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -523,8 +523,10 @@
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");