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 MIN_MEMBLOCK_SIZE   ( ( size_t ) ( 1 << ( fls ( sizeof ( struct memory_block ) - 1 ) ) ) )
 
#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...
 
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...
 

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

◆ MIN_MEMBLOCK_SIZE

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

Definition at line 62 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 88 of file malloc.c.

◆ HEAP_SIZE

#define HEAP_SIZE   ( 512 * 1024 )

Heap size.

Currently fixed at 512kB.

Definition at line 107 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 116 of file malloc.c.

116  {
117  struct memory_block *block;
118 
119  /* Do nothing unless running under Valgrind */
120  if ( RUNNING_ON_VALGRIND <= 0 )
121  return;
122 
123  /* Traverse free block list, marking each block structure as
124  * defined. Some contortions are necessary to avoid errors
125  * from list_check().
126  */
127 
128  /* Mark block list itself as defined */
129  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks, sizeof ( free_blocks ) );
130 
131  /* Mark areas accessed by list_check() as defined */
132  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.prev->next,
133  sizeof ( free_blocks.prev->next ) );
134  VALGRIND_MAKE_MEM_DEFINED ( free_blocks.next,
135  sizeof ( *free_blocks.next ) );
136  VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->next->prev,
137  sizeof ( free_blocks.next->next->prev ) );
138 
139  /* Mark each block in list as defined */
140  list_for_each_entry ( block, &free_blocks, list ) {
141 
142  /* Mark block as defined */
143  VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
144 
145  /* Mark areas accessed by list_check() as defined */
146  VALGRIND_MAKE_MEM_DEFINED ( block->list.next,
147  sizeof ( *block->list.next ) );
148  VALGRIND_MAKE_MEM_DEFINED ( &block->list.next->next->prev,
149  sizeof ( block->list.next->next->prev ) );
150  }
151 }
uint16_t block
Definition: tftp.h:12
#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:420
A free block of memory.
Definition: malloc.c:44

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

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

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

205  {
206  struct memory_block *block;
207  struct memory_block *prev = NULL;
208 
209  if ( ! ASSERTING )
210  return;
211 
212  list_for_each_entry ( block, &free_blocks, list ) {
213 
214  /* Check that list structure is intact */
215  list_check ( &block->list );
216 
217  /* Check that block size is not too small */
218  assert ( block->size >= sizeof ( *block ) );
219  assert ( block->size >= MIN_MEMBLOCK_SIZE );
220 
221  /* Check that block does not wrap beyond end of address space */
222  assert ( ( ( void * ) block + block->size ) >
223  ( ( void * ) block ) );
224 
225  /* Check that blocks remain in ascending order, and
226  * that adjacent blocks have been merged.
227  */
228  if ( prev ) {
229  assert ( ( ( void * ) block ) > ( ( void * ) prev ) );
230  assert ( ( ( void * ) block ) >
231  ( ( ( void * ) prev ) + prev->size ) );
232  }
233  prev = block;
234  }
235 }
uint16_t block
Definition: tftp.h:12
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:420
#define ASSERTING
Definition: assert.h:19
#define MIN_MEMBLOCK_SIZE
Definition: malloc.c:62
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
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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

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

242  {
243  struct cache_discarder *discarder;
244  unsigned int discarded;
245 
246  for_each_table_entry ( discarder, CACHE_DISCARDERS ) {
247  discarded = discarder->discard();
248  if ( discarded )
249  return discarded;
250  }
251  return 0;
252 }
#define CACHE_DISCARDERS
Cache discarder table.
Definition: malloc.h:93
unsigned int(* discard)(void)
Discard some cached data.
Definition: malloc.h:89
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
A cache discarder.
Definition: malloc.h:83

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

258  {
259  unsigned int discarded;
260 
261  do {
262  discarded = discard_cache();
263  } while ( discarded );
264 }
static unsigned int discard_cache(void)
Discard some cached data.
Definition: malloc.c:242

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

