diff options
45 files changed, 289 insertions, 226 deletions
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index d8b8919e21..3a7a52ccca 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -400,4 +400,5 @@ void babel_zebra_close_connexion(void) { zclient_stop(zclient); + zclient_free(zclient); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 4fff339b85..66c18c8e57 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -581,7 +581,7 @@ bgp_interface_vrf_update (int command, struct zclient *zclient, zebra_size_t len } } - if_update (ifp, ifp->name, strlen (ifp->name), new_vrf_id); + if_update_to_new_vrf (ifp, new_vrf_id); bgp = bgp_lookup_by_vrf_id (new_vrf_id); if (!bgp) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index aed78cb35a..033a3d194d 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6405,7 +6405,7 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object { epoch_tbuf = time(NULL) - uptime1; json_object_string_add(json, "peerUptime", buf); - json_object_long_add(json, "peerUptimeMsec", uptime1 * 1000); + json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000); json_object_int_add(json, "peerUptimeEstablishedEpoch", epoch_tbuf); } diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index a0ead05224..2fa8296ce2 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -267,8 +267,10 @@ eigrp_finish (struct eigrp *eigrp) && (listcount(eigrp_om->eigrp) == 0)) { if (zclient) - zclient_free (zclient); - + { + zclient_stop (zclient); + zclient_free (zclient); + } exit(0); } diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 58070c7f2a..674592f46b 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -101,6 +101,7 @@ void sigusr1(void); static __attribute__((__noreturn__)) void terminate (int i) { + isis_zebra_stop (); exit (i); } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 0009dd5e27..af77250a01 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -720,3 +720,10 @@ isis_zebra_init (struct thread_master *master) return; } + +void +isis_zebra_stop (void) +{ + zclient_stop (zclient); + zclient_free (zclient); +} diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index 621c32c363..82d5a48d3e 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -25,6 +25,8 @@ extern struct zclient *zclient; void isis_zebra_init(struct thread_master *); +void isis_zebra_stop(void); + void isis_zebra_route_update (struct prefix *prefix, struct isis_route_info *route_info); int isis_distribute_list_update (int routetype); diff --git a/ldpd/lde.c b/ldpd/lde.c index 0ef46dab3d..602dc8805e 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -131,7 +131,7 @@ lde(void) ldpd_process = PROC_LDE_ENGINE; log_procname = log_procnames[PROC_LDE_ENGINE]; - master = thread_master_create(); + master = thread_master_create(NULL); /* setup signal handler */ signal_init(master, array_size(lde_signals), lde_signals); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index ba153dfde2..b2f9fdce55 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -109,7 +109,7 @@ ldpe(void) ldpd_process = PROC_LDP_ENGINE; log_procname = log_procnames[ldpd_process]; - master = thread_master_create(); + master = thread_master_create(NULL); /* setup signal handler */ signal_init(master, array_size(ldpe_signals), ldpe_signals); diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index 17bc82f5da..614c722be1 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -86,7 +86,7 @@ struct frr_pthread *frr_pthread_new(const char *name, unsigned int id, XCALLOC(MTYPE_FRR_PTHREAD, sizeof(struct frr_pthread)); fpt->id = id; - fpt->master = thread_master_create(); + fpt->master = thread_master_create(name); fpt->start_routine = start_routine; fpt->stop_routine = stop_routine; fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index 3bf0e268cf..02aefd603d 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -38,7 +38,7 @@ int main(int argc, char **argv) { struct thread thread; - master = thread_master_create (); + master = thread_master_create(NULL); openzlog ("grammar_sandbox", "NONE", 0, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); @@ -158,7 +158,7 @@ if_create (const char *name, int namelen, vrf_id_t vrf_id) /* Create new interface structure. */ void -if_update (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id) +if_update_to_new_vrf (struct interface *ifp, vrf_id_t vrf_id) { struct list *intf_list = vrf_iflist_get (vrf_id); @@ -166,10 +166,6 @@ if_update (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id if (vrf_iflist (ifp->vrf_id)) listnode_delete (vrf_iflist (ifp->vrf_id), ifp); - assert (name); - assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ - strncpy (ifp->name, name, namelen); - ifp->name[namelen] = '\0'; ifp->vrf_id = vrf_id; if (if_lookup_by_name (ifp->name, vrf_id) == NULL) listnode_add_sort (intf_list, ifp); @@ -453,7 +449,7 @@ if_get_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) } else { - if_update (ifp, name, namelen, vrf_id); + if_update_to_new_vrf (ifp, vrf_id); return ifp; } } @@ -393,8 +393,7 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); -extern void if_update (struct interface *, const char *name, int namelen, - vrf_id_t vrf_id); +extern void if_update_to_new_vrf (struct interface *, vrf_id_t vrf_id); extern struct interface *if_create (const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); diff --git a/lib/json.c b/lib/json.c index 5b7c3e9ffa..d8c97e4486 100644 --- a/lib/json.c +++ b/lib/json.c @@ -48,13 +48,7 @@ json_object_string_add(struct json_object* obj, const char *key, } void -json_object_int_add(struct json_object* obj, const char *key, int32_t i) -{ - json_object_object_add(obj, key, json_object_new_int(i)); -} - -void -json_object_long_add(struct json_object* obj, const char *key, int64_t i) +json_object_int_add(struct json_object* obj, const char *key, int64_t i) { #if defined(HAVE_JSON_C_JSON_H) json_object_object_add(obj, key, json_object_new_int64(i)); diff --git a/lib/json.h b/lib/json.h index 5faaaa841a..86271703f4 100644 --- a/lib/json.h +++ b/lib/json.h @@ -43,8 +43,6 @@ extern int use_json(const int argc, struct cmd_token *argv[]); extern void json_object_string_add(struct json_object* obj, const char *key, const char *s); extern void json_object_int_add(struct json_object* obj, const char *key, - int32_t i); -extern void json_object_long_add(struct json_object* obj, const char *key, int64_t i); extern void json_object_boolean_false_add(struct json_object* obj, const char *key); diff --git a/lib/libfrr.c b/lib/libfrr.c index 132f7d4d2c..8d816437cb 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -366,7 +366,7 @@ struct thread_master *frr_init(void) zprivs_init(di->privs); - master = thread_master_create(); + master = thread_master_create(NULL); signal_init(master, di->n_signals, di->signals); if (di->flags & FRR_LIMITED_CLI) @@ -509,16 +509,18 @@ zlog_signal(int signo, const char *action ); s = buf; - if (!thread_current) + struct thread *tc; + tc = pthread_getspecific (thread_current); + if (!tc) s = str_append (LOC, "no thread information available\n"); else { s = str_append (LOC, "in thread "); - s = str_append (LOC, thread_current->funcname); + s = str_append (LOC, tc->funcname); s = str_append (LOC, " scheduled from "); - s = str_append (LOC, thread_current->schedfrom); + s = str_append (LOC, tc->schedfrom); s = str_append (LOC, ":"); - s = num_append (LOC, thread_current->schedfrom_line); + s = num_append (LOC, tc->schedfrom_line); s = str_append (LOC, "\n"); } @@ -700,10 +702,13 @@ ZLOG_FUNC(zlog_debug, LOG_DEBUG) void zlog_thread_info (int log_level) { - if (thread_current) + struct thread *tc; + tc = pthread_getspecific (thread_current); + + if (tc) zlog(log_level, "Current thread function %s, scheduled from " - "file %s, line %u", thread_current->funcname, - thread_current->schedfrom, thread_current->schedfrom_line); + "file %s, line %u", tc->funcname, + tc->schedfrom, tc->schedfrom_line); else zlog(log_level, "Current thread not known/applicable"); } diff --git a/lib/thread.c b/lib/thread.c index a1a9e7c359..801168a799 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -47,16 +47,15 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") write (m->io_pipe[1], &wakebyte, 1); \ } while (0); -static pthread_mutex_t cpu_record_mtx = PTHREAD_MUTEX_INITIALIZER; -static struct hash *cpu_record = NULL; +/* control variable for initializer */ +pthread_once_t init_once = PTHREAD_ONCE_INIT; +pthread_key_t thread_current; -static unsigned long -timeval_elapsed (struct timeval a, struct timeval b) -{ - return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO) - + (a.tv_usec - b.tv_usec)); -} +pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER; +static struct list *masters; + +/* CLI start ---------------------------------------------------------------- */ static unsigned int cpu_record_hash_key (struct cpu_thread_history *a) { @@ -106,12 +105,12 @@ vty_out_cpu_thread_history(struct vty* vty, } static void -cpu_record_hash_print(struct hash_backet *bucket, - void *args[]) +cpu_record_hash_print(struct hash_backet *bucket, void *args[]) { struct cpu_thread_history *totals = args[0]; struct vty *vty = args[1]; thread_type *filter = args[2]; + struct cpu_thread_history *a = bucket->data; if ( !(a->types & *filter) ) @@ -132,169 +131,174 @@ cpu_record_print(struct vty *vty, thread_type filter) { struct cpu_thread_history tmp; void *args[3] = {&tmp, vty, &filter}; + struct thread_master *m; + struct listnode *ln; memset(&tmp, 0, sizeof tmp); tmp.funcname = "TOTAL"; tmp.types = filter; - vty_outln (vty, "%21s %18s %18s", - "", "CPU (user+system):", "Real (wall-clock):"); - vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); - vty_out(vty, " Avg uSec Max uSecs"); - vty_outln (vty, " Type Thread"); - - pthread_mutex_lock (&cpu_record_mtx); + pthread_mutex_lock (&masters_mtx); { - hash_iterate(cpu_record, - (void(*)(struct hash_backet*,void*))cpu_record_hash_print, - args); + for (ALL_LIST_ELEMENTS_RO (masters, ln, m)) { + const char *name = m->name ? m->name : "main"; + + char underline[strlen(name) + 1]; + memset (underline, '-', sizeof (underline)); + underline[sizeof(underline)] = '\0'; + + vty_out (vty, VTYNL); + vty_outln(vty, "Showing statistics for pthread %s", name); + vty_outln(vty, "-------------------------------%s", underline); + vty_outln(vty, "%21s %18s %18s", "", "CPU (user+system):", "Real (wall-clock):"); + vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); + vty_out(vty, " Avg uSec Max uSecs"); + vty_outln(vty, " Type Thread"); + + if (m->cpu_record->count) + hash_iterate(m->cpu_record, + (void (*)(struct hash_backet *, void *)) + cpu_record_hash_print, + args); + else + vty_outln(vty, "No data to display yet."); + + vty_out(vty, VTYNL); + } } - pthread_mutex_unlock (&cpu_record_mtx); + pthread_mutex_unlock (&masters_mtx); + + vty_out(vty, VTYNL); + vty_outln(vty, "Total thread statistics"); + vty_outln(vty, "-------------------------"); + vty_outln(vty, "%21s %18s %18s", "", "CPU (user+system):", "Real (wall-clock):"); + vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); + vty_out(vty, " Avg uSec Max uSecs"); + vty_outln(vty, " Type Thread"); if (tmp.total_calls > 0) vty_out_cpu_thread_history(vty, &tmp); } -DEFUN (show_thread_cpu, - show_thread_cpu_cmd, - "show thread cpu [FILTER]", - SHOW_STR - "Thread information\n" - "Thread CPU usage\n" - "Display filter (rwtexb)\n") -{ - int idx_filter = 3; - int i = 0; - thread_type filter = (thread_type) -1U; - - if (argc > 3) - { - filter = 0; - while (argv[idx_filter]->arg[i] != '\0') - { - switch ( argv[idx_filter]->arg[i] ) - { - case 'r': - case 'R': - filter |= (1 << THREAD_READ); - break; - case 'w': - case 'W': - filter |= (1 << THREAD_WRITE); - break; - case 't': - case 'T': - filter |= (1 << THREAD_TIMER); - break; - case 'e': - case 'E': - filter |= (1 << THREAD_EVENT); - break; - case 'x': - case 'X': - filter |= (1 << THREAD_EXECUTE); - break; - default: - break; - } - ++i; - } - if (filter == 0) - { - vty_outln (vty, "Invalid filter \"%s\" specified," - " must contain at least one of 'RWTEXB'", - argv[idx_filter]->arg); - return CMD_WARNING; - } - } - - cpu_record_print(vty, filter); - return CMD_SUCCESS; -} - static void -cpu_record_hash_clear (struct hash_backet *bucket, - void *args) +cpu_record_hash_clear (struct hash_backet *bucket, void *args[]) { - thread_type *filter = args; + thread_type *filter = args[0]; + struct hash *cpu_record = args[1]; + struct cpu_thread_history *a = bucket->data; if ( !(a->types & *filter) ) return; - pthread_mutex_lock (&cpu_record_mtx); - { - hash_release (cpu_record, bucket->data); - } - pthread_mutex_unlock (&cpu_record_mtx); + hash_release (cpu_record, bucket->data); } static void cpu_record_clear (thread_type filter) { thread_type *tmp = &filter; + struct thread_master *m; + struct listnode *ln; - pthread_mutex_lock (&cpu_record_mtx); + pthread_mutex_lock (&masters_mtx); { - hash_iterate (cpu_record, - (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear, - tmp); + for (ALL_LIST_ELEMENTS_RO (masters, ln, m)) { + pthread_mutex_lock (&m->mtx); + { + void *args[2] = { tmp, m->cpu_record }; + hash_iterate (m->cpu_record, + (void (*) (struct hash_backet*,void*)) + cpu_record_hash_clear, + args); + } + pthread_mutex_unlock (&m->mtx); + } } - pthread_mutex_unlock (&cpu_record_mtx); + pthread_mutex_unlock (&masters_mtx); +} + +static thread_type +parse_filter (const char *filterstr) +{ + int i = 0; + int filter = 0; + + while (filterstr[i] != '\0') + { + switch (filterstr[i]) + { + case 'r': + case 'R': + filter |= (1 << THREAD_READ); + break; + case 'w': + case 'W': + filter |= (1 << THREAD_WRITE); + break; + case 't': + case 'T': + filter |= (1 << THREAD_TIMER); + break; + case 'e': + case 'E': + filter |= (1 << THREAD_EVENT); + break; + case 'x': + case 'X': + filter |= (1 << THREAD_EXECUTE); + break; + default: + break; + } + ++i; + } + return filter; +} + +DEFUN (show_thread_cpu, + show_thread_cpu_cmd, + "show thread cpu [FILTER]", + SHOW_STR + "Thread information\n" + "Thread CPU usage\n" + "Display filter (rwtexb)\n") +{ + thread_type filter = (thread_type) -1U; + int idx = 0; + + if (argv_find (argv, argc, "FILTER", &idx)) { + filter = parse_filter (argv[idx]->arg); + if (!filter) { + vty_outln(vty, "Invalid filter \"%s\" specified; must contain at least" + "one of 'RWTEXB'%s", argv[idx]->arg); + return CMD_WARNING; + } + } + + cpu_record_print(vty, filter); + return CMD_SUCCESS; } DEFUN (clear_thread_cpu, clear_thread_cpu_cmd, "clear thread cpu [FILTER]", - "Clear stored data\n" + "Clear stored data in all pthreads\n" "Thread information\n" "Thread CPU usage\n" "Display filter (rwtexb)\n") { - int idx_filter = 3; - int i = 0; thread_type filter = (thread_type) -1U; - - if (argc > 3) - { - filter = 0; - while (argv[idx_filter]->arg[i] != '\0') - { - switch ( argv[idx_filter]->arg[i] ) - { - case 'r': - case 'R': - filter |= (1 << THREAD_READ); - break; - case 'w': - case 'W': - filter |= (1 << THREAD_WRITE); - break; - case 't': - case 'T': - filter |= (1 << THREAD_TIMER); - break; - case 'e': - case 'E': - filter |= (1 << THREAD_EVENT); - break; - case 'x': - case 'X': - filter |= (1 << THREAD_EXECUTE); - break; - default: - break; - } - ++i; - } - if (filter == 0) - { - vty_outln (vty, "Invalid filter \"%s\" specified," - " must contain at least one of 'RWTEXB'", - argv[idx_filter]->arg); - return CMD_WARNING; - } + int idx = 0; + + if (argv_find (argv, argc, "FILTER", &idx)) { + filter = parse_filter (argv[idx]->arg); + if (!filter) { + vty_outln(vty, "Invalid filter \"%s\" specified; must contain at least" + "one of 'RWTEXB'%s", argv[idx]->arg); + return CMD_WARNING; } + } cpu_record_clear (filter); return CMD_SUCCESS; @@ -306,6 +310,8 @@ thread_cmd_init (void) install_element (VIEW_NODE, &show_thread_cpu_cmd); install_element (ENABLE_NODE, &clear_thread_cpu_cmd); } +/* CLI end ------------------------------------------------------------------ */ + static int thread_timer_cmp(void *a, void *b) @@ -334,31 +340,37 @@ cancelreq_del (void *cr) XFREE (MTYPE_TMP, cr); } +/* initializer, only ever called once */ +static void initializer () +{ + if (!masters) + masters = list_new(); + + pthread_key_create (&thread_current, NULL); +} + /* Allocate new thread master. */ struct thread_master * -thread_master_create (void) +thread_master_create (const char *name) { struct thread_master *rv; struct rlimit limit; - getrlimit(RLIMIT_NOFILE, &limit); - - pthread_mutex_lock (&cpu_record_mtx); - { - if (cpu_record == NULL) - cpu_record = hash_create ((unsigned int (*) (void *))cpu_record_hash_key, - (int (*) (const void *, const void *)) - cpu_record_hash_cmp); - } - pthread_mutex_unlock (&cpu_record_mtx); + pthread_once (&init_once, &initializer); rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master)); if (rv == NULL) return NULL; + /* Initialize master mutex */ pthread_mutex_init (&rv->mtx, NULL); pthread_cond_init (&rv->cancel_cond, NULL); + /* Set name */ + rv->name = name ? XSTRDUP (MTYPE_THREAD_MASTER, name) : NULL; + + /* Initialize I/O task data structures */ + getrlimit(RLIMIT_NOFILE, &limit); rv->fd_limit = (int)limit.rlim_cur; rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); if (rv->read == NULL) @@ -366,7 +378,6 @@ thread_master_create (void) XFREE (MTYPE_THREAD_MASTER, rv); return NULL; } - rv->write = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); if (rv->write == NULL) { @@ -375,20 +386,32 @@ thread_master_create (void) return NULL; } + rv->cpu_record = hash_create ((unsigned int (*) (void *))cpu_record_hash_key, + (int (*) (const void *, const void *)) + cpu_record_hash_cmp); + + /* Initialize the timer queues */ rv->timer = pqueue_create(); rv->timer->cmp = thread_timer_cmp; rv->timer->update = thread_timer_update; + + /* Initialize thread_fetch() settings */ rv->spin = true; rv->handle_signals = true; + + /* Set pthread owner, should be updated by actual owner */ rv->owner = pthread_self(); rv->cancel_req = list_new (); rv->cancel_req->del = cancelreq_del; rv->canceled = true; + + /* Initialize pipe poker */ pipe (rv->io_pipe); set_nonblocking (rv->io_pipe[0]); set_nonblocking (rv->io_pipe[1]); + /* Initialize data structures for poll() */ rv->handler.pfdsize = rv->fd_limit; rv->handler.pfdcount = 0; rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER, @@ -396,6 +419,13 @@ thread_master_create (void) rv->handler.copy = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct pollfd) * rv->handler.pfdsize); + /* add to list */ + pthread_mutex_lock (&masters_mtx); + { + listnode_add (masters, rv); + } + pthread_mutex_unlock (&masters_mtx); + return rv; } @@ -545,20 +575,13 @@ thread_master_free (struct thread_master *m) close (m->io_pipe[1]); list_delete (m->cancel_req); + hash_clean (m->cpu_record, cpu_record_hash_free); + hash_free (m->cpu_record); + m->cpu_record = NULL; + XFREE (MTYPE_THREAD_MASTER, m->handler.pfds); XFREE (MTYPE_THREAD_MASTER, m->handler.copy); XFREE (MTYPE_THREAD_MASTER, m); - - pthread_mutex_lock (&cpu_record_mtx); - { - if (cpu_record) - { - hash_clean (cpu_record, cpu_record_hash_free); - hash_free (cpu_record); - cpu_record = NULL; - } - } - pthread_mutex_unlock (&cpu_record_mtx); } /* Return remain time in second. */ @@ -630,12 +653,8 @@ thread_get (struct thread_master *m, u_char type, { tmp.func = func; tmp.funcname = funcname; - pthread_mutex_lock (&cpu_record_mtx); - { - thread->hist = hash_get (cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); - } - pthread_mutex_unlock (&cpu_record_mtx); + thread->hist = hash_get (m->cpu_record, &tmp, + (void * (*) (void *))cpu_record_hash_alloc); } thread->hist->total_active++; thread->func = func; @@ -676,7 +695,7 @@ fd_poll (struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, num = poll (pfds, count + 1, timeout); - static unsigned char trash[64]; + unsigned char trash[64]; if (num > 0 && pfds[count].revents != 0 && num--) while (read (m->io_pipe[0], &trash, sizeof (trash)) > 0); @@ -1301,7 +1320,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) struct timeval now; struct timeval zerotime = { 0, 0 }; struct timeval tv; - struct timeval *tw; + struct timeval *tw = NULL; int num = 0; @@ -1401,6 +1420,13 @@ thread_fetch (struct thread_master *m, struct thread *fetch) return fetch; } +static unsigned long +timeval_elapsed (struct timeval a, struct timeval b) +{ + return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO) + + (a.tv_usec - b.tv_usec)); +} + unsigned long thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) { @@ -1449,8 +1475,6 @@ thread_getrusage (RUSAGE_T *r) getrusage(RUSAGE_SELF, &(r->cpu)); } -struct thread *thread_current = NULL; - /* We check thread consumed time. If the system has getrusage, we'll use that to get in-depth stats on the performance of the thread in addition to wall clock time stats from gettimeofday. */ @@ -1463,9 +1487,9 @@ thread_call (struct thread *thread) GETRUSAGE (&before); thread->real = before.real; - thread_current = thread; + pthread_setspecific (thread_current, thread); (*thread->func) (thread); - thread_current = NULL; + pthread_setspecific (thread_current, NULL); GETRUSAGE (&after); @@ -1518,12 +1542,8 @@ funcname_thread_execute (struct thread_master *m, tmp.func = dummy.func = func; tmp.funcname = dummy.funcname = funcname; - pthread_mutex_lock (&cpu_record_mtx); - { - dummy.hist = hash_get (cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); - } - pthread_mutex_unlock (&cpu_record_mtx); + dummy.hist = hash_get (m->cpu_record, &tmp, + (void * (*) (void *))cpu_record_hash_alloc); dummy.schedfrom = schedfrom; dummy.schedfrom_line = fromln; diff --git a/lib/thread.h b/lib/thread.h index e48068b174..ad923c413f 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -71,6 +71,8 @@ struct cancel_req { /* Master of the theads. */ struct thread_master { + char *name; + struct thread **read; struct thread **write; struct pqueue *timer; @@ -80,6 +82,7 @@ struct thread_master struct list *cancel_req; bool canceled; pthread_cond_t cancel_cond; + struct hash *cpu_record; int io_pipe[2]; int fd_limit; struct fd_handler handler; @@ -177,7 +180,7 @@ struct cpu_thread_history #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) /* Prototypes. */ -extern struct thread_master *thread_master_create (void); +extern struct thread_master *thread_master_create (const char *); extern void thread_master_free (struct thread_master *); extern void thread_master_free_unused(struct thread_master *); @@ -220,6 +223,6 @@ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, unsigned long *cpu_time_elapsed); /* only for use in logging functions! */ -extern struct thread *thread_current; +extern pthread_key_t thread_current; #endif /* _ZEBRA_THREAD_H */ diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 7f8cad6e92..89972f8f98 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -379,6 +379,7 @@ void nhrp_zebra_init(void) void nhrp_zebra_terminate(void) { zclient_stop(zclient); + zclient_free(zclient); route_table_finish(zebra_rib[AFI_IP]); route_table_finish(zebra_rib[AFI_IP6]); } diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index f69c1e1bca..0a4a3a28c3 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -110,7 +110,10 @@ ospf6_exit (int status) cmd_terminate (); if (zclient) - zclient_free (zclient); + { + zclient_stop (zclient); + zclient_free (zclient); + } if (master) thread_master_free (master); diff --git a/ospfclient/ospfclient.c b/ospfclient/ospfclient.c index affcbc9d6a..63fcafb736 100644 --- a/ospfclient/ospfclient.c +++ b/ospfclient/ospfclient.c @@ -326,7 +326,7 @@ main (int argc, char *argv[]) /* Initialization */ zprivs_init (&ospfd_privs); - master = thread_master_create (); + master = thread_master_create(NULL); /* Open connection to OSPF daemon */ oclient = ospf_apiclient_connect (args[1], ASYNCPORT); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 38213aeb6a..9af9f7f314 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -497,6 +497,8 @@ ospf_terminate (void) * One or more ospf_finish()'s may have deferred shutdown to a timer * thread */ + zclient_stop (zclient); + zclient_free (zclient); } void diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 779cc14183..e7ffe0f4ad 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -115,6 +115,7 @@ static void zclient_lookup_failed(struct zclient *zlookup) void zclient_lookup_free (void) { + zclient_stop (zlookup); zclient_free (zlookup); zlookup = NULL; } diff --git a/pimd/pimd.c b/pimd/pimd.c index c31d2a99a1..ec1fe5b6d0 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -313,6 +313,8 @@ void pim_init() void pim_terminate() { + struct zclient *zclient; + pim_free(); /* reverse prefix_list_init */ @@ -321,4 +323,11 @@ void pim_terminate() prefix_list_reset (); pim_vrf_terminate (); + + zclient = pim_zebra_zclient_get (); + if (zclient) + { + zclient_stop (zclient); + zclient_free (zclient); + } } diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 38c2875949..1a7d03bca1 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -100,6 +100,8 @@ sigint (void) if (! retain_mode) rip_clean (); + rip_zclient_stop (); + exit (0); } diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 337555b0b7..31204872ac 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -711,3 +711,10 @@ rip_zclient_init (struct thread_master *master) install_element (RIP_NODE, &rip_default_information_originate_cmd); install_element (RIP_NODE, &no_rip_default_information_originate_cmd); } + +void +rip_zclient_stop (void) +{ + zclient_stop (zclient); + zclient_free (zclient); +} diff --git a/ripd/ripd.h b/ripd/ripd.h index d52df0d992..a8e65d1236 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -388,6 +388,7 @@ extern void rip_if_down_all (void); extern void rip_route_map_init (void); extern void rip_route_map_reset (void); extern void rip_zclient_init(struct thread_master *); +extern void rip_zclient_stop(void); extern void rip_zclient_reset (void); extern void rip_offset_init (void); extern int if_check_address (struct in_addr addr); diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index e517817147..9d700305ed 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -103,6 +103,7 @@ sigint (void) if (! retain_mode) ripng_clean (); + ripng_zebra_stop (); exit (0); } diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 2d62823b11..465d33992f 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -557,3 +557,10 @@ zebra_init (struct thread_master *master) install_element (RIPNG_NODE, &ripng_redistribute_type_metric_routemap_cmd); install_element (RIPNG_NODE, &no_ripng_redistribute_type_cmd); } + +void +ripng_zebra_stop (void) +{ + zclient_stop (zclient); + zclient_free (zclient); +} diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 62b7b073f8..ce8ea07a41 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -353,6 +353,7 @@ extern void ripng_route_map_reset (void); extern void ripng_terminate (void); /* zclient_init() is done by ripng_zebra.c:zebra_init() */ extern void zebra_init(struct thread_master *); +extern void ripng_zebra_stop (void); extern void ripng_zclient_reset (void); extern void ripng_offset_init (void); diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index 2d83fe6828..461fb829d4 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -1331,7 +1331,7 @@ main (void) { int i = 0; qobj_init (); - bgp_master_init (thread_master_create ()); + bgp_master_init (thread_master_create(NULL)); master = bm->master; bgp_option_set (BGP_OPT_NO_LISTEN); bgp_attr_init (); diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index 1e3a5be4e3..be0ca37b1f 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -648,7 +648,7 @@ main (void) term_bgp_debug_as4 = -1UL; qobj_init (); - master = thread_master_create (); + master = thread_master_create(NULL); bgp_master_init (master); vrf_init (NULL, NULL, NULL, NULL); bgp_option_set (BGP_OPT_NO_LISTEN); diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index e323748e97..f6f0fb70a5 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -748,7 +748,7 @@ main (void) term_bgp_debug_as4 = -1UL; qobj_init (); - master = thread_master_create (); + master = thread_master_create(NULL); bgp_master_init (master); vrf_init (NULL, NULL, NULL, NULL); bgp_option_set (BGP_OPT_NO_LISTEN); diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index affebbafea..3309a93227 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -376,7 +376,7 @@ static int global_test_init (void) { qobj_init (); - master = thread_master_create (); + master = thread_master_create(NULL); zclient = zclient_new(master); bgp_master_init (master); vrf_init (NULL, NULL, NULL, NULL); diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c index b0e80fb674..f842b03727 100644 --- a/tests/helpers/c/main.c +++ b/tests/helpers/c/main.c @@ -116,7 +116,7 @@ main (int argc, char **argv) progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); /* master init. */ - master = thread_master_create (); + master = thread_master_create(NULL); while (1) { diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index 27b28b126f..728ae8cb04 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -67,7 +67,7 @@ main (int argc, char **argv) umask (0027); /* master init. */ - master = thread_master_create (); + master = thread_master_create(NULL); openzlog("common-cli", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); diff --git a/tests/lib/test_segv.c b/tests/lib/test_segv.c index c43431622d..14384f4327 100644 --- a/tests/lib/test_segv.c +++ b/tests/lib/test_segv.c @@ -45,7 +45,7 @@ threadfunc (struct thread *thread) int main (void) { - master = thread_master_create (); + master = thread_master_create(NULL); signal_init (master, array_size(sigs), sigs); openzlog("testsegv", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); diff --git a/tests/lib/test_sig.c b/tests/lib/test_sig.c index a04c9f4206..1ffc6692f1 100644 --- a/tests/lib/test_sig.c +++ b/tests/lib/test_sig.c @@ -61,7 +61,7 @@ struct thread t; int main (void) { - master = thread_master_create (); + master = thread_master_create(NULL); signal_init (master, array_size(sigs), sigs); openzlog("testsig", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); diff --git a/tests/lib/test_timer_correctness.c b/tests/lib/test_timer_correctness.c index 10461be1ef..8fbe5bcbd7 100644 --- a/tests/lib/test_timer_correctness.c +++ b/tests/lib/test_timer_correctness.c @@ -115,7 +115,7 @@ int main(int argc, char **argv) struct thread t; struct timeval **alarms; - master = thread_master_create(); + master = thread_master_create(NULL); log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; log_buf_pos = 0; diff --git a/tests/lib/test_timer_performance.c b/tests/lib/test_timer_performance.c index b67af19aea..2bd02b5b01 100644 --- a/tests/lib/test_timer_performance.c +++ b/tests/lib/test_timer_performance.c @@ -49,7 +49,7 @@ int main(int argc, char **argv) struct timeval tv_start, tv_lap, tv_stop; unsigned long t_schedule, t_remove; - master = thread_master_create(); + master = thread_master_create(NULL); prng = prng_new(0); timers = calloc(SCHEDULE_TIMERS, sizeof(*timers)); diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c index d830094bad..a659447e72 100644 --- a/tests/test_lblmgr.c +++ b/tests/test_lblmgr.c @@ -140,7 +140,7 @@ int main (int argc, char *argv[]) printf ("Sequence to be tested: %s\n", sequence); - master = thread_master_create(); + master = thread_master_create(NULL); init_zclient (master, ZSERV_PATH); zebra_send_label_manager_connect (); diff --git a/zebra/client_main.c b/zebra/client_main.c index 0e77ea4aec..2903b8425d 100644 --- a/zebra/client_main.c +++ b/zebra/client_main.c @@ -200,7 +200,7 @@ main (int argc, char **argv) if (argc == 1) usage_exit (); - master = thread_master_create(); + master = thread_master_create(NULL); /* Establish connection to zebra. */ zclient = zclient_new(master); zclient->enable = 1; diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index dba916403d..8c50a95065 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -774,7 +774,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) - if_update (ifp, name, strlen(name), vrf_id); + if_update_to_new_vrf (ifp, vrf_id); } /* Update interface information. */ diff --git a/zebra/interface.c b/zebra/interface.c index a8ac405e36..b8426c6890 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -737,7 +737,7 @@ if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id) zebra_interface_vrf_update_del (ifp, vrf_id); /* update VRF */ - if_update (ifp, ifp->name, strlen (ifp->name), vrf_id); + if_update_to_new_vrf (ifp, vrf_id); /* Send out notification on interface VRF change. */ /* This is to issue an ADD, if needed. */ |
