iPXE
Data Structures | Macros | Functions | Variables
malloc.c File Reference

Dynamic memory allocation. More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <strings.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 MEMBLOCK_ALIGN   ( ( size_t ) ( 1 << ( fls ( sizeof ( struct memory_block ) - 1 ) ) ) )
 Physical address alignment maintained for free blocks of memory. More...
 
#define NOWHERE   ( ( void * ) ~( ( intptr_t ) 0 ) )
 Address for zero-length memory blocks. More...
 
#define HEAP_SIZE   ( 512 * 1024 )
 Heap size. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static LIST_HEAD (free_blocks)
 List of free memory blocks. More...
 
static void valgrind_make_blocks_defined (void)
 Mark all blocks in free list as defined. More...
 
static void valgrind_make_blocks_noaccess (void)
 Mark all blocks in free list as inaccessible. More...
 
static void check_blocks (void)
 Check integrity of the blocks in the free list. More...
 
static unsigned int discard_cache (void)
 Discard some cached data. More...
 
static void discard_all_cache (void)
 Discard all cached data. More...
 
void * alloc_memblock (size_t size, size_t align, size_t offset)
 Allocate a memory block. More...
 
void free_memblock (void *ptr, size_t size)
 Free a memory block. More...
 
void * realloc (void *old_ptr, size_t new_size)
 Reallocate memory. More...
 
void * malloc (size_t size)
 Allocate memory. More...
 
void free (void *ptr)
 Free memory. More...
 
void * zalloc (size_t size)
 Allocate cleared memory. More...
 
static void mpopulate (void *start, size_t len)
 Add memory to allocation pool. More...
 
static void init_heap (void)
 Initialise the heap. More...
 
struct init_fn heap_init_fn __init_fn (INIT_EARLY)
 Memory allocator initialisation function. More...
 
static void shutdown_cache (int booting __unused)
 Discard all cached data on shutdown. More...
 
struct startup_fn heap_startup_fn __startup_fn (STARTUP_EARLY)
 Memory allocator shutdown function. More...
 
void mdumpfree (void)
 Dump free block list (for debugging) More...
 

Variables

size_t freemem
 Total amount of free memory. More...
 
size_t usedmem
 Total amount of used memory. More...
 
size_t maxusedmem
 Maximum amount of used memory. More...
 
static char heap [HEAP_SIZE]
 The heap itself. More...
 

Detailed Description

Dynamic memory allocation.

Definition in file malloc.c.

Macro Definition Documentation

◆ MEMBLOCK_ALIGN

#define MEMBLOCK_ALIGN   ( ( size_t ) ( 1 << ( fls ( sizeof ( struct memory_block ) - 1 ) ) ) )

Physical address alignment maintained for free blocks of memory.

Definition at line 63 of file malloc.c.

◆ NOWHERE

#define NOWHERE   ( ( void * ) ~( ( intptr_t ) 0 ) )

Address for zero-length memory blocks.

malloc(0) or realloc(ptr,0) will return the special value NOWHERE. Calling free(NOWHERE) will have no effect.

This is consistent with the ANSI C standards, which state that "either NULL or a pointer suitable to be passed to free()" must be returned in these cases. Using a special non-NULL value means that the caller can take a NULL return value to indicate failure, without first having to check for a requested size of zero.

Code outside of malloc.c do not ever need to refer to the actual value of NOWHERE; this is an internal definition.

Definition at line 89 of file malloc.c.

◆ HEAP_SIZE

#define HEAP_SIZE   ( 512 * 1024 )

Heap size.

Currently fixed at 512kB.

Definition at line 108 of file malloc.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ LIST_HEAD()

static LIST_HEAD ( free_blocks  )
static

List of free memory blocks.

◆ valgrind_make_blocks_defined()

static void valgrind_make_blocks_defined ( void  )
inlinestatic

Mark all blocks in free list as defined.

