]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[malloc] Allow allocation of memory with a specified alignment offset
authorMichael Brown <mcb30@ipxe.org>
Wed, 29 Aug 2012 14:35:46 +0000 (15:35 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 31 Aug 2012 20:22:45 +0000 (21:22 +0100)
Allow for allocation of memory blocks having a specified offset from a
specified physical alignment, such as being 12 bytes before a 2kB
boundary.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/malloc.c
src/include/ipxe/malloc.h

index 9d81ca5c0e28dd760f5f9c55e8acb064bedf99a9..56ca7edc625aedde6a4e44537b20a75c8cf835a4 100644 (file)
@@ -220,6 +220,7 @@ static void discard_all_cache ( void ) {
  *
  * @v size             Requested size
  * @v align            Physical alignment
+ * @v offset           Offset from physical alignment
  * @ret ptr            Memory block, or NULL
  *
  * Allocates a memory block @b physically aligned as requested.  No
@@ -227,7 +228,7 @@ static void discard_all_cache ( void ) {
  *
  * @c align must be a power of two.  @c size may not be zero.
  */
-void * alloc_memblock ( size_t size, size_t align ) {
+void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
        struct memory_block *block;
        size_t align_mask;
        size_t pre_size;
@@ -244,12 +245,13 @@ void * alloc_memblock ( size_t size, size_t align ) {
        size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
        align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
 
-       DBG ( "Allocating %#zx (aligned %#zx)\n", size, align );
+       DBG ( "Allocating %#zx (aligned %#zx+%zx)\n", size, align, offset );
        while ( 1 ) {
                /* Search through blocks for the first one with enough space */
                list_for_each_entry ( block, &free_blocks, list ) {
-                       pre_size = ( - virt_to_phys ( block ) ) & align_mask;
-                       post_size = block->size - pre_size - size;
+                       pre_size = ( ( offset - virt_to_phys ( block ) )
+                                    & align_mask );
+                       post_size = ( block->size - pre_size - size );
                        if ( post_size >= 0 ) {
                                /* Split block into pre-block, block, and
                                 * post-block.  After this split, the "pre"
@@ -418,7 +420,7 @@ void * realloc ( void *old_ptr, size_t new_size ) {
        if ( new_size ) {
                new_total_size = ( new_size +
                                   offsetof ( struct autosized_block, data ) );
-               new_block = alloc_memblock ( new_total_size, 1 );
+               new_block = alloc_memblock ( new_total_size, 1, 0 );
                if ( ! new_block )
                        return NULL;
                VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) );
index d41b056284cf8a6102c3cd986c92cbc29a7ed9e0..bbd6cb89850532f08f641e25cba59feedc49fccc 100644 (file)
@@ -23,7 +23,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 extern size_t freemem;
 
-extern void * __malloc alloc_memblock ( size_t size, size_t align );
+extern void * __malloc alloc_memblock ( size_t size, size_t align,
+                                       size_t offset );
 extern void free_memblock ( void *ptr, size_t size );
 extern void mpopulate ( void *start, size_t len );
 extern void mdumpfree ( void );
@@ -33,19 +34,37 @@ extern void mdumpfree ( void );
  *
  * @v size             Requested size
  * @v align            Physical alignment
+ * @v offset           Offset from physical alignment
  * @ret ptr            Memory, or NULL
  *
  * Allocates physically-aligned memory for DMA.
  *
  * @c align must be a power of two.  @c size may not be zero.
  */
-static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
-       void * ptr = alloc_memblock ( size, phys_align );
+static inline void * __malloc malloc_dma_offset ( size_t size,
+                                                 size_t phys_align,
+                                                 size_t offset ) {
+       void * ptr = alloc_memblock ( size, phys_align, offset );
        if ( ptr && size )
                VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
        return ptr;
 }
 
+/**
+ * Allocate memory for DMA
+ *
+ * @v size             Requested size
+ * @v align            Physical alignment
+ * @ret ptr            Memory, or NULL
+ *
+ * Allocates physically-aligned memory for DMA.
+ *
+ * @c align must be a power of two.  @c size may not be zero.
+ */
+static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
+       return malloc_dma_offset ( size, phys_align, 0 );
+}
+
 /**
  * Free memory allocated with malloc_dma()
  *