From 1c42f5f8ed1972f13424197e9493bbed8e401576 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 29 Nov 2007 12:14:26 +0100 Subject: [PATCH] Add a threading framework Signed-off-by: Pierre Habouzit --- Makefile | 2 +- common.h | 7 ++-- epoll.h | 5 ++- main-postlicyd.c | 12 ++---- mem.h | 13 ++++++ threads.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++ threads.h | 45 +++++++++++++++++++++ 7 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 threads.c create mode 100644 threads.h diff --git a/Makefile b/Makefile index 249f9df..0e9e02c 100644 --- 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 diff --git a/common.h b/common.h index 801457c..e70c9a7 100644 --- a/common.h +++ b/common.h @@ -33,14 +33,13 @@ * Copyright © 2007 Pierre Habouzit */ -#ifndef PFIXTOOLS_H -#define PFIXTOOLS_H +#ifndef PFIXTOOLS_COMMON_H +#define PFIXTOOLS_COMMON_H #include #include #include #include -#include #include #include #include @@ -54,6 +53,8 @@ #include #include +#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 --- a/epoll.h +++ b/epoll.h @@ -33,9 +33,12 @@ * Copyright © 2007 Pierre Habouzit */ -#include +#ifndef PFIXTOOLS_EPOLL_H +#define PFIXTOOLS_EPOLL_H +#include #include "common.h" extern int epollfd; +#endif diff --git a/main-postlicyd.c b/main-postlicyd.c index 01eb9e6..fe4a851 100644 --- a/main-postlicyd.c +++ b/main-postlicyd.c @@ -35,8 +35,8 @@ #include -#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 --- a/mem.h +++ b/mem.h @@ -53,6 +53,19 @@ #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 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 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 + +int thread_launch(void *(*f)(int fd, void *), int fd, void *); +void threads_join(void); + +#endif -- 2.20.1