Definition at line 117 of file malloc.c.

117  {
118  struct memory_block *block;
119 
120  /* Do nothing unless running under Valgrind */
121  if ( RUNNING_ON_VALGRIND <= 0 )
122  return;
123 
124  /* Traverse free block list, marking each block structure as
125  * defined. Some contortions are necessary to avoid errors
126  * from list_check().
127  */
128 
129  /* Mark block list itself as defined */
130  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks, sizeof ( free_blocks ) );
131 
132  /* Mark areas accessed by list_check() as defined */
133  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.prev->next,
134  sizeof ( free_blocks.prev->next ) );
135  VALGRIND_MAKE_MEM_DEFINED ( free_blocks.next,
136  sizeof ( *free_blocks.next ) );
137  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->next->prev,
138  sizeof ( free_blocks.next->next->prev ) );
139 
140  /* Mark each block in list as defined */
141  list_for_each_entry ( block, &free_blocks, list ) {
142 
143  /* Mark block as defined */
144  VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
145 
146  /* Mark areas accessed by list_check() as defined */
147  VALGRIND_MAKE_MEM_DEFINED ( block->list.next,
148  sizeof ( *block->list.next ) );
149  VALGRIND_MAKE_MEM_DEFINED ( &block->list.next->next->prev,
150  sizeof ( block->list.next->next->prev ) );
151  }
152 }
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:131
#define RUNNING_ON_VALGRIND
Definition: valgrind.h:4175
struct list_head list
List of free blocks.
Definition: malloc.c:59
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
A free block of memory.
Definition: malloc.c:44
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12

References block, memory_block::list, list_for_each_entry, RUNNING_ON_VALGRIND, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by alloc_memblock(), and free_memblock().

◆ valgrind_make_blocks_noaccess()

static void valgrind_make_blocks_noaccess ( void  )
inlinestatic

Mark all blocks in free list as inaccessible.

Definition at line 158 of file malloc.c.

158  {
159  struct memory_block *block;
160  struct memory_block *prev = NULL;
161 
162  /* Do nothing unless running under Valgrind */
163  if ( RUNNING_ON_VALGRIND <= 0 )
164  return;
165 
166  /* Traverse free block list, marking each block structure as
167  * inaccessible. Some contortions are necessary to avoid
168  * errors from list_check().
169  */
170 
171  /* Mark each block in list as inaccessible */
172  list_for_each_entry ( block, &free_blocks, list ) {
173 
174  /* Mark previous block (if any) as inaccessible. (Current
175  * block will be accessed by list_check().)
176  */
177  if ( prev )
178  VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
179  prev = block;
180 
181  /* At the end of the list, list_check() will end up
182  * accessing the first list item. Temporarily mark
183  * this area as defined.
184  */
185  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->prev,
186  sizeof ( free_blocks.next->prev ) );
187  }
188  /* Mark last block (if any) as inaccessible */
189  if ( prev )
190  VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
191 
192  /* Mark as inaccessible the area that was temporarily marked
193  * as defined to avoid errors from list_check().
194  */
195  VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks.next->prev,
196  sizeof ( free_blocks.next->prev ) );
197 
198  /* Mark block list itself as inaccessible */
199  VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
200 }
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:131
#define RUNNING_ON_VALGRIND
Definition: valgrind.h:4175
struct list_head list
List of free blocks.
Definition: malloc.c:59
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
A free block of memory.
Definition: malloc.c:44
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References block, memory_block::list, list_for_each_entry, NULL, RUNNING_ON_VALGRIND, VALGRIND_MAKE_MEM_DEFINED, and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by alloc_memblock(), and free_memblock().

◆ check_blocks()

static void check_blocks ( void  )
inlinestatic

Check integrity of the blocks in the free list.

Definition at line 206 of file malloc.c.

