@ -314,41 +314,81 @@ void sys_heap_stress(void *(*alloc)(void *arg, size_t bytes),
@@ -314,41 +314,81 @@ void sys_heap_stress(void *(*alloc)(void *arg, size_t bytes),
}
/*
* Dump heap structure content for debugging / analysis purpose
* Print heap info for debugging / analysis purpose
*/
void heap_dum p ( struct z_heap * h )
void heap_print_info ( struct z_heap * h , bool dump_chunks )
{
int i , nb_buckets = bucket_idx ( h , h - > len ) + 1 ;
size_t free_bytes , allocated_bytes , total , overhead ;
printk ( " Heap at %p contains %d units \n " , chunk_buf ( h ) , h - > len ) ;
printk ( " Heap at %p contains %d units in %d buckets \n \n " ,
chunk_buf ( h ) , h - > len , nb_buckets ) ;
printk ( " bucket# min units total largest largest \n "
" threshold chunks (units) (bytes) \n "
" ----------------------------------------------------------- \n " ) ;
for ( i = 0 ; i < nb_buckets ; i + + ) {
chunkid_t first = h - > buckets [ i ] . next ;
size_t largest = 0 ;
int count = 0 ;
if ( first ) {
chunkid_t curr = first ;
do {
count + + ;
largest = MAX ( largest , chunk_size ( h , curr ) ) ;
curr = next_free_chunk ( h , curr ) ;
} while ( curr ! = first ) ;
}
printk ( " bucket %d (min %d units): %d chunks \n " , i ,
( 1 < < i ) - 1 + min_chunk_size ( h ) , count ) ;
if ( count ) {
printk ( " %9d %12d %12d %12zd %12zd \n " ,
i , ( 1 < < i ) - 1 + min_chunk_size ( h ) , count ,
largest , largest * CHUNK_UNIT - chunk_header_bytes ( h ) ) ;
}
}
if ( dump_chunks ) {
printk ( " \n Chunk dump: \n " ) ;
}
free_bytes = allocated_bytes = 0 ;
for ( chunkid_t c = 0 ; ; c = right_chunk ( h , c ) ) {
printk ( " chunk %3zd: %c %3zd] %3zd [%zd \n " ,
c , chunk_used ( h , c ) ? ' * ' : ' - ' ,
left_chunk ( h , c ) , chunk_size ( h , c ) , right_chunk ( h , c ) ) ;
if ( c = = 0 | | c = = h - > len ) {
/* those are always allocated for internal purposes */
} else if ( chunk_used ( h , c ) ) {
allocated_bytes + = chunk_size ( h , c ) * CHUNK_UNIT
- chunk_header_bytes ( h ) ;
} else if ( ! solo_free_header ( h , c ) ) {
free_bytes + = chunk_size ( h , c ) * CHUNK_UNIT
- chunk_header_bytes ( h ) ;
}
if ( dump_chunks ) {
printk ( " chunk %4zd: [%c] size=%-4zd left=%-4zd right=%zd \n " ,
c ,
chunk_used ( h , c ) ? ' * '
: solo_free_header ( h , c ) ? ' . '
: ' - ' ,
chunk_size ( h , c ) ,
left_chunk ( h , c ) ,
right_chunk ( h , c ) ) ;
}
if ( c = = h - > len ) {
break ;
}
}
/*
* The final chunk at h - > len is just a header serving as a end
* marker . It is part of the overhead .
*/
total = h - > len * CHUNK_UNIT + chunk_header_bytes ( h ) ;
overhead = total - free_bytes - allocated_bytes ;
printk ( " \n %zd free bytes, %zd allocated bytes, overhead = %zd bytes (%zd.%zd%%) \n " ,
free_bytes , allocated_bytes , overhead ,
( 1000 * overhead + total / 2 ) / total / 10 ,
( 1000 * overhead + total / 2 ) / total % 10 ) ;
}
void sys_heap_dump ( struct sys_heap * heap )
void sys_heap_print_info ( struct sys_heap * heap , bool dump_chunks )
{
heap_dump ( heap - > heap ) ;
heap_print_info ( heap - > heap , dump_chunks ) ;
}