]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[umalloc] Fail allocations when we run out of external memory
authorMichael Brown <mcb30@ipxe.org>
Mon, 26 Mar 2012 23:18:12 +0000 (00:18 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 26 Mar 2012 23:30:54 +0000 (00:30 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/interface/pcbios/memtop_umalloc.c

index 16736e194b4d91cf5ba2cd4a886c95419b583f20..6c581feeb5fdbac39fde1b58a3f7c178aa7450a2 100644 (file)
@@ -52,6 +52,9 @@ static userptr_t top = UNULL;
 /** Bottom of heap (current lowest allocated block) */
 static userptr_t bottom = UNULL;
 
+/** Remaining space on heap */
+static size_t heap_size;
+
 /**
  * Initialise external heap
  *
@@ -59,12 +62,12 @@ static userptr_t bottom = UNULL;
  */
 static int init_eheap ( void ) {
        struct memory_map memmap;
-       unsigned long heap_size = 0;
        unsigned int i;
 
        DBG ( "Allocating external heap\n" );
 
        get_memmap ( &memmap );
+       heap_size = 0;
        for ( i = 0 ; i < memmap.count ; i++ ) {
                struct memory_region *region = &memmap.regions[i];
                unsigned long r_start, r_end;
@@ -99,8 +102,8 @@ static int init_eheap ( void ) {
                return -ENOMEM;
        }
 
-       DBG ( "External heap grows downwards from %lx\n",
-             user_to_phys ( top, 0 ) );
+       DBG ( "External heap grows downwards from %lx (size %zx)\n",
+             user_to_phys ( top, 0 ), heap_size );
        return 0;
 }
 
@@ -110,6 +113,7 @@ static int init_eheap ( void ) {
  */
 static void ecollect_free ( void ) {
        struct external_memory extmem;
+       size_t len;
 
        /* Walk the free list and collect empty blocks */
        while ( bottom != top ) {
@@ -119,8 +123,9 @@ static void ecollect_free ( void ) {
                        break;
                DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
                      user_to_phys ( bottom, extmem.size ) );
-               bottom = userptr_add ( bottom,
-                                      ( extmem.size + sizeof ( extmem ) ) );
+               len = ( extmem.size + sizeof ( extmem ) );
+               bottom = userptr_add ( bottom, len );
+               heap_size += len;
        }
 }
 
@@ -153,7 +158,12 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
                                 sizeof ( extmem ) );
        } else {
                /* Create a zero-length block */
+               if ( heap_size < sizeof ( extmem ) ) {
+                       DBG ( "EXTMEM out of space\n" );
+                       return UNULL;
+               }
                ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
+               heap_size -= sizeof ( extmem );
                DBG ( "EXTMEM allocating [%lx,%lx)\n",
                      user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
                extmem.size = 0;
@@ -163,6 +173,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
        /* Expand/shrink block if possible */
        if ( ptr == bottom ) {
                /* Update block */
+               if ( new_size > ( heap_size - extmem.size ) ) {
+                       DBG ( "EXTMEM out of space\n" );
+                       return UNULL;
+               }
                new = userptr_add ( ptr, - ( new_size - extmem.size ) );
                align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
                new_size += align;
@@ -174,8 +188,9 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
                      user_to_phys ( new, new_size ));
                memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
                                                 extmem.size : new_size ) );
-               extmem.size = new_size;
                bottom = new;
+               heap_size -= ( new_size - extmem.size );
+               extmem.size = new_size;
        } else {
                /* Cannot expand; can only pretend to shrink */
                if ( new_size > extmem.size ) {
@@ -193,7 +208,7 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
 
        /* Collect any free blocks and update hidden memory region */
        ecollect_free();
-       hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ),
+       hide_umalloc ( user_to_phys ( bottom, 0 ),
                       user_to_phys ( top, 0 ) );
 
        return ( new_size ? new : UNOWHERE );