#define LOOP_NAME(loop) domain_name((loop)->time.domain)
-#define LOOP_TRACE(loop, fmt, args...) do { if (config && config->latency_debug) log(L_TRACE "%s (%p): " fmt, LOOP_NAME(loop), (loop), ##args); } while (0)
-#define THREAD_TRACE(...) do { if (config && config->latency_debug) log(L_TRACE "Thread: " __VA_ARGS__); } while (0)
+#define LOOP_TRACE(loop, flags, fmt, args...) do { if (config && (config->latency_debug & (flags))) log(L_TRACE "%s (%p): " fmt, LOOP_NAME(loop), (loop), ##args); } while (0)
+#define THREAD_TRACE(flags, ...) do { if (config && (config->latency_debug & (flags))) log(L_TRACE "Thread: " __VA_ARGS__); } while (0)
#define LOOP_WARN(loop, fmt, args...) log(L_WARN "%s (%p): " fmt, LOOP_NAME(loop), (loop), ##args)
/* Somebody else is already pinging, be idempotent */
if (ltt & LTT_PING)
{
- LOOP_TRACE(loop, "already being pinged");
+ LOOP_TRACE(loop, DL_PING, "already being pinged");
return 0;
}
/* Thread moving is an implicit ping */
if (ltt & LTT_MOVE)
{
- LOOP_TRACE(loop, "ping while moving");
+ LOOP_TRACE(loop, DL_PING, "ping while moving");
return 1;
}
/* No ping when not picked up */
if (!loop->thread)
{
- LOOP_TRACE(loop, "not picked up yet, can't ping");
+ LOOP_TRACE(loop, DL_PING, "not picked up yet, can't ping");
return 1;
}
/* No ping when masked */
if (loop == birdloop_wakeup_masked)
{
- LOOP_TRACE(loop, "wakeup masked, can't ping");
+ LOOP_TRACE(loop, DL_PING, "wakeup masked, can't ping");
birdloop_wakeup_masked_count++;
return 1;
}
/* Send meta event to ping */
if ((loop != loop->thread->meta) && (loop != &main_birdloop))
{
- LOOP_TRACE(loop, "Ping by meta event to %p", loop->thread->meta);
+ LOOP_TRACE(loop, DL_PING, "Ping by meta event to %p", loop->thread->meta);
ev_send_loop(loop->thread->meta, &loop->event);
return 1;
}
/* Do the real ping of Meta or Main */
- LOOP_TRACE(loop, "sending pipe ping");
+ LOOP_TRACE(loop, DL_WAKEUP, "sending pipe ping");
wakeup_do_kick(loop->thread);
return 0;
}
{
if (!birdloop_inside(loop))
{
- LOOP_TRACE(loop, "ping from outside");
+ LOOP_TRACE(loop, DL_PING, "ping from outside");
birdloop_do_ping(loop);
}
else
{
- LOOP_TRACE(loop, "ping from inside, pending=%d", loop->ping_pending);
+ LOOP_TRACE(loop, DL_PING, "ping from inside, pending=%d", loop->ping_pending);
if (!loop->ping_pending)
loop->ping_pending++;
}
ASSERT_DIE(birdloop_inside(loop));
ASSERT_DIE(!s->loop);
- LOOP_TRACE(loop, "adding socket %p (total=%d)", s, loop->sock_num);
+ LOOP_TRACE(loop, DL_SOCKETS, "adding socket %p (total=%d)", s, loop->sock_num);
add_tail(&loop->sock_list, &s->n);
loop->sock_num++;
ASSERT_DIE(s->loop == loop);
/* Decouple the socket from the loop at all. */
- LOOP_TRACE(loop, "removing socket %p (total=%d)", s, loop->sock_num);
+ LOOP_TRACE(loop, DL_SOCKETS, "removing socket %p (total=%d)", s, loop->sock_num);
if (loop->sock_active == s)
loop->sock_active = sk_next(s);
}
s->index = pfd->pfd.used;
- LOOP_TRACE(loop, "socket %p poll index is %d", s, s->index);
+ LOOP_TRACE(loop, DL_SOCKETS, "socket %p poll index is %d", s, s->index);
BUFFER_PUSH(pfd->pfd) = (struct pollfd) {
.fd = s->fd,
if (drop)
{
+ THREAD_TRACE(DL_SCHEDULING, "Loop drop requested (tbc=%d, tc=%d, lc=%d)",
+ group->thread_busy_count, group->thread_count, this_thread->loop_count);
UNLOCK_DOMAIN(attrs, group->domain);
node *n;
birdloop_enter(loop);
if (ev_active(&loop->event))
{
- LOOP_TRACE(loop, "Moving to another thread");
+ LOOP_TRACE(loop, DL_SCHEDULING, "Dropping from thread");
/* Pass to another thread */
rem_node(&loop->n);
this_thread->loop_count--;
if (take)
{
+ THREAD_TRACE(DL_SCHEDULING, "Loop take requested");
+
/* Take a proportional amount of loops from the pickup list and unlock */
uint thread_count = group->thread_count + 1;
if (group->thread_busy_count < group->thread_count)
birdloop_enter(loop);
birdloop_set_thread(loop, this_thread, group);
+ LOOP_TRACE(loop, DL_SCHEDULING, "Picked up by thread");
node *n;
WALK_LIST(n, loop->sock_list)
birdloop_enter(thr->meta);
this_birdloop = thr->meta;
+ THREAD_TRACE(DL_SCHEDULING, "Started");
+
tmp_init(thr->pool);
init_list(&thr->loops);
int more_events = ev_run_list(&thr->meta->event_list);
if (more_events)
{
- THREAD_TRACE("More events to run");
+ THREAD_TRACE(DL_SCHEDULING, "More metaevents to run");
timeout = 0;
}
else
{
timeout = poll_timeout(thr->meta);
if (timeout == -1)
- THREAD_TRACE("No timers, no events");
+ THREAD_TRACE(DL_SCHEDULING, "No timers, no events in meta");
else
- THREAD_TRACE("Next timer in %d ms", timeout);
+ THREAD_TRACE(DL_SCHEDULING, "Next meta timer in %d ms", timeout);
}
/* Run priority events before sleeping */
/* Do we have to refresh sockets? */
if (thr->sock_changed)
{
+ THREAD_TRACE(DL_SOCKETS, "Recalculating socket poll");
thr->sock_changed = 0;
BUFFER_FLUSH(pfd.pfd);
}
ASSERT_DIE(pfd.loop.used == pfd.pfd.used);
+ THREAD_TRACE(DL_SOCKETS, "Total %d sockets", pfd.pfd.used);
}
/* Nothing to do in at least 5 seconds, flush local hot page cache */
else if ((timeout > 5000) || (timeout < 0))
/* Drain wakeup fd */
if (pfd.pfd.data[0].revents & POLLIN)
{
+ THREAD_TRACE(DL_WAKEUP, "Ping received");
ASSERT_DIE(rv > 0);
rv--;
wakeup_drain(thr);
for (uint i = 1; i < pfd.pfd.used; i++)
if (pfd.pfd.data[i].revents)
{
- LOOP_TRACE(pfd.loop.data[i], "socket id %d got revents=%d", i, pfd.pfd.data[i].revents);
+ LOOP_TRACE(pfd.loop.data[i], DL_SOCKETS, "socket id %d got revents=0x%x", i, pfd.pfd.data[i].revents);
ev_send_loop(thr->meta, &pfd.loop.data[i]->event);
}
}
UNLOCK_DOMAIN(attrs, group->domain);
- DBG("Thread pickup size differs from dropper goal by %d%s\n", dif, tdl_stop ? ", stopping" : "");
+ THREAD_TRACE(DL_SCHEDULING, "Thread pickup size differs from dropper goal by %d%s", dif, tdl_stop ? ", stopping" : "");
if (tdl_stop)
{
birdloop_leave(thr->meta);
/* Exit! */
+ THREAD_TRACE(DL_SCHEDULING, "Stopped");
pthread_exit(NULL);
}
static void
birdloop_stop_internal(struct birdloop *loop)
{
- LOOP_TRACE(loop, "Stopping");
+ LOOP_TRACE(loop, DL_SCHEDULING, "Stopping");
/* Block incoming pings */
u32 ltt = atomic_load_explicit(&loop->thread_transition, memory_order_acquire);
uint repeat, loop_runs = 0;
do {
repeat = 0;
- LOOP_TRACE(loop, "Regular run");
+ LOOP_TRACE(loop, DL_SCHEDULING, "Regular run (%d)", loop_runs);
loop_runs++;
if (loop->stopped)
birdloop_run_timer(timer *tm)
{
struct birdloop *loop = tm->data;
- LOOP_TRACE(loop, "Timer ready, requesting run");
+ LOOP_TRACE(loop, DL_TIMERS, "Meta timer ready, requesting run");
ev_send_loop(loop->thread->meta, &loop->event);
}
birdloop_enter_locked(loop);
- ev_init_list(&loop->event_list, loop, name);
+ ev_init_list(&loop->event_list, loop, p->name);
timers_init(&loop->time, p);
sockets_init(loop);
loop->event = (event) { .hook = birdloop_run, .data = loop, };
loop->timer = (timer) { .hook = birdloop_run_timer, .data = loop, };
+ LOOP_TRACE(loop, DL_SCHEDULING, "New loop: %s", p->name);
+
if (group)
{
LOCK_DOMAIN(attrs, group->domain);
static void
birdloop_do_stop(struct birdloop *loop, void (*stopped)(void *data), void *data)
{
- LOOP_TRACE(loop, "Stop requested");
+ LOOP_TRACE(loop, DL_SCHEDULING, "Stop requested");
loop->stopped = stopped;
loop->stop_data = data;
/* Send pending pings */
if (loop->ping_pending)
{
- LOOP_TRACE(loop, "sending pings on leave");
+ LOOP_TRACE(loop, DL_PING, "sending pings on leave");
loop->ping_pending = 0;
birdloop_do_ping(loop);
}
* entry is kept open (in @event_open) so the duration can be filled later.
*/
void
-io_log_event(void *hook, void *data)
+io_log_event(void *hook, void *data, uint flag)
{
- if (config->latency_debug)
+ if (config->latency_debug & flag)
io_update_time();
struct event_log_entry *en = event_log + event_log_pos;
event_log_pos++;
event_log_pos %= EVENT_LOG_LENGTH;
- event_open = config->latency_debug ? en : NULL;
+ event_open = (config->latency_debug & flag) ? en : NULL;
}
static inline void
if (async_config_flag)
{
- io_log_event(async_config, NULL);
+ io_log_event(async_config, NULL, DL_EVENTS);
async_config();
async_config_flag = 0;
continue;
}
if (async_dump_flag)
{
- io_log_event(async_dump, NULL);
+ io_log_event(async_dump, NULL, DL_EVENTS);
async_dump();
async_dump_flag = 0;
continue;
}
if (async_shutdown_flag)
{
- io_log_event(async_shutdown, NULL);
+ io_log_event(async_shutdown, NULL, DL_EVENTS);
async_shutdown();
async_shutdown_flag = 0;
continue;
do
{
steps--;
- io_log_event(s->rx_hook, s->data);
+ io_log_event(s->rx_hook, s->data, DL_SOCKETS);
e = sk_read(s, pfd.pfd.data[s->index].revents);
}
while (e && (main_birdloop.sock_active == s) && s->rx_hook && steps);
do
{
steps--;
- io_log_event(s->tx_hook, s->data);
+ io_log_event(s->tx_hook, s->data, DL_SOCKETS);
e = sk_write(s);
}
while (e && (main_birdloop.sock_active == s) && steps);
if (!s->fast_rx && (pfd.pfd.data[s->index].revents & POLLIN) && s->rx_hook)
{
count++;
- io_log_event(s->rx_hook, s->data);
+ io_log_event(s->rx_hook, s->data, DL_SOCKETS);
sk_read(s, pfd.pfd.data[s->index].revents);
if (s != main_birdloop.sock_active)
continue;