lib/xref: use to transport thread_* file/line/func

Just a better way of doing what was previously the "debugargdef" macro.

Signed-off-by: David Lamparter <equinox@diac24.net>
This commit is contained in:
David Lamparter 2020-04-28 09:30:50 +02:00
parent b2fa8c0fa3
commit 60a3efec24
8 changed files with 181 additions and 137 deletions

View File

@ -74,7 +74,8 @@ int isis_run_dr(struct thread *thread)
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
zlog_warn("%s: scheduled for non broadcast circuit from %s:%d",
__func__, thread->schedfrom, thread->schedfrom_line);
__func__, thread->xref->xref.file,
thread->xref->xref.line);
return ISIS_WARNING;
}

View File

@ -135,9 +135,8 @@ static int frrzmq_read_msg(struct thread *t)
if (read)
frrzmq_check_events(cbp, &cb->write, ZMQ_POLLOUT);
funcname_thread_add_read_write(
THREAD_READ, t->master, frrzmq_read_msg, cbp, cb->fd,
&cb->read.thread, t->funcname, t->schedfrom, t->schedfrom_line);
_thread_add_read_write(t->xref, t->master, frrzmq_read_msg, cbp,
cb->fd, &cb->read.thread);
return 0;
out_err:
@ -148,14 +147,14 @@ out_err:
return 1;
}
int funcname_frrzmq_thread_add_read(struct thread_master *master,
void (*msgfunc)(void *arg, void *zmqsock),
void (*partfunc)(void *arg, void *zmqsock,
zmq_msg_t *msg,
unsigned partnum),
void (*errfunc)(void *arg, void *zmqsock),
void *arg, void *zmqsock,
struct frrzmq_cb **cbp, debugargdef)
int _frrzmq_thread_add_read(const struct xref_threadsched *xref,
struct thread_master *master,
void (*msgfunc)(void *arg, void *zmqsock),
void (*partfunc)(void *arg, void *zmqsock,
zmq_msg_t *msg, unsigned partnum),
void (*errfunc)(void *arg, void *zmqsock),
void *arg, void *zmqsock,
struct frrzmq_cb **cbp)
{
int fd, events;
size_t len;
@ -192,13 +191,11 @@ int funcname_frrzmq_thread_add_read(struct thread_master *master,
if (events & ZMQ_POLLIN) {
thread_cancel(&cb->read.thread);
funcname_thread_add_event(master, frrzmq_read_msg, cbp, fd,
&cb->read.thread, funcname, schedfrom,
fromln);
_thread_add_event(xref, master, frrzmq_read_msg, cbp, fd,
&cb->read.thread);
} else
funcname_thread_add_read_write(
THREAD_READ, master, frrzmq_read_msg, cbp, fd,
&cb->read.thread, funcname, schedfrom, fromln);
_thread_add_read_write(xref, master, frrzmq_read_msg, cbp, fd,
&cb->read.thread);
return 0;
}
@ -244,10 +241,8 @@ static int frrzmq_write_msg(struct thread *t)
if (written)
frrzmq_check_events(cbp, &cb->read, ZMQ_POLLIN);
funcname_thread_add_read_write(THREAD_WRITE, t->master,
frrzmq_write_msg, cbp, cb->fd,
&cb->write.thread, t->funcname,
t->schedfrom, t->schedfrom_line);
_thread_add_read_write(t->xref, t->master, frrzmq_write_msg, cbp,
cb->fd, &cb->write.thread);
return 0;
out_err:
@ -257,11 +252,12 @@ out_err:
cb->write.cb_error(cb->write.arg, cb->zmqsock);
return 1;
}
int funcname_frrzmq_thread_add_write(struct thread_master *master,
void (*msgfunc)(void *arg, void *zmqsock),
void (*errfunc)(void *arg, void *zmqsock),
void *arg, void *zmqsock,
struct frrzmq_cb **cbp, debugargdef)
int _frrzmq_thread_add_write(const struct xref_threadsched *xref,
struct thread_master *master,
void (*msgfunc)(void *arg, void *zmqsock),
void (*errfunc)(void *arg, void *zmqsock),
void *arg, void *zmqsock, struct frrzmq_cb **cbp)
{
int fd, events;
size_t len;
@ -298,13 +294,11 @@ int funcname_frrzmq_thread_add_write(struct thread_master *master,
if (events & ZMQ_POLLOUT) {
thread_cancel(&cb->write.thread);
funcname_thread_add_event(master, frrzmq_write_msg, cbp, fd,
&cb->write.thread, funcname,
schedfrom, fromln);
_thread_add_event(xref, master, frrzmq_write_msg, cbp, fd,
&cb->write.thread);
} else
funcname_thread_add_read_write(
THREAD_WRITE, master, frrzmq_write_msg, cbp, fd,
&cb->write.thread, funcname, schedfrom, fromln);
_thread_add_read_write(xref, master, frrzmq_write_msg, cbp, fd,
&cb->write.thread);
return 0;
}

View File

@ -67,18 +67,32 @@ extern void *frrzmq_context;
extern void frrzmq_init(void);
extern void frrzmq_finish(void);
#define debugargdef const char *funcname, const char *schedfrom, int fromln
#define _xref_zmq_a(type, f, d, call) \
({ \
static const struct xref_threadsched _xref \
__attribute__((used)) = { \
.xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
.funcname = #f, \
.dest = #d, \
.thread_type = THREAD_ ## type, \
}; \
XREF_LINK(_xref.xref); \
call; \
}) \
/* end */
/* core event registration, one of these 2 macros should be used */
#define frrzmq_thread_add_read_msg(m, f, e, a, z, d) \
funcname_frrzmq_thread_add_read(m, f, NULL, e, a, z, d, #f, __FILE__, \
__LINE__)
_xref_zmq_a(READ, f, d, \
_frrzmq_thread_add_read(&_xref, m, f, NULL, e, a, z, d))
#define frrzmq_thread_add_read_part(m, f, e, a, z, d) \
funcname_frrzmq_thread_add_read(m, NULL, f, e, a, z, d, #f, __FILE__, \
__LINE__)
_xref_zmq_a(READ, f, d, \
_frrzmq_thread_add_read(&_xref, m, NULL, f, e, a, z, d))
#define frrzmq_thread_add_write_msg(m, f, e, a, z, d) \
funcname_frrzmq_thread_add_write(m, f, e, a, z, d, #f, __FILE__, \
__LINE__)
_xref_zmq_a(WRITE, f, d, \
_frrzmq_thread_add_write(&_xref, m, f, e, a, z, d))
struct cb_core;
struct frrzmq_cb;
@ -104,16 +118,18 @@ struct frrzmq_cb;
* may schedule the event to run as soon as libfrr is back in its main
* loop.
*/
extern int funcname_frrzmq_thread_add_read(
struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock),
extern int _frrzmq_thread_add_read(
const struct xref_threadsched *xref, struct thread_master *master,
void (*msgfunc)(void *arg, void *zmqsock),
void (*partfunc)(void *arg, void *zmqsock, zmq_msg_t *msg,
unsigned partnum),
void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock,
struct frrzmq_cb **cb, debugargdef);
extern int funcname_frrzmq_thread_add_write(
struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock),
struct frrzmq_cb **cb);
extern int _frrzmq_thread_add_write(
const struct xref_threadsched *xref, struct thread_master *master,
void (*msgfunc)(void *arg, void *zmqsock),
void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock,
struct frrzmq_cb **cb, debugargdef);
struct frrzmq_cb **cb);
extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core);

