Changeset 17aca1c in mainline for uspace/lib/c/generic/malloc.c


Ignore:
Timestamp:
2011-02-04T20:56:52Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0397e5a4, e29e09cf
Parents:
e778543 (diff), 0b37882 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

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

    re778543 r17aca1c  
    4545#include <futex.h>
    4646#include <adt/gcdlcm.h>
    47 
    48 /* Magic used in heap headers. */
    49 #define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0101
    50 
    51 /* Magic used in heap footers. */
    52 #define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0202
    53 
    54 /** Allocation alignment (this also covers the alignment of fields
    55     in the heap header and footer) */
     47#include "private/malloc.h"
     48
     49/** Magic used in heap headers. */
     50#define HEAP_BLOCK_HEAD_MAGIC  UINT32_C(0xBEEF0101)
     51
     52/** Magic used in heap footers. */
     53#define HEAP_BLOCK_FOOT_MAGIC  UINT32_C(0xBEEF0202)
     54
     55/** Magic used in heap descriptor. */
     56#define HEAP_AREA_MAGIC  UINT32_C(0xBEEFCAFE)
     57
     58/** Allocation alignment.
     59 *
     60 * This also covers the alignment of fields
     61 * in the heap header and footer.
     62 *
     63 */
    5664#define BASE_ALIGN  16
    5765
    58 /**
    59  * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
    60  */
    61 #define MAX_HEAP_SIZE  (sizeof(uintptr_t) << 28)
    62 
    63 /**
    64  *
    65  */
    66 #define STRUCT_OVERHEAD  (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
    67 
    68 /**
    69  * Calculate real size of a heap block (with header and footer)
     66/** Overhead of each heap block. */
     67#define STRUCT_OVERHEAD \
     68        (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
     69
     70/** Calculate real size of a heap block.
     71 *
     72 * Add header and footer size.
     73 *
    7074 */
    7175#define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
    7276
    73 /**
    74  * Calculate net size of a heap block (without header and footer)
     77/** Calculate net size of a heap block.
     78 *
     79 * Subtract header and footer size.
     80 *
    7581 */
    7682#define NET_SIZE(size)  ((size) - STRUCT_OVERHEAD)
     83
     84/** Get first block in heap area.
     85 *
     86 */
     87#define AREA_FIRST_BLOCK(area) \
     88        (ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN))
     89
     90/** Get footer in heap block.
     91 *
     92 */
     93#define BLOCK_FOOT(head) \
     94        ((heap_block_foot_t *) \
     95            (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t)))
     96
     97/** Heap area.
     98 *
     99 * The memory managed by the heap allocator is divided into
     100 * multiple discontinuous heaps. Each heap is represented
     101 * by a separate address space area which has this structure
     102 * at its very beginning.
     103 *
     104 */
     105typedef struct heap_area {
     106        /** Start of the heap area (including this structure)
     107         *
     108         * Aligned on page boundary.
     109         *
     110         */
     111        void *start;
     112       
     113        /** End of the heap area (aligned on page boundary) */
     114        void *end;
     115       
     116        /** Next heap area */
     117        struct heap_area *next;
     118       
     119        /** A magic value */
     120        uint32_t magic;
     121} heap_area_t;
    77122
    78123/** Header of a heap block
     
    86131        bool free;
    87132       
     133        /** Heap area this block belongs to */
     134        heap_area_t *area;
     135       
    88136        /* A magic value to detect overwrite of heap header */
    89137        uint32_t magic;
     
    101149} heap_block_foot_t;
    102150
    103 /** Linker heap symbol */
    104 extern char _heap;
     151/** First heap area */
     152static heap_area_t *first_heap_area = NULL;
     153
     154/** Last heap area */
     155static heap_area_t *last_heap_area = NULL;
     156
     157/** Next heap block to examine (next fit algorithm) */
     158static heap_block_head_t *next = NULL;
    105159
    106160/** Futex for thread-safe heap manipulation */
    107161static futex_t malloc_futex = FUTEX_INITIALIZER;
    108162
    109 /** Address of heap start */
    110 static void *heap_start = 0;
    111 
    112 /** Address of heap end */
    113 static void *heap_end = 0;
    114 
    115 /** Maximum heap size */
    116 static size_t max_heap_size = (size_t) -1;
    117 
    118 /** Current number of pages of heap area */
    119 static size_t heap_pages = 0;
    120 
    121163/** Initialize a heap block
    122164 *
    123  * Fills in the structures related to a heap block.
     165 * Fill in the structures related to a heap block.
    124166 * Should be called only inside the critical section.
    125167 *
     
    127169 * @param size Size of the block including the header and the footer.
    128170 * @param free Indication of a free block.
    129  *
    130  */
    131 static void block_init(void *addr, size_t size, bool free)
     171 * @param area Heap area the block belongs to.
     172 *
     173 */
     174static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
    132175{
    133176        /* Calculate the position of the header and the footer */
    134177        heap_block_head_t *head = (heap_block_head_t *) addr;
    135         heap_block_foot_t *foot =
    136             (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
    137178       
    138179        head->size = size;
    139180        head->free = free;
     181        head->area = area;
    140182        head->magic = HEAP_BLOCK_HEAD_MAGIC;
     183       
     184        heap_block_foot_t *foot = BLOCK_FOOT(head);
    141185       
    142186        foot->size = size;
     
    159203        assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
    160204       
    161         heap_block_foot_t *foot =
    162             (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
     205        heap_block_foot_t *foot = BLOCK_FOOT(head);
    163206       
    164207        assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
     
    166209}
    167210
    168 /** Increase the heap area size
    169  *
    170  * Should be called only inside the critical section.
    171  *
    172  * @param size Number of bytes to grow the heap by.
    173  *
    174  */
    175 static bool grow_heap(size_t size)
     211/** Check a heap area structure
     212 *
     213 * @param addr Address of the heap area.
     214 *
     215 */
     216static void area_check(void *addr)
     217{
     218        heap_area_t *area = (heap_area_t *) addr;
     219       
     220        assert(area->magic == HEAP_AREA_MAGIC);
     221        assert(area->start < area->end);
     222        assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
     223        assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
     224}
     225
     226/** Create new heap area
     227 *
     228 * @param start Preffered starting address of the new area.
     229 * @param size  Size of the area.
     230 *
     231 */
     232static bool area_create(size_t size)
     233{
     234        void *start = as_get_mappable_page(size);
     235        if (start == NULL)
     236                return false;
     237       
     238        /* Align the heap area on page boundary */
     239        void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE);
     240        size_t asize = ALIGN_UP(size, PAGE_SIZE);
     241       
     242        astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
     243        if (astart == (void *) -1)
     244                return false;
     245       
     246        heap_area_t *area = (heap_area_t *) astart;
     247       
     248        area->start = astart;
     249        area->end = (void *)
     250            ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN);
     251        area->next = NULL;
     252        area->magic = HEAP_AREA_MAGIC;
     253       
     254        void *block = (void *) AREA_FIRST_BLOCK(area);
     255        size_t bsize = (size_t) (area->end - block);
     256       
     257        block_init(block, bsize, true, area);
     258       
     259        if (last_heap_area == NULL) {
     260                first_heap_area = area;
     261                last_heap_area = area;
     262        } else {
     263                last_heap_area->next = area;
     264                last_heap_area = area;
     265        }
     266       
     267        return true;
     268}
     269
     270/** Try to enlarge a heap area
     271 *
     272 * @param area Heap area to grow.
     273 * @param size Gross size of item to allocate (bytes).
     274 *
     275 */
     276static bool area_grow(heap_area_t *area, size_t size)
    176277{
    177278        if (size == 0)
     279                return true;
     280       
     281        area_check(area);
     282       
     283        size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size,
     284            PAGE_SIZE);
     285       
     286        /* New heap area size */
     287        void *end = (void *)
     288            ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN);
     289       
     290        /* Check for overflow */
     291        if (end < area->start)
    178292                return false;
    179 
    180         if ((heap_start + size < heap_start) || (heap_end + size < heap_end))
     293       
     294        /* Resize the address space area */
     295        int ret = as_area_resize(area->start, asize, 0);
     296        if (ret != EOK)
    181297                return false;
    182298       
    183         size_t heap_size = (size_t) (heap_end - heap_start);
    184        
    185         if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
    186                 return false;
    187        
    188         size_t pages = (size - 1) / PAGE_SIZE + 1;
    189        
    190         if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
    191             == EOK) {
    192                 void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
    193                     (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
    194                 block_init(heap_end, end - heap_end, true);
    195                 heap_pages += pages;
    196                 heap_end = end;
     299        /* Add new free block */
     300        block_init(area->end, (size_t) (end - area->end), true, area);
     301       
     302        /* Update heap area parameters */
     303        area->end = end;
     304       
     305        return true;
     306}
     307
     308/** Try to enlarge any of the heap areas
     309 *
     310 * @param size Gross size of item to allocate (bytes).
     311 *
     312 */
     313static bool heap_grow(size_t size)
     314{
     315        if (size == 0)
    197316                return true;
    198         }
    199        
    200         return false;
    201 }
    202 
    203 /** Decrease the heap area
    204  *
    205  * Should be called only inside the critical section.
    206  *
    207  * @param size Number of bytes to shrink the heap by.
    208  *
    209  */
    210 static void shrink_heap(void)
    211 {
    212         // TODO
     317       
     318        /* First try to enlarge some existing area */
     319        heap_area_t *area;
     320        for (area = first_heap_area; area != NULL; area = area->next) {
     321                if (area_grow(area, size))
     322                        return true;
     323        }
     324       
     325        /* Eventually try to create a new area */
     326        return area_create(AREA_FIRST_BLOCK(size));
     327}
     328
     329/** Try to shrink heap space
     330 *
     331 * In all cases the next pointer is reset.
     332 *
     333 */
     334static void heap_shrink(void)
     335{
     336        next = NULL;
    213337}
    214338
    215339/** Initialize the heap allocator
    216340 *
    217  * Find how much physical memory we have and create
    218  * the heap management structures that mark the whole
    219  * physical memory as a single free block.
    220  *
    221  */
    222 void __heap_init(void)
    223 {
    224         futex_down(&malloc_futex);
    225        
    226         if (as_area_create((void *) &_heap, PAGE_SIZE,
    227             AS_AREA_WRITE | AS_AREA_READ)) {
    228                 heap_pages = 1;
    229                 heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
    230                 heap_end =
    231                     (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
    232                
    233                 /* Make the entire area one large block. */
    234                 block_init(heap_start, heap_end - heap_start, true);
    235         }
    236        
    237         futex_up(&malloc_futex);
    238 }
    239 
    240 /** Get maximum heap address
    241  *
    242  */
    243 uintptr_t get_max_heap_addr(void)
    244 {
    245         futex_down(&malloc_futex);
    246        
    247         if (max_heap_size == (size_t) -1)
    248                 max_heap_size =
    249                     max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
    250        
    251         uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
    252        
    253         futex_up(&malloc_futex);
    254        
    255         return max_heap_addr;
     341 * Create initial heap memory area. This routine is
     342 * only called from libc initialization, thus we do not
     343 * take any locks.
     344 *
     345 */
     346void __malloc_init(void)
     347{
     348        if (!area_create(PAGE_SIZE))
     349                abort();
    256350}
    257351
     
    275369                /* Block big enough -> split. */
    276370                void *next = ((void *) cur) + size;
    277                 block_init(next, cur->size - size, true);
    278                 block_init(cur, size, false);
     371                block_init(next, cur->size - size, true, cur->area);
     372                block_init(cur, size, false, cur->area);
    279373        } else {
    280374                /* Block too small -> use as is. */
     
    283377}
    284378
    285 /** Allocate a memory block
     379/** Allocate memory from heap area starting from given block
    286380 *
    287381 * Should be called only inside the critical section.
    288  *
    289  * @param size  The size of the block to allocate.
    290  * @param align Memory address alignment.
    291  *
    292  * @return the address of the block or NULL when not enough memory.
    293  *
    294  */
    295 static void *malloc_internal(const size_t size, const size_t align)
    296 {
    297         if (align == 0)
    298                 return NULL;
    299        
    300         size_t falign = lcm(align, BASE_ALIGN);
    301         size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
    302        
    303         bool grown = false;
    304         void *result;
    305        
    306 loop:
    307         result = NULL;
    308         heap_block_head_t *cur = (heap_block_head_t *) heap_start;
    309        
    310         while ((result == NULL) && ((void *) cur < heap_end)) {
     382 * As a side effect this function also sets the current
     383 * pointer on successful allocation.
     384 *
     385 * @param area        Heap area where to allocate from.
     386 * @param first_block Starting heap block.
     387 * @param final_block Heap block where to finish the search
     388 *                    (may be NULL).
     389 * @param real_size   Gross number of bytes to allocate.
     390 * @param falign      Physical alignment of the block.
     391 *
     392 * @return Address of the allocated block or NULL on not enough memory.
     393 *
     394 */
     395static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block,
     396    heap_block_head_t *final_block, size_t real_size, size_t falign)
     397{
     398        area_check((void *) area);
     399        assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area));
     400        assert((void *) first_block < area->end);
     401       
     402        heap_block_head_t *cur;
     403        for (cur = first_block; (void *) cur < area->end;
     404            cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
    311405                block_check(cur);
     406               
     407                /* Finish searching on the final block */
     408                if ((final_block != NULL) && (cur == final_block))
     409                        break;
    312410               
    313411                /* Try to find a block that is free and large enough. */
    314412                if ((cur->free) && (cur->size >= real_size)) {
    315                         /* We have found a suitable block.
    316                            Check for alignment properties. */
    317                         void *addr = ((void *) cur) + sizeof(heap_block_head_t);
    318                         void *aligned = (void *) ALIGN_UP(addr, falign);
     413                        /*
     414                         * We have found a suitable block.
     415                         * Check for alignment properties.
     416                         */
     417                        void *addr = (void *)
     418                            ((uintptr_t) cur + sizeof(heap_block_head_t));
     419                        void *aligned = (void *)
     420                            ALIGN_UP((uintptr_t) addr, falign);
    319421                       
    320422                        if (addr == aligned) {
    321423                                /* Exact block start including alignment. */
    322424                                split_mark(cur, real_size);
    323                                 result = addr;
     425                               
     426                                next = cur;
     427                                return addr;
    324428                        } else {
    325429                                /* Block start has to be aligned */
     
    327431                               
    328432                                if (cur->size >= real_size + excess) {
    329                                         /* The current block is large enough to fit
    330                                            data in including alignment */
    331                                         if ((void *) cur > heap_start) {
    332                                                 /* There is a block before the current block.
    333                                                    This previous block can be enlarged to compensate
    334                                                    for the alignment excess */
    335                                                 heap_block_foot_t *prev_foot =
    336                                                     ((void *) cur) - sizeof(heap_block_foot_t);
     433                                        /*
     434                                         * The current block is large enough to fit
     435                                         * data in (including alignment).
     436                                         */
     437                                        if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) {
     438                                                /*
     439                                                 * There is a block before the current block.
     440                                                 * This previous block can be enlarged to
     441                                                 * compensate for the alignment excess.
     442                                                 */
     443                                                heap_block_foot_t *prev_foot = (heap_block_foot_t *)
     444                                                    ((void *) cur - sizeof(heap_block_foot_t));
    337445                                               
    338                                                 heap_block_head_t *prev_head =
    339                                                     (heap_block_head_t *) (((void *) cur) - prev_foot->size);
     446                                                heap_block_head_t *prev_head = (heap_block_head_t *)
     447                                                    ((void *) cur - prev_foot->size);
    340448                                               
    341449                                                block_check(prev_head);
     
    344452                                                heap_block_head_t *next_head = ((void *) cur) + excess;
    345453                                               
    346                                                 if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
    347                                                         /* The previous block is not free and there is enough
    348                                                            space to fill in a new free block between the previous
    349                                                            and current block */
    350                                                         block_init(cur, excess, true);
     454                                                if ((!prev_head->free) &&
     455                                                    (excess >= STRUCT_OVERHEAD)) {
     456                                                        /*
     457                                                         * The previous block is not free and there
     458                                                         * is enough free space left to fill in
     459                                                         * a new free block between the previous
     460                                                         * and current block.
     461                                                         */
     462                                                        block_init(cur, excess, true, area);
    351463                                                } else {
    352                                                         /* The previous block is free (thus there is no need to
    353                                                            induce additional fragmentation to the heap) or the
    354                                                            excess is small, thus just enlarge the previous block */
    355                                                         block_init(prev_head, prev_head->size + excess, prev_head->free);
     464                                                        /*
     465                                                         * The previous block is free (thus there
     466                                                         * is no need to induce additional
     467                                                         * fragmentation to the heap) or the
     468                                                         * excess is small. Therefore just enlarge
     469                                                         * the previous block.
     470                                                         */
     471                                                        block_init(prev_head, prev_head->size + excess,
     472                                                            prev_head->free, area);
    356473                                                }
    357474                                               
    358                                                 block_init(next_head, reduced_size, true);
     475                                                block_init(next_head, reduced_size, true, area);
    359476                                                split_mark(next_head, real_size);
    360                                                 result = aligned;
    361                                                 cur = next_head;
     477                                               
     478                                                next = next_head;
     479                                                return aligned;
    362480                                        } else {
    363                                                 /* The current block is the first block on the heap.
    364                                                    We have to make sure that the alignment excess
    365                                                    is large enough to fit a new free block just
    366                                                    before the current block */
     481                                                /*
     482                                                 * The current block is the first block
     483                                                 * in the heap area. We have to make sure
     484                                                 * that the alignment excess is large enough
     485                                                 * to fit a new free block just before the
     486                                                 * current block.
     487                                                 */
    367488                                                while (excess < STRUCT_OVERHEAD) {
    368489                                                        aligned += falign;
     
    373494                                                if (cur->size >= real_size + excess) {
    374495                                                        size_t reduced_size = cur->size - excess;
    375                                                         cur = (heap_block_head_t *) (heap_start + excess);
     496                                                        cur = (heap_block_head_t *)
     497                                                            (AREA_FIRST_BLOCK(area) + excess);
    376498                                                       
    377                                                         block_init(heap_start, excess, true);
    378                                                         block_init(cur, reduced_size, true);
     499                                                        block_init((void *) AREA_FIRST_BLOCK(area), excess,
     500                                                            true, area);
     501                                                        block_init(cur, reduced_size, true, area);
    379502                                                        split_mark(cur, real_size);
    380                                                         result = aligned;
     503                                                       
     504                                                        next = cur;
     505                                                        return aligned;
    381506                                                }
    382507                                        }
     
    384509                        }
    385510                }
    386                
    387                 /* Advance to the next block. */
    388                 cur = (heap_block_head_t *) (((void *) cur) + cur->size);
    389         }
    390        
    391         if ((result == NULL) && (!grown)) {
    392                 if (grow_heap(real_size)) {
    393                         grown = true;
     511        }
     512       
     513        return NULL;
     514}
     515
     516/** Allocate a memory block
     517 *
     518 * Should be called only inside the critical section.
     519 *
     520 * @param size  The size of the block to allocate.
     521 * @param align Memory address alignment.
     522 *
     523 * @return Address of the allocated block or NULL on not enough memory.
     524 *
     525 */
     526static void *malloc_internal(const size_t size, const size_t align)
     527{
     528        assert(first_heap_area != NULL);
     529       
     530        if (align == 0)
     531                return NULL;
     532       
     533        size_t falign = lcm(align, BASE_ALIGN);
     534        size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
     535       
     536        bool retry = false;
     537        heap_block_head_t *split;
     538       
     539loop:
     540       
     541        /* Try the next fit approach */
     542        split = next;
     543       
     544        if (split != NULL) {
     545                void *addr = malloc_area(split->area, split, NULL, real_size,
     546                    falign);
     547               
     548                if (addr != NULL)
     549                        return addr;
     550        }
     551       
     552        /* Search the entire heap */
     553        heap_area_t *area;
     554        for (area = first_heap_area; area != NULL; area = area->next) {
     555                heap_block_head_t *first = (heap_block_head_t *)
     556                    AREA_FIRST_BLOCK(area);
     557               
     558                void *addr = malloc_area(area, first, split, real_size,
     559                    falign);
     560               
     561                if (addr != NULL)
     562                        return addr;
     563        }
     564       
     565        if (!retry) {
     566                /* Try to grow the heap space */
     567                if (heap_grow(real_size)) {
     568                        retry = true;
    394569                        goto loop;
    395570                }
    396571        }
    397572       
    398         return result;
     573        return NULL;
    399574}
    400575
     
    475650            (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    476651       
    477         assert((void *) head >= heap_start);
    478         assert((void *) head < heap_end);
    479        
    480652        block_check(head);
    481653        assert(!head->free);
     654       
     655        heap_area_t *area = head->area;
     656       
     657        area_check(area);
     658        assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
     659        assert((void *) head < area->end);
    482660       
    483661        void *ptr = NULL;
     
    489667                /* Shrink */
    490668                if (orig_size - real_size >= STRUCT_OVERHEAD) {
    491                         /* Split the original block to a full block
    492                            and a trailing free block */
    493                         block_init((void *) head, real_size, false);
     669                        /*
     670                         * Split the original block to a full block
     671                         * and a trailing free block.
     672                         */
     673                        block_init((void *) head, real_size, false, area);
    494674                        block_init((void *) head + real_size,
    495                             orig_size - real_size, true);
    496                         shrink_heap();
     675                            orig_size - real_size, true, area);
     676                        heap_shrink();
    497677                }
    498678               
    499679                ptr = ((void *) head) + sizeof(heap_block_head_t);
    500680        } else {
    501                 /* Look at the next block. If it is free and the size is
    502                    sufficient then merge the two. Otherwise just allocate
    503                    a new block, copy the original data into it and
    504                    free the original block. */
     681                /*
     682                 * Look at the next block. If it is free and the size is
     683                 * sufficient then merge the two. Otherwise just allocate
     684                 * a new block, copy the original data into it and
     685                 * free the original block.
     686                 */
    505687                heap_block_head_t *next_head =
    506688                    (heap_block_head_t *) (((void *) head) + head->size);
    507689               
    508                 if (((void *) next_head < heap_end) &&
     690                if (((void *) next_head < area->end) &&
    509691                    (head->size + next_head->size >= real_size) &&
    510692                    (next_head->free)) {
    511693                        block_check(next_head);
    512                         block_init(head, head->size + next_head->size, false);
     694                        block_init(head, head->size + next_head->size, false, area);
    513695                        split_mark(head, real_size);
    514696                       
    515697                        ptr = ((void *) head) + sizeof(heap_block_head_t);
     698                        next = NULL;
    516699                } else
    517700                        reloc = true;
     
    544727            = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    545728       
    546         assert((void *) head >= heap_start);
    547         assert((void *) head < heap_end);
    548        
    549729        block_check(head);
    550730        assert(!head->free);
     731       
     732        heap_area_t *area = head->area;
     733       
     734        area_check(area);
     735        assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
     736        assert((void *) head < area->end);
    551737       
    552738        /* Mark the block itself as free. */
     
    557743            = (heap_block_head_t *) (((void *) head) + head->size);
    558744       
    559         if ((void *) next_head < heap_end) {
     745        if ((void *) next_head < area->end) {
    560746                block_check(next_head);
    561747                if (next_head->free)
    562                         block_init(head, head->size + next_head->size, true);
     748                        block_init(head, head->size + next_head->size, true, area);
    563749        }
    564750       
    565751        /* Look at the previous block. If it is free, merge the two. */
    566         if ((void *) head > heap_start) {
     752        if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
    567753                heap_block_foot_t *prev_foot =
    568754                    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
     
    574760               
    575761                if (prev_head->free)
    576                         block_init(prev_head, prev_head->size + head->size, true);
    577         }
    578        
    579         shrink_heap();
     762                        block_init(prev_head, prev_head->size + head->size, true,
     763                            area);
     764        }
     765       
     766        heap_shrink();
    580767       
    581768        futex_up(&malloc_futex);
Note: See TracChangeset for help on using the changeset viewer.