summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2023-04-27 11:02:02 +0200
committerMaria Matejka <mq@ucw.cz>2023-05-03 21:30:29 +0200
commit9bc5cbd3c74a20a0071ce87884bfb217c0aacb8d (patch)
treea04b9a1fd31be6f9862abc9ecdc0b44f5fc39b86
parent8bc27583ff6d5d8f6789ca1b3d628c967f24a13a (diff)
Show threads: Fixed problems with CLI buffer reallocation
... by allocating all the output locally and then sending it out at once.
-rw-r--r--sysdep/unix/io-loop.c68
1 files changed, 49 insertions, 19 deletions
diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c
index 9f2ac634..c2bb71f0 100644
--- a/sysdep/unix/io-loop.c
+++ b/sysdep/unix/io-loop.c
@@ -1014,13 +1014,22 @@ DEFINE_DOMAIN(control);
struct bird_thread_show_data {
cli *cli;
pool *pool;
+ linpool *lp;
DOMAIN(control) lock;
uint total;
uint done;
event finish_event;
u8 show_loops;
+ uint line_pos;
+ uint line_max;
+ const char *lines[];
};
+#define tsd_append(...) do { \
+ ASSERT_DIE(tsd->line_pos < tsd->line_max); \
+ tsd->lines[tsd->line_pos++] = lp_sprintf(tsd->lp, __VA_ARGS__); \
+} while (0)
+
static void
bird_thread_show_cli_cont(struct cli *c UNUSED)
{
@@ -1034,7 +1043,7 @@ bird_thread_show_cli_cleanup(struct cli *c UNUSED)
}
static void
-bird_thread_show_spent_time(struct cli *c, const char *name, struct spent_time *st)
+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;
@@ -1045,15 +1054,15 @@ bird_thread_show_spent_time(struct cli *c, const char *name, struct spent_time *
(cs - i > fs) ? 0 : st->by_sec_ns[(cs - i) % TIME_BY_SEC_SIZE]);
bptr[-1] = 0; /* Drop the trailing space */
- cli_printf(c, -1026, " %s total time: % 9t s; last %d secs [ns]: %s", name, st->total_ns NS, MIN(CURRENT_SEC+1, TIME_BY_SEC_SIZE), b);
+ 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 cli *c, struct birdloop *loop)
+bird_thread_show_loop(struct bird_thread_show_data *tsd, struct birdloop *loop)
{
- cli_printf(c, -1026, " Loop %s", domain_name(loop->time.domain));
- bird_thread_show_spent_time(c, " Working", &loop->working);
- bird_thread_show_spent_time(c, " Locking", &loop->locking);
+ 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
@@ -1063,14 +1072,14 @@ bird_thread_show(void *data)
LOCK_DOMAIN(control, tsd->lock);
if (tsd->show_loops)
- cli_printf(tsd->cli, -1026, "Thread %p", this_thread);
+ tsd_append("Thread %p", this_thread);
u64 total_time_ns = 0;
struct birdloop *loop;
WALK_LIST(loop, this_thread->loops)
{
if (tsd->show_loops)
- bird_thread_show_loop(tsd->cli, loop);
+ bird_thread_show_loop(tsd, loop);
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
}
@@ -1079,11 +1088,11 @@ bird_thread_show(void *data)
if (tsd->show_loops)
{
- cli_printf(tsd->cli, (last ? 1 : -1) * 1026, " Total working time: %t", total_time_ns NS);
- bird_thread_show_spent_time(tsd->cli, " Overhead", &this_thread->overhead);
+ tsd_append(" Total working time: %t", total_time_ns NS);
+ bird_thread_show_spent_time(tsd, " Overhead", &this_thread->overhead);
}
else
- cli_printf(tsd->cli, (last ? 1 : -1) * 1026, "Thread %p working %t s overhead %t s",
+ tsd_append("Thread %p working %t s overhead %t s",
this_thread, total_time_ns NS, this_thread->overhead.total_ns NS);
if (last)
@@ -1100,6 +1109,9 @@ static void
bird_thread_show_finish(void *data)
{
struct bird_thread_show_data *tsd = data;
+ ASSERT_DIE(birdloop_inside(&main_birdloop));
+ DOMAIN(control) lock = tsd->lock;
+ LOCK_DOMAIN(control, lock);
for (int i=0; i<2; i++)
{
@@ -1111,33 +1123,35 @@ bird_thread_show_finish(void *data)
if (!EMPTY_LIST(group->loops))
{
if (tsd->show_loops)
- cli_printf(tsd->cli, -1026, "Unassigned 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->cli, loop);
+ bird_thread_show_loop(tsd, loop);
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
count++;
}
if (tsd->show_loops)
- cli_printf(tsd->cli, 1026, " Total working time: %t", total_time_ns NS);
+ tsd_append(" Total working time: %t", total_time_ns NS);
else
- cli_printf(tsd->cli, 1026, "Unassigned %d loops, total time %t", count, total_time_ns NS);
+ tsd_append("Unassigned %d loops in group %d, total time %t", count, i, total_time_ns NS);
}
else
- cli_printf(tsd->cli, 1026, "All loops are assigned.");
+ tsd_append("All loops in group %d are assigned.", i);
UNLOCK_DOMAIN(resource, group->domain);
}
+ for (uint i = 0; i < tsd->line_pos - 1; i++)
+ cli_printf(tsd->cli, -1026, "%s", tsd->lines[i]);
+
+ cli_printf(tsd->cli, 1026, "%s", tsd->lines[tsd->line_pos-1]);
cli_write_trigger(tsd->cli);
- DOMAIN(control) lock = tsd->lock;
- LOCK_DOMAIN(control, lock);
rp_free(tsd->pool);
UNLOCK_DOMAIN(control, lock);
DOMAIN_FREE(control, lock);
@@ -1150,15 +1164,31 @@ cmd_show_threads(int show_loops)
LOCK_DOMAIN(control, lock);
pool *p = rp_new(&root_pool, lock.control, "Show Threads");
- struct bird_thread_show_data *tsd = mb_allocz(p, sizeof(struct bird_thread_show_data));
+ uint total_threads = 0, total_loops = 0;
+ for (int i=0; i<2; i++)
+ {
+ struct birdloop_pickup_group *group = &pickup_groups[i];
+ LOCK_DOMAIN(resource, group->domain);
+ total_threads += group->thread_count;
+ total_loops += group->loop_count;
+ UNLOCK_DOMAIN(resource, group->domain);
+ }
+
+ /* Total number of lines must be recalculated when changing the code! */
+ uint total_lines = total_threads * (show_loops + 1) + total_loops * 3 * show_loops + 10;
+
+ struct bird_thread_show_data *tsd = mb_allocz(p, sizeof(struct bird_thread_show_data) + total_lines * sizeof(const char *));
tsd->cli = this_cli;
tsd->pool = p;
+ tsd->lp = lp_new(p);
tsd->lock = lock;
tsd->show_loops = show_loops;
tsd->finish_event = (event) {
.hook = bird_thread_show_finish,
.data = tsd,
};
+ tsd->line_pos = 0;
+ tsd->line_max = total_lines;
this_cli->cont = bird_thread_show_cli_cont;
this_cli->cleanup = bird_thread_show_cli_cleanup;