206  {
207  struct memory_block *block;
208  struct memory_block *prev = NULL;
209 
210  if ( ! ASSERTING )
211  return;
212 
213  list_for_each_entry ( block, &free_blocks, list ) {
214 
215  /* Check alignment */
216  assert ( ( virt_to_phys ( block ) &
217  ( MEMBLOCK_ALIGN - 1 ) ) == 0 );
218 
219  /* Check that list structure is intact */
220  list_check ( &block->list );
221 
222  /* Check that block size is not too small */
223  assert ( block->size >= sizeof ( *block ) );
224  assert ( block->size >= MEMBLOCK_ALIGN );
225 
226  /* Check that block does not wrap beyond end of address space */
227  assert ( ( ( void * ) block + block->size ) >
228  ( ( void * ) block ) );
229 
230  /* Check that blocks remain in ascending order, and
231  * that adjacent blocks have been merged.
232  */
233  if ( prev ) {
234  assert ( ( ( void * ) block ) > ( ( void * ) prev ) );
235  assert ( ( ( void * ) block ) >
236  ( ( ( void * ) prev ) + prev->size ) );
237  }
238  prev = block;
239  }
240 }
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:361
struct list_head list
List of free blocks.
Definition: malloc.c:59
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
#define ASSERTING
Definition: assert.h:19
#define MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
Definition: malloc.c:63
A free block of memory.
Definition: malloc.c:44
#define list_check(list)
Check a list entry or list head is valid.
Definition: list.h:55
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References assert(), ASSERTING, block, memory_block::list, list_check, list_for_each_entry, MEMBLOCK_ALIGN, NULL, and virt_to_phys().

Referenced by alloc_memblock(), and free_memblock().

◆ discard_cache()

static unsigned int discard_cache ( void  )
static

Discard some cached data.

Return values
discardedNumber of cached items discarded

Definition at line 247 of file malloc.c.

247  {
248  struct cache_discarder *discarder;
249  unsigned int discarded;
250 
251  for_each_table_entry ( discarder, CACHE_DISCARDERS ) {
252  discarded = discarder->discard();
253  if ( discarded )
254  return discarded;
255  }
256  return 0;
257 }
#define CACHE_DISCARDERS
Cache discarder table.
Definition: malloc.h:92
unsigned int(* discard)(void)
Discard some cached data.
Definition: malloc.h:88
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
A cache discarder.
Definition: malloc.h:82

References CACHE_DISCARDERS, cache_discarder::discard, and for_each_table_entry.

Referenced by alloc_memblock(), and discard_all_cache().

◆ discard_all_cache()

static void discard_all_cache ( void  )
static

Discard all cached data.

Definition at line 263 of file malloc.c.

263  {
264  unsigned int discarded;
265 
266  do {
267  discarded = discard_cache();
268  } while ( discarded );
269 }
static unsigned int discard_cache(void)
Discard some cached data.
Definition: malloc.c:247

References discard_cache().

Referenced by shutdown_cache().

◆ alloc_memblock()

void* alloc_memblock ( size_t  size,
size_t  align,
size_t  offset 
)

Allocate a memory block.

Parameters
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 284 of file malloc.c.