279  {
280  struct memory_block *block;
281  size_t align_mask;
282  size_t actual_size;
283  size_t pre_size;
284  size_t post_size;
285  struct memory_block *pre;
286  struct memory_block *post;
287  unsigned int discarded;
288  void *ptr;
289 
290  /* Sanity checks */
291  assert ( size != 0 );
292  assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) );
294  check_blocks();
295 
296  /* Round up size to multiple of MIN_MEMBLOCK_SIZE and
297  * calculate alignment mask.
298  */
299  actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
300  ~( MIN_MEMBLOCK_SIZE - 1 ) );
301  if ( ! actual_size ) {
302  /* The requested size is not permitted to be zero. A
303  * zero result at this point indicates that either the
304  * original requested size was zero, or that unsigned
305  * integer overflow has occurred.
306  */
307  ptr = NULL;
308  goto done;
309  }
310  assert ( actual_size >= size );
311  align_mask = ( ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ) );
312 
313  DBGC2 ( &heap, "Allocating %#zx (aligned %#zx+%zx)\n",
314  size, align, offset );
315  while ( 1 ) {
316  /* Search through blocks for the first one with enough space */
317  list_for_each_entry ( block, &free_blocks, list ) {
318  pre_size = ( ( offset - virt_to_phys ( block ) )
319  & align_mask );
320  if ( ( block->size < pre_size ) ||
321  ( ( block->size - pre_size ) < actual_size ) )
322  continue;
323  post_size = ( block->size - pre_size - actual_size );
324  /* Split block into pre-block, block, and
325  * post-block. After this split, the "pre"
326  * block is the one currently linked into the
327  * free list.
328  */
329  pre = block;
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 ) );
335  /* If there is a "post" block, add it in to
336  * the free list. Leak it if it is too small
337  * (which can happen only at the very end of
338  * the heap).
339  */
340  if ( post_size >= MIN_MEMBLOCK_SIZE ) {
342  sizeof ( *post ));
343  post->size = post_size;
344  list_add ( &post->list, &pre->list );
345  }
346  /* Shrink "pre" block, leaving the main block
347  * isolated and no longer part of the free
348  * list.
349  */
350  pre->size = pre_size;
351  /* If there is no "pre" block, remove it from
352  * the list. Also remove it (i.e. leak it) if
353  * it is too small, which can happen only at
354  * the very start of the heap.
355  */
356  if ( pre_size < MIN_MEMBLOCK_SIZE ) {
357  list_del ( &pre->list );
359  sizeof ( *pre ) );
360  }
361  /* Update memory usage statistics */
362  freemem -= actual_size;
363  usedmem += actual_size;
364  if ( usedmem > maxusedmem )
366  /* Return allocated block */
367  DBGC2 ( &heap, "Allocated [%p,%p)\n", block,
368  ( ( ( void * ) block ) + size ) );
369  ptr = block;
371  goto done;
372  }
373 
374  /* Try discarding some cached data to free up memory */
375  DBGC ( &heap, "Attempting discard for %#zx (aligned %#zx+%zx), "
376  "used %zdkB\n", size, align, offset, ( usedmem >> 10 ) );
378  discarded = discard_cache();
380  check_blocks();
381  if ( ! discarded ) {
382  /* Nothing available to discard */
383  DBGC ( &heap, "Failed to allocate %#zx (aligned "
384  "%#zx)\n", size, align );
385  ptr = NULL;
386  goto done;
387  }
388  }
389 
390  done:
391  check_blocks();
393  return ptr;
394 }
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
uint16_t block
Definition: tftp.h:12
#define DBGC(...)
Definition: compiler.h:505
static void valgrind_make_blocks_noaccess(void)
Mark all blocks in free list as inaccessible.
Definition: malloc.c:157
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
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:94
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:205
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
#define MIN_MEMBLOCK_SIZE
Definition: malloc.c:62
A free block of memory.
Definition: malloc.c:44
static unsigned int discard_cache(void)
Discard some cached data.
Definition: malloc.c:242
#define DBGC2(...)
Definition: compiler.h:522
size_t size
Size of this block.
Definition: malloc.c:46
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
static void valgrind_make_blocks_defined(void)
Mark all blocks in free list as defined.
Definition: malloc.c:116
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:121
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
size_t maxusedmem
Maximum amount of used memory.
Definition: malloc.c:100
struct bofm_section_header done
Definition: bofm_test.c:46
size_t usedmem
Total amount of used memory.
Definition: malloc.c:97

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, MIN_MEMBLOCK_SIZE, 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 404 of file malloc.c.

