Ignore:
File:
1 edited

Legend:

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

    r1b20da0 ra35b458  
    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.