Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 7aafdb86 in mainline


Ignore:
Timestamp:
2012-07-23T04:22:12Z (9 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
e7c3fa0
Parents:
76c07e4
git-author:
Jiri Zarevucky <zarevucky.jiri@…> (2012-07-23 04:22:12)
git-committer:
Jakub Jermar <jakub@…> (2012-07-23 04:22:12)
Message:

When growing heap to satisfy an allocation request of s bytes aligned to
an a-byte boundary, the heap needs to be grown by at least a + s bytes.

When growing heap, try the subsequent allocation on the area which has
been grown to avoid unnecessary search of a suitable area.

(Thanks to Jiri Zarevucky.)

File:
1 edited

Legend:

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

    r76c07e4 r7aafdb86  
    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 *
     
    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 = (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
     352       
     353        if (last_head->free) {
     354                /* Add the new space to the last block. */
     355                size_t net_size = (size_t) (end - area->end) + last_head->size;
     356                malloc_assert(net_size > 0);
     357                block_init(last_head, net_size, true, area);
     358        } else {
     359                /* Add new free block */
     360                size_t net_size = (size_t) (end - area->end);
     361                if (net_size > 0)
     362                        block_init(area->end, net_size, true, area);
     363        }
    352364       
    353365        /* Update heap area parameters */
     
    355367       
    356368        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));
    380369}
    381370
     
    661650}
    662651
     652/** Try to enlarge any of the heap areas.
     653 *  If successful, allocate block of the given size in the area.
     654 *
     655 * Should be called only inside the critical section.
     656 *
     657 * @param size Gross size of item to allocate (bytes).
     658 * @param align Memory address alignment.
     659 *
     660 */
     661static void *heap_grow_and_alloc(size_t size, size_t align)
     662{
     663        if (size == 0)
     664                return NULL;
     665               
     666        /* First try to enlarge some existing area */
     667        for (heap_area_t *area = first_heap_area; area != NULL;
     668            area = area->next) {
     669           
     670                if (area_grow(area, size + align)) {
     671                        heap_block_head_t *first = (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
     672                       
     673                        void *addr = malloc_area(area, first, NULL, size, align);
     674                        malloc_assert(addr != NULL);
     675                        return addr;
     676                }
     677        }
     678       
     679        /* Eventually try to create a new area */
     680        if (area_create(AREA_OVERHEAD(size + align))) {
     681                heap_block_head_t *first = (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(last_heap_area);
     682               
     683                void *addr = malloc_area(last_heap_area, first, NULL, size, align);
     684                malloc_assert(addr != NULL);
     685                return addr;
     686        }
     687       
     688        return NULL;
     689}
     690
    663691/** Allocate a memory block
    664692 *
     
    679707       
    680708        size_t falign = lcm(align, BASE_ALIGN);
    681         size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
    682        
    683         bool retry = false;
     709        size_t gross_size = GROSS_SIZE(size);
     710       
    684711        heap_block_head_t *split;
    685        
    686 loop:
    687712       
    688713        /* Try the next fit approach */
     
    690715       
    691716        if (split != NULL) {
    692                 void *addr = malloc_area(split->area, split, NULL, real_size,
     717                void *addr = malloc_area(split->area, split, NULL, gross_size,
    693718                    falign);
    694719               
     
    703728                    AREA_FIRST_BLOCK_HEAD(area);
    704729               
    705                 void *addr = malloc_area(area, first, split, real_size,
     730                void *addr = malloc_area(area, first, split, gross_size,
    706731                    falign);
    707732               
     
    710735        }
    711736       
    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;
     737        /* Finally, try to grow heap space and allocate in the new area. */
     738        return heap_grow_and_alloc(gross_size, falign);
    721739}
    722740
Note: See TracChangeset for help on using the changeset viewer.