iPXE
malloc.c File Reference

Dynamic memory allocation. More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <ipxe/io.h>
#include <ipxe/list.h>
#include <ipxe/init.h>
#include <ipxe/refcnt.h>
#include <ipxe/malloc.h>
#include <valgrind/memcheck.h>

Go to the source code of this file.

Data Structures

struct  memory_block
 A free block of memory. More...
struct  autosized_block
 A block of allocated memory complete with size information. More...

Macros

#define MIN_MEMBLOCK_ALIGN   ( 4 * sizeof ( void * ) )
 Physical address alignment maintained for free blocks of memory.
#define HEAP_SIZE   ( 4096 * 1024 )
 Heap area size.
#define HEAP_ALIGN   MIN_MEMBLOCK_ALIGN
 Heap area alignment.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static void valgrind_make_blocks_defined (struct heap *heap)
 Mark all blocks in free list as defined.
static void valgrind_make_blocks_noaccess (struct heap *heap)
 Mark all blocks in free list as inaccessible.
static void check_blocks (struct heap *heap)
 Check integrity of the blocks in the free list.
static unsigned int discard_cache (size_t size __unused)
 Discard some cached data.
static void discard_all_cache (void)
 Discard all cached data.
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.
void * heap_realloc (struct heap *heap, void *old_ptr, size_t new_size)
 Reallocate memory.
void * realloc (void *old_ptr, size_t new_size)
 Reallocate memory.
void * malloc (size_t size)
 Allocate memory.
void free (void *ptr)
 Free memory.
void * zalloc (size_t size)
 Allocate cleared memory.
void * malloc_phys_offset (size_t size, size_t phys_align, size_t offset)
 Allocate memory with specified physical alignment and offset.
void * malloc_phys (size_t size, size_t phys_align)
 Allocate memory with specified physical alignment.
void free_phys (void *ptr, size_t size)
 Free memory allocated with malloc_phys()
void heap_populate (struct heap *heap, void *start, size_t len)
 Add memory to allocation pool.
static void init_heap (void)
 Initialise the heap.
struct init_fn heap_init_fn __init_fn (INIT_EARLY)
 Memory allocator initialisation function.
static void shutdown_cache (int booting __unused)
 Discard all cached data on shutdown.
struct startup_fn heap_startup_fn __startup_fn (STARTUP_EARLY)
 Memory allocator shutdown function.
void heap_dump (struct heap *heap)
 Dump free block list (for debugging)

Variables

static char heap_area [HEAP_SIZE]
 The heap area.
static struct heap heap
 The global heap.

Detailed Description

Dynamic memory allocation.

Definition in file malloc.c.

Macro Definition Documentation

◆ MIN_MEMBLOCK_ALIGN

#define MIN_MEMBLOCK_ALIGN   ( 4 * sizeof ( void * ) )

Physical address alignment maintained for free blocks of memory.

We keep memory blocks aligned on a power of two that is at least large enough to hold a struct memory_block.

Definition at line 67 of file malloc.c.

Referenced by init_heap().

◆ HEAP_SIZE

#define HEAP_SIZE   ( 4096 * 1024 )

Heap area size.

Currently fixed at 4MB.

Definition at line 82 of file malloc.c.

◆ HEAP_ALIGN

#define HEAP_ALIGN   MIN_MEMBLOCK_ALIGN

Heap area alignment.

Definition at line 85 of file malloc.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ valgrind_make_blocks_defined()

void valgrind_make_blocks_defined ( struct heap * heap)
inlinestatic

Mark all blocks in free list as defined.

Parameters
heapHeap

Definition at line 95 of file malloc.c.

95 {
96 struct memory_block *block;
97
98 /* Do nothing unless running under Valgrind */
99 if ( RUNNING_ON_VALGRIND <= 0 )
100 return;
101
102 /* Traverse free block list, marking each block structure as
103 * defined. Some contortions are necessary to avoid errors
104 * from list_check().
105 */
106
107 /* Mark block list itself as defined */
109
110 /* Mark areas accessed by list_check() as defined */
112 sizeof ( heap->blocks.prev->next ) );
114 sizeof ( *heap->blocks.next ) );
116 sizeof ( heap->blocks.next->next->prev ) );
117
118 /* Mark each block in list as defined */
120
121 /* Mark block as defined */
122 VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
123
124 /* Mark areas accessed by list_check() as defined */
125 VALGRIND_MAKE_MEM_DEFINED ( block->list.next,
126 sizeof ( *block->list.next ) );
127 VALGRIND_MAKE_MEM_DEFINED ( &block->list.next->next->prev,
128 sizeof ( block->list.next->next->prev ) );
129 }
130}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
Definition memcheck.h:132
uint8_t block[3][8]
DES-encrypted blocks.
Definition mschapv2.h:1
A heap.
Definition malloc.h:45
struct list_head blocks
List of free memory blocks.
Definition malloc.h:47
struct list_head * next
Next list entry.
Definition list.h:21
struct list_head * prev
Previous list entry.
Definition list.h:23
A free block of memory.
Definition malloc.c:44
struct list_head list
List of free blocks.
Definition malloc.c:59
#define RUNNING_ON_VALGRIND
Definition valgrind.h:4176

References block, heap::blocks, memory_block::list, list_for_each_entry, list_head::next, list_head::prev, RUNNING_ON_VALGRIND, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by heap_alloc_block(), and heap_free_block().

◆ valgrind_make_blocks_noaccess()

void valgrind_make_blocks_noaccess ( struct heap * heap)
inlinestatic

Mark all blocks in free list as inaccessible.

Parameters
heapHeap

Definition at line 137 of file malloc.c.

