Merge pull request #723 from qlyoung/fix-static-pipe-poker-buf

lib: more multithreading infra work
This commit is contained in:
Jafar Al-Gharaibeh 2017-06-30 10:00:43 -05:00 committed by GitHub
commit b5a46fd2a6
21 changed files with 230 additions and 202 deletions

View File

@ -131,7 +131,7 @@ lde(void)
ldpd_process = PROC_LDE_ENGINE; ldpd_process = PROC_LDE_ENGINE;
log_procname = log_procnames[PROC_LDE_ENGINE]; log_procname = log_procnames[PROC_LDE_ENGINE];
master = thread_master_create(); master = thread_master_create(NULL);
/* setup signal handler */ /* setup signal handler */
signal_init(master, array_size(lde_signals), lde_signals); signal_init(master, array_size(lde_signals), lde_signals);

View File

@ -109,7 +109,7 @@ ldpe(void)
ldpd_process = PROC_LDP_ENGINE; ldpd_process = PROC_LDP_ENGINE;
log_procname = log_procnames[ldpd_process]; log_procname = log_procnames[ldpd_process];
master = thread_master_create(); master = thread_master_create(NULL);
/* setup signal handler */ /* setup signal handler */
signal_init(master, array_size(ldpe_signals), ldpe_signals); signal_init(master, array_size(ldpe_signals), ldpe_signals);

View File

@ -86,7 +86,7 @@ struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
XCALLOC(MTYPE_FRR_PTHREAD, XCALLOC(MTYPE_FRR_PTHREAD,
sizeof(struct frr_pthread)); sizeof(struct frr_pthread));
fpt->id = id; fpt->id = id;
fpt->master = thread_master_create(); fpt->master = thread_master_create(name);
fpt->start_routine = start_routine; fpt->start_routine = start_routine;
fpt->stop_routine = stop_routine; fpt->stop_routine = stop_routine;
fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);

View File

@ -38,7 +38,7 @@ int main(int argc, char **argv)
{ {
struct thread thread; struct thread thread;
master = thread_master_create (); master = thread_master_create(NULL);
openzlog ("grammar_sandbox", "NONE", 0, openzlog ("grammar_sandbox", "NONE", 0,
LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);

View File

@ -366,7 +366,7 @@ struct thread_master *frr_init(void)
zprivs_init(di->privs); zprivs_init(di->privs);
master = thread_master_create(); master = thread_master_create(NULL);
signal_init(master, di->n_signals, di->signals); signal_init(master, di->n_signals, di->signals);
if (di->flags & FRR_LIMITED_CLI) if (di->flags & FRR_LIMITED_CLI)

View File

@ -509,16 +509,18 @@ zlog_signal(int signo, const char *action
); );
s = buf; s = buf;
if (!thread_current) struct thread *tc;
tc = pthread_getspecific (thread_current);
if (!tc)
s = str_append (LOC, "no thread information available\n"); s = str_append (LOC, "no thread information available\n");
else else
{ {
s = str_append (LOC, "in thread "); 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, " scheduled from ");
s = str_append (LOC, thread_current->schedfrom); s = str_append (LOC, tc->schedfrom);
s = str_append (LOC, ":"); s = str_append (LOC, ":");
s = num_append (LOC, thread_current->schedfrom_line); s = num_append (LOC, tc->schedfrom_line);
s = str_append (LOC, "\n"); s = str_append (LOC, "\n");
} }
@ -700,10 +702,13 @@ ZLOG_FUNC(zlog_debug, LOG_DEBUG)
void zlog_thread_info (int log_level) 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 " zlog(log_level, "Current thread function %s, scheduled from "
"file %s, line %u", thread_current->funcname, "file %s, line %u", tc->funcname,
thread_current->schedfrom, thread_current->schedfrom_line); tc->schedfrom, tc->schedfrom_line);
else else
zlog(log_level, "Current thread not known/applicable"); zlog(log_level, "Current thread not known/applicable");
} }

View File

