TT#14008 improve timerthread performance

The only reason the wait time in timer threads is capped at 100 ms is to
catch the daemon's shutdown. Since these threads already use a
condition variable to be woken up, we can use the same condition to wake
up the threads during a shutdown, allowing for a much longer (possibly
unlimited) sleep time in timer threads.

Change-Id: I3b5f280a4d502176a731e8b52b1b731022c8db4f
pull/1287/head
Richard Fuchs 5 years ago
parent 232f3470b3
commit 6f3bf25789

@ -39,6 +39,8 @@ static mutex_t threads_lists_lock = MUTEX_STATIC_INIT;
static GList *threads_to_join; static GList *threads_to_join;
static GList *threads_running; static GList *threads_running;
static cond_t threads_cond = COND_STATIC_INIT; static cond_t threads_cond = COND_STATIC_INIT;
static mutex_t thread_wakers_lock = MUTEX_STATIC_INIT;
static GList *thread_wakers;
volatile int rtpe_shutdown; volatile int rtpe_shutdown;
@ -135,8 +137,17 @@ void threads_join_all(int wait) {
pthread_t *t; pthread_t *t;
GList *l; GList *l;
mutex_lock(&threads_lists_lock);
while (1) { while (1) {
mutex_lock(&thread_wakers_lock);
for (l = thread_wakers; l; l = l->next) {
struct thread_waker *wk = l->data;
mutex_lock(wk->lock);
cond_broadcast(wk->cond);
mutex_unlock(wk->lock);
}
mutex_unlock(&thread_wakers_lock);
mutex_lock(&threads_lists_lock);
while (threads_to_join) { while (threads_to_join) {
t = threads_to_join->data; t = threads_to_join->data;
pthread_join(*t, NULL); pthread_join(*t, NULL);
@ -151,13 +162,24 @@ void threads_join_all(int wait) {
g_slice_free1(sizeof(*t), t); g_slice_free1(sizeof(*t), t);
} }
if (!wait) if (!wait || !threads_running) {
break; mutex_unlock(&threads_lists_lock);
if (!threads_running)
break; break;
}
cond_wait(&threads_cond, &threads_lists_lock); cond_wait(&threads_cond, &threads_lists_lock);
mutex_unlock(&threads_lists_lock);
} }
mutex_unlock(&threads_lists_lock); }
void thread_waker_add(struct thread_waker *wk) {
mutex_lock(&thread_wakers_lock);
thread_wakers = g_list_prepend(thread_wakers, wk);
mutex_unlock(&thread_wakers_lock);
}
void thread_waker_del(struct thread_waker *wk) {
mutex_lock(&thread_wakers_lock);
thread_wakers = g_list_remove(thread_wakers, wk);
mutex_unlock(&thread_wakers_lock);
} }
static void *thread_detach_func(void *d) { static void *thread_detach_func(void *d) {

@ -30,6 +30,9 @@ void timerthread_free(struct timerthread *tt) {
void timerthread_run(void *p) { void timerthread_run(void *p) {
struct timerthread *tt = p; struct timerthread *tt = p;
struct thread_waker waker = { .lock = &tt->lock, .cond = &tt->cond };
thread_waker_add(&waker);
mutex_lock(&tt->lock); mutex_lock(&tt->lock);
while (!rtpe_shutdown) { while (!rtpe_shutdown) {
@ -59,14 +62,15 @@ void timerthread_run(void *p) {
sleep:; sleep:;
/* figure out how long we should sleep */ /* figure out how long we should sleep */
long long sleeptime = tt_obj ? timeval_diff(&tt_obj->next_check, &rtpe_now) : 100000; long long sleeptime = tt_obj ? timeval_diff(&tt_obj->next_check, &rtpe_now) : 10000000;
sleeptime = MIN(100000, sleeptime); /* 100 ms at the most */ sleeptime = MIN(10000000, sleeptime); /* 100 ms at the most */
struct timeval tv = rtpe_now; struct timeval tv = rtpe_now;
timeval_add_usec(&tv, sleeptime); timeval_add_usec(&tv, sleeptime);
cond_timedwait(&tt->cond, &tt->lock, &tv); cond_timedwait(&tt->cond, &tt->lock, &tv);
} }
mutex_unlock(&tt->lock); mutex_unlock(&tt->lock);
thread_waker_del(&waker);
} }
void timerthread_obj_schedule_abs_nl(struct timerthread_obj *tt_obj, const struct timeval *tv) { void timerthread_obj_schedule_abs_nl(struct timerthread_obj *tt_obj, const struct timeval *tv) {

@ -286,6 +286,13 @@ taint_func(srandom, "use RAND_seed() instead");
/*** THREAD HELPERS ***/ /*** THREAD HELPERS ***/
struct thread_waker {
mutex_t *lock;
cond_t *cond;
};
void thread_waker_add(struct thread_waker *);
void thread_waker_del(struct thread_waker *);
void threads_join_all(int); void threads_join_all(int);
void thread_create_detach_prio(void (*)(void *), void *, const char *, int, const char *); void thread_create_detach_prio(void (*)(void *), void *, const char *, int, const char *);
INLINE void thread_create_detach(void (*f)(void *), void *a, const char *name) { INLINE void thread_create_detach(void (*f)(void *), void *a, const char *name) {

Loading…
Cancel
Save