137 {
138 struct memory_block *block;
139 struct memory_block *prev = NULL;
140
141 /* Do nothing unless running under Valgrind */
142 if ( RUNNING_ON_VALGRIND <= 0 )
143 return;
144
145 /* Traverse free block list, marking each block structure as
146 * inaccessible. Some contortions are necessary to avoid
147 * errors from list_check().
148 */
149
150 /* Mark each block in list as inaccessible */
152
153 /* Mark previous block (if any) as inaccessible. (Current
154 * block will be accessed by list_check().)
155 */
156 if ( prev )
157 VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
158 prev = block;
159
160 /* At the end of the list, list_check() will end up
161 * accessing the first list item. Temporarily mark
162 * this area as defined.
163 */
165 sizeof ( heap->blocks.next->prev ));
166 }
167 /* Mark last block (if any) as inaccessible */
168 if ( prev )
169 VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
170
171 /* Mark as inaccessible the area that was temporarily marked
172 * as defined to avoid errors from list_check().
173 */
175 sizeof ( heap->blocks.next->prev ) );
176
177 /* Mark block list itself as inaccessible */
179}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition memcheck.h:112

References block, heap::blocks, memory_block::list, list_for_each_entry, list_head::next, NULL, list_head::prev, RUNNING_ON_VALGRIND, VALGRIND_MAKE_MEM_DEFINED, and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by heap_alloc_block(), and heap_free_block().

◆ check_blocks()

void check_blocks ( struct heap * heap)
inlinestatic

Check integrity of the blocks in the free list.

Parameters
heapHeap

Definition at line 186 of file malloc.c.

186 {
187 struct memory_block *block;
188 struct memory_block *prev = NULL;
189
190 if ( ! ASSERTING )
191 return;
192
194
195 /* Check alignment */
196 assert ( ( virt_to_phys ( block ) &
197 ( heap->align - 1 ) ) == 0 );
198
199 /* Check that list structure is intact */
200 list_check ( &block->list );
201
202 /* Check that block size is not too small */
203 assert ( block->size >= sizeof ( *block ) );
204 assert ( block->size >= heap->align );
205
206 /* Check that block does not wrap beyond end of address space */
207 assert ( ( ( void * ) block + block->size ) >
208 ( ( void * ) block ) );
209
210 /* Check that blocks remain in ascending order, and
211 * that adjacent blocks have been merged.
212 */
213 if ( prev ) {
214 assert ( ( ( void * ) block ) > ( ( void * ) prev ) );
215 assert ( ( ( void * ) block ) >
216 ( ( ( void * ) prev ) + prev->size ) );
217 }
218 prev = block;
219 }
220}
#define ASSERTING
Definition assert.h:20
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define list_check(list)
Check a list entry or list head is valid.
Definition list.h:56
size_t align
Alignment for free memory blocks.
Definition malloc.h:50

References heap::align, assert, ASSERTING, block, heap::blocks, memory_block::list, list_check, list_for_each_entry, and NULL.

Referenced by heap_alloc_block(), and heap_free_block().

◆ discard_cache()

unsigned int discard_cache ( size_t size __unused)
static

Discard some cached data.

Parameters
sizeFailed allocation size
Return values
discardedNumber of cached items discarded

Definition at line 228 of file malloc.c.

228 {
229 struct cache_discarder *discarder;
230 unsigned int discarded;
231
233 discarded = discarder->discard();
234 if ( discarded )
235 return discarded;
236 }
237 return 0;
238}
#define CACHE_DISCARDERS
Cache discarder table.
Definition malloc.h:103
A cache discarder.
Definition malloc.h:93
unsigned int(* discard)(void)
Discard some cached data.
Definition malloc.h:99
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References __unused, CACHE_DISCARDERS, cache_discarder::discard, for_each_table_entry, and size.

Referenced by discard_all_cache().

◆ discard_all_cache()

void discard_all_cache ( void )
static

Discard all cached data.

Definition at line 244 of file malloc.c.

244 {
245 unsigned int discarded;
246
247 do {
248 discarded = discard_cache ( 0 );
249 } while ( discarded );
250}
static unsigned int discard_cache(size_t size __unused)
Discard some cached data.
Definition malloc.c:228

References discard_cache().

Referenced by shutdown_cache().

◆ heap_alloc_block()

void * heap_alloc_block ( struct heap * heap,
size_t size,
size_t align,
size_t offset )
static

Allocate a memory block.

Parameters
heapHeap
sizeRequested size
alignPhysical alignment
offsetOffset from physical alignment
Return values
ptrMemory block, or NULL

Allocates a memory block physically aligned as requested. No guarantees are provided for the alignment of the virtual address.

align must be a power of two. size may not be zero.

Definition at line 266 of file malloc.c.

