lib, zebra: Add ability to tell thread system to ignore late timers

Add a thread_ignore_late_timer(struct thread *thread) function
that allows thread.c to ignore when timers are late to the party.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2022-01-19 14:56:25 -05:00
parent ab01a00176
commit e8b3a2f74b
4 changed files with 23 additions and 9 deletions

View file

@ -787,6 +787,7 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
thread->arg = arg; thread->arg = arg;
thread->yield = THREAD_YIELD_TIME_SLOT; /* default */ thread->yield = THREAD_YIELD_TIME_SLOT; /* default */
thread->ref = NULL; thread->ref = NULL;
thread->ignore_timer_late = false;
/* /*
* So if the passed in funcname is not what we have * So if the passed in funcname is not what we have
@ -1667,12 +1668,12 @@ static unsigned int thread_process_timers(struct thread_master *m,
* really getting behind on handling of events. * really getting behind on handling of events.
* Let's log it and do the right thing with it. * Let's log it and do the right thing with it.
*/ */
if (timercmp(timenow, &prev, >)) { if (!displayed && !thread->ignore_timer_late &&
if (!displayed) timercmp(timenow, &prev, >)) {
flog_warn( flog_warn(
EC_LIB_STARVE_THREAD, EC_LIB_STARVE_THREAD,
"Thread Starvation: %pTHD was scheduled to pop greater than 4s ago", "Thread Starvation: %pTHD was scheduled to pop greater than 4s ago",
thread); thread);
displayed = true; displayed = true;
} }

View file

@ -126,6 +126,7 @@ struct thread {
unsigned long yield; /* yield time in microseconds */ unsigned long yield; /* yield time in microseconds */
const struct xref_threadsched *xref; /* origin location */ const struct xref_threadsched *xref; /* origin location */
pthread_mutex_t mtx; /* mutex for thread.c functions */ pthread_mutex_t mtx; /* mutex for thread.c functions */
bool ignore_timer_late;
}; };
#ifdef _FRR_ATTRIBUTE_PRINTFRR #ifdef _FRR_ATTRIBUTE_PRINTFRR
@ -285,6 +286,11 @@ extern bool thread_is_scheduled(struct thread *thread);
/* Debug signal mask */ /* Debug signal mask */
void debug_signals(const sigset_t *sigs); void debug_signals(const sigset_t *sigs);
static inline void thread_ignore_late_timer(struct thread *thread)
{
thread->ignore_timer_late = true;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -135,10 +135,11 @@ static int work_queue_schedule(struct work_queue *wq, unsigned int delay)
/* Schedule timer if there's a delay, otherwise just schedule /* Schedule timer if there's a delay, otherwise just schedule
* as an 'event' * as an 'event'
*/ */
if (delay > 0) if (delay > 0) {
thread_add_timer_msec(wq->master, work_queue_run, wq, thread_add_timer_msec(wq->master, work_queue_run, wq,
delay, &wq->thread); delay, &wq->thread);
else thread_ignore_late_timer(wq->thread);
} else
thread_add_event(wq->master, work_queue_run, wq, 0, thread_add_event(wq->master, work_queue_run, wq, 0,
&wq->thread); &wq->thread);

View file

@ -91,9 +91,12 @@ static int if_zebra_speed_update(struct thread *thread)
changed = true; changed = true;
} }
if (changed || new_speed == UINT32_MAX) if (changed || new_speed == UINT32_MAX) {
thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 5, thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 5,
&zif->speed_update); &zif->speed_update);
thread_ignore_late_timer(zif->speed_update);
}
return 1; return 1;
} }
@ -187,6 +190,8 @@ static int if_zebra_new_hook(struct interface *ifp)
*/ */
thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15, thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15,
&zebra_if->speed_update); &zebra_if->speed_update);
thread_ignore_late_timer(zebra_if->speed_update);
return 0; return 0;
} }
@ -1074,6 +1079,7 @@ void if_up(struct interface *ifp)
thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0, thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0,
&zif->speed_update); &zif->speed_update);
thread_ignore_late_timer(zif->speed_update);
} }
/* Interface goes down. We have to manage different behavior of based /* Interface goes down. We have to manage different behavior of based