284  {
285  struct memory_block *block;
286  size_t actual_offset;
287  size_t align_mask;
288  size_t actual_size;
289  size_t pre_size;
290  size_t post_size;
291  struct memory_block *pre;
292  struct memory_block *post;
293  unsigned int discarded;
294  void *ptr;
295 
296  /* Sanity checks */
297  assert ( size != 0 );
298  assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) );
300  check_blocks();
301 
302  /* Calculate offset of memory block */
303  actual_offset = ( offset & ~( MEMBLOCK_ALIGN - 1 ) );
304  assert ( actual_offset <= offset );
305 
306  /* Calculate size of memory block */
307  actual_size = ( ( size + offset - actual_offset + MEMBLOCK_ALIGN - 1 )
308  & ~( MEMBLOCK_ALIGN - 1 ) );
309  if ( ! actual_size ) {
310  /* The requested size is not permitted to be zero. A
311  * zero result at this point indicates that either the
312  * original requested size was zero, or that unsigned
313  * integer overflow has occurred.
314  */
315  ptr = NULL;
316  goto done;
317  }
318  assert ( actual_size >= size );
319 
320  /* Calculate alignment mask */
321  align_mask = ( ( align - 1 ) | ( MEMBLOCK_ALIGN - 1 ) );
322 
323  DBGC2 ( &heap, "HEAP allocating %#zx (aligned %#zx+%zx)\n",
324  size, align, offset );
325  while ( 1 ) {
326  /* Search through blocks for the first one with enough space */
327  list_for_each_entry ( block, &free_blocks, list ) {
328  pre_size = ( ( actual_offset - virt_to_phys ( block ) )
329  & align_mask );
330  if ( ( block->size < pre_size ) ||
331  ( ( block->size - pre_size ) < actual_size ) )
332  continue;
333  post_size = ( block->size - pre_size - actual_size );
334  /* Split block into pre-block, block, and
335  * post-block. After this split, the "pre"
336  * block is the one currently linked into the
337  * free list.
338  */
339  pre = block;
340  block = ( ( ( void * ) pre ) + pre_size );
341  post = ( ( ( void * ) block ) + actual_size );
342  DBGC2 ( &heap, "HEAP splitting [%p,%p) -> [%p,%p) "
343  "+ [%p,%p)\n", pre,
344  ( ( ( void * ) pre ) + pre->size ), pre, block,
345  post, ( ( ( void * ) pre ) + pre->size ) );
346  /* If there is a "post" block, add it in to
347  * the free list.
348  */
349  if ( post_size ) {
350  assert ( post_size >= MEMBLOCK_ALIGN );
352  sizeof ( *post ));
353  post->size = post_size;
354  list_add ( &post->list, &pre->list );
355  }
356  /* Shrink "pre" block, leaving the main block
357  * isolated and no longer part of the free
358  * list.
359  */
360  pre->size = pre_size;
361  /* If there is no "pre" block, remove it from
362  * the list.
363  */
364  if ( ! pre_size ) {
365  list_del ( &pre->list );
367  sizeof ( *pre ) );
368  } else {
369  assert ( pre_size >= MEMBLOCK_ALIGN );
370  }
371  /* Update memory usage statistics */
372  freemem -= actual_size;
373  usedmem += actual_size;
374  if ( usedmem > maxusedmem )
376  /* Return allocated block */
377  ptr = ( ( ( void * ) block ) + offset - actual_offset );
378  DBGC2 ( &heap, "HEAP allocated [%p,%p) within "
379  "[%p,%p)\n", ptr, ( ptr + size ), block,
380  ( ( ( void * ) block ) + actual_size ) );
382  goto done;
383  }
384 
385  /* Try discarding some cached data to free up memory */
386  DBGC ( &heap, "HEAP attempting discard for %#zx (aligned "
387  "%#zx+%zx), used %zdkB\n", size, align, offset,
388  ( usedmem >> 10 ) );
390  discarded = discard_cache();
392  check_blocks();
393  if ( ! discarded ) {
394  /* Nothing available to discard */
395  DBGC ( &heap, "HEAP failed to allocate %#zx (aligned "
396  "%#zx)\n", size, align );
397  ptr = NULL;
398  goto done;
399  }
400  }
401 
402  done:
403  check_blocks();
405  return ptr;
406 }
static __always_inline void struct dma_mapping size_t size_t align
Definition: dma.h:222
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
static void valgrind_make_blocks_noaccess(void)
Mark all blocks in free list as inaccessible.
Definition: malloc.c:158
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:361
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
struct list_head list
List of free blocks.
Definition: malloc.c:59
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
size_t freemem
Total amount of free memory.
Definition: malloc.c:95
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void check_blocks(void)
Check integrity of the blocks in the free list.
Definition: malloc.c:206
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
#define MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
Definition: malloc.c:63
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
A free block of memory.
Definition: malloc.c:44
static unsigned int discard_cache(void)
Discard some cached data.
Definition: malloc.c:247
#define DBGC2(...)
Definition: compiler.h:522
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
size_t size
Size of this block.
Definition: malloc.c:46
static void valgrind_make_blocks_defined(void)
Mark all blocks in free list as defined.
Definition: malloc.c:117
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:121
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
size_t maxusedmem
Maximum amount of used memory.
Definition: malloc.c:101
struct bofm_section_header done
Definition: bofm_test.c:46
size_t usedmem
Total amount of used memory.
Definition: malloc.c:98

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