267 {
268 struct memory_block *block;
269 size_t actual_offset;
270 size_t align_mask;
271 size_t actual_size;
272 size_t pre_size;
273 size_t post_size;
274 struct memory_block *pre;
275 struct memory_block *post;
276 unsigned int grown;
277 void *ptr;
278
279 /* Sanity checks */
280 assert ( size != 0 );
281 assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) );
283 check_blocks ( heap );
284
285 /* Limit offset to requested alignment */
286 offset &= ( align ? ( align - 1 ) : 0 );
287
288 /* Calculate offset of memory block */
289 actual_offset = ( offset & ~( heap->align - 1 ) );
290 assert ( actual_offset <= offset );
291
292 /* Calculate size of memory block */
293 actual_size = ( ( size + offset - actual_offset + heap->align - 1 )
294 & ~( heap->align - 1 ) );
295 if ( ! actual_size ) {
296 /* The requested size is not permitted to be zero. A
297 * zero result at this point indicates that either the
298 * original requested size was zero, or that unsigned
299 * integer overflow has occurred.
300 */
301 ptr = NULL;
302 goto done;
303 }
304 assert ( actual_size >= size );
305
306 /* Calculate alignment mask */
307 align_mask = ( ( align - 1 ) | ( heap->align - 1 ) );
308
309 DBGC2 ( heap, "HEAP allocating %#zx (aligned %#zx+%#zx)\n",
310 size, align, offset );
311 while ( 1 ) {
312 /* Search through blocks for the first one with enough space */
314 pre_size = ( ( actual_offset - virt_to_phys ( block ) )
315 & align_mask );
316 if ( ( block->size < pre_size ) ||
317 ( ( block->size - pre_size ) < actual_size ) )
318 continue;
319 post_size = ( block->size - pre_size - actual_size );
320 /* Split block into pre-block, block, and
321 * post-block. After this split, the "pre"
322 * block is the one currently linked into the
323 * free list.
324 */
325 pre = block;
326 block = ( ( ( void * ) pre ) + pre_size );
327 post = ( ( ( void * ) block ) + actual_size );
328 DBGC2 ( heap, "HEAP splitting [%p,%p) -> [%p,%p) "
329 "+ [%p,%p)\n", pre,
330 ( ( ( void * ) pre ) + pre->size ), pre, block,
331 post, ( ( ( void * ) pre ) + pre->size ) );
332 /* If there is a "post" block, add it in to
333 * the free list.
334 */
335 if ( post_size ) {
336 assert ( post_size >= sizeof ( *block ) );
337 assert ( ( post_size &
338 ( heap->align - 1 ) ) == 0 );
340 sizeof ( *post ));
341 post->size = post_size;
342 list_add ( &post->list, &pre->list );
343 }
344 /* Shrink "pre" block, leaving the main block
345 * isolated and no longer part of the free
346 * list.
347 */
348 pre->size = pre_size;
349 /* If there is no "pre" block, remove it from
350 * the list.
351 */
352 if ( ! pre_size ) {
353 list_del ( &pre->list );
355 sizeof ( *pre ) );
356 } else {
357 assert ( pre_size >= sizeof ( *block ) );
358 assert ( ( pre_size &
359 ( heap->align - 1 ) ) == 0 );
360 }
361 /* Update memory usage statistics */
362 heap->freemem -= actual_size;
363 heap->usedmem += actual_size;
364 if ( heap->usedmem > heap->maxusedmem )
366 /* Return allocated block */
367 ptr = ( ( ( void * ) block ) + offset - actual_offset );
368 DBGC2 ( heap, "HEAP allocated [%p,%p) within "
369 "[%p,%p)\n", ptr, ( ptr + size ), block,
370 ( ( ( void * ) block ) + actual_size ) );
372 goto done;
373 }
374
375 /* Attempt to grow heap to satisfy allocation */
376 DBGC ( heap, "HEAP attempting to grow for %#zx (aligned "
377 "%#zx+%zx), used %zdkB\n", size, align, offset,
378 ( heap->usedmem >> 10 ) );
380 grown = ( heap->grow ? heap->grow ( actual_size ) : 0 );
382 check_blocks ( heap );
383 if ( ! grown ) {
384 /* Heap did not grow: fail allocation */
385 DBGC ( heap, "HEAP failed to allocate %#zx (aligned "
386 "%#zx)\n", size, align );
387 ptr = NULL;
388 goto done;
389 }
390 }
391
392 done:
393 check_blocks ( heap );
395 return ptr;
396}
struct bofm_section_header done
Definition bofm_test.c:46
uint16_t offset
Offset to command line.
Definition bzimage.h:3
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
uint16_t size
Buffer size.
Definition dwmac.h:3
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
static void valgrind_make_blocks_defined(struct heap *heap)
Mark all blocks in free list as defined.
Definition malloc.c:95
static void check_blocks(struct heap *heap)
Check integrity of the blocks in the free list.
Definition malloc.c:186
static void valgrind_make_blocks_noaccess(struct heap *heap)
Mark all blocks in free list as inaccessible.
Definition malloc.c:137
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
Definition memcheck.h:122
size_t usedmem
Total amount of used memory.
Definition malloc.h:57
size_t freemem
Total amount of free memory.
Definition malloc.h:55
unsigned int(* grow)(size_t size)
Attempt to grow heap (optional)
Definition malloc.h:67
size_t maxusedmem
Maximum amount of used memory.
Definition malloc.h:59
size_t size
Size of this block.
Definition malloc.c:46

References heap::align, assert, block, heap::blocks, check_blocks(), DBGC, DBGC2, done, heap::freemem, heap::grow, memory_block::list, list_add, list_del, list_for_each_entry, heap::maxusedmem, NULL, offset, memory_block::size, size, heap::usedmem, valgrind_make_blocks_defined(), valgrind_make_blocks_noaccess(), VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MAKE_MEM_UNDEFINED.

Referenced by heap_realloc(), and malloc_phys_offset().

◆ heap_free_block()

void heap_free_block ( struct heap * heap,
void * ptr,
size_t size )
static

Free a memory block.

Parameters
heapHeap
ptrMemory allocated by heap_alloc_block(), or NULL
sizeSize of the memory

If ptr is NULL, no action is taken.

Definition at line 407 of file malloc.c.

407 {
408 struct memory_block *freeing;
409 struct memory_block *block;
410 struct memory_block *tmp;
411 size_t sub_offset;
412 size_t actual_size;
413 ssize_t gap_before;
414 ssize_t gap_after = -1;
415
416 /* Allow for ptr==NULL */
417 if ( ! ptr )
418 return;
420
421 /* Sanity checks */
423 check_blocks ( heap );
424
425 /* Round up to match actual block that heap_alloc_block() would
426 * have allocated.
427 */
428 assert ( size != 0 );
429 sub_offset = ( virt_to_phys ( ptr ) & ( heap->align - 1 ) );
430 freeing = ( ptr - sub_offset );
431 actual_size = ( ( size + sub_offset + heap->align - 1 ) &
432 ~( heap->align - 1 ) );
433 DBGC2 ( heap, "HEAP freeing [%p,%p) within [%p,%p)\n",
434 ptr, ( ptr + size ), freeing,
435 ( ( ( void * ) freeing ) + actual_size ) );
436 VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) );
437
438 /* Check that this block does not overlap the free list */
439 if ( ASSERTING ) {
441 if ( ( ( ( void * ) block ) <
442 ( ( void * ) freeing + actual_size ) ) &&
443 ( ( void * ) freeing <
444 ( ( void * ) block + block->size ) ) ) {
445 assert ( 0 );
446 DBGC ( heap, "HEAP double free of [%p,%p) "
447 "overlapping [%p,%p) detected from %p\n",
448 freeing,
449 ( ( ( void * ) freeing ) + size ), block,
450 ( ( void * ) block + block->size ),
451 __builtin_return_address ( 0 ) );
452 }
453 }
454 }
455
456 /* Insert/merge into free list */
457 freeing->size = actual_size;
459 /* Calculate gaps before and after the "freeing" block */
460 gap_before = ( ( ( void * ) freeing ) -
461 ( ( ( void * ) block ) + block->size ) );
462 gap_after = ( ( ( void * ) block ) -
463 ( ( ( void * ) freeing ) + freeing->size ) );
464 /* Merge with immediately preceding block, if possible */
465 if ( gap_before == 0 ) {
466 DBGC2 ( heap, "HEAP merging [%p,%p) + [%p,%p) -> "
467 "[%p,%p)\n", block,
468 ( ( ( void * ) block ) + block->size ), freeing,
469 ( ( ( void * ) freeing ) + freeing->size ),
470 block,
471 ( ( ( void * ) freeing ) + freeing->size ) );
472 block->size += actual_size;
473 list_del ( &block->list );
475 sizeof ( *freeing ) );
476 freeing = block;
477 }
478 /* Stop processing as soon as we reach a following block */
479 if ( gap_after >= 0 )
480 break;
481 }
482
483 /* Insert before the immediately following block. If
484 * possible, merge the following block into the "freeing"
485 * block.
486 */
487 DBGC2 ( heap, "HEAP freed [%p,%p)\n",
488 freeing, ( ( ( void * ) freeing ) + freeing->size ) );
489 list_add_tail ( &freeing->list, &block->list );
490 if ( gap_after == 0 ) {
491 DBGC2 ( heap, "HEAP merging [%p,%p) + [%p,%p) -> [%p,%p)\n",
492 freeing, ( ( ( void * ) freeing ) + freeing->size ),
493 block, ( ( ( void * ) block ) + block->size ), freeing,
494 ( ( ( void * ) block ) + block->size ) );
495 freeing->size += block->size;
496 list_del ( &block->list );
497 VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
498 }
499
500 /* Update memory usage statistics */
501 heap->freemem += actual_size;
502 heap->usedmem -= actual_size;
503
504 /* Allow heap to shrink */
505 if ( heap->shrink && heap->shrink ( freeing, freeing->size ) ) {
506 list_del ( &freeing->list );
507 heap->freemem -= freeing->size;
508 VALGRIND_MAKE_MEM_UNDEFINED ( freeing, freeing->size );
509 }
510
511 /* Sanity checks */
512 check_blocks ( heap );
514}
signed long ssize_t
Definition stdint.h:7
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
unsigned int(* shrink)(void *ptr, size_t size)
Allow heap to shrink (optional)
Definition malloc.h:79

References heap::align, assert, ASSERTING, block, heap::blocks, check_blocks(), DBGC, DBGC2, heap::freemem, memory_block::list, list_add_tail, list_del, list_for_each_entry, list_for_each_entry_safe, heap::shrink, memory_block::size, size, tmp, heap::usedmem, valgrind_make_blocks_defined(), valgrind_make_blocks_noaccess(), VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MAKE_MEM_UNDEFINED.

Referenced by free_phys(), heap_populate(), and heap_realloc().

◆ heap_realloc()

void * heap_realloc ( struct heap * heap,
void * old_ptr,
size_t new_size )

Reallocate memory.

Parameters
heapHeap
old_ptrMemory previously allocated by heap_realloc(), or NULL
new_sizeRequested size
Return values
new_ptrAllocated memory, or NULL

Allocates memory with no particular alignment requirement. new_ptr will be aligned to at least a multiple of sizeof(void*). If old_ptr is non-NULL, then the contents of the newly allocated memory will be the same as the contents of the previously allocated memory, up to the minimum of the old and new sizes. The old memory will be freed.

If allocation fails the previously allocated block is left untouched and NULL is returned.

Calling heap_realloc() with a new size of zero is a valid way to free a memory block.

Definition at line 537 of file malloc.c.

