Merge pull request #8103 from mjstapp/fix_thread_awaken

lib: don't awaken from poll for every timer
This commit is contained in:
Donald Sharp 2021-02-19 08:21:31 -05:00 committed by GitHub
commit c6b8506c6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -58,8 +58,7 @@ static int thread_timer_cmp(const struct thread *a, const struct thread *b)
return 0; return 0;
} }
DECLARE_HEAP(thread_timer_list, struct thread, timeritem, DECLARE_HEAP(thread_timer_list, struct thread, timeritem, thread_timer_cmp)
thread_timer_cmp)
#if defined(__APPLE__) #if defined(__APPLE__)
#include <mach/mach.h> #include <mach/mach.h>
@ -910,31 +909,33 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref,
static struct thread * static struct thread *
_thread_add_timer_timeval(const struct xref_threadsched *xref, _thread_add_timer_timeval(const struct xref_threadsched *xref,
struct thread_master *m, int (*func)(struct thread *), struct thread_master *m, int (*func)(struct thread *),
int type, void *arg, struct timeval *time_relative, void *arg, struct timeval *time_relative,
struct thread **t_ptr) struct thread **t_ptr)
{ {
struct thread *thread; struct thread *thread;
struct timeval t;
assert(m != NULL); assert(m != NULL);
assert(type == THREAD_TIMER);
assert(time_relative); assert(time_relative);
frrtrace(9, frr_libfrr, schedule_timer, m, frrtrace(9, frr_libfrr, schedule_timer, m,
xref->funcname, xref->xref.file, xref->xref.line, xref->funcname, xref->xref.file, xref->xref.line,
t_ptr, 0, 0, arg, (long)time_relative->tv_sec); t_ptr, 0, 0, arg, (long)time_relative->tv_sec);
/* Compute expiration/deadline time. */
monotime(&t);
timeradd(&t, time_relative, &t);
frr_with_mutex(&m->mtx) { frr_with_mutex(&m->mtx) {
if (t_ptr && *t_ptr) if (t_ptr && *t_ptr)
/* thread is already scheduled; don't reschedule */ /* thread is already scheduled; don't reschedule */
return NULL; return NULL;
thread = thread_get(m, type, func, arg, xref); thread = thread_get(m, THREAD_TIMER, func, arg, xref);
frr_with_mutex(&thread->mtx) { frr_with_mutex(&thread->mtx) {
monotime(&thread->u.sands); thread->u.sands = t;
timeradd(&thread->u.sands, time_relative,
&thread->u.sands);
thread_timer_list_add(&m->timer, thread); thread_timer_list_add(&m->timer, thread);
if (t_ptr) { if (t_ptr) {
*t_ptr = thread; *t_ptr = thread;
@ -942,6 +943,11 @@ _thread_add_timer_timeval(const struct xref_threadsched *xref,
} }
} }
/* The timer list is sorted - if this new timer
* might change the time we'll wait for, give the pthread
* a chance to re-compute.
*/
if (thread_timer_list_first(&m->timer) == thread)
AWAKEN(m); AWAKEN(m);
} }
@ -962,8 +968,7 @@ struct thread *_thread_add_timer(const struct xref_threadsched *xref,
trel.tv_sec = timer; trel.tv_sec = timer;
trel.tv_usec = 0; trel.tv_usec = 0;
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr);
&trel, t_ptr);
} }
/* Add timer event thread with "millisecond" resolution */ /* Add timer event thread with "millisecond" resolution */
@ -980,19 +985,17 @@ struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref,
trel.tv_sec = timer / 1000; trel.tv_sec = timer / 1000;
trel.tv_usec = 1000 * (timer % 1000); trel.tv_usec = 1000 * (timer % 1000);
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, return _thread_add_timer_timeval(xref, m, func, arg, &trel, t_ptr);
&trel, t_ptr);
} }
/* Add timer event thread with "millisecond" resolution */ /* Add timer event thread with "timeval" resolution */
struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref, struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref,
struct thread_master *m, struct thread_master *m,
int (*func)(struct thread *), int (*func)(struct thread *),
void *arg, struct timeval *tv, void *arg, struct timeval *tv,
struct thread **t_ptr) struct thread **t_ptr)
{ {
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, tv, return _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr);
t_ptr);
} }
/* Add simple event thread. */ /* Add simple event thread. */
@ -1449,20 +1452,21 @@ static void thread_process_io(struct thread_master *m, unsigned int num)
} }
/* Add all timers that have popped to the ready list. */ /* Add all timers that have popped to the ready list. */
static unsigned int thread_process_timers(struct thread_timer_list_head *timers, static unsigned int thread_process_timers(struct thread_master *m,
struct timeval *timenow) struct timeval *timenow)
{ {
struct thread *thread; struct thread *thread;
unsigned int ready = 0; unsigned int ready = 0;
while ((thread = thread_timer_list_first(timers))) { while ((thread = thread_timer_list_first(&m->timer))) {
if (timercmp(timenow, &thread->u.sands, <)) if (timercmp(timenow, &thread->u.sands, <))
return ready; break;
thread_timer_list_pop(timers); thread_timer_list_pop(&m->timer);
thread->type = THREAD_READY; thread->type = THREAD_READY;
thread_list_add_tail(&thread->master->ready, thread); thread_list_add_tail(&m->ready, thread);
ready++; ready++;
} }
return ready; return ready;
} }
@ -1584,7 +1588,7 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
/* Post timers to ready queue. */ /* Post timers to ready queue. */
monotime(&now); monotime(&now);
thread_process_timers(&m->timer, &now); thread_process_timers(m, &now);
/* Post I/O to ready queue. */ /* Post I/O to ready queue. */
if (num > 0) if (num > 0)