62 #define MIN_MEMBLOCK_SIZE \ 63 ( ( size_t ) ( 1 << ( fls ( sizeof ( struct memory_block ) - 1 ) ) ) ) 88 #define NOWHERE ( ( void * ) ~( ( intptr_t ) 0 ) ) 107 #define HEAP_SIZE ( 512 * 1024 ) 133 sizeof ( free_blocks.prev->next ) );
135 sizeof ( *free_blocks.next ) );
137 sizeof ( free_blocks.next->next->prev ) );
147 sizeof ( *
block->list.next ) );
149 sizeof (
block->list.next->next->prev ) );
185 sizeof ( free_blocks.next->prev ) );
195 sizeof ( free_blocks.next->prev ) );
223 ( (
void * )
block ) );
229 assert ( ( (
void * )
block ) > ( (
void * ) prev ) );
231 ( ( (
void * ) prev ) + prev->size ) );
244 unsigned int discarded;
247 discarded = discarder->
discard();
259 unsigned int discarded;
263 }
while ( discarded );
287 unsigned int discarded;
301 if ( ! actual_size ) {
313 DBGC2 ( &
heap,
"Allocating %#zx (aligned %#zx+%zx)\n",
320 if ( (
block->size < pre_size ) ||
321 ( (
block->size - pre_size ) < actual_size ) )
323 post_size = (
block->size - pre_size - actual_size );
330 block = ( ( (
void * ) pre ) + pre_size );
331 post = ( ( (
void * )
block ) + actual_size );
332 DBGC2 ( &
heap,
"[%p,%p) -> [%p,%p) + [%p,%p)\n", pre,
333 ( ( (
void * ) pre ) + pre->size ), pre,
block,
334 post, ( ( (
void * ) pre ) + pre->size ) );
343 post->
size = post_size;
350 pre->size = pre_size;
375 DBGC ( &
heap,
"Attempting discard for %#zx (aligned %#zx+%zx), " 383 DBGC ( &
heap,
"Failed to allocate %#zx (aligned " 430 freeing, ( ( (
void * ) freeing ) +
size ) );
435 if ( ( ( (
void * )
block ) <
436 ( (
void * ) freeing + actual_size ) ) &&
437 ( (
void * ) freeing <
440 DBGC ( &
heap,
"Double free of [%p,%p) " 441 "overlapping [%p,%p) detected from %p\n",
443 ( ( (
void * ) freeing ) +
size ),
block,
445 __builtin_return_address ( 0 ) );
451 freeing->size = actual_size;
454 gap_before = ( ( (
void * ) freeing ) -
456 gap_after = ( ( (
void * )
block ) -
457 ( ( (
void * ) freeing ) + freeing->size ) );
459 if ( gap_before == 0 ) {
461 ( ( (
void * )
block ) +
block->size ), freeing,
462 ( ( (
void * ) freeing ) + freeing->size ),
464 ( ( (
void * ) freeing ) + freeing->size ) );
465 block->size += actual_size;
468 sizeof ( *freeing ) );
472 if ( gap_after >= 0 )
481 freeing, ( ( (
void * ) freeing ) + freeing->size ) );
483 if ( gap_after == 0 ) {
484 DBGC2 ( &
heap,
"[%p,%p) + [%p,%p) -> [%p,%p)\n", freeing,
485 ( ( (
void * ) freeing ) + freeing->size ),
block,
486 ( ( (
void * )
block ) +
block->size ), freeing,
488 freeing->size +=
block->size;
521 void *
realloc (
void *old_ptr,
size_t new_size ) {
524 size_t old_total_size;
525 size_t new_total_size;
533 new_total_size = ( new_size +
535 if ( new_total_size < new_size )
540 new_block->
size = new_total_size;
542 sizeof ( new_block->
size ) );
543 new_ptr = &new_block->
data;
552 if ( old_ptr && ( old_ptr !=
NOWHERE ) ) {
556 sizeof ( old_block->
size ) );
557 old_total_size = old_block->
size;
558 assert ( old_total_size != 0 );
559 old_size = ( old_total_size -
561 memcpy ( new_ptr, old_ptr,
562 ( ( old_size < new_size ) ? old_size : new_size ) );
568 DBGC ( &
heap,
"Possible memory corruption detected from %p\n",
569 __builtin_return_address ( 0 ) );
588 DBGC ( &
heap,
"Possible memory corruption detected from %p\n",
589 __builtin_return_address ( 0 ) );
608 DBGC ( &
heap,
"Possible memory corruption detected from %p\n",
609 __builtin_return_address ( 0 ) );
631 DBGC ( &
heap,
"Possible memory corruption detected from %p\n",
632 __builtin_return_address ( 0 ) );
701 printf (
"Free block list:\n" );
static __always_inline void struct dma_mapping size_t size_t align
void free_memblock(void *ptr, size_t size)
Free a memory block.
int printf(const char *fmt,...)
Write a formatted string to the console.
#define list_add(new, head)
Add a new entry to the head of a list.
#define INIT_EARLY
Early initialisation.
#define STARTUP_EARLY
Early startup.
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
uint8_t size
Entry size (in 32-bit words)
char data[0]
Remaining data.
#define CACHE_DISCARDERS
Cache discarder table.
#define RUNNING_ON_VALGRIND
#define offsetof(type, field)
Get offset of a field within a structure.
static void valgrind_make_blocks_noaccess(void)
Mark all blocks in free list as inaccessible.
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
A doubly-linked list entry (or list head)
Dynamic memory allocation.
static char heap[HEAP_SIZE]
The heap itself.
uint32_t start
Starting offset.
struct list_head list
List of free blocks.
A startup/shutdown function.
#define list_del(list)
Delete an entry from a list.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An initialisation function.
size_t freemem
Total amount of free memory.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
static void check_blocks(void)
Check integrity of the blocks in the free list.
unsigned int(* discard)(void)
Discard some cached data.
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
#define __unused
Declare a variable or data structure as unused.
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
uint16_t count
Number of entries.
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
size_t size
Size of this block.
struct init_fn heap_init_fn __init_fn(INIT_EARLY)
Memory allocator initialisation function.
void * zalloc(size_t size)
Allocate cleared memory.
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
static void discard_all_cache(void)
Discard all cached data.
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
static LIST_HEAD(free_blocks)
List of free memory blocks.
#define MIN_MEMBLOCK_SIZE
void * alloc_memblock(size_t size, size_t align, size_t offset)
Allocate a memory block.
#define NOWHERE
Address for zero-length memory blocks.
void * malloc(size_t size)
Allocate memory.
#define HEAP_SIZE
Heap size.
#define list_check(list)
Check a list entry or list head is valid.
static unsigned int discard_cache(void)
Discard some cached data.
void free(void *ptr)
Free memory.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
uint8_t block[3][8]
DES-encrypted blocks.
char pad[offsetof(struct refcnt, count)+sizeof(((struct refcnt *) NULL) ->count)]
Padding.
size_t size
Size of this block.
void mpopulate(void *start, size_t len)
Add memory to allocation pool.
A block of allocated memory complete with size information.
static void init_heap(void)
Initialise the heap.
uint8_t data[48]
Additional event data.
static void valgrind_make_blocks_defined(void)
Mark all blocks in free list as defined.
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
uint16_t offset
Offset to command line.
struct startup_fn heap_startup_fn __startup_fn(STARTUP_EARLY)
Memory allocator shutdown function.
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)
#define NULL
NULL pointer (VOID *)
size_t maxusedmem
Maximum amount of used memory.
struct bofm_section_header done
static void shutdown_cache(int booting __unused)
Discard all cached data on shutdown.
size_t usedmem
Total amount of used memory.
void * memset(void *dest, int character, size_t len) __nonnull