537 {
538 struct autosized_block *old_block;
539 struct autosized_block *new_block;
540 size_t old_total_size;
541 size_t new_total_size;
542 size_t old_size;
543 size_t offset = offsetof ( struct autosized_block, data );
544 void *new_ptr = NOWHERE;
545
546 /* Allocate new memory if necessary. If allocation fails,
547 * return without touching the old block.
548 */
549 if ( new_size ) {
550 new_total_size = ( new_size + offset );
551 if ( new_total_size < new_size )
552 return NULL;
553 new_block = heap_alloc_block ( heap, new_total_size,
554 heap->ptr_align, -offset );
555 if ( ! new_block )
556 return NULL;
557 new_block->size = new_total_size;
558 VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size,
559 sizeof ( new_block->size ) );
560 new_ptr = &new_block->data;
561 VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
562 assert ( ( ( ( intptr_t ) new_ptr ) &
563 ( heap->ptr_align - 1 ) ) == 0 );
564 }
565
566 /* Copy across relevant part of the old data region (if any),
567 * then free it. Note that at this point either (a) new_ptr
568 * is valid, or (b) new_size is 0; either way, the memcpy() is
569 * valid.
570 */
571 if ( old_ptr && ( old_ptr != NOWHERE ) ) {
572 old_block = container_of ( old_ptr, struct autosized_block,
573 data );
574 VALGRIND_MAKE_MEM_DEFINED ( &old_block->size,
575 sizeof ( old_block->size ) );
576 old_total_size = old_block->size;
577 assert ( old_total_size != 0 );
578 old_size = ( old_total_size - offset );
579 memcpy ( new_ptr, old_ptr,
580 ( ( old_size < new_size ) ? old_size : new_size ) );
581 VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
582 heap_free_block ( heap, old_block, old_total_size );
583 }
584
585 if ( ASSERTED ) {
586 DBGC ( heap, "HEAP detected possible memory corruption "
587 "from %p\n", __builtin_return_address ( 0 ) );
588 }
589 return new_ptr;
590}
unsigned long intptr_t
Definition stdint.h:21
#define ASSERTED
Definition assert.h:26
uint8_t data[48]
Additional event data.
Definition ena.h:11
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static void * heap_alloc_block(struct heap *heap, size_t size, size_t align, size_t offset)
Allocate a memory block.
Definition malloc.c:266
static void heap_free_block(struct heap *heap, void *ptr, size_t size)
Free a memory block.
Definition malloc.c:407
#define NOWHERE
Address for zero-length memory blocks.
Definition malloc.h:42
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A block of allocated memory complete with size information.
Definition malloc.c:70
size_t size
Size of this block.
Definition malloc.c:72
char data[0]
Remaining data.
Definition malloc.c:74
size_t ptr_align
Alignment for size-tracked allocations.
Definition malloc.h:52
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
Definition valgrind.h:4412
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)
Definition valgrind.h:4422

References assert, ASSERTED, container_of, autosized_block::data, data, DBGC, heap_alloc_block(), heap_free_block(), memcpy(), NOWHERE, NULL, offset, offsetof, heap::ptr_align, autosized_block::size, VALGRIND_FREELIKE_BLOCK, VALGRIND_MAKE_MEM_DEFINED, VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MALLOCLIKE_BLOCK.

Referenced by realloc(), and uheap_realloc().

◆ realloc()

void * realloc ( void * old_ptr,
size_t new_size )

Reallocate memory.

Parameters
old_ptrMemory previously allocated by malloc(), or NULL
new_sizeRequested size
Return values
new_ptrAllocated memory, or NULL

Definition at line 607 of file malloc.c.

