2 * Buffer-based memory allocator
4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
6 * This file is part of mbed TLS (https://tls.mbed.org)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #if !defined(POLARSSL_CONFIG_FILE)
24 #include "polarssl/config.h"
26 #include POLARSSL_CONFIG_FILE
29 #if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
30 #include "polarssl/memory_buffer_alloc.h"
32 /* No need for the header guard as POLARSSL_MEMORY_BUFFER_ALLOC_C
33 is dependent upon POLARSSL_PLATFORM_C */
34 #include "polarssl/platform.h"
38 #if defined(POLARSSL_MEMORY_BACKTRACE)
42 #if defined(POLARSSL_THREADING_C)
43 #include "polarssl/threading.h"
46 /* Implementation that should never be optimized out by the compiler */
47 static void polarssl_zeroize( void *v
, size_t n
) {
48 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
51 #define MAGIC1 0xFF00AA55
52 #define MAGIC2 0xEE119966
55 typedef struct _memory_header memory_header
;
63 memory_header
*prev_free
;
64 memory_header
*next_free
;
65 #if defined(POLARSSL_MEMORY_BACKTRACE)
77 memory_header
*first_free
;
79 #if defined(POLARSSL_MEMORY_DEBUG)
85 size_t maximum_header_count
;
87 #if defined(POLARSSL_THREADING_C)
88 threading_mutex_t mutex
;
93 static buffer_alloc_ctx heap
;
95 #if defined(POLARSSL_MEMORY_DEBUG)
96 static void debug_header( memory_header
*hdr
)
98 #if defined(POLARSSL_MEMORY_BACKTRACE)
102 polarssl_fprintf( stderr
, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
103 "ALLOC(%zu), SIZE(%10zu)\n",
104 (size_t) hdr
, (size_t) hdr
->prev
, (size_t) hdr
->next
,
105 hdr
->alloc
, hdr
->size
);
106 polarssl_fprintf( stderr
, " FPREV(%10zu), FNEXT(%10zu)\n",
107 (size_t) hdr
->prev_free
, (size_t) hdr
->next_free
);
109 #if defined(POLARSSL_MEMORY_BACKTRACE)
110 polarssl_fprintf( stderr
, "TRACE: \n" );
111 for( i
= 0; i
< hdr
->trace_count
; i
++ )
112 polarssl_fprintf( stderr
, "%s\n", hdr
->trace
[i
] );
113 polarssl_fprintf( stderr
, "\n" );
117 static void debug_chain()
119 memory_header
*cur
= heap
.first
;
121 polarssl_fprintf( stderr
, "\nBlock list\n" );
128 polarssl_fprintf( stderr
, "Free list\n" );
129 cur
= heap
.first_free
;
134 cur
= cur
->next_free
;
137 #endif /* POLARSSL_MEMORY_DEBUG */
139 static int verify_header( memory_header
*hdr
)
141 if( hdr
->magic1
!= MAGIC1
)
143 #if defined(POLARSSL_MEMORY_DEBUG)
144 polarssl_fprintf( stderr
, "FATAL: MAGIC1 mismatch\n" );
149 if( hdr
->magic2
!= MAGIC2
)
151 #if defined(POLARSSL_MEMORY_DEBUG)
152 polarssl_fprintf( stderr
, "FATAL: MAGIC2 mismatch\n" );
159 #if defined(POLARSSL_MEMORY_DEBUG)
160 polarssl_fprintf( stderr
, "FATAL: alloc has illegal value\n" );
165 if( hdr
->prev
!= NULL
&& hdr
->prev
== hdr
->next
)
167 #if defined(POLARSSL_MEMORY_DEBUG)
168 polarssl_fprintf( stderr
, "FATAL: prev == next\n" );
173 if( hdr
->prev_free
!= NULL
&& hdr
->prev_free
== hdr
->next_free
)
175 #if defined(POLARSSL_MEMORY_DEBUG)
176 polarssl_fprintf( stderr
, "FATAL: prev_free == next_free\n" );
184 static int verify_chain()
186 memory_header
*prv
= heap
.first
, *cur
= heap
.first
->next
;
188 if( verify_header( heap
.first
) != 0 )
190 #if defined(POLARSSL_MEMORY_DEBUG)
191 polarssl_fprintf( stderr
, "FATAL: verification of first header "
197 if( heap
.first
->prev
!= NULL
)
199 #if defined(POLARSSL_MEMORY_DEBUG)
200 polarssl_fprintf( stderr
, "FATAL: verification failed: "
201 "first->prev != NULL\n" );
208 if( verify_header( cur
) != 0 )
210 #if defined(POLARSSL_MEMORY_DEBUG)
211 polarssl_fprintf( stderr
, "FATAL: verification of header "
217 if( cur
->prev
!= prv
)
219 #if defined(POLARSSL_MEMORY_DEBUG)
220 polarssl_fprintf( stderr
, "FATAL: verification failed: "
221 "cur->prev != prv\n" );
233 static void *buffer_alloc_malloc( size_t len
)
235 memory_header
*new, *cur
= heap
.first_free
;
237 #if defined(POLARSSL_MEMORY_BACKTRACE)
238 void *trace_buffer
[MAX_BT
];
242 if( heap
.buf
== NULL
|| heap
.first
== NULL
)
245 if( len
% POLARSSL_MEMORY_ALIGN_MULTIPLE
)
247 len
-= len
% POLARSSL_MEMORY_ALIGN_MULTIPLE
;
248 len
+= POLARSSL_MEMORY_ALIGN_MULTIPLE
;
251 // Find block that fits
255 if( cur
->size
>= len
)
258 cur
= cur
->next_free
;
264 if( cur
->alloc
!= 0 )
266 #if defined(POLARSSL_MEMORY_DEBUG)
267 polarssl_fprintf( stderr
, "FATAL: block in free_list but allocated "
273 #if defined(POLARSSL_MEMORY_DEBUG)
277 // Found location, split block if > memory_header + 4 room left
279 if( cur
->size
- len
< sizeof(memory_header
) +
280 POLARSSL_MEMORY_ALIGN_MULTIPLE
)
284 // Remove from free_list
286 if( cur
->prev_free
!= NULL
)
287 cur
->prev_free
->next_free
= cur
->next_free
;
289 heap
.first_free
= cur
->next_free
;
291 if( cur
->next_free
!= NULL
)
292 cur
->next_free
->prev_free
= cur
->prev_free
;
294 cur
->prev_free
= NULL
;
295 cur
->next_free
= NULL
;
297 #if defined(POLARSSL_MEMORY_DEBUG)
298 heap
.total_used
+= cur
->size
;
299 if( heap
.total_used
> heap
.maximum_used
)
300 heap
.maximum_used
= heap
.total_used
;
302 #if defined(POLARSSL_MEMORY_BACKTRACE)
303 trace_cnt
= backtrace( trace_buffer
, MAX_BT
);
304 cur
->trace
= backtrace_symbols( trace_buffer
, trace_cnt
);
305 cur
->trace_count
= trace_cnt
;
308 if( ( heap
.verify
& MEMORY_VERIFY_ALLOC
) && verify_chain() != 0 )
311 return( ( (unsigned char *) cur
) + sizeof(memory_header
) );
314 p
= ( (unsigned char *) cur
) + sizeof(memory_header
) + len
;
315 new = (memory_header
*) p
;
317 new->size
= cur
->size
- len
- sizeof(memory_header
);
320 new->next
= cur
->next
;
321 #if defined(POLARSSL_MEMORY_BACKTRACE)
323 new->trace_count
= 0;
325 new->magic1
= MAGIC1
;
326 new->magic2
= MAGIC2
;
328 if( new->next
!= NULL
)
329 new->next
->prev
= new;
331 // Replace cur with new in free_list
333 new->prev_free
= cur
->prev_free
;
334 new->next_free
= cur
->next_free
;
335 if( new->prev_free
!= NULL
)
336 new->prev_free
->next_free
= new;
338 heap
.first_free
= new;
340 if( new->next_free
!= NULL
)
341 new->next_free
->prev_free
= new;
346 cur
->prev_free
= NULL
;
347 cur
->next_free
= NULL
;
349 #if defined(POLARSSL_MEMORY_DEBUG)
351 if( heap
.header_count
> heap
.maximum_header_count
)
352 heap
.maximum_header_count
= heap
.header_count
;
353 heap
.total_used
+= cur
->size
;
354 if( heap
.total_used
> heap
.maximum_used
)
355 heap
.maximum_used
= heap
.total_used
;
357 #if defined(POLARSSL_MEMORY_BACKTRACE)
358 trace_cnt
= backtrace( trace_buffer
, MAX_BT
);
359 cur
->trace
= backtrace_symbols( trace_buffer
, trace_cnt
);
360 cur
->trace_count
= trace_cnt
;
363 if( ( heap
.verify
& MEMORY_VERIFY_ALLOC
) && verify_chain() != 0 )
366 return( ( (unsigned char *) cur
) + sizeof(memory_header
) );
369 static void buffer_alloc_free( void *ptr
)
371 memory_header
*hdr
, *old
= NULL
;
372 unsigned char *p
= (unsigned char *) ptr
;
374 if( ptr
== NULL
|| heap
.buf
== NULL
|| heap
.first
== NULL
)
377 if( p
< heap
.buf
|| p
> heap
.buf
+ heap
.len
)
379 #if defined(POLARSSL_MEMORY_DEBUG)
380 polarssl_fprintf( stderr
, "FATAL: polarssl_free() outside of managed "
386 p
-= sizeof(memory_header
);
387 hdr
= (memory_header
*) p
;
389 if( verify_header( hdr
) != 0 )
392 if( hdr
->alloc
!= 1 )
394 #if defined(POLARSSL_MEMORY_DEBUG)
395 polarssl_fprintf( stderr
, "FATAL: polarssl_free() on unallocated "
403 #if defined(POLARSSL_MEMORY_DEBUG)
405 heap
.total_used
-= hdr
->size
;
408 // Regroup with block before
410 if( hdr
->prev
!= NULL
&& hdr
->prev
->alloc
== 0 )
412 #if defined(POLARSSL_MEMORY_DEBUG)
415 hdr
->prev
->size
+= sizeof(memory_header
) + hdr
->size
;
416 hdr
->prev
->next
= hdr
->next
;
420 if( hdr
->next
!= NULL
)
421 hdr
->next
->prev
= hdr
;
423 #if defined(POLARSSL_MEMORY_BACKTRACE)
426 memset( old
, 0, sizeof(memory_header
) );
429 // Regroup with block after
431 if( hdr
->next
!= NULL
&& hdr
->next
->alloc
== 0 )
433 #if defined(POLARSSL_MEMORY_DEBUG)
436 hdr
->size
+= sizeof(memory_header
) + hdr
->next
->size
;
438 hdr
->next
= hdr
->next
->next
;
440 if( hdr
->prev_free
!= NULL
|| hdr
->next_free
!= NULL
)
442 if( hdr
->prev_free
!= NULL
)
443 hdr
->prev_free
->next_free
= hdr
->next_free
;
445 heap
.first_free
= hdr
->next_free
;
447 if( hdr
->next_free
!= NULL
)
448 hdr
->next_free
->prev_free
= hdr
->prev_free
;
451 hdr
->prev_free
= old
->prev_free
;
452 hdr
->next_free
= old
->next_free
;
454 if( hdr
->prev_free
!= NULL
)
455 hdr
->prev_free
->next_free
= hdr
;
457 heap
.first_free
= hdr
;
459 if( hdr
->next_free
!= NULL
)
460 hdr
->next_free
->prev_free
= hdr
;
462 if( hdr
->next
!= NULL
)
463 hdr
->next
->prev
= hdr
;
465 #if defined(POLARSSL_MEMORY_BACKTRACE)
468 memset( old
, 0, sizeof(memory_header
) );
471 // Prepend to free_list if we have not merged
472 // (Does not have to stay in same order as prev / next list)
476 hdr
->next_free
= heap
.first_free
;
477 if( heap
.first_free
!= NULL
)
478 heap
.first_free
->prev_free
= hdr
;
479 heap
.first_free
= hdr
;
482 #if defined(POLARSSL_MEMORY_BACKTRACE)
484 hdr
->trace_count
= 0;
487 if( ( heap
.verify
& MEMORY_VERIFY_FREE
) && verify_chain() != 0 )
491 void memory_buffer_set_verify( int verify
)
493 heap
.verify
= verify
;
496 int memory_buffer_alloc_verify()
498 return verify_chain();
501 #if defined(POLARSSL_MEMORY_DEBUG)
502 void memory_buffer_alloc_status()
504 polarssl_fprintf( stderr
,
505 "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
506 "%zu bytes (total %zu bytes), malloc / free: %zu / %zu\n",
507 heap
.header_count
, heap
.total_used
,
508 heap
.maximum_header_count
, heap
.maximum_used
,
509 heap
.maximum_header_count
* sizeof( memory_header
)
511 heap
.malloc_count
, heap
.free_count
);
513 if( heap
.first
->next
== NULL
)
514 polarssl_fprintf( stderr
, "All memory de-allocated in stack buffer\n" );
517 polarssl_fprintf( stderr
, "Memory currently allocated:\n" );
522 void memory_buffer_alloc_max_get( size_t *max_used
, size_t *max_blocks
)
524 *max_used
= heap
.maximum_used
;
525 *max_blocks
= heap
.maximum_header_count
;
528 void memory_buffer_alloc_max_reset( void )
530 heap
.maximum_used
= 0;
531 heap
.maximum_header_count
= 0;
534 void memory_buffer_alloc_cur_get( size_t *cur_used
, size_t *cur_blocks
)
536 *cur_used
= heap
.total_used
;
537 *cur_blocks
= heap
.header_count
;
539 #endif /* POLARSSL_MEMORY_DEBUG */
541 #if defined(POLARSSL_THREADING_C)
542 static void *buffer_alloc_malloc_mutexed( size_t len
)
545 polarssl_mutex_lock( &heap
.mutex
);
546 buf
= buffer_alloc_malloc( len
);
547 polarssl_mutex_unlock( &heap
.mutex
);
551 static void buffer_alloc_free_mutexed( void *ptr
)
553 polarssl_mutex_lock( &heap
.mutex
);
554 buffer_alloc_free( ptr
);
555 polarssl_mutex_unlock( &heap
.mutex
);
557 #endif /* POLARSSL_THREADING_C */
559 int memory_buffer_alloc_init( unsigned char *buf
, size_t len
)
561 memset( &heap
, 0, sizeof(buffer_alloc_ctx
) );
562 memset( buf
, 0, len
);
564 #if defined(POLARSSL_THREADING_C)
565 polarssl_mutex_init( &heap
.mutex
);
566 platform_set_malloc_free( buffer_alloc_malloc_mutexed
,
567 buffer_alloc_free_mutexed
);
569 platform_set_malloc_free( buffer_alloc_malloc
, buffer_alloc_free
);
572 if( (size_t) buf
% POLARSSL_MEMORY_ALIGN_MULTIPLE
)
574 /* Adjust len first since buf is used in the computation */
575 len
-= POLARSSL_MEMORY_ALIGN_MULTIPLE
576 - (size_t) buf
% POLARSSL_MEMORY_ALIGN_MULTIPLE
;
577 buf
+= POLARSSL_MEMORY_ALIGN_MULTIPLE
578 - (size_t) buf
% POLARSSL_MEMORY_ALIGN_MULTIPLE
;
584 heap
.first
= (memory_header
*) buf
;
585 heap
.first
->size
= len
- sizeof(memory_header
);
586 heap
.first
->magic1
= MAGIC1
;
587 heap
.first
->magic2
= MAGIC2
;
588 heap
.first_free
= heap
.first
;
592 void memory_buffer_alloc_free()
594 #if defined(POLARSSL_THREADING_C)
595 polarssl_mutex_free( &heap
.mutex
);
597 polarssl_zeroize( &heap
, sizeof(buffer_alloc_ctx
) );
600 #if defined(POLARSSL_SELF_TEST)
601 static int check_pointer( void *p
)
606 if( (size_t) p
% POLARSSL_MEMORY_ALIGN_MULTIPLE
!= 0 )
612 static int check_all_free( )
615 #if defined(POLARSSL_MEMORY_DEBUG)
616 heap
.total_used
!= 0 ||
618 heap
.first
!= heap
.first_free
||
619 (void *) heap
.first
!= (void *) heap
.buf
)
627 #define TEST_ASSERT( condition ) \
628 if( ! (condition) ) \
631 polarssl_printf( "failed\n" ); \
637 int memory_buffer_alloc_self_test( int verbose
)
639 unsigned char buf
[1024];
640 unsigned char *p
, *q
, *r
, *end
;
644 polarssl_printf( " MBA test #1 (basic alloc-free cycle): " );
646 memory_buffer_alloc_init( buf
, sizeof( buf
) );
648 p
= polarssl_malloc( 1 );
649 q
= polarssl_malloc( 128 );
650 r
= polarssl_malloc( 16 );
652 TEST_ASSERT( check_pointer( p
) == 0 &&
653 check_pointer( q
) == 0 &&
654 check_pointer( r
) == 0 );
660 TEST_ASSERT( check_all_free( ) == 0 );
662 /* Memorize end to compare with the next test */
663 end
= heap
.buf
+ heap
.len
;
665 memory_buffer_alloc_free( );
668 polarssl_printf( "passed\n" );
671 polarssl_printf( " MBA test #2 (buf not aligned): " );
673 memory_buffer_alloc_init( buf
+ 1, sizeof( buf
) - 1 );
675 TEST_ASSERT( heap
.buf
+ heap
.len
== end
);
677 p
= polarssl_malloc( 1 );
678 q
= polarssl_malloc( 128 );
679 r
= polarssl_malloc( 16 );
681 TEST_ASSERT( check_pointer( p
) == 0 &&
682 check_pointer( q
) == 0 &&
683 check_pointer( r
) == 0 );
689 TEST_ASSERT( check_all_free( ) == 0 );
691 memory_buffer_alloc_free( );
694 polarssl_printf( "passed\n" );
697 polarssl_printf( " MBA test #3 (full): " );
699 memory_buffer_alloc_init( buf
, sizeof( buf
) );
701 p
= polarssl_malloc( sizeof( buf
) - sizeof( memory_header
) );
703 TEST_ASSERT( check_pointer( p
) == 0 );
704 TEST_ASSERT( polarssl_malloc( 1 ) == NULL
);
708 p
= polarssl_malloc( sizeof( buf
) - 2 * sizeof( memory_header
) - 16 );
709 q
= polarssl_malloc( 16 );
711 TEST_ASSERT( check_pointer( p
) == 0 && check_pointer( q
) == 0 );
712 TEST_ASSERT( polarssl_malloc( 1 ) == NULL
);
716 TEST_ASSERT( polarssl_malloc( 17 ) == NULL
);
720 TEST_ASSERT( check_all_free( ) == 0 );
722 memory_buffer_alloc_free( );
725 polarssl_printf( "passed\n" );
728 memory_buffer_alloc_free( );
732 #endif /* POLARSSL_SELF_TEST */
734 #endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */