Ignore:
File:
1 edited

Legend:

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

    ra35b458 r1b20da0  
    142142         */
    143143        void *start;
    144 
     144       
    145145        /** End of the heap area (aligned on page boundary) */
    146146        void *end;
    147 
     147       
    148148        /** Previous heap area */
    149149        struct heap_area *prev;
    150 
     150       
    151151        /** Next heap area */
    152152        struct heap_area *next;
    153 
     153       
    154154        /** A magic value */
    155155        uint32_t magic;
     
    162162        /* Size of the block (including header and footer) */
    163163        size_t size;
    164 
     164       
    165165        /* Indication of a free block */
    166166        bool free;
    167 
     167       
    168168        /** Heap area this block belongs to */
    169169        heap_area_t *area;
    170 
     170       
    171171        /* A magic value to detect overwrite of heap header */
    172172        uint32_t magic;
     
    179179        /* Size of the block (including header and footer) */
    180180        size_t size;
    181 
     181       
    182182        /* A magic value to detect overwrite of heap footer */
    183183        uint32_t magic;
     
    277277        /* Calculate the position of the header and the footer */
    278278        heap_block_head_t *head = (heap_block_head_t *) addr;
    279 
     279       
    280280        head->size = size;
    281281        head->free = free;
    282282        head->area = area;
    283283        head->magic = HEAP_BLOCK_HEAD_MAGIC;
    284 
     284       
    285285        heap_block_foot_t *foot = BLOCK_FOOT(head);
    286 
     286       
    287287        foot->size = size;
    288288        foot->magic = HEAP_BLOCK_FOOT_MAGIC;
     
    301301{
    302302        heap_block_head_t *head = (heap_block_head_t *) addr;
    303 
     303       
    304304        malloc_assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
    305 
     305       
    306306        heap_block_foot_t *foot = BLOCK_FOOT(head);
    307 
     307       
    308308        malloc_assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
    309309        malloc_assert(head->size == foot->size);
     
    320320{
    321321        heap_area_t *area = (heap_area_t *) addr;
    322 
     322       
    323323        malloc_assert(area->magic == HEAP_AREA_MAGIC);
    324324        malloc_assert(addr == area->start);
     
    343343        if (astart == AS_MAP_FAILED)
    344344                return false;
    345 
     345       
    346346        heap_area_t *area = (heap_area_t *) astart;
    347 
     347       
    348348        area->start = astart;
    349349        area->end = (void *) ((uintptr_t) astart + asize);
     
    351351        area->next = NULL;
    352352        area->magic = HEAP_AREA_MAGIC;
    353 
     353       
    354354        void *block = (void *) AREA_FIRST_BLOCK_HEAD(area);
    355355        size_t bsize = (size_t) (area->end - block);
    356 
     356       
    357357        block_init(block, bsize, true, area);
    358 
     358       
    359359        if (last_heap_area == NULL) {
    360360                first_heap_area = area;
     
    365365                last_heap_area = area;
    366366        }
    367 
     367       
    368368        return true;
    369369}
     
    383383        if (size == 0)
    384384                return true;
    385 
     385       
    386386        area_check(area);
    387 
     387       
    388388        /* New heap area size */
    389389        size_t gross_size = (size_t) (area->end - area->start) + size;
    390390        size_t asize = ALIGN_UP(gross_size, PAGE_SIZE);
    391391        void *end = (void *) ((uintptr_t) area->start + asize);
    392 
     392       
    393393        /* Check for overflow */
    394394        if (end < area->start)
    395395                return false;
    396 
     396       
    397397        /* Resize the address space area */
    398398        errno_t ret = as_area_resize(area->start, asize, 0);
    399399        if (ret != EOK)
    400400                return false;
    401 
     401       
    402402        heap_block_head_t *last_head =
    403403            (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
    404 
     404       
    405405        if (last_head->free) {
    406406                /* Add the new space to the last block. */
     
    414414                        block_init(area->end, net_size, true, area);
    415415        }
    416 
     416       
    417417        /* Update heap area parameters */
    418418        area->end = end;
    419 
     419       
    420420        return true;
    421421}
     
    432432{
    433433        area_check(area);
    434 
     434       
    435435        heap_block_foot_t *last_foot =
    436436            (heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area);
    437437        heap_block_head_t *last_head = BLOCK_HEAD(last_foot);
    438 
     438       
    439439        block_check((void *) last_head);
    440440        malloc_assert(last_head->area == area);
    441 
     441       
    442442        if (last_head->free) {
    443443                /*
     
    446446                 * shrunk.
    447447                 */
    448 
     448               
    449449                heap_block_head_t *first_head =
    450450                    (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(area);
    451 
     451               
    452452                block_check((void *) first_head);
    453453                malloc_assert(first_head->area == area);
    454 
     454               
    455455                size_t shrink_size = ALIGN_DOWN(last_head->size, PAGE_SIZE);
    456 
     456               
    457457                if (first_head == last_head) {
    458458                        /*
     
    461461                         * of it entirely.
    462462                         */
    463 
     463                       
    464464                        heap_area_t *prev = area->prev;
    465465                        heap_area_t *next = area->next;
    466 
     466                       
    467467                        if (prev != NULL) {
    468468                                area_check(prev);
     
    470470                        } else
    471471                                first_heap_area = next;
    472 
     472                       
    473473                        if (next != NULL) {
    474474                                area_check(next);
     
    476476                        } else
    477477                                last_heap_area = prev;
    478 
     478                       
    479479                        as_area_destroy(area->start);
    480480                } else if (shrink_size >= SHRINK_GRANULARITY) {
     
    484484                         * the block layout accordingly.
    485485                         */
    486 
     486                       
    487487                        size_t asize = (size_t) (area->end - area->start) - shrink_size;
    488488                        void *end = (void *) ((uintptr_t) area->start + asize);
    489 
     489                       
    490490                        /* Resize the address space area */
    491491                        errno_t ret = as_area_resize(area->start, asize, 0);
    492492                        if (ret != EOK)
    493493                                abort();
    494 
     494                       
    495495                        /* Update heap area parameters */
    496496                        area->end = end;
    497497                        size_t excess = ((size_t) area->end) - ((size_t) last_head);
    498 
     498                       
    499499                        if (excess > 0) {
    500500                                if (excess >= STRUCT_OVERHEAD) {
     
    513513                                            (((uintptr_t) last_head) - sizeof(heap_block_foot_t));
    514514                                        heap_block_head_t *prev_head = BLOCK_HEAD(prev_foot);
    515 
     515                                       
    516516                                        block_check((void *) prev_head);
    517 
     517                                       
    518518                                        block_init(prev_head, prev_head->size + excess,
    519519                                            prev_head->free, area);
     
    522522                }
    523523        }
    524 
     524       
    525525        next_fit = NULL;
    526526}
     
    551551{
    552552        malloc_assert(cur->size >= size);
    553 
     553       
    554554        /* See if we should split the block. */
    555555        size_t split_limit = GROSS_SIZE(size);
    556 
     556       
    557557        if (cur->size > split_limit) {
    558558                /* Block big enough -> split. */
     
    588588        malloc_assert((void *) first_block >= (void *) AREA_FIRST_BLOCK_HEAD(area));
    589589        malloc_assert((void *) first_block < area->end);
    590 
     590       
    591591        for (heap_block_head_t *cur = first_block; (void *) cur < area->end;
    592592            cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
    593593                block_check(cur);
    594 
     594               
    595595                /* Finish searching on the final block */
    596596                if ((final_block != NULL) && (cur == final_block))
    597597                        break;
    598 
     598               
    599599                /* Try to find a block that is free and large enough. */
    600600                if ((cur->free) && (cur->size >= real_size)) {
     
    607607                        void *aligned = (void *)
    608608                            ALIGN_UP((uintptr_t) addr, falign);
    609 
     609                       
    610610                        if (addr == aligned) {
    611611                                /* Exact block start including alignment. */
    612612                                split_mark(cur, real_size);
    613 
     613                               
    614614                                next_fit = cur;
    615615                                return addr;
     
    617617                                /* Block start has to be aligned */
    618618                                size_t excess = (size_t) (aligned - addr);
    619 
     619                               
    620620                                if (cur->size >= real_size + excess) {
    621621                                        /*
     
    631631                                                heap_block_foot_t *prev_foot = (heap_block_foot_t *)
    632632                                                    ((void *) cur - sizeof(heap_block_foot_t));
    633 
     633                                               
    634634                                                heap_block_head_t *prev_head = (heap_block_head_t *)
    635635                                                    ((void *) cur - prev_foot->size);
    636 
     636                                               
    637637                                                block_check(prev_head);
    638 
     638                                               
    639639                                                size_t reduced_size = cur->size - excess;
    640640                                                heap_block_head_t *next_head = ((void *) cur) + excess;
    641 
     641                                               
    642642                                                if ((!prev_head->free) &&
    643643                                                    (excess >= STRUCT_OVERHEAD)) {
     
    660660                                                            prev_head->free, area);
    661661                                                }
    662 
     662                                               
    663663                                                block_init(next_head, reduced_size, true, area);
    664664                                                split_mark(next_head, real_size);
    665 
     665                                               
    666666                                                next_fit = next_head;
    667667                                                return aligned;
     
    678678                                                        excess += falign;
    679679                                                }
    680 
     680                                               
    681681                                                /* Check for current block size again */
    682682                                                if (cur->size >= real_size + excess) {
     
    684684                                                        cur = (heap_block_head_t *)
    685685                                                            (AREA_FIRST_BLOCK_HEAD(area) + excess);
    686 
     686                                                       
    687687                                                        block_init((void *) AREA_FIRST_BLOCK_HEAD(area),
    688688                                                            excess, true, area);
    689689                                                        block_init(cur, reduced_size, true, area);
    690690                                                        split_mark(cur, real_size);
    691 
     691                                                       
    692692                                                        next_fit = cur;
    693693                                                        return aligned;
     
    698698                }
    699699        }
    700 
     700       
    701701        return NULL;
    702702}
     
    718718        if (size == 0)
    719719                return NULL;
    720 
     720       
    721721        /* First try to enlarge some existing area */
    722722        for (heap_area_t *area = first_heap_area; area != NULL;
    723723            area = area->next) {
    724 
     724               
    725725                if (area_grow(area, size + align)) {
    726726                        heap_block_head_t *first =
    727727                            (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
    728 
     728                       
    729729                        void *addr =
    730730                            malloc_area(area, first, NULL, size, align);
     
    733733                }
    734734        }
    735 
     735       
    736736        /* Eventually try to create a new area */
    737737        if (area_create(AREA_OVERHEAD(size + align))) {
    738738                heap_block_head_t *first =
    739739                    (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(last_heap_area);
    740 
     740               
    741741                void *addr =
    742742                    malloc_area(last_heap_area, first, NULL, size, align);
     
    744744                return addr;
    745745        }
    746 
     746       
    747747        return NULL;
    748748}
     
    761761{
    762762        malloc_assert(first_heap_area != NULL);
    763 
     763       
    764764        if (align == 0)
    765765                return NULL;
    766 
     766       
    767767        size_t falign = lcm(align, BASE_ALIGN);
    768 
     768       
    769769        /* Check for integer overflow. */
    770770        if (falign < align)
    771771                return NULL;
    772 
     772       
    773773        /*
    774774         * The size of the allocated block needs to be naturally
     
    778778         */
    779779        size_t gross_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
    780 
     780       
    781781        /* Try the next fit approach */
    782782        heap_block_head_t *split = next_fit;
    783 
     783       
    784784        if (split != NULL) {
    785785                void *addr = malloc_area(split->area, split, NULL, gross_size,
    786786                    falign);
    787 
     787               
    788788                if (addr != NULL)
    789789                        return addr;
    790790        }
    791 
     791       
    792792        /* Search the entire heap */
    793793        for (heap_area_t *area = first_heap_area; area != NULL;
     
    795795                heap_block_head_t *first = (heap_block_head_t *)
    796796                    AREA_FIRST_BLOCK_HEAD(area);
    797 
     797               
    798798                void *addr = malloc_area(area, first, split, gross_size,
    799799                    falign);
    800 
     800               
    801801                if (addr != NULL)
    802802                        return addr;
    803803        }
    804 
     804       
    805805        /* Finally, try to grow heap space and allocate in the new area. */
    806806        return heap_grow_and_alloc(gross_size, falign);
     
    818818{
    819819        // FIXME: Check for overflow
    820 
     820       
    821821        void *block = malloc(nmemb * size);
    822822        if (block == NULL)
    823823                return NULL;
    824 
     824       
    825825        memset(block, 0, nmemb * size);
    826826        return block;
     
    855855        if (align == 0)
    856856                return NULL;
    857 
     857       
    858858        size_t palign =
    859859            1 << (fnzb(max(sizeof(void *), align) - 1) + 1);
     
    883883        if (addr == NULL)
    884884                return malloc(size);
    885 
     885       
    886886        heap_lock();
    887 
     887       
    888888        /* Calculate the position of the header. */
    889889        heap_block_head_t *head =
    890890            (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    891 
     891       
    892892        block_check(head);
    893893        malloc_assert(!head->free);
    894 
     894       
    895895        heap_area_t *area = head->area;
    896 
     896       
    897897        area_check(area);
    898898        malloc_assert((void *) head >= (void *) AREA_FIRST_BLOCK_HEAD(area));
    899899        malloc_assert((void *) head < area->end);
    900 
     900       
    901901        void *ptr = NULL;
    902902        bool reloc = false;
    903903        size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
    904904        size_t orig_size = head->size;
    905 
     905       
    906906        if (orig_size > real_size) {
    907907                /* Shrink */
     
    916916                        heap_shrink(area);
    917917                }
    918 
     918               
    919919                ptr = ((void *) head) + sizeof(heap_block_head_t);
    920920        } else {
     
    948948                        }
    949949                }
    950 
     950               
    951951                /*
    952952                 * Look at the next block. If it is free and the size is
     
    962962                            area);
    963963                        split_mark(head, real_size);
    964 
     964                       
    965965                        ptr = ((void *) head) + sizeof(heap_block_head_t);
    966966                        next_fit = NULL;
     
    969969                }
    970970        }
    971 
     971       
    972972        heap_unlock();
    973 
     973       
    974974        if (reloc) {
    975975                ptr = malloc(size);
     
    979979                }
    980980        }
    981 
     981       
    982982        return ptr;
    983983}
     
    992992        if (addr == NULL)
    993993                return;
    994 
     994       
    995995        heap_lock();
    996 
     996       
    997997        /* Calculate the position of the header. */
    998998        heap_block_head_t *head
    999999            = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    1000 
     1000       
    10011001        block_check(head);
    10021002        malloc_assert(!head->free);
    1003 
     1003       
    10041004        heap_area_t *area = head->area;
    1005 
     1005       
    10061006        area_check(area);
    10071007        malloc_assert((void *) head >= (void *) AREA_FIRST_BLOCK_HEAD(area));
    10081008        malloc_assert((void *) head < area->end);
    1009 
     1009       
    10101010        /* Mark the block itself as free. */
    10111011        head->free = true;
    1012 
     1012       
    10131013        /* Look at the next block. If it is free, merge the two. */
    10141014        heap_block_head_t *next_head
    10151015            = (heap_block_head_t *) (((void *) head) + head->size);
    1016 
     1016       
    10171017        if ((void *) next_head < area->end) {
    10181018                block_check(next_head);
     
    10201020                        block_init(head, head->size + next_head->size, true, area);
    10211021        }
    1022 
     1022       
    10231023        /* Look at the previous block. If it is free, merge the two. */
    10241024        if ((void *) head > (void *) AREA_FIRST_BLOCK_HEAD(area)) {
    10251025                heap_block_foot_t *prev_foot =
    10261026                    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
    1027 
     1027               
    10281028                heap_block_head_t *prev_head =
    10291029                    (heap_block_head_t *) (((void *) head) - prev_foot->size);
    1030 
     1030               
    10311031                block_check(prev_head);
    1032 
     1032               
    10331033                if (prev_head->free)
    10341034                        block_init(prev_head, prev_head->size + head->size, true,
    10351035                            area);
    10361036        }
    1037 
     1037       
    10381038        heap_shrink(area);
    1039 
     1039       
    10401040        heap_unlock();
    10411041}
     
    10441044{
    10451045        heap_lock();
    1046 
     1046       
    10471047        if (first_heap_area == NULL) {
    10481048                heap_unlock();
    10491049                return (void *) -1;
    10501050        }
    1051 
     1051       
    10521052        /* Walk all heap areas */
    10531053        for (heap_area_t *area = first_heap_area; area != NULL;
    10541054            area = area->next) {
    1055 
     1055               
    10561056                /* Check heap area consistency */
    10571057                if ((area->magic != HEAP_AREA_MAGIC) ||
     
    10631063                        return (void *) area;
    10641064                }
    1065 
     1065               
    10661066                /* Walk all heap blocks */
    10671067                for (heap_block_head_t *head = (heap_block_head_t *)
    10681068                    AREA_FIRST_BLOCK_HEAD(area); (void *) head < area->end;
    10691069                    head = (heap_block_head_t *) (((void *) head) + head->size)) {
    1070 
     1070                       
    10711071                        /* Check heap block consistency */
    10721072                        if (head->magic != HEAP_BLOCK_HEAD_MAGIC) {
     
    10741074                                return (void *) head;
    10751075                        }
    1076 
     1076                       
    10771077                        heap_block_foot_t *foot = BLOCK_FOOT(head);
    1078 
     1078                       
    10791079                        if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) ||
    10801080                            (head->size != foot->size)) {
     
    10841084                }
    10851085        }
    1086 
     1086       
    10871087        heap_unlock();
    1088 
     1088       
    10891089        return NULL;
    10901090}
Note: See TracChangeset for help on using the changeset viewer.