607 {
608
609 return heap_realloc ( &heap, old_ptr, new_size );
610}
void * heap_realloc(struct heap *heap, void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:537

References heap_realloc().

Referenced by __attribute__(), asn1_grow(), bitmap_resize(), cachedhcp_record(), dhcpopt_init(), efi_ifr_op(), efi_ifr_string(), efivars_find(), free(), ibft_alloc_string(), ibft_install(), line_buffer(), malloc(), nvo_realloc(), process_script(), and xferbuf_malloc_realloc().

◆ malloc()

void * malloc ( size_t size)

Allocate memory.

Parameters
sizeRequested size
Return values
ptrMemory, or NULL

Allocates memory with no particular alignment requirement. ptr will be aligned to at least a multiple of sizeof(void*).

Definition at line 621 of file malloc.c.

621 {
622 void *ptr;
623
624 ptr = realloc ( NULL, size );
625 if ( ASSERTED ) {
626 DBGC ( &heap, "HEAP detected possible memory corruption "
627 "from %p\n", __builtin_return_address ( 0 ) );
628 }
629 return ptr;
630}
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:607

References ASSERTED, DBGC, NULL, realloc(), and size.

Referenced by add_tls(), aes_unwrap(), aes_wrap(), alloc_iob_raw(), apply_dns_search(), ath5k_hw_rfregs_init(), chap_init(), deflate_test_exec(), der_asn1(), derwin(), dhcpv6_rx(), dhe_key(), dupwin(), eap_rx_mschapv2_request(), eap_tx_response(), ecdsa_alloc(), efi_block_label(), efi_boot_path(), efi_cacert_all(), efi_cmdline_init(), efi_download_start(), efi_load_path(), efi_local_check_volume_name(), efi_local_len(), efi_locate_device(), efi_vasprintf(), efivars_fetch(), eisabus_probe(), fc_ulp_login(), fetch_setting_copy(), format_uri_alloc(), http_format_ntlm_auth(), icert_encode(), int13_hook(), ipair_rx_pubkey(), ipoib_map_remac(), ipv4_add_miniroute(), isabus_probe(), isapnpbus_probe(), iscsi_handle_chap_c_value(), iscsi_handle_chap_r_value(), iscsi_rx_buffered_data(), iscsi_scsi_command(), jme_alloc_rx_resources(), jme_alloc_tx_resources(), lldp_rx(), loopback_test(), mcabus_probe(), memcpy_test_speed(), mlx_memory_alloc_priv(), net80211_probe_start(), net80211_register(), newwin(), nfs_uri_symlink(), ntlm_authenticate_okx(), ocsp_response(), ocsp_uri_string(), parse_kv(), parse_net_args(), pci_vpd_resize(), pcibus_probe(), peerblk_decrypt(), peerblk_parse_header(), pem_asn1(), rsa_alloc(), sandev_parse_iso9660(), slirp_timer_new(), storef_setting(), storen_setting(), strndup(), t509bus_probe(), tls_new_server_key_exchange(), tls_new_session_ticket(), tls_select_handshake(), tls_send_client_key_exchange_dhe(), uhci_enqueue(), usb_config_descriptor(), usb_get_string_descriptor(), usbio_config(), usbio_path(), vasprintf(), vesafb_mode_list(), vmbus_open(), wpa_make_rsn_ie(), wpa_start(), and zalloc().

◆ free()

void free ( void * ptr)

Free memory.

Parameters
ptrMemory allocated by malloc(), or NULL

Memory allocated with malloc_phys() cannot be freed with free(); it must be freed with free_phys() instead.

If ptr is NULL, no action is taken.

Definition at line 642 of file malloc.c.

642 {
643
644 realloc ( ptr, 0 );
645 if ( ASSERTED ) {
646 DBGC ( &heap, "HEAP detected possible memory corruption "
647 "from %p\n", __builtin_return_address ( 0 ) );
648 }
649}

References ASSERTED, DBGC, and realloc().

◆ zalloc()

void * zalloc ( size_t size)

Allocate cleared memory.

Parameters
sizeRequested size
Return values
ptrAllocated memory

Allocate memory as per malloc(), and zero it.

This function name is non-standard, but pretty intuitive. zalloc(size) is always equivalent to calloc(1,size)

Definition at line 662 of file malloc.c.

662 {
663 void *data;
664
665 data = malloc ( size );
666 if ( data )
667 memset ( data, 0, size );
668 if ( ASSERTED ) {
669 DBGC ( &heap, "HEAP detected possible memory corruption "
670 "from %p\n", __builtin_return_address ( 0 ) );
671 }
672 return data;
673}
void * memset(void *dest, int character, size_t len) __nonnull
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621

References ASSERTED, data, DBGC, malloc(), memset(), and size.

Referenced by add_dynui_item(), add_parameter(), alloc_form(), alloc_gpios(), alloc_ibdev(), alloc_image(), alloc_netdev(), alloc_pixbuf(), alloc_sandev(), alloc_uart(), alloc_usb(), alloc_usb_bus(), alloc_usb_hub(), aoecmd_create(), aoedev_open(), ar9300_eeprom_restore_internal(), arbel_alloc(), arbel_create_cq(), arbel_create_qp(), ata_open(), atadev_command(), ath5k_hw_attach(), ath5k_probe(), ath9k_init_softc(), ath_descdma_setup(), atl1e_setup_ring_resources(), autovivify_child_settings(), block_translate(), cachedhcp_record(), calloc(), cms_message(), cms_parse_participants(), concat_args(), cpio_okx(), create_downloader(), create_dynui(), create_parameters(), create_pinger(), create_validator(), dhcp_deliver(), dhcpv6_register(), dns_resolv(), dt_probe_node(), dwgpio_group_probe(), dwusb_probe(), efi_block_exec(), efi_block_install(), efi_fcp_path(), efi_file_open_image(), efi_ib_srp_path(), efi_image_path(), efi_iscsi_path(), efi_local_open(), efi_netdev_path(), efi_path_uri(), efi_paths(), efi_pxe_install(), efi_snp_hii_fetch(), efi_snp_hii_install(), efi_snp_hii_process(), efi_snp_hii_store(), efi_snp_probe(), efi_uri_path(), efi_usb_install(), efi_usb_open(), efi_usb_path(), efi_usb_probe(), efidev_alloc(), efipci_start(), efivars_find(), ehci_endpoint_open(), ehci_probe(), ehci_ring_alloc(), eoib_create_peer(), exanic_probe(), fc_els_create(), fc_ns_query(), fc_peer_create(), fc_port_open(), fc_ulp_create(), fc_xchg_create(), fcpdev_open(), fcpdev_scsi_command(), fetch_string_setting_copy_alloc(), fetchf_setting_copy(), flexboot_nodnic_create_cq(), flexboot_nodnic_create_qp(), flexboot_nodnic_eth_open(), flexboot_nodnic_probe(), fragment_reassemble(), ftp_open(), generic_settings_store(), golan_alloc(), golan_create_cq(), golan_create_qp_aux(), guestinfo_fetch_type(), hermon_alloc(), hermon_create_cq(), hermon_create_qp(), http_connect(), http_open(), http_open_uri(), hub_probe(), hv_probe(), hvm_probe(), hw_open(), ib_cmrc_open(), ib_create_conn(), ib_create_cq(), ib_create_madx(), ib_create_mi(), ib_create_path(), ib_create_qp(), ib_mcast_attach(), ib_srp_open(), ibft_install(), icert_certs(), imux_probe(), init_mlx_utils(), ipair_create(), ipv6_add_miniroute(), iscsi_open(), linda_create_send_wq(), mlx_memory_zalloc_priv(), ndp_register_settings(), neighbour_create(), net80211_handle_mgmt(), net80211_prepare_assoc(), net80211_probe_start(), net80211_probe_step(), net80211_step_associate(), nfs_open(), nii_map(), numeric_resolv(), ocsp_check(), ocsp_uri_string(), open(), parse_uri(), pcibridge_probe(), peerblk_open(), peerdisc_create(), peerdisc_discovered(), peermux_filter(), ping_open(), png_pixbuf(), pxe_menu_parse(), qib7322_create_send_bufs(), qib7322_create_send_wq(), qib7322_probe(), rc80211_init(), resolv(), resolv_setting(), rtl818x_probe(), scsi_open(), scsidev_command(), sec80211_install(), sis190_mii_probe(), skge_probe(), skge_ring_alloc(), sky2_probe(), sky2_up(), slam_open(), srp_open(), srpdev_scsi_command(), start_dhcp(), start_dhcpv6(), start_ipv6conf(), start_ntp(), start_pxebs(), tcp_open(), tftp_core_open(), tg3_alloc_consistent(), tls_session(), tls_set_cipher(), txnic_bgx_probe(), txnic_pf_probe(), ucode_exec(), udp_open_common(), uhci_endpoint_open(), uhci_probe(), undipci_probe(), undirom_probe(), uri_dup(), usb_probe_all(), usbblk_probe(), usbio_endpoint_open(), usbio_interfaces(), usbio_interrupt_open(), usbio_start(), usbkbd_probe(), validator_start_download(), virtnet_open_legacy(), virtnet_open_modern(), vmbus_probe(), vmbus_probe_channels(), vxge_hw_device_initialize(), x509_alloc_chain(), x509_append(), x509_certificate(), xcm_create(), xenbus_probe_device(), xenstore_response(), xfer_open_named_socket(), xhci_bus_open(), xhci_device_open(), xhci_endpoint_open(), xhci_probe(), xhci_ring_alloc(), xsigo_ib_probe(), xve_create(), and zlib_deflate().

◆ malloc_phys_offset()

void * malloc_phys_offset ( size_t size,
size_t phys_align,
size_t offset )

Allocate memory with specified physical alignment and offset.

Parameters
sizeRequested size
alignPhysical alignment
offsetOffset from physical alignment
Return values
ptrMemory, or NULL

align must be a power of two. size may not be zero.

Definition at line 685 of file malloc.c.

685 {
686 void * ptr;
687
688 ptr = heap_alloc_block ( &heap, size, phys_align, offset );
689 if ( ptr && size ) {
690 assert ( ( phys_align == 0 ) ||
691 ( ( ( virt_to_phys ( ptr ) ^ offset ) &
692 ( phys_align - 1 ) ) == 0 ) );
693 VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
694 }
695 return ptr;
696}

References assert, heap_alloc_block(), offset, size, and VALGRIND_MALLOCLIKE_BLOCK.

Referenced by alloc_iob_raw(), and malloc_phys().

◆ malloc_phys()

void * malloc_phys ( size_t size,
size_t phys_align )

Allocate memory with specified physical alignment.

Parameters
sizeRequested size
alignPhysical alignment
Return values
ptrMemory, or NULL

align must be a power of two. size may not be zero.

Definition at line 707 of file malloc.c.

707 {
708
709 return malloc_phys_offset ( size, phys_align, 0 );
710}
void * malloc_phys_offset(size_t size, size_t phys_align, size_t offset)
Allocate memory with specified physical alignment and offset.
Definition malloc.c:685

References malloc_phys_offset(), and size.

Referenced by __vxge_hw_fifo_create(), __vxge_hw_ring_create(), a3c90x_setup_rx_ring(), a3c90x_setup_tx_ring(), arbel_alloc(), arbel_alloc_icm(), arbel_create_cq(), arbel_create_eq(), arbel_create_recv_wq(), arbel_create_send_wq(), ath5k_desc_alloc(), ath_descdma_setup(), atl1e_setup_ring_resources(), b44_init_rx_ring(), b44_init_tx_ring(), efx_hunt_alloc_special_buffer(), ehci_bus_open(), ehci_ring_alloc(), ena_create_admin(), ena_create_async(), ena_create_cq(), ena_create_sq(), ena_probe(), exanic_probe(), falcon_alloc_special_buffer(), golan_cmd_init(), golan_create_cq(), golan_create_eq(), golan_create_qp_aux(), hermon_alloc(), hermon_create_cq(), hermon_create_eq(), hermon_create_qp(), hv_alloc_message(), hv_alloc_pages(), hvm_map_hypercall(), icplus_create_ring(), ifec_net_open(), ifec_tx_setup(), igbvf_setup_rx_resources(), igbvf_setup_tx_resources(), jme_alloc_rx_resources(), jme_alloc_tx_resources(), legacy_probe(), linda_create_recv_wq(), linda_init_send(), mlx_memory_alloc_dma_priv(), myri10ge_net_open(), myson_create_ring(), natsemi_create_ring(), netfront_create_ring(), nv_init_rings(), pcnet32_setup_rx_resources(), pcnet32_setup_tx_resources(), phantom_create_rx_ctx(), phantom_create_tx_ctx(), phantom_open(), qib7322_create_recv_wq(), qib7322_init_send(), rhine_create_ring(), rtl818x_init_rx_ring(), rtl818x_init_tx_ring(), sis190_open(), skge_up(), sky2_probe(), sky2_up(), tg3_alloc_consistent(), tg3_test_dma(), uhci_bus_open(), uhci_enqueue(), uhci_ring_alloc(), velocity_alloc_rings(), vmbus_open(), and vmxnet3_open().

◆ free_phys()

void free_phys ( void * ptr,
size_t size )

Free memory allocated with malloc_phys()

Parameters
ptrMemory allocated by malloc_phys(), or NULL
sizeSize of memory, as passed to malloc_phys()

Memory allocated with malloc_phys() can only be freed with free_phys(); it cannot be freed with the standard free().

If ptr is NULL, no action is taken.

Definition at line 723 of file malloc.c.

723 {
724
725 VALGRIND_FREELIKE_BLOCK ( ptr, 0 );
726 heap_free_block ( &heap, ptr, size );
727}

References heap_free_block(), size, and VALGRIND_FREELIKE_BLOCK.

Referenced by __vxge_hw_fifo_delete(), __vxge_hw_ring_delete(), a3c90x_free_rx_ring(), a3c90x_free_tx_ring(), alloc_iob_raw(), arbel_alloc(), arbel_alloc_icm(), arbel_create_cq(), arbel_create_eq(), arbel_create_qp(), arbel_create_recv_wq(), arbel_destroy_cq(), arbel_destroy_eq(), arbel_destroy_qp(), arbel_free(), arbel_free_icm(), ath5k_desc_alloc(), ath5k_desc_free(), ath_descdma_cleanup(), ath_descdma_setup(), atl1e_free_ring_resources(), b44_free_rx_ring(), b44_free_tx_ring(), b44_init_rx_ring(), b44_init_tx_ring(), efx_hunt_free_special_buffer(), ehci_bus_close(), ehci_bus_open(), ehci_ring_alloc(), ehci_ring_free(), ena_create_admin(), ena_create_async(), ena_create_cq(), ena_create_sq(), ena_destroy_admin(), ena_destroy_async(), ena_destroy_cq(), ena_destroy_sq(), ena_probe(), ena_remove(), exanic_probe(), exanic_remove(), falcon_free_special_buffer(), free_iob(), golan_cmd_init(), golan_cmd_uninit(), golan_create_cq(), golan_create_eq(), golan_create_qp_aux(), golan_destory_eq(), golan_destroy_cq(), golan_destroy_qp(), hermon_alloc(), hermon_create_cq(), hermon_create_eq(), hermon_create_qp(), hermon_destroy_cq(), hermon_destroy_eq(), hermon_destroy_qp(), hermon_free(), hv_alloc_pages(), hv_free_message(), hv_free_pages(), hvm_unmap_hypercall(), icplus_create_ring(), icplus_destroy_ring(), ifec_free(), ifec_net_open(), igbvf_free_rx_resources(), igbvf_free_tx_resources(), jme_free_rx_resources(), jme_free_tx_resources(), legacy_probe(), legacy_remove(), linda_create_recv_wq(), linda_destroy_recv_wq(), linda_fini_send(), linda_init_send(), mlx_memory_free_dma_priv(), myri10ge_net_close(), myri10ge_net_open(), myson_create_ring(), myson_destroy_ring(), natsemi_create_ring(), natsemi_destroy_ring(), netfront_create_ring(), netfront_destroy_ring(), nv_free_rxtx_resources(), pcnet32_free_rx_resources(), pcnet32_free_tx_resources(), phantom_close(), phantom_create_rx_ctx(), phantom_create_tx_ctx(), phantom_open(), qib7322_create_recv_wq(), qib7322_destroy_recv_wq(), qib7322_fini_send(), qib7322_init_send(), rhine_destroy_ring(), rtl818x_free_rx_ring(), rtl818x_free_tx_ring(), sis190_free(), skge_free(), sky2_free_rings(), sky2_probe(), sky2_remove(), tg3_free_consistent(), tg3_rx_prodring_fini(), tg3_test_dma(), uhci_bus_close(), uhci_bus_open(), uhci_dequeue(), uhci_enqueue(), uhci_ring_alloc(), uhci_ring_free(), velocity_alloc_rings(), velocity_close(), vmbus_close(), vmbus_open(), vmxnet3_close(), and vmxnet3_open().

◆ heap_populate()

void heap_populate ( struct heap * heap,
void * start,
size_t len )

Add memory to allocation pool.

Parameters
heapHeap
startStart address
lenLength of memory

Adds a block of memory to the allocation pool. The memory must be aligned to the heap's required free memory block alignment.

Definition at line 739 of file malloc.c.

739 {
740
741 /* Sanity checks */
742 assert ( ( virt_to_phys ( start ) & ( heap->align - 1 ) ) == 0 );
743 assert ( ( len & ( heap->align - 1 ) ) == 0 );
744
745 /* Add to allocation pool */
747
748 /* Fix up memory usage statistics */
749 heap->usedmem += len;
750}
ring len
Length.
Definition dwmac.h:226
uint32_t start
Starting offset.
Definition netvsc.h:1

References heap::align, assert, heap_free_block(), len, start, and heap::usedmem.

Referenced by init_heap(), and uheap_grow().

◆ init_heap()

void init_heap ( void )
static

Initialise the heap.

Definition at line 756 of file malloc.c.

756 {
757
758 /* Sanity check */
759 build_assert ( MIN_MEMBLOCK_ALIGN >= sizeof ( struct memory_block ) );
760
761 /* Populate heap */
764 heap_populate ( &heap, heap_area, sizeof ( heap_area ) );
765}
#define build_assert(condition)
Assert a condition at build time (after dead code elimination)
Definition assert.h:77
static char heap_area[HEAP_SIZE]
The heap area.
Definition malloc.c:88
#define MIN_MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
Definition malloc.c:67
void heap_populate(struct heap *heap, void *start, size_t len)
Add memory to allocation pool.
Definition malloc.c:739

References heap::blocks, build_assert, heap_area, heap_populate(), MIN_MEMBLOCK_ALIGN, and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by __init_fn().

◆ __init_fn()

struct init_fn heap_init_fn __init_fn ( INIT_EARLY )

Memory allocator initialisation function.

References __init_fn, INIT_EARLY, and init_heap().

◆ shutdown_cache()

void shutdown_cache ( int booting __unused)
static

Discard all cached data on shutdown.

Definition at line 777 of file malloc.c.

777 {
779 DBGC ( &heap, "HEAP maximum usage %zdkB\n",
780 ( heap.maxusedmem >> 10 ) );
781}
static void discard_all_cache(void)
Discard all cached data.
Definition malloc.c:244

References __unused, DBGC, discard_all_cache(), and heap::maxusedmem.

Referenced by __startup_fn().

◆ __startup_fn()

struct startup_fn heap_startup_fn __startup_fn ( STARTUP_EARLY )

Memory allocator shutdown function.

References __startup_fn, shutdown_cache(), and STARTUP_EARLY.

◆ heap_dump()

void heap_dump ( struct heap * heap)

Dump free block list (for debugging)

Definition at line 793 of file malloc.c.

793 {
794 struct memory_block *block;
795
796 dbg_printf ( "HEAP free block list:\n" );
798 dbg_printf ( "...[%p,%p] (size %#zx)\n", block,
799 ( ( ( void * ) block ) + block->size ),
800 block->size );
801 }
802}
void dbg_printf(const char *fmt,...)
Print debug message.
Definition debug.c:39

References block, heap::blocks, dbg_printf(), memory_block::list, and list_for_each_entry.

Variable Documentation

◆ heap_area

char heap_area[HEAP_SIZE]
static

The heap area.

Definition at line 88 of file malloc.c.

Referenced by init_heap().

◆ heap

struct heap heap
static
Initial value:
= {
.blocks = LIST_HEAD_INIT ( heap.blocks ),
.ptr_align = sizeof ( void * ),
}
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition list.h:31

The global heap.

Definition at line 593 of file malloc.c.

593 {
594 .blocks = LIST_HEAD_INIT ( heap.blocks ),
595 .align = MIN_MEMBLOCK_ALIGN,
596 .ptr_align = sizeof ( void * ),
597 .grow = discard_cache,
598};