From bd9a48e7ffca063e21d580e9e0d94b1691c03687 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 19 May 2015 14:22:13 +0930 Subject: [PATCH] timer: better dump code. Signed-off-by: Rusty Russell --- ccan/timer/timer.c | 94 +++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/ccan/timer/timer.c b/ccan/timer/timer.c index 0d7deb12..f0e017ba 100644 --- a/ccan/timer/timer.c +++ b/ccan/timer/timer.c @@ -389,50 +389,84 @@ past_levels: } #ifdef CCAN_TIMER_DEBUG -void timers_dump(const struct timers *timers, FILE *fp) +static void dump_bucket_stats(FILE *fp, const struct list_head *h) { - unsigned int l, i; - uint64_t min, max, num; + unsigned long long min, max, num; struct timer *t; - if (!fp) - fp = stderr; - - fprintf(fp, "Base: %llu\n", timers->base); - - for (l = 0; timers->level[l] && l < ARRAY_SIZE(timers->level); l++) { - fprintf(fp, "Level %i (+%llu):\n", - l, (uint64_t)1 << (TIMER_LEVEL_BITS * l)); - for (i = 0; i < (1 << TIMER_LEVEL_BITS); i++) { - - if (list_empty(&timers->level[l]->list[i])) - continue; - min = -1ULL; - max = 0; - num = 0; - list_for_each(&timers->level[l]->list[i], t, list) { - if (t->time < min) - min = t->time; - if (t->time > max) - max = t->time; - num++; - } - fprintf(stderr, " %llu (+%llu-+%llu)\n", - num, min - timers->base, max - timers->base); - } + if (list_empty(h)) { + printf("\n"); + return; } min = -1ULL; max = 0; num = 0; - list_for_each(&timers->far, t, list) { + list_for_each(h, t, list) { if (t->time < min) min = t->time; if (t->time > max) max = t->time; num++; } - fprintf(stderr, "Far: %llu (%llu-%llu)\n", num, min, max); + fprintf(fp, " %llu (%llu-%llu)\n", + num, min, max); +} + +void timers_dump(const struct timers *timers, FILE *fp) +{ + unsigned int l, i, off; + unsigned long long base; + + if (!fp) + fp = stderr; + + fprintf(fp, "Base: %llu\n", (unsigned long long)timers->base); + + if (!timers->level[0]) + goto past_levels; + + fprintf(fp, "Level 0:\n"); + + /* First level is simple. */ + off = timers->base % PER_LEVEL; + for (i = 0; i < PER_LEVEL; i++) { + const struct list_head *h; + + fprintf(fp, " Bucket %llu (%lu):", + (i+off) % PER_LEVEL, timers->base + i); + h = &timers->level[0]->list[(i+off) % PER_LEVEL]; + dump_bucket_stats(fp, h); + } + + /* For other levels, "current" bucket has been emptied, and may contain + * entries for the current + level_size bucket. */ + for (l = 1; l < ARRAY_SIZE(timers->level) && timers->level[l]; l++) { + uint64_t per_bucket = 1ULL << (TIMER_LEVEL_BITS * l); + + off = ((timers->base >> (l*TIMER_LEVEL_BITS)) % PER_LEVEL); + /* We start at *next* bucket. */ + base = (timers->base & ~(per_bucket - 1)) + per_bucket; + + fprintf(fp, "Level %u:\n", l); + for (i = 1; i <= PER_LEVEL; i++) { + const struct list_head *h; + + fprintf(fp, " Bucket %llu (%llu - %llu):", + (i+off) % PER_LEVEL, + base, base + per_bucket - 1); + + h = &timers->level[l]->list[(i+off) % PER_LEVEL]; + dump_bucket_stats(fp, h); + base += per_bucket; + } + } + +past_levels: + if (!list_empty(&timers->far)) { + fprintf(fp, "Far timers:"); + dump_bucket_stats(fp, &timers->far); + } } #endif -- 2.39.2