View File

@ -161,8 +161,9 @@ void zlog_signal(int signo, const char *action, void *siginfo_v,
if (!tc)
bprintfrr(&fb, "no thread information available\n");
else
bprintfrr(&fb, "in thread %s scheduled from %s:%d\n",
tc->funcname, tc->schedfrom, tc->schedfrom_line);
bprintfrr(&fb, "in thread %s scheduled from %s:%d %s()\n",
tc->xref->funcname, tc->xref->xref.file,
tc->xref->xref.line, tc->xref->xref.func);
zlog_sigsafe(fb.buf, fb.pos - fb.buf);
}
@ -300,8 +301,9 @@ void zlog_thread_info(int log_level)
if (tc)
zlog(log_level,
"Current thread function %s, scheduled from file %s, line %u",
tc->funcname, tc->schedfrom, tc->schedfrom_line);
"Current thread function %s, scheduled from file %s, line %u in %s()",
tc->xref->funcname, tc->xref->xref.file,
tc->xref->xref.line, tc->xref->xref.func);
else
zlog(log_level, "Current thread not known/applicable");
}

View File

@ -342,7 +342,7 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
if (!thread)
vty_out(vty, "ERROR ");
else
vty_out(vty, "%s ", thread->funcname);
vty_out(vty, "%s ", thread->xref->funcname);
} else
vty_out(vty, " ");
@ -352,7 +352,7 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
if (!thread)
vty_out(vty, "ERROR\n");
else
vty_out(vty, "%s\n", thread->funcname);
vty_out(vty, "%s\n", thread->xref->funcname);
} else
vty_out(vty, "\n");
}
@ -678,7 +678,7 @@ char *thread_timer_to_hhmmss(char *buf, int buf_size,
/* Get new thread. */
static struct thread *thread_get(struct thread_master *m, uint8_t type,
int (*func)(struct thread *), void *arg,
debugargdef)
const struct xref_threadsched *xref)
{
struct thread *thread = thread_list_pop(&m->unuse);
struct cpu_thread_history tmp;
@ -707,18 +707,17 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
* This hopefully saves us some serious
* hash_get lookups.
*/
if (thread->funcname != funcname || thread->func != func) {
if ((thread->xref && thread->xref->funcname != xref->funcname)
|| thread->func != func) {
tmp.func = func;
tmp.funcname = funcname;
tmp.funcname = xref->funcname;
thread->hist =
hash_get(m->cpu_record, &tmp,
(void *(*)(void *))cpu_record_hash_alloc);
}
thread->hist->total_active++;
thread->func = func;
thread->funcname = funcname;
thread->schedfrom = schedfrom;
thread->schedfrom_line = fromln;
thread->xref = xref;
return thread;
}
@ -832,12 +831,12 @@ done:
}
/* Add new read thread. */
struct thread *funcname_thread_add_read_write(int dir, struct thread_master *m,
int (*func)(struct thread *),
void *arg, int fd,
struct thread **t_ptr,
debugargdef)
struct thread *_thread_add_read_write(const struct xref_threadsched *xref,
struct thread_master *m,
int (*func)(struct thread *),
void *arg, int fd, struct thread **t_ptr)
{
int dir = xref->thread_type;
struct thread *thread = NULL;
struct thread **thread_array;
@ -882,7 +881,7 @@ struct thread *funcname_thread_add_read_write(int dir, struct thread_master *m,
/* make sure we have room for this fd + pipe poker fd */
assert(queuepos + 1 < m->handler.pfdsize);
thread = thread_get(m, dir, func, arg, debugargpass);
thread = thread_get(m, dir, func, arg, xref);
m->handler.pfds[queuepos].fd = fd;
m->handler.pfds[queuepos].events |=
@ -910,10 +909,10 @@ struct thread *funcname_thread_add_read_write(int dir, struct thread_master *m,
}
static struct thread *
funcname_thread_add_timer_timeval(struct thread_master *m,
int (*func)(struct thread *), int type,
void *arg, struct timeval *time_relative,
struct thread **t_ptr, debugargdef)
_thread_add_timer_timeval(const struct xref_threadsched *xref,
struct thread_master *m, int (*func)(struct thread *),
int type, void *arg, struct timeval *time_relative,
struct thread **t_ptr)
{
struct thread *thread;
@ -930,7 +929,7 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
/* thread is already scheduled; don't reschedule */
return NULL;
thread = thread_get(m, type, func, arg, debugargpass);
thread = thread_get(m, type, func, arg, xref);
frr_with_mutex(&thread->mtx) {
monotime(&thread->u.sands);
@ -951,10 +950,10 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
/* Add timer event thread. */
struct thread *funcname_thread_add_timer(struct thread_master *m,
int (*func)(struct thread *),
void *arg, long timer,
struct thread **t_ptr, debugargdef)
struct thread *_thread_add_timer(const struct xref_threadsched *xref,
struct thread_master *m,
int (*func)(struct thread *),
void *arg, long timer, struct thread **t_ptr)
{
struct timeval trel;
@ -963,16 +962,16 @@ struct thread *funcname_thread_add_timer(struct thread_master *m,
trel.tv_sec = timer;
trel.tv_usec = 0;
return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg,
&trel, t_ptr, debugargpass);
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg,
&trel, t_ptr);
}
/* Add timer event thread with "millisecond" resolution */
struct thread *funcname_thread_add_timer_msec(struct thread_master *m,
int (*func)(struct thread *),
void *arg, long timer,
struct thread **t_ptr,
debugargdef)
struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref,
struct thread_master *m,
int (*func)(struct thread *),
void *arg, long timer,
struct thread **t_ptr)
{
struct timeval trel;
@ -981,25 +980,26 @@ struct thread *funcname_thread_add_timer_msec(struct thread_master *m,
trel.tv_sec = timer / 1000;
trel.tv_usec = 1000 * (timer % 1000);
return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg,
&trel, t_ptr, debugargpass);
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg,
&trel, t_ptr);
}
/* Add timer event thread with "millisecond" resolution */
struct thread *funcname_thread_add_timer_tv(struct thread_master *m,
int (*func)(struct thread *),
void *arg, struct timeval *tv,
struct thread **t_ptr, debugargdef)
struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref,
struct thread_master *m,
int (*func)(struct thread *),
void *arg, struct timeval *tv,
struct thread **t_ptr)
{
return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg, tv,
t_ptr, debugargpass);
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, tv,
t_ptr);
}
/* Add simple event thread. */
struct thread *funcname_thread_add_event(struct thread_master *m,
int (*func)(struct thread *),
void *arg, int val,
struct thread **t_ptr, debugargdef)
struct thread *_thread_add_event(const struct xref_threadsched *xref,
struct thread_master *m,
int (*func)(struct thread *),
void *arg, int val, struct thread **t_ptr)
{
struct thread *thread = NULL;
@ -1013,7 +1013,7 @@ struct thread *funcname_thread_add_event(struct thread_master *m,
/* thread is already scheduled; don't reschedule */
break;
thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
thread = thread_get(m, THREAD_EVENT, func, arg, xref);
frr_with_mutex(&thread->mtx) {
thread->u.val = val;
thread_list_add_tail(&m->event, thread);
@ -1724,7 +1724,7 @@ void thread_call(struct thread *thread)
flog_warn(
EC_LIB_SLOW_THREAD,
"SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
thread->funcname, (unsigned long)thread->func,
thread->xref->funcname, (unsigned long)thread->func,
realtime / 1000, cputime / 1000);
}
#endif /* CONSUMED_TIME_CHECK */
@ -1732,15 +1732,15 @@ void thread_call(struct thread *thread)
}
/* Execute thread */
void funcname_thread_execute(struct thread_master *m,
int (*func)(struct thread *), void *arg, int val,
debugargdef)
void _thread_execute(const struct xref_threadsched *xref,
struct thread_master *m, int (*func)(struct thread *),
void *arg, int val)
{
struct thread *thread;
/* Get or allocate new thread to execute. */
frr_with_mutex(&m->mtx) {
thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
thread = thread_get(m, THREAD_EVENT, func, arg, xref);
/* Set its event value. */
frr_with_mutex(&thread->mtx) {

View File

@ -27,6 +27,7 @@
#include "monotime.h"
#include "frratomic.h"
#include "typesafe.h"
#include "xref.h"
#ifdef __cplusplus
extern "C" {
@ -66,6 +67,14 @@ struct cancel_req {
struct thread **threadref;
};
struct xref_threadsched {
struct xref xref;
const char *funcname;
const char *dest;
uint32_t thread_type;
};
/* Master of the theads. */
struct thread_master {
char *name;
@ -107,9 +116,7 @@ struct thread {
struct timeval real;
struct cpu_thread_history *hist; /* cache pointer to cpu_history */
unsigned long yield; /* yield time in microseconds */
const char *funcname; /* name of thread function */
const char *schedfrom; /* source file thread was scheduled from */
int schedfrom_line; /* line number of source file */
const struct xref_threadsched *xref; /* origin location */
pthread_mutex_t mtx; /* mutex for thread.c functions */
};
@ -156,17 +163,45 @@ struct cpu_thread_history {
thread_cancel(&(thread)); \
} while (0)
#define debugargdef const char *funcname, const char *schedfrom, int fromln
/*
* Macro wrappers to generate xrefs for all thread add calls. Includes
* file/line/function info for debugging/tracing.
*/
#include "lib/xref.h"
#define thread_add_read(m,f,a,v,t) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_add_write(m,f,a,v,t) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_add_timer(m,f,a,v,t) funcname_thread_add_timer(m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_add_timer_msec(m,f,a,v,t) funcname_thread_add_timer_msec(m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_add_timer_tv(m,f,a,v,t) funcname_thread_add_timer_tv(m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_add_event(m,f,a,v,t) funcname_thread_add_event(m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
#define thread_execute_name(m, f, a, v, n) \
funcname_thread_execute(m, f, a, v, n, __FILE__, __LINE__)
#define _xref_t_a(addfn, type, m, f, a, v, t) \
({ \
static const struct xref_threadsched _xref \
__attribute__((used)) = { \
.xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
.funcname = #f, \
.dest = #t, \
.thread_type = THREAD_ ## type, \
}; \
XREF_LINK(_xref.xref); \
_thread_add_ ## addfn(&_xref, m, f, a, v, t); \
}) \
/* end */
#define thread_add_read(m,f,a,v,t) _xref_t_a(read_write, READ, m,f,a,v,t)
#define thread_add_write(m,f,a,v,t) _xref_t_a(read_write, WRITE, m,f,a,v,t)
#define thread_add_timer(m,f,a,v,t) _xref_t_a(timer, TIMER, m,f,a,v,t)
#define thread_add_timer_msec(m,f,a,v,t) _xref_t_a(timer_msec, TIMER, m,f,a,v,t)
#define thread_add_timer_tv(m,f,a,v,t) _xref_t_a(timer_tv, TIMER, m,f,a,v,t)
#define thread_add_event(m,f,a,v,t) _xref_t_a(event, TIMER, m,f,a,v,t)
#define thread_execute(m,f,a,v) \
({ \
static const struct xref_threadsched _xref \
__attribute__((used)) = { \
.xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
.funcname = #f, \
.dest = NULL, \
.thread_type = THREAD_EXECUTE, \
}; \
XREF_LINK(_xref.xref); \
_thread_execute(&_xref, m, f, a, v); \
}) /* end */
/* Prototypes. */
extern struct thread_master *thread_master_create(const char *);
@ -174,35 +209,30 @@ void thread_master_set_name(struct thread_master *master, const char *name);
extern void thread_master_free(struct thread_master *);
extern void thread_master_free_unused(struct thread_master *);
extern struct thread *
funcname_thread_add_read_write(int dir, struct thread_master *,
int (*)(struct thread *), void *, int,
struct thread **, debugargdef);
extern struct thread *_thread_add_read_write(
const struct xref_threadsched *xref, struct thread_master *master,
int (*fn)(struct thread *), void *arg, int fd, struct thread **tref);
extern struct thread *funcname_thread_add_timer(struct thread_master *,
int (*)(struct thread *),
void *, long, struct thread **,
debugargdef);
extern struct thread *_thread_add_timer(
const struct xref_threadsched *xref, struct thread_master *master,
int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
extern struct thread *
funcname_thread_add_timer_msec(struct thread_master *, int (*)(struct thread *),
void *, long, struct thread **, debugargdef);
extern struct thread *_thread_add_timer_msec(
const struct xref_threadsched *xref, struct thread_master *master,
int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
extern struct thread *funcname_thread_add_timer_tv(struct thread_master *,
int (*)(struct thread *),
void *, struct timeval *,
struct thread **,
debugargdef);
extern struct thread *_thread_add_timer_tv(
const struct xref_threadsched *xref, struct thread_master *master,
int (*fn)(struct thread *), void *arg, struct timeval *tv,
struct thread **tref);
extern struct thread *funcname_thread_add_event(struct thread_master *,
int (*)(struct thread *),
void *, int, struct thread **,
debugargdef);
extern struct thread *_thread_add_event(
const struct xref_threadsched *xref, struct thread_master *master,
int (*fn)(struct thread *), void *arg, int val, struct thread **tref);
extern void funcname_thread_execute(struct thread_master *,
int (*)(struct thread *), void *, int,
debugargdef);
#undef debugargdef
extern void _thread_execute(const struct xref_threadsched *xref,
struct thread_master *master,
int (*fn)(struct thread *), void *arg, int val);
extern void thread_cancel(struct thread **event);
extern void thread_cancel_async(struct thread_master *, struct thread **,

View File

@ -73,8 +73,7 @@ static int wheel_timer_thread(struct thread *t)
wheel = THREAD_ARG(t);
thread_execute_name(wheel->master, wheel_timer_thread_helper,
wheel, 0, wheel->name);
thread_execute(wheel->master, wheel_timer_thread_helper, wheel, 0);
return 0;
}

View File

@ -25,6 +25,8 @@
enum xref_type {
XREFT_NONE = 0,
XREFT_THREADSCHED = 0x100,
};
/* struct xref is the "const" part; struct xrefdata is the writable part. */