iPXE
malloc.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stddef.h>
28#include <stdint.h>
29#include <string.h>
30#include <ipxe/io.h>
31#include <ipxe/list.h>
32#include <ipxe/init.h>
33#include <ipxe/refcnt.h>
34#include <ipxe/malloc.h>
35#include <valgrind/memcheck.h>
36
37/** @file
38 *
39 * Dynamic memory allocation
40 *
41 * @anchor malloc
42 *
43 * Memory allocation via malloc() is provided using a simple
44 * free-block list in a fixed-size heap.
45 *
46 * The standard C semantics are supported. Calling realloc() with a
47 * size of zero is a valid way to free a block. Calling malloc() or
48 * realloc() with a size of zero will return a non-NULL value that can
49 * safely be passed to free() (meaning that callers can always treat a
50 * NULL return value as an error, without having to special-case a
51 * zero-length allocation).
52 *
53 * (The POSIX semantics of setting a global @c errno variable on
54 * allocation failure are not supported: callers should check for a
55 * NULL return value and then return -ENOMEM as per the usual iPXE
56 * error propagation conventions.)
57 *
58 * Memory allocation assumes that all input parameters are untrusted
59 * and must be checked. In particular, buffer sizes are frequently
60 * derived from untrusted input obtained via the network (e.g. an HTTP
61 * Content-Length header).
62 *
63 * In contrast, memory deallocation assumes that the caller is always
64 * passing in a valid pointer value.
65 *
66 * The internal heap is relatively small. Allocation is expected to
67 * sometimes fail in normal operation, and all callers must be
68 * prepared to handle it cleanly. Device drivers attempting to
69 * allocate receive buffers to refill a receive ring can simply exit
70 * the refill loop and do nothing until the next refill opportunity.
71 * Other callers will generally have to treat allocation failure as
72 * fatal and cleanly terminate their operation (e.g. by closing a
73 * connection).
74 *
75 * The same internal heap supports both size-tracked allocations
76 * (using malloc()/free()) and known-size allocations (using
77 * malloc_phys()/free_phys(), where the caller must pass the original
78 * size when freeing the block). The latter are typically used for
79 * I/O buffers, driver descriptor rings, and other hardware-facing
80 * structures.
81 *
82 * Depending upon the build platform, the underlying heap
83 * implementation may also be used to support external ("user")
84 * allocations using umalloc() and ufree().
85 *
86 * A cache discard mechanism exists to attempt to alleviate memory
87 * pressure by discarding cached information (such as packets held in
88 * a TCP out-of-order receive queue) when an allocation attempt would
89 * otherwise fail. Code that holds pointers to discardable objects
90 * must be careful not to call any allocation functions.
91 *
92 */
93
94/** A free block of memory */
96 /** Size of this block */
97 size_t size;
98 /** Padding
99 *
100 * This padding exists to cover the "count" field of a
101 * reference counter, in the common case where a reference
102 * counter is the first element of a dynamically-allocated
103 * object. It avoids clobbering the "count" field as soon as
104 * the memory is freed, and so allows for the possibility of
105 * detecting reference counting errors.
106 */
107 char pad[ offsetof ( struct refcnt, count ) +
108 sizeof ( ( ( struct refcnt * ) NULL )->count ) ];
109 /** List of free blocks */
111};
112
113/** Physical address alignment maintained for free blocks of memory
114 *
115 * We keep memory blocks aligned on a power of two that is at least
116 * large enough to hold a @c struct @c memory_block.
117 */
118#define MIN_MEMBLOCK_ALIGN ( 4 * sizeof ( void * ) )
119
120/** A block of allocated memory complete with size information */
122 /** Size of this block */
123 size_t size;
124 /** Remaining data */
125 char data[0];
126};
127
128/**
129 * Heap area size
130 *
131 * Currently fixed at 4MB.
132 */
133#define HEAP_SIZE ( 4096 * 1024 )
134
135/** Heap area alignment */
136#define HEAP_ALIGN MIN_MEMBLOCK_ALIGN
137
138/** The heap area */
139static char __attribute__ (( aligned ( HEAP_ALIGN ) )) heap_area[HEAP_SIZE];
140
141/**
142 * Mark all blocks in free list as defined
143 *
144 * @v heap Heap
145 */
146static inline void valgrind_make_blocks_defined ( struct heap *heap ) {
147 struct memory_block *block;
148
149 /* Do nothing unless running under Valgrind */
150 if ( RUNNING_ON_VALGRIND <= 0 )
151 return;
152
153 /* Traverse free block list, marking each block structure as
154 * defined. Some contortions are necessary to avoid errors
155 * from list_check().
156 */
157
158 /* Mark block list itself as defined */
160
161 /* Mark areas accessed by list_check() as defined */
163 sizeof ( heap->blocks.prev->next ) );
165 sizeof ( *heap->blocks.next ) );
167 sizeof ( heap->blocks.next->next->prev ) );
168
169 /* Mark each block in list as defined */
171
172 /* Mark block as defined */
173 VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
174
175 /* Mark areas accessed by list_check() as defined */
176 VALGRIND_MAKE_MEM_DEFINED ( block->list.next,
177 sizeof ( *block->list.next ) );
178 VALGRIND_MAKE_MEM_DEFINED ( &block->list.next->next->prev,
179 sizeof ( block->list.next->next->prev ) );
180 }
181}
182
183/**
184 * Mark all blocks in free list as inaccessible
185 *
186 * @v heap Heap
187 */
188static inline void valgrind_make_blocks_noaccess ( struct heap *heap ) {
189 struct memory_block *block;
190 struct memory_block *prev = NULL;
191
192 /* Do nothing unless running under Valgrind */
193 if ( RUNNING_ON_VALGRIND <= 0 )
194 return;
195
196 /* Traverse free block list, marking each block structure as
197 * inaccessible. Some contortions are necessary to avoid
198 * errors from list_check().
199 */
200
201 /* Mark each block in list as inaccessible */
203
204 /* Mark previous block (if any) as inaccessible. (Current
205 * block will be accessed by list_check().)
206 */
207 if ( prev )
208 VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
209 prev = block;
210
211 /* At the end of the list, list_check() will end up
212 * accessing the first list item. Temporarily mark
213 * this area as defined.
214 */
216 sizeof ( heap->blocks.next->prev ));
217 }
218 /* Mark last block (if any) as inaccessible */
219 if ( prev )
220 VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
221
222 /* Mark as inaccessible the area that was temporarily marked
223 * as defined to avoid errors from list_check().
224 */
226 sizeof ( heap->blocks.next->prev ) );
227
228 /* Mark block list itself as inaccessible */
230}
231
232/**
233 * Check integrity of the blocks in the free list
234 *
235 * @v heap Heap
236 */
237static inline void check_blocks ( struct heap *heap ) {
238 struct memory_block *block;
239 struct memory_block *prev = NULL;
240
241 if ( ! ASSERTING )
242 return;
243
245
246 /* Check alignment */
247 assert ( ( virt_to_phys ( block ) &
248 ( heap->align - 1 ) ) == 0 );
249
250 /* Check that list structure is intact */
251 list_check ( &block->list );
252
253 /* Check that block size is not too small */
254 assert ( block->size >= sizeof ( *block ) );
255 assert ( block->size >= heap->align );
256
257 /* Check that block does not wrap beyond end of address space */
258 assert ( ( ( void * ) block + block->size ) >
259 ( ( void * ) block ) );
260
261 /* Check that blocks remain in ascending order, and
262 * that adjacent blocks have been merged.
263 */
264 if ( prev ) {
265 assert ( ( ( void * ) block ) > ( ( void * ) prev ) );
266 assert ( ( ( void * ) block ) >
267 ( ( ( void * ) prev ) + prev->size ) );
268 }
269 prev = block;
270 }
271}
272
273/**
274 * Discard some cached data
275 *
276 * @v size Failed allocation size
277 * @ret discarded Number of cached items discarded
278 */
279static unsigned int discard_cache ( size_t size __unused ) {
280 struct cache_discarder *discarder;
281 unsigned int discarded;
282
284 discarded = discarder->discard();
285 if ( discarded )
286 return discarded;
287 }
288 return 0;
289}
290
291/**
292 * Discard all cached data
293 *
294 */
295static void discard_all_cache ( void ) {
296 unsigned int discarded;
297
298 do {
299 discarded = discard_cache ( 0 );
300 } while ( discarded );
301}
302
303/**
304 * Allocate a memory block
305 *
306 * @v heap Heap
307 * @v size Requested size
308 * @v align Physical alignment
309 * @v offset Offset from physical alignment
310 * @ret ptr Memory block, or NULL
311 *
312 * Allocates a memory block @b physically aligned as requested. No
313 * guarantees are provided for the alignment of the virtual address.
314 *
315 * @c align must be a power of two. @c size may not be zero.
316 */
317static void * heap_alloc_block ( struct heap *heap, size_t size, size_t align,
318 size_t offset ) {
319 struct memory_block *block;
320 size_t actual_offset;
321 size_t align_mask;
322 size_t actual_size;
323 size_t pre_size;
324 size_t post_size;
325 struct memory_block *pre;
326 struct memory_block *post;
327 unsigned int grown;
328 void *ptr;
329
330 /* Sanity checks */
332 check_blocks ( heap );
333
334 /* Validate inputs */
335 if ( ( size == 0 ) || ( align == 0 ) || ( align & ( align - 1 ) ) ) {
336 /* This is unreachable from any of our callers and
337 * could instead be an assertion, but we perform a
338 * runtime check anyway to guard against future
339 * possible code changes.
340 */
341 DBGC ( heap, "HEAP malformed allocation %#zx (aligned "
342 "%#zx+%#zx)\n", size, align, offset );
343 ptr = NULL;
344 goto done;
345 }
346
347 /* Limit offset to requested alignment */
348 offset &= ( align - 1 );
349
350 /* Calculate offset of memory block */
351 actual_offset = ( offset & ~( heap->align - 1 ) );
352 assert ( actual_offset <= offset );
353
354 /* Calculate size of memory block and check for overflow */
355 actual_size = ( ( size + offset - actual_offset + heap->align - 1 )
356 & ~( heap->align - 1 ) );
357 if ( actual_size < size ) {
358 ptr = NULL;
359 goto done;
360 }
361
362 /* Calculate alignment mask */
363 align_mask = ( ( align - 1 ) | ( heap->align - 1 ) );
364
365 DBGC2 ( heap, "HEAP allocating %#zx (aligned %#zx+%#zx)\n",
366 size, align, offset );
367 while ( 1 ) {
368 /* Search through blocks for the first one with enough space */
370 pre_size = ( ( actual_offset - virt_to_phys ( block ) )
371 & align_mask );
372 if ( ( block->size < pre_size ) ||
373 ( ( block->size - pre_size ) < actual_size ) )
374 continue;
375 post_size = ( block->size - pre_size - actual_size );
376 /* Split block into pre-block, block, and
377 * post-block. After this split, the "pre"
378 * block is the one currently linked into the
379 * free list.
380 */
381 pre = block;
382 block = ( ( ( void * ) pre ) + pre_size );
383 post = ( ( ( void * ) block ) + actual_size );
384 DBGC2 ( heap, "HEAP splitting [%p,%p) -> [%p,%p) "
385 "+ [%p,%p)\n", pre,
386 ( ( ( void * ) pre ) + pre->size ), pre, block,
387 post, ( ( ( void * ) pre ) + pre->size ) );
388 /* If there is a "post" block, add it in to
389 * the free list.
390 */
391 if ( post_size ) {
392 assert ( post_size >= sizeof ( *block ) );
393 assert ( ( post_size &
394 ( heap->align - 1 ) ) == 0 );
396 sizeof ( *post ));
397 post->size = post_size;
398 list_add ( &post->list, &pre->list );
399 }
400 /* Shrink "pre" block, leaving the main block
401 * isolated and no longer part of the free
402 * list.
403 */
404 pre->size = pre_size;
405 /* If there is no "pre" block, remove it from
406 * the list.
407 */
408 if ( ! pre_size ) {
409 list_del ( &pre->list );
411 sizeof ( *pre ) );
412 } else {
413 assert ( pre_size >= sizeof ( *block ) );
414 assert ( ( pre_size &
415 ( heap->align - 1 ) ) == 0 );
416 }
417 /* Update memory usage statistics */
418 heap->freemem -= actual_size;
419 heap->usedmem += actual_size;
420 if ( heap->usedmem > heap->maxusedmem )
422 /* Return allocated block */
423 ptr = ( ( ( void * ) block ) + offset - actual_offset );
424 DBGC2 ( heap, "HEAP allocated [%p,%p) within "
425 "[%p,%p)\n", ptr, ( ptr + size ), block,
426 ( ( ( void * ) block ) + actual_size ) );
428 goto done;
429 }
430
431 /* Attempt to grow heap to satisfy allocation */
432 DBGC ( heap, "HEAP attempting to grow for %#zx (aligned "
433 "%#zx+%zx), used %zdkB\n", size, align, offset,
434 ( heap->usedmem >> 10 ) );
436 grown = ( heap->grow ? heap->grow ( actual_size ) : 0 );
438 check_blocks ( heap );
439 if ( ! grown ) {
440 /* Heap did not grow: fail allocation */
441 DBGC ( heap, "HEAP failed to allocate %#zx (aligned "
442 "%#zx)\n", size, align );
443 ptr = NULL;
444 goto done;
445 }
446 }
447
448 done:
449 check_blocks ( heap );
451 return ptr;
452}
453
454/**
455 * Free a memory block
456 *
457 * @v heap Heap
458 * @v ptr Memory allocated by heap_alloc_block(), or NULL
459 * @v size Size of the memory
460 *
461 * If @c ptr is NULL, no action is taken.
462 */
463static void heap_free_block ( struct heap *heap, void *ptr, size_t size ) {
464 struct memory_block *freeing;
465 struct memory_block *block;
466 struct memory_block *tmp;
467 size_t sub_offset;
468 size_t actual_size;
469 ssize_t gap_before;
470 ssize_t gap_after = -1;
471
472 /* Allow for ptr==NULL */
473 if ( ! ptr )
474 return;
476
477 /* Sanity checks */
479 check_blocks ( heap );
480
481 /* Round up to match actual block that heap_alloc_block() would
482 * have allocated.
483 */
484 assert ( size != 0 );
485 sub_offset = ( virt_to_phys ( ptr ) & ( heap->align - 1 ) );
486 freeing = ( ptr - sub_offset );
487 actual_size = ( ( size + sub_offset + heap->align - 1 ) &
488 ~( heap->align - 1 ) );
489 DBGC2 ( heap, "HEAP freeing [%p,%p) within [%p,%p)\n",
490 ptr, ( ptr + size ), freeing,
491 ( ( ( void * ) freeing ) + actual_size ) );
492 VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) );
493
494 /* Check that this block does not overlap the free list */
495 if ( ASSERTING ) {
497 if ( ( ( ( void * ) block ) <
498 ( ( void * ) freeing + actual_size ) ) &&
499 ( ( void * ) freeing <
500 ( ( void * ) block + block->size ) ) ) {
501 assert ( 0 );
502 DBGC ( heap, "HEAP double free of [%p,%p) "
503 "overlapping [%p,%p) detected from %p\n",
504 freeing,
505 ( ( ( void * ) freeing ) + size ), block,
506 ( ( void * ) block + block->size ),
507 __builtin_return_address ( 0 ) );
508 }
509 }
510 }
511
512 /* Insert/merge into free list */
513 freeing->size = actual_size;
515 /* Calculate gaps before and after the "freeing" block */
516 gap_before = ( ( ( void * ) freeing ) -
517 ( ( ( void * ) block ) + block->size ) );
518 gap_after = ( ( ( void * ) block ) -
519 ( ( ( void * ) freeing ) + freeing->size ) );
520 /* Merge with immediately preceding block, if possible */
521 if ( gap_before == 0 ) {
522 DBGC2 ( heap, "HEAP merging [%p,%p) + [%p,%p) -> "
523 "[%p,%p)\n", block,
524 ( ( ( void * ) block ) + block->size ), freeing,
525 ( ( ( void * ) freeing ) + freeing->size ),
526 block,
527 ( ( ( void * ) freeing ) + freeing->size ) );
528 block->size += actual_size;
529 list_del ( &block->list );
531 sizeof ( *freeing ) );
532 freeing = block;
533 }
534 /* Stop processing as soon as we reach a following block */
535 if ( gap_after >= 0 )
536 break;
537 }
538
539 /* Insert before the immediately following block. If
540 * possible, merge the following block into the "freeing"
541 * block.
542 */
543 DBGC2 ( heap, "HEAP freed [%p,%p)\n",
544 freeing, ( ( ( void * ) freeing ) + freeing->size ) );
545 list_add_tail ( &freeing->list, &block->list );
546 if ( gap_after == 0 ) {
547 DBGC2 ( heap, "HEAP merging [%p,%p) + [%p,%p) -> [%p,%p)\n",
548 freeing, ( ( ( void * ) freeing ) + freeing->size ),
549 block, ( ( ( void * ) block ) + block->size ), freeing,
550 ( ( ( void * ) block ) + block->size ) );
551 freeing->size += block->size;
552 list_del ( &block->list );
553 VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
554 }
555
556 /* Update memory usage statistics */
557 heap->freemem += actual_size;
558 heap->usedmem -= actual_size;
559
560 /* Allow heap to shrink */
561 if ( heap->shrink && heap->shrink ( freeing, freeing->size ) ) {
562 list_del ( &freeing->list );
563 heap->freemem -= freeing->size;
564 VALGRIND_MAKE_MEM_UNDEFINED ( freeing, freeing->size );
565 }
566
567 /* Sanity checks */
568 check_blocks ( heap );
570}
571
572/**
573 * Reallocate memory
574 *
575 * @v heap Heap
576 * @v old_ptr Memory previously allocated by heap_realloc(), or NULL
577 * @v new_size Requested size
578 * @ret new_ptr Allocated memory, or NULL
579 *
580 * Allocates memory with no particular alignment requirement. @c
581 * new_ptr will be aligned to at least a multiple of sizeof(void*).
582 * If @c old_ptr is non-NULL, then the contents of the newly allocated
583 * memory will be the same as the contents of the previously allocated
584 * memory, up to the minimum of the old and new sizes. The old memory
585 * will be freed.
586 *
587 * If allocation fails the previously allocated block is left
588 * untouched and NULL is returned.
589 *
590 * Calling heap_realloc() with a new size of zero is a valid way to
591 * free a memory block.
592 */
593void * heap_realloc ( struct heap *heap, void *old_ptr, size_t new_size ) {
594 struct autosized_block *old_block;
595 struct autosized_block *new_block;
596 size_t old_total_size;
597 size_t new_total_size;
598 size_t old_size;
599 size_t offset = offsetof ( struct autosized_block, data );
600 void *new_ptr = NOWHERE;
601
602 /* Allocate new memory if necessary. If allocation fails,
603 * return without touching the old block.
604 */
605 if ( new_size ) {
606 new_total_size = ( new_size + offset );
607 if ( new_total_size < new_size )
608 return NULL;
609 new_block = heap_alloc_block ( heap, new_total_size,
610 heap->ptr_align, -offset );
611 if ( ! new_block )
612 return NULL;
613 new_block->size = new_total_size;
614 VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size,
615 sizeof ( new_block->size ) );
616 new_ptr = &new_block->data;
617 VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
618 assert ( ( ( ( intptr_t ) new_ptr ) &
619 ( heap->ptr_align - 1 ) ) == 0 );
620 }
621
622 /* Copy across relevant part of the old data region (if any),
623 * then free it. Note that at this point either (a) new_ptr
624 * is valid, or (b) new_size is 0; either way, the memcpy() is
625 * valid.
626 */
627 if ( old_ptr && ( old_ptr != NOWHERE ) ) {
628 old_block = container_of ( old_ptr, struct autosized_block,
629 data );
630 VALGRIND_MAKE_MEM_DEFINED ( &old_block->size,
631 sizeof ( old_block->size ) );
632 old_total_size = old_block->size;
633 assert ( old_total_size != 0 );
634 old_size = ( old_total_size - offset );
635 memcpy ( new_ptr, old_ptr,
636 ( ( old_size < new_size ) ? old_size : new_size ) );
637 VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
638 heap_free_block ( heap, old_block, old_total_size );
639 }
640
641 if ( ASSERTED ) {
642 DBGC ( heap, "HEAP detected possible memory corruption "
643 "from %p\n", __builtin_return_address ( 0 ) );
644 }
645 return new_ptr;
646}
647
648/** The global heap */
649static struct heap heap = {
650 .blocks = LIST_HEAD_INIT ( heap.blocks ),
651 .align = MIN_MEMBLOCK_ALIGN,
652 .ptr_align = sizeof ( void * ),
654};
655
656/**
657 * Reallocate memory
658 *
659 * @v old_ptr Memory previously allocated by malloc(), or NULL
660 * @v new_size Requested size
661 * @ret new_ptr Allocated memory, or NULL
662 */
663void * realloc ( void *old_ptr, size_t new_size ) {
664
665 return heap_realloc ( &heap, old_ptr, new_size );
666}
667
668/**
669 * Allocate memory
670 *
671 * @v size Requested size
672 * @ret ptr Memory, or NULL
673 *
674 * Allocates memory with no particular alignment requirement. @c ptr
675 * will be aligned to at least a multiple of sizeof(void*).
676 */
677void * malloc ( size_t size ) {
678 void *ptr;
679
680 ptr = realloc ( NULL, size );
681 if ( ASSERTED ) {
682 DBGC ( &heap, "HEAP detected possible memory corruption "
683 "from %p\n", __builtin_return_address ( 0 ) );
684 }
685 return ptr;
686}
687
688/**
689 * Free memory
690 *
691 * @v ptr Memory allocated by malloc(), or NULL
692 *
693 * Memory allocated with malloc_phys() cannot be freed with free(); it
694 * must be freed with free_phys() instead.
695 *
696 * If @c ptr is NULL, no action is taken.
697 */
698void free ( void *ptr ) {
699
700 realloc ( ptr, 0 );
701 if ( ASSERTED ) {
702 DBGC ( &heap, "HEAP detected possible memory corruption "
703 "from %p\n", __builtin_return_address ( 0 ) );
704 }
705}
706
707/**
708 * Allocate cleared memory
709 *
710 * @v size Requested size
711 * @ret ptr Allocated memory
712 *
713 * Allocate memory as per malloc(), and zero it.
714 *
715 * This function name is non-standard, but pretty intuitive.
716 * zalloc(size) is always equivalent to calloc(1,size)
717 */
718void * zalloc ( size_t size ) {
719 void *data;
720
721 data = malloc ( size );
722 if ( data )
723 memset ( data, 0, size );
724 if ( ASSERTED ) {
725 DBGC ( &heap, "HEAP detected possible memory corruption "
726 "from %p\n", __builtin_return_address ( 0 ) );
727 }
728 return data;
729}
730
731/**
732 * Clear and free memory
733 *
734 * @v ptr Memory allocated by malloc(), or NULL
735 *
736 * If @c ptr is NULL, no action is taken.
737 */
738void zfree ( void *ptr ) {
739 struct autosized_block *block;
740
741 if ( ptr && ( ptr != NOWHERE ) ) {
742 block = container_of ( ptr, struct autosized_block, data );
744 sizeof ( block->size ) );
745 assert ( block->size >= sizeof ( *block ) );
746 memset ( ptr, 0, ( block->size - sizeof ( *block ) ) );
748 sizeof ( block->size ) );
749 }
750 free ( ptr );
751 if ( ASSERTED ) {
752 DBGC ( &heap, "HEAP detected possible memory corruption "
753 "from %p\n", __builtin_return_address ( 0 ) );
754 }
755}
756
757/**
758 * Allocate memory with specified physical alignment and offset
759 *
760 * @v size Requested size
761 * @v align Physical alignment
762 * @v offset Offset from physical alignment
763 * @ret ptr Memory, or NULL
764 *
765 * @c align must be a power of two. @c size may not be zero.
766 */
767void * malloc_phys_offset ( size_t size, size_t phys_align, size_t offset ) {
768 void * ptr;
769
770 assert ( phys_align != 0 );
771 ptr = heap_alloc_block ( &heap, size, phys_align, offset );
772 if ( ptr && size ) {
773 assert ( ( ( virt_to_phys ( ptr ) ^ offset ) &
774 ( phys_align - 1 ) ) == 0 );
775 VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
776 }
777 return ptr;
778}
779
780/**
781 * Allocate memory with specified physical alignment
782 *
783 * @v size Requested size
784 * @v align Physical alignment
785 * @ret ptr Memory, or NULL
786 *
787 * @c align must be a power of two. @c size may not be zero.
788 */
789void * malloc_phys ( size_t size, size_t phys_align ) {
790
791 return malloc_phys_offset ( size, phys_align, 0 );
792}
793
794/**
795 * Free memory allocated with malloc_phys()
796 *
797 * @v ptr Memory allocated by malloc_phys(), or NULL
798 * @v size Size of memory, as passed to malloc_phys()
799 *
800 * Memory allocated with malloc_phys() can only be freed with
801 * free_phys(); it cannot be freed with the standard free().
802 *
803 * If @c ptr is NULL, no action is taken.
804 */
805void free_phys ( void *ptr, size_t size ) {
806
807 VALGRIND_FREELIKE_BLOCK ( ptr, 0 );
808 heap_free_block ( &heap, ptr, size );
809}
810
811/**
812 * Add memory to allocation pool
813 *
814 * @v heap Heap
815 * @v start Start address
816 * @v len Length of memory
817 *
818 * Adds a block of memory to the allocation pool. The memory must be
819 * aligned to the heap's required free memory block alignment.
820 */
821void heap_populate ( struct heap *heap, void *start, size_t len ) {
822
823 /* Sanity checks */
824 assert ( ( virt_to_phys ( start ) & ( heap->align - 1 ) ) == 0 );
825 assert ( ( len & ( heap->align - 1 ) ) == 0 );
826
827 /* Add to allocation pool */
829
830 /* Fix up memory usage statistics */
831 heap->usedmem += len;
832}
833
834/**
835 * Initialise the heap
836 *
837 */
838static void init_heap ( void ) {
839
840 /* Sanity check */
841 build_assert ( MIN_MEMBLOCK_ALIGN >= sizeof ( struct memory_block ) );
842
843 /* Populate heap */
846 heap_populate ( &heap, heap_area, sizeof ( heap_area ) );
847}
848
849/** Memory allocator initialisation function */
850struct init_fn heap_init_fn __init_fn ( INIT_EARLY ) = {
851 .name = "heap",
852 .initialise = init_heap,
853};
854
855/**
856 * Discard all cached data on shutdown
857 *
858 */
859static void shutdown_cache ( int booting __unused ) {
861 DBGC ( &heap, "HEAP maximum usage %zdkB\n",
862 ( heap.maxusedmem >> 10 ) );
863}
864
865/** Memory allocator shutdown function */
866struct startup_fn heap_startup_fn __startup_fn ( STARTUP_EARLY ) = {
867 .name = "heap",
868 .shutdown = shutdown_cache,
869};
870
871/**
872 * Dump free block list (for debugging)
873 *
874 */
875void heap_dump ( struct heap *heap ) {
876 struct memory_block *block;
877
878 dbg_printf ( "HEAP free block list:\n" );
880 dbg_printf ( "...[%p,%p] (size %#zx)\n", block,
881 ( ( ( void * ) block ) + block->size ),
882 block->size );
883 }
884}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
unsigned long intptr_t
Definition stdint.h:21
signed long ssize_t
Definition stdint.h:7
#define build_assert(condition)
Assert a condition at build time (after dead code elimination).
Definition assert.h:88
#define ASSERTED
Definition assert.h:26
#define ASSERTING
Definition assert.h:20
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct bofm_section_header done
Definition bofm_test.c:46
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
void dbg_printf(const char *fmt,...)
Print debug message.
Definition debug.c:39
#define INIT_EARLY
Early initialisation.
Definition init.h:30
uint32_t start
Starting offset.
Definition netvsc.h:1
uint16_t size
Buffer size.
Definition dwmac.h:3
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define STARTUP_EARLY
Early startup.
Definition init.h:64
#define __attribute__(x)
Definition compiler.h:10
iPXE I/O API
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
#define __startup_fn(startup_order)
Declare a startup/shutdown function.
Definition init.h:53
unsigned long tmp
Definition linux_pci.h:65
Linked lists.
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition list.h:31
#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
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define list_check(list)
Check a list entry or list head is valid.
Definition list.h:56
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * heap_realloc(struct heap *heap, void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:593
static char heap_area[HEAP_SIZE]
The heap area.
Definition malloc.c:139
#define HEAP_SIZE
Heap area size.
Definition malloc.c:133
static unsigned int discard_cache(size_t size __unused)
Discard some cached data.
Definition malloc.c:279
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:663
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
void * malloc_phys(size_t size, size_t phys_align)
Allocate memory with specified physical alignment.
Definition malloc.c:789
static void init_heap(void)
Initialise the heap.
Definition malloc.c:838
void heap_dump(struct heap *heap)
Dump free block list (for debugging).
Definition malloc.c:875
static void shutdown_cache(int booting __unused)
Discard all cached data on shutdown.
Definition malloc.c:859
static void valgrind_make_blocks_defined(struct heap *heap)
Mark all blocks in free list as defined.
Definition malloc.c:146
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
static void discard_all_cache(void)
Discard all cached data.
Definition malloc.c:295
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:767
#define MIN_MEMBLOCK_ALIGN
Physical address alignment maintained for free blocks of memory.
Definition malloc.c:118
#define HEAP_ALIGN
Heap area alignment.
Definition malloc.c:136
void free_phys(void *ptr, size_t size)
Free memory allocated with malloc_phys().
Definition malloc.c:805
static void check_blocks(struct heap *heap)
Check integrity of the blocks in the free list.
Definition malloc.c:237
static void valgrind_make_blocks_noaccess(struct heap *heap)
Mark all blocks in free list as inaccessible.
Definition malloc.c:188
void heap_populate(struct heap *heap, void *start, size_t len)
Add memory to allocation pool.
Definition malloc.c:821
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738
static void * heap_alloc_block(struct heap *heap, size_t size, size_t align, size_t offset)
Allocate a memory block.
Definition malloc.c:317
static void heap_free_block(struct heap *heap, void *ptr, size_t size)
Free a memory block.
Definition malloc.c:463
Dynamic memory allocation.
#define CACHE_DISCARDERS
Cache discarder table.
Definition malloc.h:103
#define NOWHERE
Address for zero-length memory blocks.
Definition malloc.h:42
#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr, _qzz_len)
Definition memcheck.h:112
#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
Definition memcheck.h:132
#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
Definition memcheck.h:122
uint8_t block[3][8]
DES-encrypted blocks.
Definition mschapv2.h:1
Reference counting.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#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:121
size_t size
Size of this block.
Definition malloc.c:123
char data[0]
Remaining data.
Definition malloc.c:125
A cache discarder.
Definition malloc.h:93
unsigned int(* discard)(void)
Discard some cached data.
Definition malloc.h:99
A heap.
Definition malloc.h:45
size_t usedmem
Total amount of used memory.
Definition malloc.h:57
size_t freemem
Total amount of free memory.
Definition malloc.h:55
size_t ptr_align
Alignment for size-tracked allocations.
Definition malloc.h:52
unsigned int(* grow)(size_t size)
Attempt to grow heap (optional).
Definition malloc.h:67
struct list_head blocks
List of free memory blocks.
Definition malloc.h:47
size_t maxusedmem
Maximum amount of used memory.
Definition malloc.h:59
size_t align
Alignment for free memory blocks.
Definition malloc.h:50
unsigned int(* shrink)(void *ptr, size_t size)
Allow heap to shrink (optional).
Definition malloc.h:79
An initialisation function.
Definition init.h:15
A doubly-linked list entry (or list head).
Definition list.h:19
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:95
size_t size
Size of this block.
Definition malloc.c:97
struct list_head list
List of free blocks.
Definition malloc.c:110
char pad[offsetof(struct refcnt, count)+sizeof(((struct refcnt *) NULL) ->count)]
Padding.
Definition malloc.c:108
A reference counter.
Definition refcnt.h:27
A startup/shutdown function.
Definition init.h:43
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
Definition valgrind.h:4412
#define RUNNING_ON_VALGRIND
Definition valgrind.h:4176
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)
Definition valgrind.h:4422