summaryrefslogtreecommitdiff
path: root/ot_worker.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_worker.c')
-rw-r--r--ot_worker.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/ot_worker.c b/ot_worker.c
new file mode 100644
index 0000000..97eaeb2
--- /dev/null
+++ b/ot_worker.c
@@ -0,0 +1,75 @@
1/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever.
3
4 $id$ */
5
6/* System */
7#include <pthread.h>
8#include <stdatomic.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13/* Opentracker */
14#include "ot_worker.h"
15#include "trackerlogic.h"
16
17static struct ot_worker **g_workers;
18static size_t g_worker_count;
19
20/* Everything a worker needs doing around its own loop, in one place, so that
21 a new kind of worker cannot miss a piece of it. */
22static void *worker_trampoline(void *args) {
23 struct ot_worker *me = args;
24
25 if (workstruct_init(&me->ws) == -1)
26 fprintf(stderr, "Warning: a worker could not get its buffers and will not run.\n");
27 else {
28 me->run(me);
29 workstruct_deinit(&me->ws);
30 }
31
32 atomic_store(&me->left, 1);
33 return NULL;
34}
35
36int worker_start(ot_worker_run run, int64_t sock) {
37 struct ot_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers));
38 struct ot_worker *worker;
39
40 if (!grown)
41 return -1;
42 g_workers = grown;
43
44 if (!(worker = calloc(1, sizeof(*worker))))
45 return -1;
46 worker->sock = sock;
47 worker->run = run;
48
49 if (pthread_create(&worker->thread, NULL, worker_trampoline, worker)) {
50 free(worker);
51 return -1;
52 }
53 g_workers[g_worker_count++] = worker;
54 return 0;
55}
56
57void worker_stop_all(void) {
58 size_t i;
59
60 for (i = 0; i < g_worker_count; ++i) {
61 struct ot_worker *worker = g_workers[i];
62
63 /* Repeated because a signal only interrupts a call already under way */
64 while (!atomic_load(&worker->left)) {
65 pthread_kill(worker->thread, OT_SIGNAL_WAKE);
66 usleep(1000);
67 }
68 pthread_join(worker->thread, NULL);
69 free(worker);
70 }
71
72 free(g_workers);
73 g_workers = NULL;
74 g_worker_count = 0;
75}