404  {
405  struct memory_block *freeing;
406  struct memory_block *block;
407  struct memory_block *tmp;
408  size_t actual_size;
409  ssize_t gap_before;
410  ssize_t gap_after = -1;
411 
412  /* Allow for ptr==NULL */
413  if ( ! ptr )
414  return;
416 
417  /* Sanity checks */
419  check_blocks();
420 
421  /* Round up size to match actual size that alloc_memblock()
422  * would have used.
423  */
424  assert ( size != 0 );
425  actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
426  ~( MIN_MEMBLOCK_SIZE - 1 ) );
427  freeing = ptr;
428  VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) );
429  DBGC2 ( &heap, "Freeing [%p,%p)\n",
430  freeing, ( ( ( void * ) freeing ) + size ) );
431 
432  /* Check that this block does not overlap the free list */
433  if ( ASSERTING ) {
434  list_for_each_entry ( block, &free_blocks, list ) {
435  if ( ( ( ( void * ) block ) <
436  ( ( void * ) freeing + actual_size ) ) &&
437  ( ( void * ) freeing <
438  ( ( void * ) block + block->size ) ) ) {
439  assert ( 0 );
440  DBGC ( &heap, "Double free of [%p,%p) "
441  "overlapping [%p,%p) detected from %p\n",
442  freeing,
443  ( ( ( void * ) freeing ) + size ), block,
444  ( ( void * ) block + block->size ),
445  __builtin_return_address ( 0 ) );
446  }
447  }
448  }
449 
450  /* Insert/merge into free list */
451  freeing->size = actual_size;
452  list_for_each_entry_safe ( block, tmp, &free_blocks, list ) {
453  /* Calculate gaps before and after the "freeing" block */
454  gap_before = ( ( ( void * ) freeing ) -
455  ( ( ( void * ) block ) + block->size ) );
456  gap_after = ( ( ( void * ) block ) -
457  ( ( ( void * ) freeing ) + freeing->size ) );
458  /* Merge with immediately preceding block, if possible */
459  if ( gap_before == 0 ) {
460  DBGC2 ( &heap, "[%p,%p) + [%p,%p) -> [%p,%p)\n", block,
461  ( ( ( void * ) block ) + block->size ), freeing,
462  ( ( ( void * ) freeing ) + freeing->size ),
463  block,
464  ( ( ( void * ) freeing ) + freeing->size ) );
465  block->size += actual_size;
466  list_del ( &block->list );
467  VALGRIND_MAKE_MEM_NOACCESS ( freeing,
468  sizeof ( *freeing ) );
469  freeing = block;
470  }
471  /* Stop processing as soon as we reach a following block */
472  if ( gap_after >= 0 )
473  break;
474  }
475 
476  /* Insert before the immediately following block. If
477  * possible, merge the following block into the "freeing"
478  * block.
479  */
480  DBGC2 ( &heap, "[%p,%p)\n",
481  freeing, ( ( ( void * ) freeing ) + freeing->size ) );
482  list_add_tail ( &freeing->list, &block->list );
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,
487  ( ( ( void * ) block ) + block->size ) );
488  freeing->size += block->size;
489  list_del ( &block->list );
490  VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
491  }
492 
493  /* Update memory usage statistics */
494  freemem += actual_size;
495  usedmem -= actual_size;
496 
497  check_blocks();
499 }
uint16_t block
Definition: tftp.h:12
#define DBGC(...)
Definition: compiler.h:505
static void valgrind_make_blocks_noaccess(void)
Mark all blocks in free list as inaccessible.
Definition: malloc.c:157
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
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:94
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:205
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
#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:447
uint8_t * tmp
Definition: entropy.h:156
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
#define MIN_MEMBLOCK_SIZE
Definition: malloc.c:62
A free block of memory.
Definition: malloc.c:44
#define DBGC2(...)
Definition: compiler.h:522
size_t size
Size of this block.
Definition: malloc.c:46
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
static void valgrind_make_blocks_defined(void)
Mark all blocks in free list as defined.
Definition: malloc.c:116
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:97

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, MIN_MEMBLOCK_SIZE, size, tmp, usedmem, valgrind_make_blocks_defined(), valgrind_make_blocks_noaccess(), VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MAKE_MEM_UNDEFINED.

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

