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