Referenced by malloc_phys_offset(), and realloc().

◆ free_memblock()

void free_memblock ( void *  ptr,
size_t  size 
)

Free a memory block.

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

If ptr is NULL, no action is taken.

Definition at line 416 of file malloc.c.

416  {
417  struct memory_block *freeing;
418  struct memory_block *block;
419  struct memory_block *tmp;
420  size_t sub_offset;
421  size_t actual_size;
422  ssize_t gap_before;
423  ssize_t gap_after = -1;
424 
425  /* Allow for ptr==NULL */
426  if ( ! ptr )
427  return;
429 
430  /* Sanity checks */
432  check_blocks();
433 
434  /* Round up to match actual block that alloc_memblock() would
435  * have allocated.
436  */
437  assert ( size != 0 );
438  sub_offset = ( virt_to_phys ( ptr ) & ( MEMBLOCK_ALIGN - 1) );
439  freeing = ( ptr - sub_offset );
440  actual_size = ( ( size + sub_offset + MEMBLOCK_ALIGN - 1 ) &
441  ~( MEMBLOCK_ALIGN - 1 ) );
442  DBGC2 ( &heap, "HEAP freeing [%p,%p) within [%p,%p)\n",
443  ptr, ( ptr + size ), freeing,
444  ( ( ( void * ) freeing ) + actual_size ) );
445  VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) );
446 
447  /* Check that this block does not overlap the free list */
448  if ( ASSERTING ) {
449  list_for_each_entry ( block, &free_blocks, list ) {
450  if ( ( ( ( void * ) block ) <
451  ( ( void * ) freeing + actual_size ) ) &&
452  ( ( void * ) freeing <
453  ( ( void * ) block + block->size ) ) ) {
454  assert ( 0 );
455  DBGC ( &heap, "HEAP double free of [%p,%p) "
456  "overlapping [%p,%p) detected from %p\n",
457  freeing,
458  ( ( ( void * ) freeing ) + size ), block,
459  ( ( void * ) block + block->size ),
460  __builtin_return_address ( 0 ) );
461  }
462  }
463  }
464 
465  /* Insert/merge into free list */
466  freeing->size = actual_size;
467  list_for_each_entry_safe ( block, tmp, &free_blocks, list ) {
468  /* Calculate gaps before and after the "freeing" block */
469  gap_before = ( ( ( void * ) freeing ) -
470  ( ( ( void * ) block ) + block->size ) );
471  gap_after = ( ( ( void * ) block ) -
472  ( ( ( void * ) freeing ) + freeing->size ) );
473  /* Merge with immediately preceding block, if possible */
474  if ( gap_before == 0 ) {
475  DBGC2 ( &heap, "HEAP merging [%p,%p) + [%p,%p) -> "
476  "[%p,%p)\n", block,
477  ( ( ( void * ) block ) + block->size ), freeing,
478  ( ( ( void * ) freeing ) + freeing->size ),
479  block,
480  ( ( ( void * ) freeing ) + freeing->size ) );
481  block->size += actual_size;
482  list_del ( &block->list );
483  VALGRIND_MAKE_MEM_NOACCESS ( freeing,
484  sizeof ( *freeing ) );
485  freeing = block;
486  }
487  /* Stop processing as soon as we reach a following block */
488  if ( gap_after >= 0 )
489  break;
490  }
491 
492  /* Insert before the immediately following block. If
493  * possible, merge the following block into the "freeing"
494  * block.
495  */
496  DBGC2 ( &heap, "HEAP freed [%p,%p)\n",
497  freeing, ( ( ( void * ) freeing ) + freeing->size ) );
498  list_add_tail ( &freeing->list, &block->list );
499  if ( gap_after == 0 ) {
500  DBGC2 ( &heap, "HEAP merging [%p,%p) + [%p,%p) -> [%p,%p)\n",
501  freeing, ( ( ( void * ) freeing ) + freeing->size ),
502  block, ( ( ( void * ) block ) + block->size ), freeing,
503  ( ( ( void * ) block ) + block->size ) );
504  freeing->size += block->size;
505  list_del ( &block->list );
506  VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
507  }
508 
509  /* Update memory usage statistics */
510  freemem += actual_size;
511  usedmem -= actual_size;
512 
513  check_blocks();
515 }
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
static void valgrind_make_blocks_noaccess(void)
Mark all blocks in free list as inaccessible.
Definition: malloc.c:158
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:361
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
unsigned long tmp
Definition: linux_pci.h:63
struct list_head list
List of free blocks.
Definition: malloc.c:59
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
size_t freemem
Total amount of free memory.
Definition: malloc.c:95
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void check_blocks(void)
Check integrity of the blocks in the free list.
Definition: malloc.c:206
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
#define ASSERTING
Definition: assert.h:19
#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:458
#define MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
Definition: malloc.c:63
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
A free block of memory.
Definition: malloc.c:44
#define DBGC2(...)
Definition: compiler.h:522
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
size_t size
Size of this block.
Definition: malloc.c:46
static void valgrind_make_blocks_defined(void)
Mark all blocks in free list as defined.
Definition: malloc.c:117
signed long ssize_t
Definition: stdint.h:7
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:121
size_t usedmem
Total amount of used memory.
Definition: malloc.c:98

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