521  {
522  struct autosized_block *old_block;
523  struct autosized_block *new_block;
524  size_t old_total_size;
525  size_t new_total_size;
526  size_t old_size;
527  void *new_ptr = NOWHERE;
528 
529  /* Allocate new memory if necessary. If allocation fails,
530  * return without touching the old block.
531  */
532  if ( new_size ) {
533  new_total_size = ( new_size +
534  offsetof ( struct autosized_block, data ) );
535  if ( new_total_size < new_size )
536  return NULL;
537  new_block = alloc_memblock ( new_total_size, 1, 0 );
538  if ( ! new_block )
539  return NULL;
540  new_block->size = new_total_size;
541  VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size,
542  sizeof ( new_block->size ) );
543  new_ptr = &new_block->data;
544  VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
545  }
546 
547  /* Copy across relevant part of the old data region (if any),
548  * then free it. Note that at this point either (a) new_ptr
549  * is valid, or (b) new_size is 0; either way, the memcpy() is
550  * valid.
551  */
552  if ( old_ptr && ( old_ptr != NOWHERE ) ) {
553  old_block = container_of ( old_ptr, struct autosized_block,
554  data );
555  VALGRIND_MAKE_MEM_DEFINED ( &old_block->size,
556  sizeof ( old_block->size ) );
557  old_total_size = old_block->size;
558  assert ( old_total_size != 0 );
559  old_size = ( old_total_size -
560  offsetof ( struct autosized_block, data ) );
561  memcpy ( new_ptr, old_ptr,
562  ( ( old_size < new_size ) ? old_size : new_size ) );
563  VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
564  free_memblock ( old_block, old_total_size );
565  }
566 
567  if ( ASSERTED ) {
568  DBGC ( &heap, "Possible memory corruption detected from %p\n",
569  __builtin_return_address ( 0 ) );
570  }
571  return new_ptr;
572 }
void free_memblock(void *ptr, size_t size)
Free a memory block.
Definition: malloc.c:404
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
Definition: memcheck.h:131
char data[0]
Remaining data.
Definition: malloc.c:70
#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:110
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:68
#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:279
#define ASSERTED
Definition: assert.h:25
#define NOWHERE
Address for zero-length memory blocks.
Definition: malloc.c:88
A block of allocated memory complete with size information.
Definition: malloc.c:66
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)
Definition: valgrind.h:4421
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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 asn1_grow(), bitmap_resize(), cachedhcp_init(), dhcpopt_init(), efi_ifr_op(), efi_ifr_string(), 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 583 of file malloc.c.

583  {
584  void *ptr;
585 
586  ptr = realloc ( NULL, size );
587  if ( ASSERTED ) {
588  DBGC ( &heap, "Possible memory corruption detected from %p\n",
589  __builtin_return_address ( 0 ) );
590  }
591  return ptr;
592 }
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
#define ASSERTED
Definition: assert.h:25
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition: malloc.c:521
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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_parse_signature_value(), deflate_test_exec(), der_asn1(), derwin(), dhcpv6_rx(), dupwin(), efi_download_start(), efi_local_check_volume_name(), efi_local_len(), eisabus_probe(), fc_ulp_login(), fetch_setting_copy(), format_uri_alloc(), http_format_ntlm_auth(), int13_hook(), 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(), 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_assemble_block(), tls_assemble_stream(), tls_new_session_ticket(), 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 604 of file malloc.c.

604  {
605 
606  realloc ( ptr, 0 );
607  if ( ASSERTED ) {
608  DBGC ( &heap, "Possible memory corruption detected from %p\n",
609  __builtin_return_address ( 0 ) );
610  }
611 }
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
#define ASSERTED
Definition: assert.h:25
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition: malloc.c:521

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

