Ignore:
File:
1 edited

Legend:

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

    rfbcdeb8 r3e6a98c5  
    3535
    3636#include <malloc.h>
    37 #include <bool.h>
     37#include <stdbool.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
    111114/** Get header in heap block.
    112115 *
     
    285288        /* Align the heap area size on page boundary */
    286289        size_t asize = ALIGN_UP(size, PAGE_SIZE);
    287         void *astart = as_area_create((void *) -1, asize,
    288             AS_AREA_WRITE | AS_AREA_READ);
    289         if (astart == (void *) -1)
     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)
    290293                return false;
    291294       
     
    346349                return false;
    347350       
    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);
     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        }
    352365       
    353366        /* Update heap area parameters */
     
    355368       
    356369        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  */
    366 static 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));
    380370}
    381371
     
    661651}
    662652
     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 */
     665static 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
    663699/** Allocate a memory block
    664700 *
     
    679715       
    680716        size_t falign = lcm(align, 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        
    686 loop:
     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));
    687729       
    688730        /* Try the next fit approach */
    689         split = next_fit;
     731        heap_block_head_t *split = next_fit;
    690732       
    691733        if (split != NULL) {
    692                 void *addr = malloc_area(split->area, split, NULL, real_size,
     734                void *addr = malloc_area(split->area, split, NULL, gross_size,
    693735                    falign);
    694736               
     
    703745                    AREA_FIRST_BLOCK_HEAD(area);
    704746               
    705                 void *addr = malloc_area(area, first, split, real_size,
     747                void *addr = malloc_area(area, first, split, gross_size,
    706748                    falign);
    707749               
     
    710752        }
    711753       
    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;
     754        /* Finally, try to grow heap space and allocate in the new area. */
     755        return heap_grow_and_alloc(gross_size, falign);
    721756}
    722757
     
    731766void *calloc(const size_t nmemb, const size_t size)
    732767{
     768        // FIXME: Check for overflow
     769       
    733770        void *block = malloc(nmemb * size);
    734771        if (block == NULL)
     
    870907        if (addr == NULL)
    871908                return;
    872 
     909       
    873910        futex_down(&malloc_futex);
    874911       
Note: See TracChangeset for help on using the changeset viewer.