Referenced by free_phys(), mpopulate(), and 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

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 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  void *new_ptr = NOWHERE;
544 
545  /* Allocate new memory if necessary. If allocation fails,
546  * return without touching the old block.
547  */
548  if ( new_size ) {
549  new_total_size = ( new_size +
550  offsetof ( struct autosized_block, data ) );
551  if ( new_total_size < new_size )
552  return NULL;
553  new_block = alloc_memblock ( new_total_size, 1, 0 );
554  if ( ! new_block )
555  return NULL;
556  new_block->size = new_total_size;
557  VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size,
558  sizeof ( new_block->size ) );
559  new_ptr = &new_block->data;
560  VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
561  }
562 
563  /* Copy across relevant part of the old data region (if any),
564  * then free it. Note that at this point either (a) new_ptr
565  * is valid, or (b) new_size is 0; either way, the memcpy() is
566  * valid.
567  */
568  if ( old_ptr && ( old_ptr != NOWHERE ) ) {
569  old_block = container_of ( old_ptr, struct autosized_block,
570  data );
571  VALGRIND_MAKE_MEM_DEFINED ( &old_block->size,
572  sizeof ( old_block->size ) );
573  old_total_size = old_block->size;
574  assert ( old_total_size != 0 );
575  old_size = ( old_total_size -
576  offsetof ( struct autosized_block, data ) );
577  memcpy ( new_ptr, old_ptr,
578  ( ( old_size < new_size ) ? old_size : new_size ) );
579  VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
580  free_memblock ( old_block, old_total_size );
581  }
582 
583  if ( ASSERTED ) {
584  DBGC ( &heap, "HEAP detected possible memory corruption "
585  "from %p\n", __builtin_return_address ( 0 ) );
586  }
587  return new_ptr;
588 }
void free_memblock(void *ptr, size_t size)
Free a memory block.
Definition: malloc.c:416
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:131
char data[0]
Remaining data.
Definition: malloc.c:71
#define DBGC(...)
Definition: compiler.h:505
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
void * memcpy(void *dest, const void *src, size_t len) __nonnull
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
size_t size
Size of this block.
Definition: malloc.c:69
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
Definition: valgrind.h:4411
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
void * alloc_memblock(size_t size, size_t align, size_t offset)
Allocate a memory block.
Definition: malloc.c:284
#define ASSERTED
Definition: assert.h:25
#define NOWHERE
Address for zero-length memory blocks.
Definition: malloc.c:89
A block of allocated memory complete with size information.
Definition: malloc.c:67
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)
Definition: valgrind.h:4421
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

