diff options
author | Maria Matejka <mq@ucw.cz> | 2023-04-27 11:02:02 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2023-05-03 21:30:29 +0200 |
commit | 9bc5cbd3c74a20a0071ce87884bfb217c0aacb8d (patch) | |
tree | a04b9a1fd31be6f9862abc9ecdc0b44f5fc39b86 | |
parent | 8bc27583ff6d5d8f6789ca1b3d628c967f24a13a (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.c | 68 |
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; |