From ad17c98dd5877ededb8ac3d4e0ac1f7beed5406c Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 29 Oct 2019 18:20:21 +0100 Subject: [PATCH] MDEV-16264 - prerequisite patch, periodic thr_timer Threadpool will need a functionality for periodic thr_timer (the threadpool maintainence task is a timer that runs periodically). Also increase the stack size for the timer thread, 8k won't be enough. --- include/thr_timer.h | 2 ++ mysys/thr_timer.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/thr_timer.h b/include/thr_timer.h index 4f0c4f08660..6bca815480b 100644 --- a/include/thr_timer.h +++ b/include/thr_timer.h @@ -23,6 +23,7 @@ extern "C" { typedef struct st_timer { struct timespec expire_time; + ulonglong period; my_bool expired; uint index_in_queue; void (*func)(void*); @@ -36,6 +37,7 @@ void end_thr_timer(); /* Functions for handling one timer */ void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), void *arg); +void thr_timer_set_period(thr_timer_t* timer_data, ulonglong microseconds); my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong microseconds); void thr_timer_end(thr_timer_t *timer_data); diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c index 1532875d7f3..f87c1f75555 100644 --- a/mysys/thr_timer.c +++ b/mysys/thr_timer.c @@ -85,7 +85,7 @@ my_bool init_thr_timer(uint alloc_timers) /* Create a thread to handle timers */ pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setstacksize(&thr_attr,8196); + pthread_attr_setstacksize(&thr_attr,64*1024); thr_timer_inited= 1; if (mysql_thread_create(key_thread_timer, &timer_thread, &thr_attr, timer_handler, NULL)) @@ -141,6 +141,18 @@ void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), DBUG_VOID_RETURN; } +/* + Make timer periodic + + @param timer_data Timer structure + @param micro_seconds Period +*/ +void thr_timer_set_period(thr_timer_t* timer_data, ulonglong micro_seconds) +{ + DBUG_ENTER("thr_timer_set_period"); + timer_data->period= micro_seconds; + DBUG_VOID_RETURN; +} /* Request timer after X milliseconds @@ -240,18 +252,35 @@ static sig_handler process_timers(struct timespec *now) { void (*function)(void*); void *func_arg; + my_bool is_periodic; timer_data= (thr_timer_t*) queue_top(&timer_queue); function= timer_data->func; func_arg= timer_data->func_arg; + is_periodic= timer_data->period != 0; timer_data->expired= 1; /* Mark expired */ /* We remove timer before calling timer function to allow thread to delete it's timer data any time. + + Deleting timer inside the callback would not work + for periodic timers, they need to be removed from + queue prior to destroying timer_data. */ queue_remove_top(&timer_queue); /* Remove timer */ (*function)(func_arg); /* Inform thread of timeout */ + /* + If timer is periodic, recalculate next expiration time, and + reinsert it into the queue. + */ + if (is_periodic && timer_data->period) + { + set_timespec_nsec(timer_data->expire_time, timer_data->period * 1000); + timer_data->expired= 0; + queue_insert(&timer_queue, (uchar*)timer_data); + } + /* Check if next one has also expired */ timer_data= (thr_timer_t*) queue_top(&timer_queue); if (cmp_timespec(timer_data->expire_time, (*now)) > 0)