References alloc_memblock(), assert(), ASSERTED, container_of, data, autosized_block::data, DBGC, free_memblock(), heap, memcpy(), NOWHERE, NULL, offsetof, autosized_block::size, VALGRIND_FREELIKE_BLOCK, VALGRIND_MAKE_MEM_DEFINED, VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MALLOCLIKE_BLOCK.

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 599 of file malloc.c.

599  {
600  void *ptr;
601 
602  ptr = realloc ( NULL, size );
603  if ( ASSERTED ) {
604  DBGC ( &heap, "HEAP detected possible memory corruption "
605  "from %p\n", __builtin_return_address ( 0 ) );
606  }
607  return ptr;
608 }
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
#define ASSERTED
Definition: assert.h:25
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition: malloc.c:537
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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

Referenced by add_ipv4_miniroute(), add_tls(), aes_unwrap(), aes_wrap(), alloc_iob_raw(), apply_dns_search(), ath5k_hw_rfregs_init(), chap_init(), cmdline_init(), cms_decrypt(), deflate_test_exec(), der_asn1(), derwin(), dhcpv6_rx(), dhe_key(), dupwin(), eap_rx_mschapv2_request(), eap_tx_response(), efi_block_label(), efi_cmdline_init(), efi_download_start(), 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(), 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(), 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(), tls_send_plaintext(), 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 620 of file malloc.c.

620  {
621 
622  realloc ( ptr, 0 );
623  if ( ASSERTED ) {
624  DBGC ( &heap, "HEAP detected possible memory corruption "
625  "from %p\n", __builtin_return_address ( 0 ) );
626  }
627 }
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
#define ASSERTED
Definition: assert.h:25
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition: malloc.c:537

References ASSERTED, DBGC, heap, 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 640 of file malloc.c.

640  {
641  void *data;
642 
643  data = malloc ( size );
644  if ( data )
645  memset ( data, 0, size );
646  if ( ASSERTED ) {
647  DBGC ( &heap, "HEAP detected possible memory corruption "
648  "from %p\n", __builtin_return_address ( 0 ) );
649  }
650  return data;
651 }
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
#define ASSERTED
Definition: assert.h:25
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:599
uint8_t data[48]
Additional event data.
Definition: ena.h:22
void * memset(void *dest, int character, size_t len) __nonnull

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

Referenced by add_dynui_item(), add_parameter(), alloc_form(), alloc_ibdev(), alloc_image(), alloc_netdev(), alloc_pixbuf(), alloc_sandev(), 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(), create_downloader(), create_dynui(), create_parameters(), create_pinger(), create_validator(), dhcp_deliver(), dhcpv6_register(), dns_resolv(), 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_send_certificate(), 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().

◆ mpopulate()

static void mpopulate ( void *  start,
size_t  len 
)
static

Add memory to allocation pool.

Parameters
startStart address
lenLength of memory

Adds a block of memory to the allocation pool. This is a one-way operation; there is no way to reclaim this memory.

Definition at line 662 of file malloc.c.

