Browse Source

timer: better dump code.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 11 years ago
parent
commit
bd9a48e7ff
1 changed files with 64 additions and 30 deletions
  1. 64 30
      ccan/timer/timer.c

+ 64 - 30
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