summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_zebra.c1
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--eigrpd/eigrpd.c6
-rw-r--r--isisd/isis_main.c1
-rw-r--r--isisd/isis_zebra.c7
-rw-r--r--isisd/isis_zebra.h2
-rw-r--r--ldpd/lde.c2
-rw-r--r--ldpd/ldpe.c2
-rw-r--r--lib/frr_pthread.c2
-rw-r--r--lib/grammar_sandbox_main.c2
-rw-r--r--lib/if.c8
-rw-r--r--lib/if.h3
-rw-r--r--lib/json.c8
-rw-r--r--lib/json.h2
-rw-r--r--lib/libfrr.c2
-rw-r--r--lib/log.c19
-rw-r--r--lib/thread.c370
-rw-r--r--lib/thread.h7
-rw-r--r--nhrpd/nhrp_route.c1
-rw-r--r--ospf6d/ospf6_main.c5
-rw-r--r--ospfclient/ospfclient.c2
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--pimd/pim_zlookup.c1
-rw-r--r--pimd/pimd.c9
-rw-r--r--ripd/rip_main.c2
-rw-r--r--ripd/rip_zebra.c7
-rw-r--r--ripd/ripd.h1
-rw-r--r--ripngd/ripng_main.c1
-rw-r--r--ripngd/ripng_zebra.c7
-rw-r--r--ripngd/ripngd.h1
-rw-r--r--tests/bgpd/test_aspath.c2
-rw-r--r--tests/bgpd/test_capability.c2
-rw-r--r--tests/bgpd/test_mp_attr.c2
-rw-r--r--tests/bgpd/test_mpath.c2
-rw-r--r--tests/helpers/c/main.c2
-rw-r--r--tests/lib/cli/common_cli.c2
-rw-r--r--tests/lib/test_segv.c2
-rw-r--r--tests/lib/test_sig.c2
-rw-r--r--tests/lib/test_timer_correctness.c2
-rw-r--r--tests/lib/test_timer_performance.c2
-rw-r--r--tests/test_lblmgr.c2
-rw-r--r--zebra/client_main.c2
-rw-r--r--zebra/if_netlink.c2
-rw-r--r--zebra/interface.c2
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);
diff --git a/lib/if.c b/lib/if.c
index d9b4544271..1d6a8cb529 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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;
}
}
diff --git a/lib/if.h b/lib/if.h
index fa95901a58..a061110a4a 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -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)
diff --git a/lib/log.c b/lib/log.c
index a8b221fd64..1c61d72168 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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. */