108 sizeof ( ( (
struct refcnt * )
NULL )->count ) ];
118#define MIN_MEMBLOCK_ALIGN ( 4 * sizeof ( void * ) )
133#define HEAP_SIZE ( 4096 * 1024 )
136#define HEAP_ALIGN MIN_MEMBLOCK_ALIGN
177 sizeof ( *
block->list.next ) );
179 sizeof (
block->list.next->next->prev ) );
259 ( (
void * )
block ) );
265 assert ( ( (
void * )
block ) > ( (
void * ) prev ) );
267 ( ( (
void * ) prev ) + prev->size ) );
281 unsigned int discarded;
284 discarded = discarder->
discard();
296 unsigned int discarded;
300 }
while ( discarded );
320 size_t actual_offset;
335 if ( (
size == 0 ) || ( align == 0 ) || ( align & ( align - 1 ) ) ) {
341 DBGC (
heap,
"HEAP malformed allocation %#zx (aligned "
357 if ( actual_size <
size ) {
363 align_mask = ( ( align - 1 ) | (
heap->
align - 1 ) );
365 DBGC2 (
heap,
"HEAP allocating %#zx (aligned %#zx+%#zx)\n",
370 pre_size = ( ( actual_offset - virt_to_phys (
block ) )
372 if ( (
block->size < pre_size ) ||
373 ( (
block->size - pre_size ) < actual_size ) )
375 post_size = (
block->size - pre_size - actual_size );
382 block = ( ( (
void * ) pre ) + pre_size );
383 post = ( ( (
void * )
block ) + actual_size );
384 DBGC2 (
heap,
"HEAP splitting [%p,%p) -> [%p,%p) "
386 ( ( (
void * ) pre ) + pre->size ), pre,
block,
387 post, ( ( (
void * ) pre ) + pre->size ) );
397 post->
size = post_size;
404 pre->size = pre_size;
423 ptr = ( ( (
void * )
block ) +
offset - actual_offset );
424 DBGC2 (
heap,
"HEAP allocated [%p,%p) within "
426 ( ( (
void * )
block ) + actual_size ) );
432 DBGC (
heap,
"HEAP attempting to grow for %#zx (aligned "
433 "%#zx+%zx), used %zdkB\n",
size, align,
offset,
441 DBGC (
heap,
"HEAP failed to allocate %#zx (aligned "
442 "%#zx)\n",
size, align );
485 sub_offset = ( virt_to_phys ( ptr ) & (
heap->
align - 1 ) );
486 freeing = ( ptr - sub_offset );
489 DBGC2 (
heap,
"HEAP freeing [%p,%p) within [%p,%p)\n",
490 ptr, ( ptr +
size ), freeing,
491 ( ( (
void * ) freeing ) + actual_size ) );
497 if ( ( ( (
void * )
block ) <
498 ( (
void * ) freeing + actual_size ) ) &&
499 ( (
void * ) freeing <
502 DBGC (
heap,
"HEAP double free of [%p,%p) "
503 "overlapping [%p,%p) detected from %p\n",
505 ( ( (
void * ) freeing ) +
size ),
block,
507 __builtin_return_address ( 0 ) );
513 freeing->
size = actual_size;
516 gap_before = ( ( (
void * ) freeing ) -
518 gap_after = ( ( (
void * )
block ) -
519 ( ( (
void * ) freeing ) + freeing->size ) );
521 if ( gap_before == 0 ) {
522 DBGC2 (
heap,
"HEAP merging [%p,%p) + [%p,%p) -> "
524 ( ( (
void * )
block ) +
block->size ), freeing,
525 ( ( (
void * ) freeing ) + freeing->size ),
527 ( ( (
void * ) freeing ) + freeing->size ) );
528 block->size += actual_size;
531 sizeof ( *freeing ) );
535 if ( gap_after >= 0 )
544 freeing, ( ( (
void * ) freeing ) + freeing->
size ) );
546 if ( gap_after == 0 ) {
547 DBGC2 (
heap,
"HEAP merging [%p,%p) + [%p,%p) -> [%p,%p)\n",
548 freeing, ( ( (
void * ) freeing ) + freeing->size ),
551 freeing->size +=
block->size;
596 size_t old_total_size;
597 size_t new_total_size;
606 new_total_size = ( new_size +
offset );
607 if ( new_total_size < new_size )
613 new_block->
size = new_total_size;
615 sizeof ( new_block->
size ) );
616 new_ptr = &new_block->
data;
627 if ( old_ptr && ( old_ptr !=
NOWHERE ) ) {
631 sizeof ( old_block->
size ) );
632 old_total_size = old_block->
size;
633 assert ( old_total_size != 0 );
634 old_size = ( old_total_size -
offset );
635 memcpy ( new_ptr, old_ptr,
636 ( ( old_size < new_size ) ? old_size : new_size ) );
642 DBGC (
heap,
"HEAP detected possible memory corruption "
643 "from %p\n", __builtin_return_address ( 0 ) );
652 .ptr_align =
sizeof (
void * ),
663void *
realloc (
void *old_ptr,
size_t new_size ) {
682 DBGC ( &
heap,
"HEAP detected possible memory corruption "
683 "from %p\n", __builtin_return_address ( 0 ) );
702 DBGC ( &
heap,
"HEAP detected possible memory corruption "
703 "from %p\n", __builtin_return_address ( 0 ) );
725 DBGC ( &
heap,
"HEAP detected possible memory corruption "
726 "from %p\n", __builtin_return_address ( 0 ) );
741 if ( ptr && ( ptr !=
NOWHERE ) ) {
744 sizeof (
block->size ) );
748 sizeof (
block->size ) );
752 DBGC ( &
heap,
"HEAP detected possible memory corruption "
753 "from %p\n", __builtin_return_address ( 0 ) );
770 assert ( phys_align != 0 );
774 ( phys_align - 1 ) ) == 0 );
861 DBGC ( &
heap,
"HEAP maximum usage %zdkB\n",
#define NULL
NULL pointer (VOID *).
#define build_assert(condition)
Assert a condition at build time (after dead code elimination).
#define assert(condition)
Assert a condition at run-time.
struct bofm_section_header done
uint16_t offset
Offset to command line.
uint8_t data[48]
Additional event data.
#define __unused
Declare a variable or data structure as unused.
void dbg_printf(const char *fmt,...)
Print debug message.
#define INIT_EARLY
Early initialisation.
uint32_t start
Starting offset.
uint16_t size
Buffer size.
static unsigned int count
Number of entries.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
#define STARTUP_EARLY
Early startup.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define __init_fn(init_order)
Declare an initialisation functon.
#define __startup_fn(startup_order)
Declare a startup/shutdown function.
#define LIST_HEAD_INIT(list)
Initialise a static list head.
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
#define list_del(list)
Delete an entry from a list.
#define list_check(list)
Check a list entry or list head is valid.
#define list_add(new, head)
Add a new entry to the head of a list.
void * heap_realloc(struct heap *heap, void *old_ptr, size_t new_size)
Reallocate memory.
static char heap_area[HEAP_SIZE]
The heap area.
#define HEAP_SIZE
Heap area size.
static unsigned int discard_cache(size_t size __unused)
Discard some cached data.
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
void * zalloc(size_t size)
Allocate cleared memory.
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
static void init_heap(void)
Initialise the heap.
void heap_dump(struct heap *heap)
Dump free block list (for debugging).
static void shutdown_cache(int booting __unused)
Discard all cached data on shutdown.
static void valgrind_make_blocks_defined(struct heap *heap)
Mark all blocks in free list as defined.
void * malloc(size_t size)
Allocate memory.
static void discard_all_cache(void)
Discard all cached data.
void * malloc_phys_offset(size_t size, size_t phys_align, size_t offset)
Allocate memory with specified physical alignment and offset.
#define MIN_MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
#define HEAP_ALIGN
Heap area alignment.
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys().
static void check_blocks(struct heap *heap)
Check integrity of the blocks in the free list.
static void valgrind_make_blocks_noaccess(struct heap *heap)
Mark all blocks in free list as inaccessible.
void heap_populate(struct heap *heap, void *start, size_t len)
Add memory to allocation pool.
void zfree(void *ptr)
Clear and free memory.
static void * heap_alloc_block(struct heap *heap, size_t size, size_t align, size_t offset)
Allocate a memory block.
static void heap_free_block(struct heap *heap, void *ptr, size_t size)
Free a memory block.
Dynamic memory allocation.
#define CACHE_DISCARDERS
Cache discarder table.
#define NOWHERE
Address for zero-length memory blocks.
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
uint8_t block[3][8]
DES-encrypted blocks.
static void(* free)(struct refcnt *refcnt))
#define offsetof(type, field)
Get offset of a field within a structure.
#define container_of(ptr, type, field)
Get containing structure.
A block of allocated memory complete with size information.
size_t size
Size of this block.
char data[0]
Remaining data.
unsigned int(* discard)(void)
Discard some cached data.
size_t usedmem
Total amount of used memory.
size_t freemem
Total amount of free memory.
size_t ptr_align
Alignment for size-tracked allocations.
unsigned int(* grow)(size_t size)
Attempt to grow heap (optional).
struct list_head blocks
List of free memory blocks.
size_t maxusedmem
Maximum amount of used memory.
size_t align
Alignment for free memory blocks.
unsigned int(* shrink)(void *ptr, size_t size)
Allow heap to shrink (optional).
An initialisation function.
A doubly-linked list entry (or list head).
struct list_head * next
Next list entry.
struct list_head * prev
Previous list entry.
size_t size
Size of this block.
struct list_head list
List of free blocks.
char pad[offsetof(struct refcnt, count)+sizeof(((struct refcnt *) NULL) ->count)]
Padding.
A startup/shutdown function.
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
#define RUNNING_ON_VALGRIND
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)