diff options
Diffstat (limited to 'lib/thread.c')
| -rw-r--r-- | lib/thread.c | 85 |
1 files changed, 75 insertions, 10 deletions
diff --git a/lib/thread.c b/lib/thread.c index ada7a9cc80..90074b3d89 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -498,6 +498,41 @@ DEFUN (clear_thread_cpu, return CMD_SUCCESS; } +static void show_thread_timers_helper(struct vty *vty, struct thread_master *m) +{ + const char *name = m->name ? m->name : "main"; + char underline[strlen(name) + 1]; + struct thread *thread; + + memset(underline, '-', sizeof(underline)); + underline[sizeof(underline) - 1] = '\0'; + + vty_out(vty, "\nShowing timers for %s\n", name); + vty_out(vty, "-------------------%s\n", underline); + + frr_each (thread_timer_list, &m->timer, thread) { + vty_out(vty, " %-50s%pTH\n", thread->hist->funcname, thread); + } +} + +DEFPY_NOSH (show_thread_timers, + show_thread_timers_cmd, + "show thread timers", + SHOW_STR + "Thread information\n" + "Show all timers and how long they have in the system\n") +{ + struct listnode *node; + struct thread_master *m; + + frr_with_mutex (&masters_mtx) { + for (ALL_LIST_ELEMENTS_RO(masters, node, m)) + show_thread_timers_helper(vty, m); + } + + return CMD_SUCCESS; +} + void thread_cmd_init(void) { install_element(VIEW_NODE, &show_thread_cpu_cmd); @@ -509,6 +544,8 @@ void thread_cmd_init(void) install_element(CONFIG_NODE, &no_service_cputime_warning_cmd); install_element(CONFIG_NODE, &service_walltime_warning_cmd); install_element(CONFIG_NODE, &no_service_walltime_warning_cmd); + + install_element(VIEW_NODE, &show_thread_timers_cmd); } /* CLI end ------------------------------------------------------------------ */ @@ -773,7 +810,7 @@ char *thread_timer_to_hhmmss(char *buf, int buf_size, /* Get new thread. */ static struct thread *thread_get(struct thread_master *m, uint8_t type, - int (*func)(struct thread *), void *arg, + void (*func)(struct thread *), void *arg, const struct xref_threadsched *xref) { struct thread *thread = thread_list_pop(&m->unuse); @@ -930,7 +967,7 @@ done: /* Add new read thread. */ void _thread_add_read_write(const struct xref_threadsched *xref, struct thread_master *m, - int (*func)(struct thread *), void *arg, int fd, + void (*func)(struct thread *), void *arg, int fd, struct thread **t_ptr) { int dir = xref->thread_type; @@ -1010,7 +1047,7 @@ void _thread_add_read_write(const struct xref_threadsched *xref, static void _thread_add_timer_timeval(const struct xref_threadsched *xref, struct thread_master *m, - int (*func)(struct thread *), void *arg, + void (*func)(struct thread *), void *arg, struct timeval *time_relative, struct thread **t_ptr) { @@ -1052,12 +1089,18 @@ static void _thread_add_timer_timeval(const struct xref_threadsched *xref, if (thread_timer_list_first(&m->timer) == thread) AWAKEN(m); } +#define ONEYEAR2SEC (60 * 60 * 24 * 365) + if (time_relative->tv_sec > ONEYEAR2SEC) + flog_err( + EC_LIB_TIMER_TOO_LONG, + "Timer: %pTHD is created with an expiration that is greater than 1 year", + thread); } /* Add timer event thread. */ void _thread_add_timer(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), + struct thread_master *m, void (*func)(struct thread *), void *arg, long timer, struct thread **t_ptr) { struct timeval trel; @@ -1073,8 +1116,8 @@ void _thread_add_timer(const struct xref_threadsched *xref, /* Add timer event thread with "millisecond" resolution */ void _thread_add_timer_msec(const struct xref_threadsched *xref, struct thread_master *m, - int (*func)(struct thread *), void *arg, long timer, - struct thread **t_ptr) + void (*func)(struct thread *), void *arg, + long timer, struct thread **t_ptr) { struct timeval trel; @@ -1088,15 +1131,16 @@ void _thread_add_timer_msec(const struct xref_threadsched *xref, /* Add timer event thread with "timeval" resolution */ void _thread_add_timer_tv(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), - void *arg, struct timeval *tv, struct thread **t_ptr) + struct thread_master *m, + void (*func)(struct thread *), void *arg, + struct timeval *tv, struct thread **t_ptr) { _thread_add_timer_timeval(xref, m, func, arg, tv, t_ptr); } /* Add simple event thread. */ void _thread_add_event(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), + struct thread_master *m, void (*func)(struct thread *), void *arg, int val, struct thread **t_ptr) { struct thread *thread = NULL; @@ -1840,6 +1884,27 @@ unsigned long thread_consumed_time(RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) { #ifdef HAVE_CLOCK_THREAD_CPUTIME_ID + +#ifdef __FreeBSD__ + /* + * FreeBSD appears to have an issue when calling clock_gettime + * with CLOCK_THREAD_CPUTIME_ID really close to each other + * occassionally the now time will be before the start time. + * This is not good and FRR is ending up with CPU HOG's + * when the subtraction wraps to very large numbers + * + * What we are going to do here is cheat a little bit + * and notice that this is a problem and just correct + * it so that it is impossible to happen + */ + if (start->cpu.tv_sec == now->cpu.tv_sec && + start->cpu.tv_nsec > now->cpu.tv_nsec) + now->cpu.tv_nsec = start->cpu.tv_nsec + 1; + else if (start->cpu.tv_sec > now->cpu.tv_sec) { + now->cpu.tv_sec = start->cpu.tv_sec; + now->cpu.tv_nsec = start->cpu.tv_nsec + 1; + } +#endif *cputime = (now->cpu.tv_sec - start->cpu.tv_sec) * TIMER_SECOND_MICRO + (now->cpu.tv_nsec - start->cpu.tv_nsec) / 1000; #else @@ -2008,7 +2073,7 @@ void thread_call(struct thread *thread) /* Execute thread */ void _thread_execute(const struct xref_threadsched *xref, - struct thread_master *m, int (*func)(struct thread *), + struct thread_master *m, void (*func)(struct thread *), void *arg, int val) { struct thread *thread; |
