@@ -314,41 +314,81 @@ void sys_heap_stress(void *(*alloc)(void *arg, size_t bytes),
314
314
}
315
315
316
316
/*
317
- * Dump heap structure content for debugging / analysis purpose
317
+ * Print heap info for debugging / analysis purpose
318
318
*/
319
- void heap_dump (struct z_heap * h )
319
+ void heap_print_info (struct z_heap * h , bool dump_chunks )
320
320
{
321
321
int i , nb_buckets = bucket_idx (h , h -> len ) + 1 ;
322
+ size_t free_bytes , allocated_bytes , total , overhead ;
322
323
323
- printk ("Heap at %p contains %d units\n" , chunk_buf (h ), h -> len );
324
+ printk ("Heap at %p contains %d units in %d buckets\n\n" ,
325
+ chunk_buf (h ), h -> len , nb_buckets );
324
326
327
+ printk (" bucket# min units total largest largest\n"
328
+ " threshold chunks (units) (bytes)\n"
329
+ " -----------------------------------------------------------\n" );
325
330
for (i = 0 ; i < nb_buckets ; i ++ ) {
326
331
chunkid_t first = h -> buckets [i ].next ;
332
+ size_t largest = 0 ;
327
333
int count = 0 ;
328
334
329
335
if (first ) {
330
336
chunkid_t curr = first ;
331
337
do {
332
338
count ++ ;
339
+ largest = MAX (largest , chunk_size (h , curr ));
333
340
curr = next_free_chunk (h , curr );
334
341
} while (curr != first );
335
342
}
336
-
337
- printk ("bucket %d (min %d units): %d chunks\n" , i ,
338
- (1 << i ) - 1 + min_chunk_size (h ), count );
343
+ if (count ) {
344
+ printk ("%9d %12d %12d %12zd %12zd\n" ,
345
+ i , (1 << i ) - 1 + min_chunk_size (h ), count ,
346
+ largest , largest * CHUNK_UNIT - chunk_header_bytes (h ));
347
+ }
339
348
}
340
349
350
+ if (dump_chunks ) {
351
+ printk ("\nChunk dump:\n" );
352
+ }
353
+ free_bytes = allocated_bytes = 0 ;
341
354
for (chunkid_t c = 0 ; ; c = right_chunk (h , c )) {
342
- printk ("chunk %3zd: %c %3zd] %3zd [%zd\n" ,
343
- c , chunk_used (h , c ) ? '*' : '-' ,
344
- left_chunk (h , c ), chunk_size (h , c ), right_chunk (h , c ));
355
+ if (c == 0 || c == h -> len ) {
356
+ /* those are always allocated for internal purposes */
357
+ } else if (chunk_used (h , c )) {
358
+ allocated_bytes += chunk_size (h , c ) * CHUNK_UNIT
359
+ - chunk_header_bytes (h );
360
+ } else if (!solo_free_header (h , c )) {
361
+ free_bytes += chunk_size (h , c ) * CHUNK_UNIT
362
+ - chunk_header_bytes (h );
363
+ }
364
+ if (dump_chunks ) {
365
+ printk ("chunk %4zd: [%c] size=%-4zd left=%-4zd right=%zd\n" ,
366
+ c ,
367
+ chunk_used (h , c ) ? '*'
368
+ : solo_free_header (h , c ) ? '.'
369
+ : '-' ,
370
+ chunk_size (h , c ),
371
+ left_chunk (h , c ),
372
+ right_chunk (h , c ));
373
+ }
345
374
if (c == h -> len ) {
346
375
break ;
347
376
}
348
377
}
378
+
379
+ /*
380
+ * The final chunk at h->len is just a header serving as a end
381
+ * marker. It is part of the overhead.
382
+ */
383
+ total = h -> len * CHUNK_UNIT + chunk_header_bytes (h );
384
+ overhead = total - free_bytes - allocated_bytes ;
385
+ printk ("\n%zd free bytes, %zd allocated bytes, overhead = %zd bytes (%zd.%zd%%)\n" ,
386
+ free_bytes , allocated_bytes , overhead ,
387
+ (1000 * overhead + total /2 ) / total / 10 ,
388
+ (1000 * overhead + total /2 ) / total % 10 );
349
389
}
350
390
351
- void sys_heap_dump (struct sys_heap * heap )
391
+ void sys_heap_print_info (struct sys_heap * heap , bool dump_chunks )
352
392
{
353
- heap_dump (heap -> heap );
393
+ heap_print_info (heap -> heap , dump_chunks );
354
394
}
0 commit comments