mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 12:48:43 +00:00
Displaced show threads command to its own file
This commit is contained in:
parent
ab850e7262
commit
ab963de471
@ -7,15 +7,17 @@
|
||||
#ifndef _BIRD_IO_LOOP_H_
|
||||
#define _BIRD_IO_LOOP_H_
|
||||
|
||||
extern struct birdloop main_birdloop;
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/lists.h"
|
||||
#include "lib/locking.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/buffer.h"
|
||||
#include "lib/event.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/socket.h"
|
||||
|
||||
extern struct birdloop main_birdloop;
|
||||
|
||||
/* Currently running birdloop */
|
||||
extern _Thread_local struct birdloop *this_birdloop;
|
||||
|
||||
|
@ -120,6 +120,10 @@ void timers_fire(struct timeloop *loop);
|
||||
/* For extra fine precision */
|
||||
u64 ns_now(void);
|
||||
|
||||
#define NSEC_IN_SEC ((u64) (1000 * 1000 * 1000))
|
||||
#define NSEC_TO_SEC(x) ((x) / NSEC_IN_SEC)
|
||||
#define CURRENT_SEC NSEC_TO_SEC(ns_now())
|
||||
|
||||
struct timeformat {
|
||||
const char *fmt1, *fmt2;
|
||||
btime limit;
|
||||
|
@ -1,4 +1,4 @@
|
||||
src := alloc.c io.c io-loop.c krt.c log.c main.c random.c domain.c socket.c file.c time.c
|
||||
src := alloc.c io.c io-cli.c io-loop.c krt.c log.c main.c random.c domain.c socket.c file.c time.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
$(cf-local)
|
||||
|
166
sysdep/unix/io-cli.c
Normal file
166
sysdep/unix/io-cli.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* CLI: Show threads
|
||||
*/
|
||||
|
||||
#include "nest/bird.h"
|
||||
|
||||
#include "lib/io-loop.h"
|
||||
#include "sysdep/unix/io-loop.h"
|
||||
#include "nest/cli.h"
|
||||
#include "conf/conf.h"
|
||||
|
||||
struct bird_thread_show_data {
|
||||
struct bird_thread_syncer sync;
|
||||
cli *cli;
|
||||
linpool *lp;
|
||||
u8 show_loops;
|
||||
uint line_pos;
|
||||
uint line_max;
|
||||
const char **lines;
|
||||
};
|
||||
|
||||
#define tsd_append(...) do { \
|
||||
if (!tsd->lines) \
|
||||
tsd->lines = mb_allocz(tsd->sync.pool, sizeof(const char *) * tsd->line_max); \
|
||||
if (tsd->line_pos >= tsd->line_max) \
|
||||
tsd->lines = mb_realloc(tsd->lines, sizeof (const char *) * (tsd->line_max *= 2)); \
|
||||
tsd->lines[tsd->line_pos++] = lp_sprintf(tsd->lp, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
bird_thread_show_cli_cont(struct cli *c UNUSED)
|
||||
{
|
||||
/* Explicitly do nothing to prevent CLI from trying to parse another command. */
|
||||
}
|
||||
|
||||
static int
|
||||
bird_thread_show_cli_cleanup(struct cli *c UNUSED)
|
||||
{
|
||||
return 1; /* Defer the cleanup until the writeout is finished. */
|
||||
}
|
||||
|
||||
static void
|
||||
bird_thread_show_spent_time(struct bird_thread_show_data *tsd, const char *name, struct spent_time *st)
|
||||
{
|
||||
char b[TIME_BY_SEC_SIZE * sizeof("1234567890, ")], *bptr = b, *bend = b + sizeof(b);
|
||||
uint cs = CURRENT_SEC;
|
||||
uint fs = NSEC_TO_SEC(st->last_written_ns);
|
||||
|
||||
for (uint i = 0; i <= cs && i < TIME_BY_SEC_SIZE; i++)
|
||||
bptr += bsnprintf(bptr, bend - bptr, "% 10lu ",
|
||||
(cs - i > fs) ? 0 : st->by_sec_ns[(cs - i) % TIME_BY_SEC_SIZE]);
|
||||
bptr[-1] = 0; /* Drop the trailing space */
|
||||
|
||||
tsd_append(" %s total time: % 9t s; last %d secs [ns]: %s", name, st->total_ns NS, MIN(CURRENT_SEC+1, TIME_BY_SEC_SIZE), b);
|
||||
}
|
||||
|
||||
static void
|
||||
bird_thread_show_loop(struct bird_thread_show_data *tsd, struct birdloop *loop)
|
||||
{
|
||||
tsd_append(" Loop %s", domain_name(loop->time.domain));
|
||||
bird_thread_show_spent_time(tsd, "Working ", &loop->working);
|
||||
bird_thread_show_spent_time(tsd, "Locking ", &loop->locking);
|
||||
}
|
||||
|
||||
static void
|
||||
bird_thread_show(struct bird_thread_syncer *sync)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct bird_thread_show_data, tsd, sync, sync);
|
||||
|
||||
if (!tsd->lp)
|
||||
tsd->lp = lp_new(tsd->sync.pool);
|
||||
|
||||
if (tsd->show_loops)
|
||||
tsd_append("Thread %04x %s (busy counter %d)", THIS_THREAD_ID, this_thread->busy_active ? " [busy]" : "", this_thread->busy_counter);
|
||||
|
||||
u64 total_time_ns = 0;
|
||||
struct birdloop *loop;
|
||||
WALK_LIST(loop, this_thread->loops)
|
||||
{
|
||||
if (tsd->show_loops)
|
||||
bird_thread_show_loop(tsd, loop);
|
||||
|
||||
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
|
||||
}
|
||||
|
||||
if (tsd->show_loops)
|
||||
{
|
||||
tsd_append(" Total working time: %t", total_time_ns NS);
|
||||
bird_thread_show_spent_time(tsd, "Overhead", &this_thread->overhead);
|
||||
bird_thread_show_spent_time(tsd, "Idle ", &this_thread->idle);
|
||||
}
|
||||
else
|
||||
tsd_append("%04x%s % 9.3t s % 9.3t s % 9.3t s",
|
||||
THIS_THREAD_ID, this_thread->busy_active ? " [busy]" : " ",
|
||||
total_time_ns NS, this_thread->overhead.total_ns NS,
|
||||
(ns_now() - this_thread->meta->last_transition_ns) NS);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_show_threads_done(struct bird_thread_syncer *sync)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct bird_thread_show_data, tsd, sync, sync);
|
||||
ASSERT_DIE(birdloop_inside(&main_birdloop));
|
||||
|
||||
tsd->cli->cont = NULL;
|
||||
tsd->cli->cleanup = NULL;
|
||||
|
||||
for (int i=0; i<2; i++)
|
||||
{
|
||||
struct birdloop_pickup_group *group = &pickup_groups[i];
|
||||
|
||||
LOCK_DOMAIN(attrs, group->domain);
|
||||
uint count = 0;
|
||||
u64 total_time_ns = 0;
|
||||
if (!EMPTY_LIST(group->loops))
|
||||
{
|
||||
if (tsd->show_loops)
|
||||
tsd_append("Unassigned loops in group %d:", i);
|
||||
|
||||
struct birdloop *loop;
|
||||
WALK_LIST(loop, group->loops)
|
||||
{
|
||||
if (tsd->show_loops)
|
||||
bird_thread_show_loop(tsd, loop);
|
||||
|
||||
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (tsd->show_loops)
|
||||
tsd_append(" Total working time: %t", total_time_ns NS);
|
||||
else
|
||||
tsd_append("Unassigned %d loops in group %d, total time %t", count, i, total_time_ns NS);
|
||||
}
|
||||
else
|
||||
tsd_append("All loops in group %d are assigned.", i);
|
||||
|
||||
UNLOCK_DOMAIN(attrs, group->domain);
|
||||
}
|
||||
|
||||
if (!tsd->show_loops)
|
||||
cli_printf(tsd->cli, -1027, "Thread ID Working Overhead Last Pickup/Drop");
|
||||
|
||||
for (uint i = 0; i < tsd->line_pos - 1; i++)
|
||||
cli_printf(tsd->cli, -1027, "%s", tsd->lines[i]);
|
||||
|
||||
cli_printf(tsd->cli, 1027, "%s", tsd->lines[tsd->line_pos-1]);
|
||||
cli_write_trigger(tsd->cli);
|
||||
mb_free(tsd);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_show_threads(int show_loops)
|
||||
{
|
||||
struct bird_thread_show_data *tsd = mb_allocz(&root_pool, sizeof(struct bird_thread_show_data));
|
||||
tsd->cli = this_cli;
|
||||
tsd->show_loops = show_loops;
|
||||
tsd->line_pos = 0;
|
||||
tsd->line_max = 64;
|
||||
|
||||
this_cli->cont = bird_thread_show_cli_cont;
|
||||
this_cli->cleanup = bird_thread_show_cli_cleanup;
|
||||
|
||||
bird_thread_sync_all(&tsd->sync, bird_thread_show, cmd_show_threads_done, "Show Threads");
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "lib/io-loop.h"
|
||||
#include "sysdep/unix/io-loop.h"
|
||||
#include "conf/conf.h"
|
||||
#include "nest/cli.h"
|
||||
|
||||
#define THREAD_STACK_SIZE 65536 /* To be lowered in near future */
|
||||
|
||||
@ -54,8 +53,6 @@ static void ns_init(void)
|
||||
bug("clock_gettime: %m");
|
||||
}
|
||||
|
||||
#define NSEC_IN_SEC ((u64) (1000 * 1000 * 1000))
|
||||
|
||||
u64 ns_now(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
@ -65,9 +62,6 @@ u64 ns_now(void)
|
||||
return (u64) (ts.tv_sec - ns_begin.tv_sec) * NSEC_IN_SEC + ts.tv_nsec - ns_begin.tv_nsec;
|
||||
}
|
||||
|
||||
#define NSEC_TO_SEC(x) ((x) / NSEC_IN_SEC)
|
||||
#define CURRENT_SEC NSEC_TO_SEC(ns_now())
|
||||
|
||||
static _Thread_local struct spent_time *account_target_spent_time;
|
||||
static _Thread_local u64 *account_target_total;
|
||||
static _Thread_local u64 account_last;
|
||||
@ -571,17 +565,7 @@ sockets_fire(struct birdloop *loop, bool read, bool write)
|
||||
static void bird_thread_start_event(void *_data);
|
||||
static void bird_thread_busy_set(struct bird_thread *thr, int val);
|
||||
|
||||
struct birdloop_pickup_group {
|
||||
DOMAIN(attrs) domain;
|
||||
list loops;
|
||||
list threads;
|
||||
uint thread_count;
|
||||
uint thread_busy_count;
|
||||
uint loop_count;
|
||||
uint loop_unassigned_count;
|
||||
btime max_latency;
|
||||
event start_threads;
|
||||
} pickup_groups[2] = {
|
||||
struct birdloop_pickup_group pickup_groups[2] = {
|
||||
{
|
||||
/* all zeroes */
|
||||
},
|
||||
@ -593,7 +577,7 @@ struct birdloop_pickup_group {
|
||||
},
|
||||
};
|
||||
|
||||
static _Thread_local struct bird_thread *this_thread;
|
||||
_Thread_local struct bird_thread *this_thread;
|
||||
|
||||
static void
|
||||
birdloop_set_thread(struct birdloop *loop, struct bird_thread *thr, struct birdloop_pickup_group *group)
|
||||
@ -1235,161 +1219,6 @@ bird_thread_sync_all(struct bird_thread_syncer *sync,
|
||||
}
|
||||
|
||||
|
||||
struct bird_thread_show_data {
|
||||
struct bird_thread_syncer sync;
|
||||
cli *cli;
|
||||
linpool *lp;
|
||||
u8 show_loops;
|
||||
uint line_pos;
|
||||
uint line_max;
|
||||
const char **lines;
|
||||
};
|
||||
|
||||
#define tsd_append(...) do { \
|
||||
if (!tsd->lines) \
|
||||
tsd->lines = mb_allocz(tsd->sync.pool, sizeof(const char *) * tsd->line_max); \
|
||||
if (tsd->line_pos >= tsd->line_max) \
|
||||
tsd->lines = mb_realloc(tsd->lines, sizeof (const char *) * (tsd->line_max *= 2)); \
|
||||
tsd->lines[tsd->line_pos++] = lp_sprintf(tsd->lp, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
bird_thread_show_cli_cont(struct cli *c UNUSED)
|
||||
{
|
||||
/* Explicitly do nothing to prevent CLI from trying to parse another command. */
|
||||
}
|
||||
|
||||
static int
|
||||
bird_thread_show_cli_cleanup(struct cli *c UNUSED)
|
||||
{
|
||||
return 1; /* Defer the cleanup until the writeout is finished. */
|
||||
}
|
||||
|
||||
static void
|
||||
bird_thread_show_spent_time(struct bird_thread_show_data *tsd, const char *name, struct spent_time *st)
|
||||
{
|
||||
char b[TIME_BY_SEC_SIZE * sizeof("1234567890, ")], *bptr = b, *bend = b + sizeof(b);
|
||||
uint cs = CURRENT_SEC;
|
||||
uint fs = NSEC_TO_SEC(st->last_written_ns);
|
||||
|
||||
for (uint i = 0; i <= cs && i < TIME_BY_SEC_SIZE; i++)
|
||||
bptr += bsnprintf(bptr, bend - bptr, "% 10lu ",
|
||||
(cs - i > fs) ? 0 : st->by_sec_ns[(cs - i) % TIME_BY_SEC_SIZE]);
|
||||
bptr[-1] = 0; /* Drop the trailing space */
|
||||
|
||||
tsd_append(" %s total time: % 9t s; last %d secs [ns]: %s", name, st->total_ns NS, MIN(CURRENT_SEC+1, TIME_BY_SEC_SIZE), b);
|
||||
}
|
||||
|
||||
static void
|
||||
bird_thread_show_loop(struct bird_thread_show_data *tsd, struct birdloop *loop)
|
||||
{
|
||||
tsd_append(" Loop %s", domain_name(loop->time.domain));
|
||||
bird_thread_show_spent_time(tsd, "Working ", &loop->working);
|
||||
bird_thread_show_spent_time(tsd, "Locking ", &loop->locking);
|
||||
}
|
||||
|
||||
static void
|
||||
bird_thread_show(struct bird_thread_syncer *sync)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct bird_thread_show_data, tsd, sync, sync);
|
||||
|
||||
if (!tsd->lp)
|
||||
tsd->lp = lp_new(tsd->sync.pool);
|
||||
|
||||
if (tsd->show_loops)
|
||||
tsd_append("Thread %04x %s (busy counter %d)", THIS_THREAD_ID, this_thread->busy_active ? " [busy]" : "", this_thread->busy_counter);
|
||||
|
||||
u64 total_time_ns = 0;
|
||||
struct birdloop *loop;
|
||||
WALK_LIST(loop, this_thread->loops)
|
||||
{
|
||||
if (tsd->show_loops)
|
||||
bird_thread_show_loop(tsd, loop);
|
||||
|
||||
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
|
||||
}
|
||||
|
||||
if (tsd->show_loops)
|
||||
{
|
||||
tsd_append(" Total working time: %t", total_time_ns NS);
|
||||
bird_thread_show_spent_time(tsd, "Overhead", &this_thread->overhead);
|
||||
bird_thread_show_spent_time(tsd, "Idle ", &this_thread->idle);
|
||||
}
|
||||
else
|
||||
tsd_append("%04x%s % 9.3t s % 9.3t s % 9.3t s",
|
||||
THIS_THREAD_ID, this_thread->busy_active ? " [busy]" : " ",
|
||||
total_time_ns NS, this_thread->overhead.total_ns NS,
|
||||
(ns_now() - this_thread->meta->last_transition_ns) NS);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_show_threads_done(struct bird_thread_syncer *sync)
|
||||
{
|
||||
SKIP_BACK_DECLARE(struct bird_thread_show_data, tsd, sync, sync);
|
||||
ASSERT_DIE(birdloop_inside(&main_birdloop));
|
||||
|
||||
tsd->cli->cont = NULL;
|
||||
tsd->cli->cleanup = NULL;
|
||||
|
||||
for (int i=0; i<2; i++)
|
||||
{
|
||||
struct birdloop_pickup_group *group = &pickup_groups[i];
|
||||
|
||||
LOCK_DOMAIN(attrs, group->domain);
|
||||
uint count = 0;
|
||||
u64 total_time_ns = 0;
|
||||
if (!EMPTY_LIST(group->loops))
|
||||
{
|
||||
if (tsd->show_loops)
|
||||
tsd_append("Unassigned loops in group %d:", i);
|
||||
|
||||
struct birdloop *loop;
|
||||
WALK_LIST(loop, group->loops)
|
||||
{
|
||||
if (tsd->show_loops)
|
||||
bird_thread_show_loop(tsd, loop);
|
||||
|
||||
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (tsd->show_loops)
|
||||
tsd_append(" Total working time: %t", total_time_ns NS);
|
||||
else
|
||||
tsd_append("Unassigned %d loops in group %d, total time %t", count, i, total_time_ns NS);
|
||||
}
|
||||
else
|
||||
tsd_append("All loops in group %d are assigned.", i);
|
||||
|
||||
UNLOCK_DOMAIN(attrs, group->domain);
|
||||
}
|
||||
|
||||
if (!tsd->show_loops)
|
||||
cli_printf(tsd->cli, -1027, "Thread ID Working Overhead Last Pickup/Drop");
|
||||
|
||||
for (uint i = 0; i < tsd->line_pos - 1; i++)
|
||||
cli_printf(tsd->cli, -1027, "%s", tsd->lines[i]);
|
||||
|
||||
cli_printf(tsd->cli, 1027, "%s", tsd->lines[tsd->line_pos-1]);
|
||||
cli_write_trigger(tsd->cli);
|
||||
mb_free(tsd);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_show_threads(int show_loops)
|
||||
{
|
||||
struct bird_thread_show_data *tsd = mb_allocz(&root_pool, sizeof(struct bird_thread_show_data));
|
||||
tsd->cli = this_cli;
|
||||
tsd->show_loops = show_loops;
|
||||
tsd->line_pos = 0;
|
||||
tsd->line_max = 64;
|
||||
|
||||
this_cli->cont = bird_thread_show_cli_cont;
|
||||
this_cli->cleanup = bird_thread_show_cli_cleanup;
|
||||
|
||||
bird_thread_sync_all(&tsd->sync, bird_thread_show, cmd_show_threads_done, "Show Threads");
|
||||
}
|
||||
|
||||
bool task_still_in_limit(void)
|
||||
{
|
||||
static u64 main_counter = 0;
|
||||
|
@ -103,6 +103,7 @@ struct bird_thread
|
||||
struct spent_time overhead, idle;
|
||||
};
|
||||
|
||||
extern _Thread_local struct bird_thread *this_thread;
|
||||
|
||||
struct bird_thread_syncer {
|
||||
pool *pool;
|
||||
@ -117,4 +118,18 @@ void bird_thread_sync_all(struct bird_thread_syncer *sync,
|
||||
void (*hook)(struct bird_thread_syncer *),
|
||||
void (*done)(struct bird_thread_syncer *), const char *name);
|
||||
|
||||
struct birdloop_pickup_group {
|
||||
DOMAIN(attrs) domain;
|
||||
list loops;
|
||||
list threads;
|
||||
uint thread_count;
|
||||
uint thread_busy_count;
|
||||
uint loop_count;
|
||||
uint loop_unassigned_count;
|
||||
btime max_latency;
|
||||
event start_threads;
|
||||
};
|
||||
|
||||
extern struct birdloop_pickup_group pickup_groups[2];
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user