Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/malloc.c

    r3e6a98c5 rfbcdeb8  
    3535
    3636#include <malloc.h>
    37 #include <stdbool.h>
     37#include <bool.h>
    3838#include <as.h>
    3939#include <align.h>
     
    109109        (((uintptr_t) (area)->end) - sizeof(heap_block_foot_t))
    110110
    111 #define AREA_LAST_BLOCK_HEAD(area) \
    112         ((uintptr_t) BLOCK_HEAD(((heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area))))
    113 
    114111/** Get header in heap block.
    115112 *
     
    288285        /* Align the heap area size on page boundary */
    289286        size_t asize = ALIGN_UP(size, PAGE_SIZE);
    290         void *astart = as_area_create(AS_AREA_ANY, asize,
    291             AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE);
    292         if (astart == AS_MAP_FAILED)
     287        void *astart = as_area_create((void *) -1, asize,
     288            AS_AREA_WRITE | AS_AREA_READ);
     289        if (astart == (void *) -1)
    293290                return false;
    294291       
     
    349346                return false;
    350347       
    351         heap_block_head_t *last_head =
    352             (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
    353        
    354         if (last_head->free) {
    355                 /* Add the new space to the last block. */
    356                 size_t net_size = (size_t) (end - area->end) + last_head->size;
    357                 malloc_assert(net_size > 0);
    358                 block_init(last_head, net_size, true, area);
    359         } else {
    360                 /* Add new free block */
    361                 size_t net_size = (size_t) (end - area->end);
    362                 if (net_size > 0)
    363                         block_init(area->end, net_size, true, area);
    364         }
     348        /* Add new free block */
     349        size_t net_size = (size_t) (end - area->end);
     350        if (net_size > 0)
     351                block_init(area->end, net_size, true, area);
    365352       
    366353        /* Update heap area parameters */
     
    368355       
    369356        return true;
     357}
     358
     359/** Try to enlarge any of the heap areas
     360 *
     361 * Should be called only inside the critical section.
     362 *
     363 * @param size Gross size of item to allocate (bytes).
     364 *
     365 */
     366static bool heap_grow(size_t size)
     367{
     368        if (size == 0)
     369                return true;
     370       
     371        /* First try to enlarge some existing area */
     372        for (heap_area_t *area = first_heap_area; area != NULL;
     373            area = area->next) {
     374                if (area_grow(area, size))
     375                        return true;
     376        }
     377       
     378        /* Eventually try to create a new area */
     379        return area_create(AREA_OVERHEAD(size));
    370380}
    371381
     
    651661}
    652662
    653 /** Try to enlarge any of the heap areas.
    654  *
    655  * If successful, allocate block of the given size in the area.
    656  * Should be called only inside the critical section.
    657  *
    658  * @param size  Gross size of item to allocate (bytes).
    659  * @param align Memory address alignment.
    660  *
    661  * @return Allocated block.
    662  * @return NULL on failure.
    663  *
    664  */
    665 static void *heap_grow_and_alloc(size_t size, size_t align)
    666 {
    667         if (size == 0)
    668                 return NULL;
    669        
    670         /* First try to enlarge some existing area */
    671         for (heap_area_t *area = first_heap_area; area != NULL;
    672             area = area->next) {
    673                
    674                 if (area_grow(area, size + align)) {
    675                         heap_block_head_t *first =
    676                             (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
    677                        
    678                         void *addr =
    679                             malloc_area(area, first, NULL, size, align);
    680                         malloc_assert(addr != NULL);
    681                         return addr;
    682                 }
    683         }
    684        
    685         /* Eventually try to create a new area */
    686         if (area_create(AREA_OVERHEAD(size + align))) {
    687                 heap_block_head_t *first =
    688                     (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(last_heap_area);
    689                
    690                 void *addr =
    691                     malloc_area(last_heap_area, first, NULL, size, align);
    692                 malloc_assert(addr != NULL);
    693                 return addr;
    694         }
    695        
    696         return NULL;
    697 }
    698 
    699663/** Allocate a memory block
    700664 *
     
    715679       
    716680        size_t falign = lcm(align, BASE_ALIGN);
    717        
    718         /* Check for integer overflow. */
    719         if (falign < align)
    720                 return NULL;
    721        
    722         /*
    723          * The size of the allocated block needs to be naturally
    724          * aligned, because the footer structure also needs to reside
    725          * on a naturally aligned address in order to avoid unaligned
    726          * memory accesses.
    727          */
    728         size_t gross_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
     681        size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
     682       
     683        bool retry = false;
     684        heap_block_head_t *split;
     685       
     686loop:
    729687       
    730688        /* Try the next fit approach */
    731         heap_block_head_t *split = next_fit;
     689        split = next_fit;
    732690       
    733691        if (split != NULL) {
    734                 void *addr = malloc_area(split->area, split, NULL, gross_size,
     692                void *addr = malloc_area(split->area, split, NULL, real_size,
    735693                    falign);
    736694               
     
    745703                    AREA_FIRST_BLOCK_HEAD(area);
    746704               
    747                 void *addr = malloc_area(area, first, split, gross_size,
     705                void *addr = malloc_area(area, first, split, real_size,
    748706                    falign);
    749707               
     
    752710        }
    753711       
    754         /* Finally, try to grow heap space and allocate in the new area. */
    755         return heap_grow_and_alloc(gross_size, falign);
     712        if (!retry) {
     713                /* Try to grow the heap space */
     714                if (heap_grow(real_size)) {
     715                        retry = true;
     716                        goto loop;
     717                }
     718        }
     719       
     720        return NULL;
    756721}
    757722
     
    766731void *calloc(const size_t nmemb, const size_t size)
    767732{
    768         // FIXME: Check for overflow
    769        
    770733        void *block = malloc(nmemb * size);
    771734        if (block == NULL)
     
    907870        if (addr == NULL)
    908871                return;
    909        
     872
    910873        futex_down(&malloc_futex);
    911874       
Note: See TracChangeset for help on using the changeset viewer.