624  {
625  void *data;
626 
627  data = malloc ( size );
628  if ( data )
629  memset ( data, 0, size );
630  if ( ASSERTED ) {
631  DBGC ( &heap, "Possible memory corruption detected from %p\n",
632  __builtin_return_address ( 0 ) );
633  }
634  return data;
635 }
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
#define ASSERTED
Definition: assert.h:25
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
void * memset(void *dest, int character, size_t len) __nonnull

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

Referenced by add_menu_item(), add_parameter(), 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_init(), calloc(), cms_parse(), cms_signature(), concat_args(), create_downloader(), create_menu(), create_parameters(), create_pinger(), create_validator(), dhcp_deliver(), dhcpv6_register(), dns_resolv(), efi_block_boot_image(), efi_block_install(), efi_driver_start(), efi_fcp_path(), efi_file_open(), efi_ib_srp_path(), efi_image_cmdline(), efi_image_path(), efi_iscsi_path(), efi_local_open(), efi_netdev_path(), 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(), efipci_start(), 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(), fcoe_probe(), 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(), guestinfo_net_probe(), hermon_alloc(), hermon_create_cq(), hermon_create_qp(), http_connect(), http_open(), http_open_post_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(), init_mlx_utils(), ipv6_add_miniroute(), ipv6_register_settings(), 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(), 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(), 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(), vp_alloc_vq(), 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(), and xve_create().

◆ mpopulate()

void mpopulate ( void *  start,
size_t  len 
)

Add memory to allocation pool.

Parameters
startStart address
endEnd address

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

start must be aligned to at least a multiple of sizeof(void*).

Definition at line 648 of file malloc.c.

648  {
649 
650  /* Prevent free_memblock() from rounding up len beyond the end
651  * of what we were actually given...
652  */
653  len &= ~( MIN_MEMBLOCK_SIZE - 1 );
654 
655  /* Add to allocation pool */
656  free_memblock ( start, len );
657 
658  /* Fix up memory usage statistics */
659  usedmem += len;
660 }
void free_memblock(void *ptr, size_t size)
Free a memory block.
Definition: malloc.c:404
uint32_t start
Starting offset.
Definition: netvsc.h:12
#define MIN_MEMBLOCK_SIZE
Definition: malloc.c:62
uint32_t len
Length.
Definition: ena.h:14
size_t usedmem
Total amount of used memory.
Definition: malloc.c:97

References free_memblock(), len, MIN_MEMBLOCK_SIZE, start, and usedmem.

Referenced by init_heap().

◆ init_heap()

static void init_heap ( void  )
static

Initialise the heap.

Definition at line 666 of file malloc.c.

666  {
667  VALGRIND_MAKE_MEM_NOACCESS ( heap, sizeof ( heap ) );
668  VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
669  mpopulate ( heap, sizeof ( heap ) );
670 }
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition: memcheck.h:111
void mpopulate(void *start, size_t len)
Add memory to allocation pool.
Definition: malloc.c:648

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

681  {
683  DBGC ( &heap, "Maximum heap usage %zdkB\n", ( maxusedmem >> 10 ) );
684 }
#define DBGC(...)
Definition: compiler.h:505
static char heap[HEAP_SIZE]
The heap itself.
Definition: malloc.c:110
static void discard_all_cache(void)
Discard all cached data.
Definition: malloc.c:258
size_t maxusedmem
Maximum amount of used memory.
Definition: malloc.c:100

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

◆ __startup_fn()

struct startup_fn heap_startup_fn __startup_fn ( STARTUP_EARLY  )

Memory allocator shutdown function.

Variable Documentation

◆ freemem

size_t freemem

Total amount of free memory.

Definition at line 94 of file malloc.c.

Referenced by alloc_memblock(), and free_memblock().

◆ usedmem

size_t usedmem

Total amount of used memory.

Definition at line 97 of file malloc.c.

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

◆ maxusedmem

size_t maxusedmem

Maximum amount of used memory.

Definition at line 100 of file malloc.c.

Referenced by alloc_memblock(), and shutdown_cache().

◆ heap

char heap[HEAP_SIZE]
static

The heap itself.

Definition at line 110 of file malloc.c.

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