diff --git a/src/backend/threads.c b/src/backend/threads.c index d52c7eb2c..ded04a60e 100644 --- a/src/backend/threads.c +++ b/src/backend/threads.c @@ -33,6 +33,7 @@ //TODO: System includes// #include +#include #include /** @@ -136,6 +137,8 @@ lumiera_thread_run (enum lumiera_thread_class kind, self->function = function; self->arguments = arg; + self->deadline.tv_sec = 0; + // and let it really run (signal the condition var, the thread waits on it) self->state = LUMIERA_THREADSTATE_WAKEUP; @@ -169,6 +172,8 @@ lumiera_thread_new (enum lumiera_thread_class kind, self->state = LUMIERA_THREADSTATE_STARTUP; self->function = NULL; self->arguments = NULL; + self->deadline.tv_sec = 0; + self->deadline.tv_nsec = 0; int error = pthread_create (&self->id, attrs, &thread_loop, self); if (error) @@ -223,6 +228,65 @@ lumiera_thread_self (void) } +/** + * Set a threads deadline + * A thread must finish before its deadline is hit. Otherwise it counts as stalled + * which is a fatal error which might pull the application down. + */ +LumieraThread +lumiera_thread_deadline_set (struct timespec deadline) +{ + LumieraThread self = lumiera_thread_self (); + if (self) + self->deadline = deadline; + return self; +} + + +/** + * Extend a threads deadline + * sets the deadline to now+ms in future. This can be used to implement a heartbeat. + */ +LumieraThread +lumiera_thread_deadline_extend (unsigned ms) +{ + LumieraThread self = lumiera_thread_self (); + if (self) + { + struct timespec deadline; + clock_gettime (CLOCK_REALTIME, &deadline); + deadline.tv_sec += ms / 1000; + deadline.tv_nsec += 1000000 * (ms % 1000); + if (deadline.tv_nsec > 1000000000) + { + deadline.tv_sec += (deadline.tv_nsec / 1000000000); + deadline.tv_nsec %= 1000000000; + } + self->deadline = deadline; + } + + return self; +} + + +/** + * Clear a threads deadline + * Threads without deadline will not be checked against deadlocks (this is the default) + */ +LumieraThread +lumiera_thread_deadline_clear (void) +{ + LumieraThread self = lumiera_thread_self (); + if (self) + { + self->deadline.tv_sec = 0; + self->deadline.tv_nsec = 0; + } + return self; +} + + + LumieraThread lumiera_thread_sync_other (LumieraThread other, int state) { diff --git a/src/backend/threads.h b/src/backend/threads.h index 34a38eb40..131d25911 100644 --- a/src/backend/threads.h +++ b/src/backend/threads.h @@ -142,6 +142,8 @@ struct lumiera_thread_struct // TODO: maybe this condition variable should be renamed when we have a better understanding of how it will be used lumiera_condition signal; // control signal, state change signal + struct timespec deadline; + struct nobug_resource_user** rh; // the following member could have been called "class" except that it would conflict with C++ keyword @@ -210,6 +212,40 @@ lumiera_thread_run (enum lumiera_thread_class kind, LumieraThread lumiera_thread_self (void); +/** + * Heartbeat and Deadlines + * + * Any thread can have an optional 'deadline' which must never be hit. + * This deadlines are lazily checked and if hit this is a fatal error which triggers + * an emergency shutdown. Thus threads are obliged to set and extend their deadlines + * accordingly. + * + */ + +/** + * Set a threads deadline + * A thread must finish before its deadline is hit. Otherwise it counts as stalled + * which is a fatal error which might pull the application down. + */ +LumieraThread +lumiera_thread_deadline_set (struct timespec deadline); + + +/** + * Extend a threads deadline + * sets the deadline to now+ms in future. This can be used to implement a heartbeat. + */ +LumieraThread +lumiera_thread_deadline_extend (unsigned ms); + + +/** + * Clear a threads deadline + * Threads without deadline will not be checked against deadlocks (this is the default) + */ +LumieraThread +lumiera_thread_deadline_clear (void); + /** * Thread syncronization