]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MAJOR] auto-registering of pollers at load time
authorWilly Tarreau <w@1wt.eu>
Sun, 15 Apr 2007 22:25:25 +0000 (00:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 15 Apr 2007 22:25:25 +0000 (00:25 +0200)
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.

include/proto/fd.h
src/ev_epoll.c
src/ev_kqueue.c
src/ev_poll.c
src/ev_select.c
src/fd.c
src/haproxy.c

index 72b2c6be84246bdd53344b97d75e8d199d17d80e..287c8bd80a3555df8c5767c044f98f1469e1d2ff 100644 (file)
  */
 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();
 
index 403e71c3c625ff4ab68458840a481b86619eb207..b4844998ad495bd549821b631bab1cbb0db091e8 100644 (file)
@@ -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;
 }
 
 
index dd990e47067b4511dc1b6644950300fa7c0bf262..55419f6f02b3e385b62cacef894516c0bf510cbf 100644 (file)
@@ -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;
 }
 
 
index 1dbf22889607f4263c67042387fb7aa127225d88..c48f502151f87c181eab32347bfc2f6e196bd99c 100644 (file)
@@ -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;
 }
 
 
index 6c1a13294e3b2ba20ddba909d2a8bc7655ea9b6b..ed79abf01e959197fec773acacc42cdd75515081 100644 (file)
@@ -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;
 }
 
 
index 5ddfebdd0095901c5edc431371782c100e1dd12c..9c370faf93d7179b2e40a40f8eae05e849ee7f75 100644 (file)
--- 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)
 {
index 785bd740f8c9f93ef2982edd77e5cad47d3af35c..f1e5cc3b7e40d1286f9679711bf8f411fb27e732 100644 (file)
@@ -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");