Add a threading framework
authorPierre Habouzit <madcoder@debian.org>
Thu, 29 Nov 2007 11:14:26 +0000 (12:14 +0100)
committerPierre Habouzit <madcoder@debian.org>
Thu, 29 Nov 2007 11:14:26 +0000 (12:14 +0100)
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Makefile
common.h
epoll.h
main-postlicyd.c
mem.h
threads.c [new file with mode: 0644]
threads.h [new file with mode: 0644]

index 249f9df..0e9e02c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ TESTS    = tst-rbl
 
 GENERATED = tokens.h tokens.c
 
-postlicyd_SOURCES = common.c epoll.c str.c buffer.c rbl.c \
+postlicyd_SOURCES = common.c threads.c str.c buffer.c rbl.c \
                    $(GENERATED) postfix.c main-postlicyd.c
 postlicyd_LIBADD = -lpthread
 
index 801457c..e70c9a7 100644 (file)
--- a/common.h
+++ b/common.h
  * Copyright © 2007 Pierre Habouzit
  */
 
-#ifndef PFIXTOOLS_H
-#define PFIXTOOLS_H
+#ifndef PFIXTOOLS_COMMON_H
+#define PFIXTOOLS_COMMON_H
 
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <netinet/in.h>
-#include <pthread.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <stdbool.h>
@@ -54,6 +53,8 @@
 #include <time.h>
 #include <unistd.h>
 
+#include "mem.h"
+
 #define UNIXERR(fun)                                    \
         syslog(LOG_ERR, "%s:%d:%s: %s: %m",             \
                __FILE__, __LINE__, __func__, fun)
diff --git a/epoll.h b/epoll.h
index f4e1453..bd52773 100644 (file)
--- a/epoll.h
+++ b/epoll.h
  * Copyright © 2007 Pierre Habouzit
  */
 
-#include <sys/epoll.h>
+#ifndef PFIXTOOLS_EPOLL_H
+#define PFIXTOOLS_EPOLL_H
 
+#include <sys/epoll.h>
 #include "common.h"
 
 extern int epollfd;
 
+#endif
index 01eb9e6..fe4a851 100644 (file)
@@ -35,8 +35,8 @@
 
 #include <getopt.h>
 
-#include "common.h"
 #include "epoll.h"
+#include "threads.h"
 
 /* administrivia {{{ */
 
@@ -61,12 +61,9 @@ module_exit(main_shutdown);
 
 /* }}} */
 
-void *job_run(void *_fd)
+void *job_run(int fd, void *data)
 {
-    int fd = (intptr_t)_fd;
-
     close(fd);
-    pthread_detach(pthread_self());
     return NULL;
 }
 
@@ -77,15 +74,14 @@ static int main_loop(void)
 
     while (!sigint) {
         int fd = accept(sock, NULL, 0);
-        pthread_t dummy;
-
         if (fd < 0) {
             if (errno != EINTR || errno != EAGAIN)
                 UNIXERR("accept");
             continue;
         }
 
-        pthread_create(&dummy, NULL, job_run, (void *)(intptr_t)fd);
+        thread_launch(job_run, fd, NULL);
+        threads_join();
     }
 
     close(sock);
diff --git a/mem.h b/mem.h
index ae69575..44630ef 100644 (file)
--- a/mem.h
+++ b/mem.h
 #define p_dupstr(p, len)        xmemdupstr((p), (len))
 #define p_realloc(pp, count)    xrealloc((void*)(pp), sizeof(**(pp)) * (count))
 
+#  define p_alloc_nr(x) (((x) + 16) * 3 / 2)
+#  define p_allocgrow(pp, goalnb, allocnb)                  \
+    do {                                                    \
+        if ((goalnb) > *(allocnb)) {                        \
+            if (p_alloc_nr(goalnb) > *(allocnb)) {          \
+                *(allocnb) = (goalnb);                      \
+            } else {                                        \
+                *(allocnb) = p_alloc_nr(goalnb);            \
+            }                                               \
+            p_realloc(pp, *(allocnb));                      \
+        }                                                   \
+    } while (0)
+
 #ifdef __GNUC__
 
 #  define p_delete(mem_pp)                          \
