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