662  {
663  size_t skip;
664 
665  /* Align start of block */
666  skip = ( ( -virt_to_phys ( start ) ) & ( MEMBLOCK_ALIGN - 1 ) );
667  if ( skip > len )
668  return;
669  start += skip;
670  len -= skip;
671 
672  /* Align end of block */
673  len &= ~( MEMBLOCK_ALIGN - 1 );
674  if ( ! len )
675  return;
676 
677  /* Add to allocation pool */
678  free_memblock ( start, len );
679 
680  /* Fix up memory usage statistics */
681  usedmem += len;
682 }
void free_memblock(void *ptr, size_t size)
Free a memory block.
Definition: malloc.c:416
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:361
uint32_t start
Starting offset.
Definition: netvsc.h:12
#define MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
Definition: malloc.c:63
uint32_t len
Length.
Definition: ena.h:14
size_t usedmem
Total amount of used memory.
Definition: malloc.c:98

References free_memblock(), len, MEMBLOCK_ALIGN, start, usedmem, and virt_to_phys().

Referenced by init_heap().

◆ init_heap()

static void init_heap ( void  )
static

Initialise the heap.

Definition at line 688 of file malloc.c.

688  {
689  VALGRIND_MAKE_MEM_NOACCESS ( heap, sizeof ( heap ) );
690  VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
691  mpopulate ( heap, sizeof ( heap ) );
692 }
static void mpopulate(void *start, size_t len)
Add memory to allocation pool.
Definition: malloc.c:662
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111

References heap, mpopulate(), and VALGRIND_MAKE_MEM_NOACCESS.

◆ __init_fn()

struct init_fn heap_init_fn __init_fn ( INIT_EARLY  )

Memory allocator initialisation function.

◆ shutdown_cache()

static void shutdown_cache ( int booting  __unused)
static

Discard all cached data on shutdown.

Definition at line 703 of file malloc.c.

703  {
705  DBGC ( &heap, "HEAP maximum usage %zdkB\n", ( maxusedmem >> 10 ) );
706 }
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:111
static void discard_all_cache(void)
Discard all cached data.
Definition: malloc.c:263
size_t maxusedmem
Maximum amount of used memory.
Definition: malloc.c:101

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

◆ __startup_fn()

struct startup_fn heap_startup_fn __startup_fn ( STARTUP_EARLY  )

Memory allocator shutdown function.

◆ mdumpfree()

void mdumpfree ( void  )

Dump free block list (for debugging)

Definition at line 718 of file malloc.c.

718  {
719  struct memory_block *block;
720 
721  dbg_printf ( "HEAP free block list:\n" );
722  list_for_each_entry ( block, &free_blocks, list ) {
723  dbg_printf ( "...[%p,%p] (size %#zx)\n", block,
724  ( ( ( void * ) block ) + block->size ),
725  block->size );
726  }
727 }
struct list_head list
List of free blocks.
Definition: malloc.c:59
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
A free block of memory.
Definition: malloc.c:44
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
void dbg_printf(const char *fmt,...)
Print debug message.
Definition: debug.c:38

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

Variable Documentation

◆ freemem

size_t freemem

Total amount of free memory.

Definition at line 95 of file malloc.c.

Referenced by alloc_memblock(), and free_memblock().

◆ usedmem

size_t usedmem

Total amount of used memory.

Definition at line 98 of file malloc.c.

Referenced by alloc_memblock(), free_memblock(), and mpopulate().

◆ maxusedmem

size_t maxusedmem

Maximum amount of used memory.

Definition at line 101 of file malloc.c.

Referenced by alloc_memblock(), and shutdown_cache().

◆ heap

char heap[HEAP_SIZE]
static

The heap itself.

Definition at line 111 of file malloc.c.

Referenced by alloc_memblock(), free(), free_memblock(), init_heap(), malloc(), realloc(), shutdown_cache(), and zalloc().