diff --git a/threads.c b/threads.c
new file mode 100644 (file)
index 0000000..249a123
--- /dev/null
+++ b/threads.c
@@ -0,0 +1,102 @@
+/******************************************************************************/
+/*          pfixtools: a collection of postfix related tools                  */
+/*          ~~~~~~~~~                                                         */
+/*  ________________________________________________________________________  */
+/*                                                                            */
+/*  Redistribution and use in source and binary forms, with or without        */
+/*  modification, are permitted provided that the following conditions        */
+/*  are met:                                                                  */
+/*                                                                            */
+/*  1. Redistributions of source code must retain the above copyright         */
+/*     notice, this list of conditions and the following disclaimer.          */
+/*  2. Redistributions in binary form must reproduce the above copyright      */
+/*     notice, this list of conditions and the following disclaimer in the    */
+/*     documentation and/or other materials provided with the distribution.   */
+/*  3. The names of its contributors may not be used to endorse or promote    */
+/*     products derived from this software without specific prior written     */
+/*     permission.                                                            */
+/*                                                                            */
+/*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
+/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
+/*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
+/*  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS    */
+/*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR    */
+/*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
+/*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
+/*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
+/*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
+/*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
+/*  THE POSSIBILITY OF SUCH DAMAGE.                                           */
+/******************************************************************************/
+
+/*
+ * Copyright © 2007 Pierre Habouzit
+ */
+
+#include "threads.h"
+
+static struct {
+    pthread_spinlock_t spin;
+    pthread_t *deads;
+    int count, size;
+} morgue;
+
+struct thread_foo {
+    void *(*fun)(int fd, void *);
+    int fd;
+    void *data;
+};
+
+void thread_register_dead(void *tid)
+{
+    pthread_spin_lock(&morgue.spin);
+    if (morgue.count >= morgue.size) {
+        p_allocgrow(&morgue.deads, morgue.count + 1, &morgue.size);
+    }
+    morgue.deads[morgue.count++] = (pthread_t)tid;
+    pthread_spin_unlock(&morgue.spin);
+}
+
+static void *thread_wrapper(void *arg)
+{
+    struct thread_foo *foo = arg;
+    void *res;
+    pthread_cleanup_push(thread_register_dead, (void *)pthread_self());
+    res = (*foo->fun)(foo->fd, foo->data);
+    pthread_cleanup_pop(1);
+    return res;
+}
+
+int thread_launch(void *(*f)(int, void *), int fd, void *data)
+{
+    struct thread_foo foo = { f, fd, data };
+    pthread_t t;
+    return pthread_create(&t, NULL, &thread_wrapper, &foo);
+}
+
+void threads_join(void)
+{
+    if (!morgue.count)
+        return;
+
+    pthread_spin_lock(&morgue.spin);
+    while (morgue.count-- > 0) {
+        pthread_join(morgue.deads[morgue.count], NULL);
+    }
+    pthread_spin_unlock(&morgue.spin);
+}
+
+
+static int threads_initialize(void)
+{
+    pthread_spin_init(&morgue.spin, PTHREAD_PROCESS_PRIVATE);
+    return 0;
+}
+
+static void threads_shutdown(void)
+{
+    pthread_spin_destroy(&morgue.spin);
+}
+
+module_init(threads_initialize);
+module_exit(threads_shutdown);
diff --git a/threads.h b/threads.h
new file mode 100644 (file)
index 0000000..58a0731
--- /dev/null
+++ b/threads.h
@@ -0,0 +1,45 @@
+/******************************************************************************/
+/*          pfixtools: a collection of postfix related tools                  */
+/*          ~~~~~~~~~                                                         */
+/*  ________________________________________________________________________  */
+/*                                                                            */
+/*  Redistribution and use in source and binary forms, with or without        */
+/*  modification, are permitted provided that the following conditions        */
+/*  are met:                                                                  */
+/*                                                                            */
+/*  1. Redistributions of source code must retain the above copyright         */
+/*     notice, this list of conditions and the following disclaimer.          */
+/*  2. Redistributions in binary form must reproduce the above copyright      */
+/*     notice, this list of conditions and the following disclaimer in the    */
+/*     documentation and/or other materials provided with the distribution.   */
+/*  3. The names of its contributors may not be used to endorse or promote    */
+/*     products derived from this software without specific prior written     */
+/*     permission.                                                            */
+/*                                                                            */
+/*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
+/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
+/*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
+/*  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS    */
+/*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR    */
+/*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
+/*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
+/*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
+/*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
+/*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
+/*  THE POSSIBILITY OF SUCH DAMAGE.                                           */
+/******************************************************************************/
+
+/*
+ * Copyright © 2007 Pierre Habouzit
+ */
+
+#ifndef PFIXTOOLS_THREADS_H
+#define PFIXTOOLS_THREADS_H
+
+#include "common.h"
+#include <pthread.h>
+
+int thread_launch(void *(*f)(int fd, void *), int fd, void *);
+void threads_join(void);
+
+#endif