Just a better way of doing what was previously the "debugargdef" macro.
Signed-off-by: David Lamparter <equinox@diac24.net>
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;
}
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:
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;
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;
}
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:
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;
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;
}
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;
* 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);
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);
}
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");
}
if (!thread)
vty_out(vty, "ERROR ");
else
- vty_out(vty, "%s ", thread->funcname);
+ vty_out(vty, "%s ", thread->xref->funcname);
} else
vty_out(vty, " ");
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");
}
/* 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;
* 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;
}
}
/* 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;
/* 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 |=
}
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;
/* 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);
/* 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;
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;
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;
/* 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);
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 */
}
/* 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) {
#include "monotime.h"
#include "frratomic.h"
#include "typesafe.h"
+#include "xref.h"
#ifdef __cplusplus
extern "C" {
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;
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 */
};
thread_cancel(&(thread)); \
} while (0)
-#define debugargdef const char *funcname, const char *schedfrom, int fromln
-
-#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__)
+/*
+ * Macro wrappers to generate xrefs for all thread add calls. Includes
+ * file/line/function info for debugging/tracing.
+ */
+#include "lib/xref.h"
+
+#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 *);
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 *funcname_thread_add_timer(struct thread_master *,
- int (*)(struct thread *),
- void *, long, struct thread **,
- debugargdef);
-
-extern struct thread *
-funcname_thread_add_timer_msec(struct thread_master *, int (*)(struct thread *),
- void *, long, struct thread **, debugargdef);
-
-extern struct thread *funcname_thread_add_timer_tv(struct thread_master *,
- int (*)(struct thread *),
- void *, struct timeval *,
- struct thread **,
- debugargdef);
-
-extern struct thread *funcname_thread_add_event(struct thread_master *,
- int (*)(struct thread *),
- void *, int, struct thread **,
- debugargdef);
-
-extern void funcname_thread_execute(struct thread_master *,
- int (*)(struct thread *), void *, int,
- debugargdef);
-#undef 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 *_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 *_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 *_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 *_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 _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 **,
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;
}
enum xref_type {
XREFT_NONE = 0,
+
+ XREFT_THREADSCHED = 0x100,
};
/* struct xref is the "const" part; struct xrefdata is the writable part. */