mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-30 04:31:02 +00:00
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:
parent
b2fa8c0fa3
commit
60a3efec24
@ -74,7 +74,8 @@ int isis_run_dr(struct thread *thread)
|
|||||||
|
|
||||||
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
|
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
|
||||||
zlog_warn("%s: scheduled for non broadcast circuit from %s:%d",
|
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;
|
return ISIS_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,9 +135,8 @@ static int frrzmq_read_msg(struct thread *t)
|
|||||||
if (read)
|
if (read)
|
||||||
frrzmq_check_events(cbp, &cb->write, ZMQ_POLLOUT);
|
frrzmq_check_events(cbp, &cb->write, ZMQ_POLLOUT);
|
||||||
|
|
||||||
funcname_thread_add_read_write(
|
_thread_add_read_write(t->xref, t->master, frrzmq_read_msg, cbp,
|
||||||
THREAD_READ, t->master, frrzmq_read_msg, cbp, cb->fd,
|
cb->fd, &cb->read.thread);
|
||||||
&cb->read.thread, t->funcname, t->schedfrom, t->schedfrom_line);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
@ -148,14 +147,14 @@ out_err:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int funcname_frrzmq_thread_add_read(struct thread_master *master,
|
int _frrzmq_thread_add_read(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *master,
|
||||||
void (*msgfunc)(void *arg, void *zmqsock),
|
void (*msgfunc)(void *arg, void *zmqsock),
|
||||||
void (*partfunc)(void *arg, void *zmqsock,
|
void (*partfunc)(void *arg, void *zmqsock,
|
||||||
zmq_msg_t *msg,
|
zmq_msg_t *msg, unsigned partnum),
|
||||||
unsigned partnum),
|
|
||||||
void (*errfunc)(void *arg, void *zmqsock),
|
void (*errfunc)(void *arg, void *zmqsock),
|
||||||
void *arg, void *zmqsock,
|
void *arg, void *zmqsock,
|
||||||
struct frrzmq_cb **cbp, debugargdef)
|
struct frrzmq_cb **cbp)
|
||||||
{
|
{
|
||||||
int fd, events;
|
int fd, events;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -192,13 +191,11 @@ int funcname_frrzmq_thread_add_read(struct thread_master *master,
|
|||||||
if (events & ZMQ_POLLIN) {
|
if (events & ZMQ_POLLIN) {
|
||||||
thread_cancel(&cb->read.thread);
|
thread_cancel(&cb->read.thread);
|
||||||
|
|
||||||
funcname_thread_add_event(master, frrzmq_read_msg, cbp, fd,
|
_thread_add_event(xref, master, frrzmq_read_msg, cbp, fd,
|
||||||
&cb->read.thread, funcname, schedfrom,
|
&cb->read.thread);
|
||||||
fromln);
|
|
||||||
} else
|
} else
|
||||||
funcname_thread_add_read_write(
|
_thread_add_read_write(xref, master, frrzmq_read_msg, cbp, fd,
|
||||||
THREAD_READ, master, frrzmq_read_msg, cbp, fd,
|
&cb->read.thread);
|
||||||
&cb->read.thread, funcname, schedfrom, fromln);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,10 +241,8 @@ static int frrzmq_write_msg(struct thread *t)
|
|||||||
if (written)
|
if (written)
|
||||||
frrzmq_check_events(cbp, &cb->read, ZMQ_POLLIN);
|
frrzmq_check_events(cbp, &cb->read, ZMQ_POLLIN);
|
||||||
|
|
||||||
funcname_thread_add_read_write(THREAD_WRITE, t->master,
|
_thread_add_read_write(t->xref, t->master, frrzmq_write_msg, cbp,
|
||||||
frrzmq_write_msg, cbp, cb->fd,
|
cb->fd, &cb->write.thread);
|
||||||
&cb->write.thread, t->funcname,
|
|
||||||
t->schedfrom, t->schedfrom_line);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
@ -257,11 +252,12 @@ out_err:
|
|||||||
cb->write.cb_error(cb->write.arg, cb->zmqsock);
|
cb->write.cb_error(cb->write.arg, cb->zmqsock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int funcname_frrzmq_thread_add_write(struct thread_master *master,
|
|
||||||
|
int _frrzmq_thread_add_write(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *master,
|
||||||
void (*msgfunc)(void *arg, void *zmqsock),
|
void (*msgfunc)(void *arg, void *zmqsock),
|
||||||
void (*errfunc)(void *arg, void *zmqsock),
|
void (*errfunc)(void *arg, void *zmqsock),
|
||||||
void *arg, void *zmqsock,
|
void *arg, void *zmqsock, struct frrzmq_cb **cbp)
|
||||||
struct frrzmq_cb **cbp, debugargdef)
|
|
||||||
{
|
{
|
||||||
int fd, events;
|
int fd, events;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -298,13 +294,11 @@ int funcname_frrzmq_thread_add_write(struct thread_master *master,
|
|||||||
if (events & ZMQ_POLLOUT) {
|
if (events & ZMQ_POLLOUT) {
|
||||||
thread_cancel(&cb->write.thread);
|
thread_cancel(&cb->write.thread);
|
||||||
|
|
||||||
funcname_thread_add_event(master, frrzmq_write_msg, cbp, fd,
|
_thread_add_event(xref, master, frrzmq_write_msg, cbp, fd,
|
||||||
&cb->write.thread, funcname,
|
&cb->write.thread);
|
||||||
schedfrom, fromln);
|
|
||||||
} else
|
} else
|
||||||
funcname_thread_add_read_write(
|
_thread_add_read_write(xref, master, frrzmq_write_msg, cbp, fd,
|
||||||
THREAD_WRITE, master, frrzmq_write_msg, cbp, fd,
|
&cb->write.thread);
|
||||||
&cb->write.thread, funcname, schedfrom, fromln);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,18 +67,32 @@ extern void *frrzmq_context;
|
|||||||
extern void frrzmq_init(void);
|
extern void frrzmq_init(void);
|
||||||
extern void frrzmq_finish(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 */
|
/* core event registration, one of these 2 macros should be used */
|
||||||
#define frrzmq_thread_add_read_msg(m, f, e, a, z, d) \
|
#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__, \
|
_xref_zmq_a(READ, f, d, \
|
||||||
__LINE__)
|
_frrzmq_thread_add_read(&_xref, m, f, NULL, e, a, z, d))
|
||||||
|
|
||||||
#define frrzmq_thread_add_read_part(m, f, 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__, \
|
_xref_zmq_a(READ, f, d, \
|
||||||
__LINE__)
|
_frrzmq_thread_add_read(&_xref, m, NULL, f, e, a, z, d))
|
||||||
|
|
||||||
#define frrzmq_thread_add_write_msg(m, 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__, \
|
_xref_zmq_a(WRITE, f, d, \
|
||||||
__LINE__)
|
_frrzmq_thread_add_write(&_xref, m, f, e, a, z, d))
|
||||||
|
|
||||||
struct cb_core;
|
struct cb_core;
|
||||||
struct frrzmq_cb;
|
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
|
* may schedule the event to run as soon as libfrr is back in its main
|
||||||
* loop.
|
* loop.
|
||||||
*/
|
*/
|
||||||
extern int funcname_frrzmq_thread_add_read(
|
extern int _frrzmq_thread_add_read(
|
||||||
struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock),
|
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,
|
void (*partfunc)(void *arg, void *zmqsock, zmq_msg_t *msg,
|
||||||
unsigned partnum),
|
unsigned partnum),
|
||||||
void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock,
|
void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock,
|
||||||
struct frrzmq_cb **cb, debugargdef);
|
struct frrzmq_cb **cb);
|
||||||
extern int funcname_frrzmq_thread_add_write(
|
extern int _frrzmq_thread_add_write(
|
||||||
struct thread_master *master, void (*msgfunc)(void *arg, void *zmqsock),
|
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,
|
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);
|
extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core);
|
||||||
|
|
||||||
|
10
lib/log.c
10
lib/log.c
@ -161,8 +161,9 @@ void zlog_signal(int signo, const char *action, void *siginfo_v,
|
|||||||
if (!tc)
|
if (!tc)
|
||||||
bprintfrr(&fb, "no thread information available\n");
|
bprintfrr(&fb, "no thread information available\n");
|
||||||
else
|
else
|
||||||
bprintfrr(&fb, "in thread %s scheduled from %s:%d\n",
|
bprintfrr(&fb, "in thread %s scheduled from %s:%d %s()\n",
|
||||||
tc->funcname, tc->schedfrom, tc->schedfrom_line);
|
tc->xref->funcname, tc->xref->xref.file,
|
||||||
|
tc->xref->xref.line, tc->xref->xref.func);
|
||||||
|
|
||||||
zlog_sigsafe(fb.buf, fb.pos - fb.buf);
|
zlog_sigsafe(fb.buf, fb.pos - fb.buf);
|
||||||
}
|
}
|
||||||
@ -300,8 +301,9 @@ void zlog_thread_info(int log_level)
|
|||||||
|
|
||||||
if (tc)
|
if (tc)
|
||||||
zlog(log_level,
|
zlog(log_level,
|
||||||
"Current thread function %s, scheduled from file %s, line %u",
|
"Current thread function %s, scheduled from file %s, line %u in %s()",
|
||||||
tc->funcname, tc->schedfrom, tc->schedfrom_line);
|
tc->xref->funcname, tc->xref->xref.file,
|
||||||
|
tc->xref->xref.line, tc->xref->xref.func);
|
||||||
else
|
else
|
||||||
zlog(log_level, "Current thread not known/applicable");
|
zlog(log_level, "Current thread not known/applicable");
|
||||||
}
|
}
|
||||||
|
82
lib/thread.c
82
lib/thread.c
@ -342,7 +342,7 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
|
|||||||
if (!thread)
|
if (!thread)
|
||||||
vty_out(vty, "ERROR ");
|
vty_out(vty, "ERROR ");
|
||||||
else
|
else
|
||||||
vty_out(vty, "%s ", thread->funcname);
|
vty_out(vty, "%s ", thread->xref->funcname);
|
||||||
} else
|
} else
|
||||||
vty_out(vty, " ");
|
vty_out(vty, " ");
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
|
|||||||
if (!thread)
|
if (!thread)
|
||||||
vty_out(vty, "ERROR\n");
|
vty_out(vty, "ERROR\n");
|
||||||
else
|
else
|
||||||
vty_out(vty, "%s\n", thread->funcname);
|
vty_out(vty, "%s\n", thread->xref->funcname);
|
||||||
} else
|
} else
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
@ -678,7 +678,7 @@ char *thread_timer_to_hhmmss(char *buf, int buf_size,
|
|||||||
/* Get new thread. */
|
/* Get new thread. */
|
||||||
static struct thread *thread_get(struct thread_master *m, uint8_t type,
|
static struct thread *thread_get(struct thread_master *m, uint8_t type,
|
||||||
int (*func)(struct thread *), void *arg,
|
int (*func)(struct thread *), void *arg,
|
||||||
debugargdef)
|
const struct xref_threadsched *xref)
|
||||||
{
|
{
|
||||||
struct thread *thread = thread_list_pop(&m->unuse);
|
struct thread *thread = thread_list_pop(&m->unuse);
|
||||||
struct cpu_thread_history tmp;
|
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
|
* This hopefully saves us some serious
|
||||||
* hash_get lookups.
|
* 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.func = func;
|
||||||
tmp.funcname = funcname;
|
tmp.funcname = xref->funcname;
|
||||||
thread->hist =
|
thread->hist =
|
||||||
hash_get(m->cpu_record, &tmp,
|
hash_get(m->cpu_record, &tmp,
|
||||||
(void *(*)(void *))cpu_record_hash_alloc);
|
(void *(*)(void *))cpu_record_hash_alloc);
|
||||||
}
|
}
|
||||||
thread->hist->total_active++;
|
thread->hist->total_active++;
|
||||||
thread->func = func;
|
thread->func = func;
|
||||||
thread->funcname = funcname;
|
thread->xref = xref;
|
||||||
thread->schedfrom = schedfrom;
|
|
||||||
thread->schedfrom_line = fromln;
|
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
@ -832,12 +831,12 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add new read thread. */
|
/* Add new read thread. */
|
||||||
struct thread *funcname_thread_add_read_write(int dir, struct thread_master *m,
|
struct thread *_thread_add_read_write(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *m,
|
||||||
int (*func)(struct thread *),
|
int (*func)(struct thread *),
|
||||||
void *arg, int fd,
|
void *arg, int fd, struct thread **t_ptr)
|
||||||
struct thread **t_ptr,
|
|
||||||
debugargdef)
|
|
||||||
{
|
{
|
||||||
|
int dir = xref->thread_type;
|
||||||
struct thread *thread = NULL;
|
struct thread *thread = NULL;
|
||||||
struct thread **thread_array;
|
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 */
|
/* make sure we have room for this fd + pipe poker fd */
|
||||||
assert(queuepos + 1 < m->handler.pfdsize);
|
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].fd = fd;
|
||||||
m->handler.pfds[queuepos].events |=
|
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 *
|
static struct thread *
|
||||||
funcname_thread_add_timer_timeval(struct thread_master *m,
|
_thread_add_timer_timeval(const struct xref_threadsched *xref,
|
||||||
int (*func)(struct thread *), int type,
|
struct thread_master *m, int (*func)(struct thread *),
|
||||||
void *arg, struct timeval *time_relative,
|
int type, void *arg, struct timeval *time_relative,
|
||||||
struct thread **t_ptr, debugargdef)
|
struct thread **t_ptr)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
|
|
||||||
@ -930,7 +929,7 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
|
|||||||
/* thread is already scheduled; don't reschedule */
|
/* thread is already scheduled; don't reschedule */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
thread = thread_get(m, type, func, arg, debugargpass);
|
thread = thread_get(m, type, func, arg, xref);
|
||||||
|
|
||||||
frr_with_mutex(&thread->mtx) {
|
frr_with_mutex(&thread->mtx) {
|
||||||
monotime(&thread->u.sands);
|
monotime(&thread->u.sands);
|
||||||
@ -951,10 +950,10 @@ funcname_thread_add_timer_timeval(struct thread_master *m,
|
|||||||
|
|
||||||
|
|
||||||
/* Add timer event thread. */
|
/* Add timer event thread. */
|
||||||
struct thread *funcname_thread_add_timer(struct thread_master *m,
|
struct thread *_thread_add_timer(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *m,
|
||||||
int (*func)(struct thread *),
|
int (*func)(struct thread *),
|
||||||
void *arg, long timer,
|
void *arg, long timer, struct thread **t_ptr)
|
||||||
struct thread **t_ptr, debugargdef)
|
|
||||||
{
|
{
|
||||||
struct timeval trel;
|
struct timeval trel;
|
||||||
|
|
||||||
@ -963,16 +962,16 @@ struct thread *funcname_thread_add_timer(struct thread_master *m,
|
|||||||
trel.tv_sec = timer;
|
trel.tv_sec = timer;
|
||||||
trel.tv_usec = 0;
|
trel.tv_usec = 0;
|
||||||
|
|
||||||
return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg,
|
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg,
|
||||||
&trel, t_ptr, debugargpass);
|
&trel, t_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add timer event thread with "millisecond" resolution */
|
/* Add timer event thread with "millisecond" resolution */
|
||||||
struct thread *funcname_thread_add_timer_msec(struct thread_master *m,
|
struct thread *_thread_add_timer_msec(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *m,
|
||||||
int (*func)(struct thread *),
|
int (*func)(struct thread *),
|
||||||
void *arg, long timer,
|
void *arg, long timer,
|
||||||
struct thread **t_ptr,
|
struct thread **t_ptr)
|
||||||
debugargdef)
|
|
||||||
{
|
{
|
||||||
struct timeval trel;
|
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_sec = timer / 1000;
|
||||||
trel.tv_usec = 1000 * (timer % 1000);
|
trel.tv_usec = 1000 * (timer % 1000);
|
||||||
|
|
||||||
return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg,
|
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg,
|
||||||
&trel, t_ptr, debugargpass);
|
&trel, t_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add timer event thread with "millisecond" resolution */
|
/* Add timer event thread with "millisecond" resolution */
|
||||||
struct thread *funcname_thread_add_timer_tv(struct thread_master *m,
|
struct thread *_thread_add_timer_tv(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *m,
|
||||||
int (*func)(struct thread *),
|
int (*func)(struct thread *),
|
||||||
void *arg, struct timeval *tv,
|
void *arg, struct timeval *tv,
|
||||||
struct thread **t_ptr, debugargdef)
|
struct thread **t_ptr)
|
||||||
{
|
{
|
||||||
return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg, tv,
|
return _thread_add_timer_timeval(xref, m, func, THREAD_TIMER, arg, tv,
|
||||||
t_ptr, debugargpass);
|
t_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add simple event thread. */
|
/* Add simple event thread. */
|
||||||
struct thread *funcname_thread_add_event(struct thread_master *m,
|
struct thread *_thread_add_event(const struct xref_threadsched *xref,
|
||||||
|
struct thread_master *m,
|
||||||
int (*func)(struct thread *),
|
int (*func)(struct thread *),
|
||||||
void *arg, int val,
|
void *arg, int val, struct thread **t_ptr)
|
||||||
struct thread **t_ptr, debugargdef)
|
|
||||||
{
|
{
|
||||||
struct thread *thread = NULL;
|
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 */
|
/* thread is already scheduled; don't reschedule */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
|
thread = thread_get(m, THREAD_EVENT, func, arg, xref);
|
||||||
frr_with_mutex(&thread->mtx) {
|
frr_with_mutex(&thread->mtx) {
|
||||||
thread->u.val = val;
|
thread->u.val = val;
|
||||||
thread_list_add_tail(&m->event, thread);
|
thread_list_add_tail(&m->event, thread);
|
||||||
@ -1724,7 +1724,7 @@ void thread_call(struct thread *thread)
|
|||||||
flog_warn(
|
flog_warn(
|
||||||
EC_LIB_SLOW_THREAD,
|
EC_LIB_SLOW_THREAD,
|
||||||
"SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
|
"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);
|
realtime / 1000, cputime / 1000);
|
||||||
}
|
}
|
||||||
#endif /* CONSUMED_TIME_CHECK */
|
#endif /* CONSUMED_TIME_CHECK */
|
||||||
@ -1732,15 +1732,15 @@ void thread_call(struct thread *thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Execute thread */
|
/* Execute thread */
|
||||||
void funcname_thread_execute(struct thread_master *m,
|
void _thread_execute(const struct xref_threadsched *xref,
|
||||||
int (*func)(struct thread *), void *arg, int val,
|
struct thread_master *m, int (*func)(struct thread *),
|
||||||
debugargdef)
|
void *arg, int val)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
|
|
||||||
/* Get or allocate new thread to execute. */
|
/* Get or allocate new thread to execute. */
|
||||||
frr_with_mutex(&m->mtx) {
|
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. */
|
/* Set its event value. */
|
||||||
frr_with_mutex(&thread->mtx) {
|
frr_with_mutex(&thread->mtx) {
|
||||||
|
104
lib/thread.h
104
lib/thread.h
@ -27,6 +27,7 @@
|
|||||||
#include "monotime.h"
|
#include "monotime.h"
|
||||||
#include "frratomic.h"
|
#include "frratomic.h"
|
||||||
#include "typesafe.h"
|
#include "typesafe.h"
|
||||||
|
#include "xref.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -66,6 +67,14 @@ struct cancel_req {
|
|||||||
struct thread **threadref;
|
struct thread **threadref;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xref_threadsched {
|
||||||
|
struct xref xref;
|
||||||
|
|
||||||
|
const char *funcname;
|
||||||
|
const char *dest;
|
||||||
|
uint32_t thread_type;
|
||||||
|
};
|
||||||
|
|
||||||
/* Master of the theads. */
|
/* Master of the theads. */
|
||||||
struct thread_master {
|
struct thread_master {
|
||||||
char *name;
|
char *name;
|
||||||
@ -107,9 +116,7 @@ struct thread {
|
|||||||
struct timeval real;
|
struct timeval real;
|
||||||
struct cpu_thread_history *hist; /* cache pointer to cpu_history */
|
struct cpu_thread_history *hist; /* cache pointer to cpu_history */
|
||||||
unsigned long yield; /* yield time in microseconds */
|
unsigned long yield; /* yield time in microseconds */
|
||||||
const char *funcname; /* name of thread function */
|
const struct xref_threadsched *xref; /* origin location */
|
||||||
const char *schedfrom; /* source file thread was scheduled from */
|
|
||||||
int schedfrom_line; /* line number of source file */
|
|
||||||
pthread_mutex_t mtx; /* mutex for thread.c functions */
|
pthread_mutex_t mtx; /* mutex for thread.c functions */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,17 +163,45 @@ struct cpu_thread_history {
|
|||||||
thread_cancel(&(thread)); \
|
thread_cancel(&(thread)); \
|
||||||
} while (0)
|
} 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 _xref_t_a(addfn, type, m, f, a, v, t) \
|
||||||
#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__)
|
static const struct xref_threadsched _xref \
|
||||||
#define thread_add_timer_msec(m,f,a,v,t) funcname_thread_add_timer_msec(m,f,a,v,t,#f,__FILE__,__LINE__)
|
__attribute__((used)) = { \
|
||||||
#define thread_add_timer_tv(m,f,a,v,t) funcname_thread_add_timer_tv(m,f,a,v,t,#f,__FILE__,__LINE__)
|
.xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
|
||||||
#define thread_add_event(m,f,a,v,t) funcname_thread_add_event(m,f,a,v,t,#f,__FILE__,__LINE__)
|
.funcname = #f, \
|
||||||
#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
|
.dest = #t, \
|
||||||
#define thread_execute_name(m, f, a, v, n) \
|
.thread_type = THREAD_ ## type, \
|
||||||
funcname_thread_execute(m, f, a, v, n, __FILE__, __LINE__)
|
}; \
|
||||||
|
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. */
|
/* Prototypes. */
|
||||||
extern struct thread_master *thread_master_create(const char *);
|
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(struct thread_master *);
|
||||||
extern void thread_master_free_unused(struct thread_master *);
|
extern void thread_master_free_unused(struct thread_master *);
|
||||||
|
|
||||||
extern struct thread *
|
extern struct thread *_thread_add_read_write(
|
||||||
funcname_thread_add_read_write(int dir, struct thread_master *,
|
const struct xref_threadsched *xref, struct thread_master *master,
|
||||||
int (*)(struct thread *), void *, int,
|
int (*fn)(struct thread *), void *arg, int fd, struct thread **tref);
|
||||||
struct thread **, debugargdef);
|
|
||||||
|
|
||||||
extern struct thread *funcname_thread_add_timer(struct thread_master *,
|
extern struct thread *_thread_add_timer(
|
||||||
int (*)(struct thread *),
|
const struct xref_threadsched *xref, struct thread_master *master,
|
||||||
void *, long, struct thread **,
|
int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
|
||||||
debugargdef);
|
|
||||||
|
|
||||||
extern struct thread *
|
extern struct thread *_thread_add_timer_msec(
|
||||||
funcname_thread_add_timer_msec(struct thread_master *, int (*)(struct thread *),
|
const struct xref_threadsched *xref, struct thread_master *master,
|
||||||
void *, long, struct thread **, debugargdef);
|
int (*fn)(struct thread *), void *arg, long t, struct thread **tref);
|
||||||
|
|
||||||
extern struct thread *funcname_thread_add_timer_tv(struct thread_master *,
|
extern struct thread *_thread_add_timer_tv(
|
||||||
int (*)(struct thread *),
|
const struct xref_threadsched *xref, struct thread_master *master,
|
||||||
void *, struct timeval *,
|
int (*fn)(struct thread *), void *arg, struct timeval *tv,
|
||||||
struct thread **,
|
struct thread **tref);
|
||||||
debugargdef);
|
|
||||||
|
|
||||||
extern struct thread *funcname_thread_add_event(struct thread_master *,
|
extern struct thread *_thread_add_event(
|
||||||
int (*)(struct thread *),
|
const struct xref_threadsched *xref, struct thread_master *master,
|
||||||
void *, int, struct thread **,
|
int (*fn)(struct thread *), void *arg, int val, struct thread **tref);
|
||||||
debugargdef);
|
|
||||||
|
|
||||||
extern void funcname_thread_execute(struct thread_master *,
|
extern void _thread_execute(const struct xref_threadsched *xref,
|
||||||
int (*)(struct thread *), void *, int,
|
struct thread_master *master,
|
||||||
debugargdef);
|
int (*fn)(struct thread *), void *arg, int val);
|
||||||
#undef debugargdef
|
|
||||||
|
|
||||||
extern void thread_cancel(struct thread **event);
|
extern void thread_cancel(struct thread **event);
|
||||||
extern void thread_cancel_async(struct thread_master *, struct thread **,
|
extern void thread_cancel_async(struct thread_master *, struct thread **,
|
||||||
|
@ -73,8 +73,7 @@ static int wheel_timer_thread(struct thread *t)
|
|||||||
|
|
||||||
wheel = THREAD_ARG(t);
|
wheel = THREAD_ARG(t);
|
||||||
|
|
||||||
thread_execute_name(wheel->master, wheel_timer_thread_helper,
|
thread_execute(wheel->master, wheel_timer_thread_helper, wheel, 0);
|
||||||
wheel, 0, wheel->name);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
enum xref_type {
|
enum xref_type {
|
||||||
XREFT_NONE = 0,
|
XREFT_NONE = 0,
|
||||||
|
|
||||||
|
XREFT_THREADSCHED = 0x100,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* struct xref is the "const" part; struct xrefdata is the writable part. */
|
/* struct xref is the "const" part; struct xrefdata is the writable part. */
|
||||||
|
Loading…
Reference in New Issue
Block a user