@ -47,16 +47,15 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
write (m->io_pipe[1], &wakebyte, 1); \ write (m->io_pipe[1], &wakebyte, 1); \
} while (0); } while (0);
static pthread_mutex_t cpu_record_mtx = PTHREAD_MUTEX_INITIALIZER; /* control variable for initializer */
static struct hash *cpu_record = NULL; pthread_once_t init_once = PTHREAD_ONCE_INIT;
pthread_key_t thread_current;
static unsigned long pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
timeval_elapsed (struct timeval a, struct timeval b) static struct list *masters;
{
return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
+ (a.tv_usec - b.tv_usec));
}
/* CLI start ---------------------------------------------------------------- */
static unsigned int static unsigned int
cpu_record_hash_key (struct cpu_thread_history *a) cpu_record_hash_key (struct cpu_thread_history *a)
{ {
@ -106,12 +105,12 @@ vty_out_cpu_thread_history(struct vty* vty,
} }
static void static void
cpu_record_hash_print(struct hash_backet *bucket, cpu_record_hash_print(struct hash_backet *bucket, void *args[])
void *args[])
{ {
struct cpu_thread_history *totals = args[0]; struct cpu_thread_history *totals = args[0];
struct vty *vty = args[1]; struct vty *vty = args[1];
thread_type *filter = args[2]; thread_type *filter = args[2];
struct cpu_thread_history *a = bucket->data; struct cpu_thread_history *a = bucket->data;
if ( !(a->types & *filter) ) if ( !(a->types & *filter) )
@ -132,29 +131,131 @@ cpu_record_print(struct vty *vty, thread_type filter)
{ {
struct cpu_thread_history tmp; struct cpu_thread_history tmp;
void *args[3] = {&tmp, vty, &filter}; void *args[3] = {&tmp, vty, &filter};
struct thread_master *m;
struct listnode *ln;
memset(&tmp, 0, sizeof tmp); memset(&tmp, 0, sizeof tmp);
tmp.funcname = "TOTAL"; tmp.funcname = "TOTAL";
tmp.types = filter; tmp.types = filter;
vty_outln (vty, "%21s %18s %18s", pthread_mutex_lock (&masters_mtx);
"", "CPU (user+system):", "Real (wall-clock):"); {
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, "Active Runtime(ms) Invoked Avg uSec Max uSecs");
vty_out(vty, " Avg uSec Max uSecs"); vty_out(vty, " Avg uSec Max uSecs");
vty_outln (vty, " Type Thread"); vty_outln(vty, " Type Thread");
pthread_mutex_lock (&cpu_record_mtx); if (m->cpu_record->count)
{ hash_iterate(m->cpu_record,
hash_iterate(cpu_record, (void (*)(struct hash_backet *, void *))
(void(*)(struct hash_backet*,void*))cpu_record_hash_print, cpu_record_hash_print,
args); 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) if (tmp.total_calls > 0)
vty_out_cpu_thread_history(vty, &tmp); vty_out_cpu_thread_history(vty, &tmp);
} }
static void
cpu_record_hash_clear (struct hash_backet *bucket, void *args[])
{
thread_type *filter = args[0];
struct hash *cpu_record = args[1];
struct cpu_thread_history *a = bucket->data;
if ( !(a->types & *filter) )
return;
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 (&masters_mtx);
{
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 (&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, DEFUN (show_thread_cpu,
show_thread_cpu_cmd, show_thread_cpu_cmd,
"show thread cpu [FILTER]", "show thread cpu [FILTER]",
@ -163,47 +264,14 @@ DEFUN (show_thread_cpu,
"Thread CPU usage\n" "Thread CPU usage\n"
"Display filter (rwtexb)\n") "Display filter (rwtexb)\n")
{ {
int idx_filter = 3;
int i = 0;
thread_type filter = (thread_type) -1U; thread_type filter = (thread_type) -1U;
int idx = 0;
if (argc > 3) if (argv_find (argv, argc, "FILTER", &idx)) {
{ filter = parse_filter (argv[idx]->arg);
filter = 0; if (!filter) {
while (argv[idx_filter]->arg[i] != '\0') vty_outln(vty, "Invalid filter \"%s\" specified; must contain at least"
{ "one of 'RWTEXB'%s", argv[idx]->arg);
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; return CMD_WARNING;
} }
} }
@ -212,86 +280,22 @@ DEFUN (show_thread_cpu,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static void
cpu_record_hash_clear (struct hash_backet *bucket,
void *args)
{
thread_type *filter = args;
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);
}
static void
cpu_record_clear (thread_type filter)
{
thread_type *tmp = &filter;
pthread_mutex_lock (&cpu_record_mtx);
{
hash_iterate (cpu_record,
(void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
tmp);
}
pthread_mutex_unlock (&cpu_record_mtx);
}
DEFUN (clear_thread_cpu, DEFUN (clear_thread_cpu,
clear_thread_cpu_cmd, clear_thread_cpu_cmd,
"clear thread cpu [FILTER]", "clear thread cpu [FILTER]",
"Clear stored data\n" "Clear stored data in all pthreads\n"
"Thread information\n" "Thread information\n"
"Thread CPU usage\n" "Thread CPU usage\n"
"Display filter (rwtexb)\n") "Display filter (rwtexb)\n")
{ {
int idx_filter = 3;
int i = 0;
thread_type filter = (thread_type) -1U; thread_type filter = (thread_type) -1U;
int idx = 0;
if (argc > 3) if (argv_find (argv, argc, "FILTER", &idx)) {
{ filter = parse_filter (argv[idx]->arg);
filter = 0; if (!filter) {
while (argv[idx_filter]->arg[i] != '\0') vty_outln(vty, "Invalid filter \"%s\" specified; must contain at least"
{ "one of 'RWTEXB'%s", argv[idx]->arg);
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; return CMD_WARNING;
} }
} }
@ -306,6 +310,8 @@ thread_cmd_init (void)
install_element (VIEW_NODE, &show_thread_cpu_cmd); install_element (VIEW_NODE, &show_thread_cpu_cmd);
install_element (ENABLE_NODE, &clear_thread_cpu_cmd); install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
} }
/* CLI end ------------------------------------------------------------------ */
static int static int
thread_timer_cmp(void *a, void *b) thread_timer_cmp(void *a, void *b)
@ -334,31 +340,37 @@ cancelreq_del (void *cr)
XFREE (MTYPE_TMP, 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. */ /* Allocate new thread master. */
struct thread_master * struct thread_master *
thread_master_create (void) thread_master_create (const char *name)
{ {
struct thread_master *rv; struct thread_master *rv;
struct rlimit limit; struct rlimit limit;
getrlimit(RLIMIT_NOFILE, &limit); pthread_once (&init_once, &initializer);
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);
rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master)); rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master));
if (rv == NULL) if (rv == NULL)
return NULL; return NULL;
/* Initialize master mutex */
pthread_mutex_init (&rv->mtx, NULL); pthread_mutex_init (&rv->mtx, NULL);
pthread_cond_init (&rv->cancel_cond, 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->fd_limit = (int)limit.rlim_cur;
rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit);
if (rv->read == NULL) if (rv->read == NULL)
@ -366,7 +378,6 @@ thread_master_create (void)
XFREE (MTYPE_THREAD_MASTER, rv); XFREE (MTYPE_THREAD_MASTER, rv);
return NULL; return NULL;
} }
rv->write = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); rv->write = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit);
if (rv->write == NULL) if (rv->write == NULL)
{ {
@ -375,20 +386,32 @@ thread_master_create (void)
return NULL; 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 */ /* Initialize the timer queues */
rv->timer = pqueue_create(); rv->timer = pqueue_create();
rv->timer->cmp = thread_timer_cmp; rv->timer->cmp = thread_timer_cmp;
rv->timer->update = thread_timer_update; rv->timer->update = thread_timer_update;
/* Initialize thread_fetch() settings */
rv->spin = true; rv->spin = true;
rv->handle_signals = true; rv->handle_signals = true;
/* Set pthread owner, should be updated by actual owner */
rv->owner = pthread_self(); rv->owner = pthread_self();
rv->cancel_req = list_new (); rv->cancel_req = list_new ();
rv->cancel_req->del = cancelreq_del; rv->cancel_req->del = cancelreq_del;
rv->canceled = true; rv->canceled = true;
/* Initialize pipe poker */
pipe (rv->io_pipe); pipe (rv->io_pipe);
set_nonblocking (rv->io_pipe[0]); set_nonblocking (rv->io_pipe[0]);
set_nonblocking (rv->io_pipe[1]); set_nonblocking (rv->io_pipe[1]);
/* Initialize data structures for poll() */
rv->handler.pfdsize = rv->fd_limit; rv->handler.pfdsize = rv->fd_limit;
rv->handler.pfdcount = 0; rv->handler.pfdcount = 0;
rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER, rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER,
@ -396,6 +419,13 @@ thread_master_create (void)
rv->handler.copy = XCALLOC (MTYPE_THREAD_MASTER, rv->handler.copy = XCALLOC (MTYPE_THREAD_MASTER,
sizeof (struct pollfd) * rv->handler.pfdsize); 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; return rv;
} }
@ -545,20 +575,13 @@ thread_master_free (struct thread_master *m)
close (m->io_pipe[1]); close (m->io_pipe[1]);
list_delete (m->cancel_req); 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.pfds);
XFREE (MTYPE_THREAD_MASTER, m->handler.copy); XFREE (MTYPE_THREAD_MASTER, m->handler.copy);
XFREE (MTYPE_THREAD_MASTER, m); 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. */ /* Return remain time in second. */
@ -630,13 +653,9 @@ thread_get (struct thread_master *m, u_char type,
{ {
tmp.func = func; tmp.func = func;
tmp.funcname = funcname; tmp.funcname = funcname;
pthread_mutex_lock (&cpu_record_mtx); thread->hist = hash_get (m->cpu_record, &tmp,
{
thread->hist = hash_get (cpu_record, &tmp,
(void * (*) (void *))cpu_record_hash_alloc); (void * (*) (void *))cpu_record_hash_alloc);
} }
pthread_mutex_unlock (&cpu_record_mtx);
}
thread->hist->total_active++; thread->hist->total_active++;
thread->func = func; thread->func = func;
thread->funcname = funcname; thread->funcname = funcname;
@ -676,7 +695,7 @@ fd_poll (struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
num = poll (pfds, count + 1, timeout); num = poll (pfds, count + 1, timeout);
static unsigned char trash[64]; unsigned char trash[64];
if (num > 0 && pfds[count].revents != 0 && num--) if (num > 0 && pfds[count].revents != 0 && num--)
while (read (m->io_pipe[0], &trash, sizeof (trash)) > 0); while (read (m->io_pipe[0], &trash, sizeof (trash)) > 0);
@ -1401,6 +1420,13 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
return 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 unsigned long
thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) 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)); getrusage(RUSAGE_SELF, &(r->cpu));
} }
struct thread *thread_current = NULL;
/* We check thread consumed time. If the system has getrusage, we'll /* 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 use that to get in-depth stats on the performance of the thread in addition
to wall clock time stats from gettimeofday. */ to wall clock time stats from gettimeofday. */
@ -1463,9 +1487,9 @@ thread_call (struct thread *thread)
GETRUSAGE (&before); GETRUSAGE (&before);
thread->real = before.real; thread->real = before.real;
thread_current = thread; pthread_setspecific (thread_current, thread);
(*thread->func) (thread); (*thread->func) (thread);
thread_current = NULL; pthread_setspecific (thread_current, NULL);
GETRUSAGE (&after); GETRUSAGE (&after);
@ -1518,12 +1542,8 @@ funcname_thread_execute (struct thread_master *m,
tmp.func = dummy.func = func; tmp.func = dummy.func = func;
tmp.funcname = dummy.funcname = funcname; tmp.funcname = dummy.funcname = funcname;
pthread_mutex_lock (&cpu_record_mtx); dummy.hist = hash_get (m->cpu_record, &tmp,
{
dummy.hist = hash_get (cpu_record, &tmp,
(void * (*) (void *))cpu_record_hash_alloc); (void * (*) (void *))cpu_record_hash_alloc);
}
pthread_mutex_unlock (&cpu_record_mtx);
dummy.schedfrom = schedfrom; dummy.schedfrom = schedfrom;
dummy.schedfrom_line = fromln; dummy.schedfrom_line = fromln;

View File

@ -71,6 +71,8 @@ struct cancel_req {
/* Master of the theads. */ /* Master of the theads. */
struct thread_master struct thread_master
{ {
char *name;
struct thread **read; struct thread **read;
struct thread **write; struct thread **write;
struct pqueue *timer; struct pqueue *timer;
@ -80,6 +82,7 @@ struct thread_master
struct list *cancel_req; struct list *cancel_req;
bool canceled; bool canceled;
pthread_cond_t cancel_cond; pthread_cond_t cancel_cond;
struct hash *cpu_record;
int io_pipe[2]; int io_pipe[2];
int fd_limit; int fd_limit;
struct fd_handler handler; 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__) #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
/* Prototypes. */ /* 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 (struct thread_master *);
extern void thread_master_free_unused(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); unsigned long *cpu_time_elapsed);
/* only for use in logging functions! */ /* only for use in logging functions! */
extern struct thread *thread_current; extern pthread_key_t thread_current;
#endif /* _ZEBRA_THREAD_H */ #endif /* _ZEBRA_THREAD_H */

View File

@ -326,7 +326,7 @@ main (int argc, char *argv[])
/* Initialization */ /* Initialization */
zprivs_init (&ospfd_privs); zprivs_init (&ospfd_privs);
master = thread_master_create (); master = thread_master_create(NULL);
/* Open connection to OSPF daemon */ /* Open connection to OSPF daemon */
oclient = ospf_apiclient_connect (args[1], ASYNCPORT); oclient = ospf_apiclient_connect (args[1], ASYNCPORT);

View File

@ -1331,7 +1331,7 @@ main (void)
{ {
int i = 0; int i = 0;
qobj_init (); qobj_init ();
bgp_master_init (thread_master_create ()); bgp_master_init (thread_master_create(NULL));
master = bm->master; master = bm->master;
bgp_option_set (BGP_OPT_NO_LISTEN); bgp_option_set (BGP_OPT_NO_LISTEN);
bgp_attr_init (); bgp_attr_init ();

View File

@ -648,7 +648,7 @@ main (void)
term_bgp_debug_as4 = -1UL; term_bgp_debug_as4 = -1UL;
qobj_init (); qobj_init ();
master = thread_master_create (); master = thread_master_create(NULL);
bgp_master_init (master); bgp_master_init (master);
vrf_init (NULL, NULL, NULL, NULL); vrf_init (NULL, NULL, NULL, NULL);
bgp_option_set (BGP_OPT_NO_LISTEN); bgp_option_set (BGP_OPT_NO_LISTEN);

View File

@ -748,7 +748,7 @@ main (void)
term_bgp_debug_as4 = -1UL; term_bgp_debug_as4 = -1UL;
qobj_init (); qobj_init ();
master = thread_master_create (); master = thread_master_create(NULL);
bgp_master_init (master); bgp_master_init (master);
vrf_init (NULL, NULL, NULL, NULL); vrf_init (NULL, NULL, NULL, NULL);
bgp_option_set (BGP_OPT_NO_LISTEN); bgp_option_set (BGP_OPT_NO_LISTEN);

View File

@ -376,7 +376,7 @@ static int
global_test_init (void) global_test_init (void)
{ {
qobj_init (); qobj_init ();
master = thread_master_create (); master = thread_master_create(NULL);
zclient = zclient_new(master); zclient = zclient_new(master);
bgp_master_init (master); bgp_master_init (master);
vrf_init (NULL, NULL, NULL, NULL); vrf_init (NULL, NULL, NULL, NULL);

View File

@ -116,7 +116,7 @@ main (int argc, char **argv)
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
/* master init. */ /* master init. */
master = thread_master_create (); master = thread_master_create(NULL);
while (1) while (1)
{ {

View File

@ -67,7 +67,7 @@ main (int argc, char **argv)
umask (0027); umask (0027);
/* master init. */ /* master init. */
master = thread_master_create (); master = thread_master_create(NULL);
openzlog("common-cli", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, openzlog("common-cli", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID,
LOG_DAEMON); LOG_DAEMON);

View File

@ -45,7 +45,7 @@ threadfunc (struct thread *thread)
int int
main (void) main (void)
{ {
master = thread_master_create (); master = thread_master_create(NULL);
signal_init (master, array_size(sigs), sigs); signal_init (master, array_size(sigs), sigs);
openzlog("testsegv", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); openzlog("testsegv", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);

View File

@ -61,7 +61,7 @@ struct thread t;
int int
main (void) main (void)
{ {
master = thread_master_create (); master = thread_master_create(NULL);
signal_init (master, array_size(sigs), sigs); signal_init (master, array_size(sigs), sigs);
openzlog("testsig", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); openzlog("testsig", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);

View File

@ -115,7 +115,7 @@ int main(int argc, char **argv)
struct thread t; struct thread t;
struct timeval **alarms; struct timeval **alarms;
master = thread_master_create(); master = thread_master_create(NULL);
log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1;
log_buf_pos = 0; log_buf_pos = 0;

View File

@ -49,7 +49,7 @@ int main(int argc, char **argv)
struct timeval tv_start, tv_lap, tv_stop; struct timeval tv_start, tv_lap, tv_stop;
unsigned long t_schedule, t_remove; unsigned long t_schedule, t_remove;
master = thread_master_create(); master = thread_master_create(NULL);
prng = prng_new(0); prng = prng_new(0);
timers = calloc(SCHEDULE_TIMERS, sizeof(*timers)); timers = calloc(SCHEDULE_TIMERS, sizeof(*timers));

View File

@ -140,7 +140,7 @@ int main (int argc, char *argv[])
printf ("Sequence to be tested: %s\n", sequence); printf ("Sequence to be tested: %s\n", sequence);
master = thread_master_create(); master = thread_master_create(NULL);
init_zclient (master, ZSERV_PATH); init_zclient (master, ZSERV_PATH);
zebra_send_label_manager_connect (); zebra_send_label_manager_connect ();

View File

@ -200,7 +200,7 @@ main (int argc, char **argv)
if (argc == 1) if (argc == 1)
usage_exit (); usage_exit ();
master = thread_master_create(); master = thread_master_create(NULL);
/* Establish connection to zebra. */ /* Establish connection to zebra. */
zclient = zclient_new(master); zclient = zclient_new(master);
zclient->enable = 1; zclient->enable = 1;