-
Notifications
You must be signed in to change notification settings - Fork 0
/
threadmanager.c
91 lines (81 loc) · 3.02 KB
/
threadmanager.c
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "threadmanager.h"
#include "timeutils.h"
#include "logger.h"
#include <time.h>
#include <signal.h>
struct thread_info {
pthread_t thr;
void (*inner_function)(void);
struct timespec last_wd_kick;
int loopdelay;
pthread_mutex_t thrlock;
char* thrname;
};
static struct thread_info** registered_threads = NULL;
static pthread_cond_t loop_thread_signal;
static unsigned int num_registered = 0;
static int thread_manager_exit = 0;
static pthread_t lastparrent;
static void* threadloop(void* ti_v){
struct thread_info* ti = (struct thread_info*)(ti_v);
pthread_mutex_lock(&(ti->thrlock));
while(!thread_manager_exit){
(ti->inner_function)();
struct timespec ts = get_time_in_future(ti->loopdelay);
pthread_cond_timedwait(&(loop_thread_signal), &(ti->thrlock), &ts);
clock_gettime(CLOCK_MONOTONIC, &(ti->last_wd_kick));
}
pthread_mutex_unlock(&(ti->thrlock));
dlog("Thread %s finished loop\n", ti->thrname);
return NULL;
}
void create_thread(void (*inner_function)(void), int loopdelay, char* name){
if (num_registered == 0){
pthread_cond_init(&loop_thread_signal, NULL);
}
registered_threads = realloc(registered_threads, sizeof(struct thread_info*)*(num_registered+1));
registered_threads[num_registered] = malloc(sizeof(struct thread_info));
registered_threads[num_registered]->inner_function = inner_function;
registered_threads[num_registered]->loopdelay = loopdelay;
registered_threads[num_registered]->thrname = name;
lastparrent = pthread_self();
pthread_mutex_init(&(registered_threads[num_registered]->thrlock), NULL);
pthread_create(&(registered_threads[num_registered]->thr), NULL, threadloop, (void*)(registered_threads[num_registered]));
clock_gettime(CLOCK_MONOTONIC, &(registered_threads[num_registered]->last_wd_kick));
num_registered++;
dlog("Thread %s has been created\n", name);
}
void watchdog(void){
for (unsigned int i = 0; i < num_registered; i++){
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
struct timespec delta = get_delta_time(&(registered_threads[i]->last_wd_kick), &now);
if (delta.tv_sec > 2){
printf("Terminating (Watchdog fail)\n");
dlog("Thread %s failed\n", registered_threads[i]->thrname);
pthread_kill(lastparrent, SIGTERM);
}
}
}
void exitThreads(void){
thread_manager_exit = 1;
}
void joinThreads(void){
pthread_cond_broadcast(&loop_thread_signal);
for (unsigned int i = 0; i < num_registered; i++){
pthread_join(registered_threads[i]->thr, NULL);
dlog("Thread %s joined\n", registered_threads[i]->thrname);
}
}
void destroyThreadManager(void){
pthread_cond_destroy(&loop_thread_signal);
for (unsigned int i = 0; i < num_registered; i++){
pthread_mutex_destroy(&(registered_threads[i]->thrlock));
free(registered_threads[i]);
}
free(registered_threads);
}