Changes in / [0b37882:ae6f303] in mainline


Ignore:
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/mm/as.h

    r0b37882 rae6f303  
    313313extern sysarg_t sys_as_area_change_flags(uintptr_t, unsigned int);
    314314extern sysarg_t sys_as_area_destroy(uintptr_t);
    315 extern sysarg_t sys_as_get_unmapped_area(uintptr_t, size_t);
    316315
    317316/* Introspection functions. */
  • kernel/generic/include/syscall/syscall.h

    r0b37882 rae6f303  
    5959        SYS_AS_AREA_CHANGE_FLAGS,
    6060        SYS_AS_AREA_DESTROY,
    61         SYS_AS_GET_UNMAPPED_AREA,
    6261       
    6362        SYS_IPC_CALL_SYNC_FAST,
  • kernel/generic/src/mm/as.c

    r0b37882 rae6f303  
    7171#include <memstr.h>
    7272#include <macros.h>
    73 #include <bitops.h>
    7473#include <arch.h>
    7574#include <errno.h>
     
    289288/** Check area conflicts with other areas.
    290289 *
    291  * @param as    Address space.
    292  * @param addr  Starting virtual address of the area being tested.
    293  * @param count Number of pages in the area being tested.
    294  * @param avoid Do not touch this area.
     290 * @param as         Address space.
     291 * @param va         Starting virtual address of the area being tested.
     292 * @param size       Size of the area being tested.
     293 * @param avoid_area Do not touch this area.
    295294 *
    296295 * @return True if there is no conflict, false otherwise.
    297296 *
    298297 */
    299 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
    300     size_t count, as_area_t *avoid)
    301 {
    302         ASSERT((addr % PAGE_SIZE) == 0);
     298NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
     299    as_area_t *avoid_area)
     300{
    303301        ASSERT(mutex_locked(&as->lock));
    304302       
     
    306304         * We don't want any area to have conflicts with NULL page.
    307305         */
    308         if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
     306        if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
    309307                return false;
    310308       
     
    318316        btree_node_t *leaf;
    319317        as_area_t *area =
    320             (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
     318            (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    321319        if (area) {
    322                 if (area != avoid)
     320                if (area != avoid_area)
    323321                        return false;
    324322        }
     
    330328                area = (as_area_t *) node->value[node->keys - 1];
    331329               
    332                 if (area != avoid) {
    333                         mutex_lock(&area->lock);
    334                        
    335                         if (overlaps(addr, count << PAGE_WIDTH,
    336                             area->base, area->pages << PAGE_WIDTH)) {
    337                                 mutex_unlock(&area->lock);
    338                                 return false;
    339                         }
    340                        
     330                mutex_lock(&area->lock);
     331               
     332                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    341333                        mutex_unlock(&area->lock);
    342                 }
     334                        return false;
     335                }
     336               
     337                mutex_unlock(&area->lock);
    343338        }
    344339       
     
    347342                area = (as_area_t *) node->value[0];
    348343               
    349                 if (area != avoid) {
    350                         mutex_lock(&area->lock);
    351                        
    352                         if (overlaps(addr, count << PAGE_WIDTH,
    353                             area->base, area->pages << PAGE_WIDTH)) {
    354                                 mutex_unlock(&area->lock);
    355                                 return false;
    356                         }
    357                        
     344                mutex_lock(&area->lock);
     345               
     346                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    358347                        mutex_unlock(&area->lock);
    359                 }
     348                        return false;
     349                }
     350               
     351                mutex_unlock(&area->lock);
    360352        }
    361353       
     
    365357                area = (as_area_t *) leaf->value[i];
    366358               
    367                 if (area == avoid)
     359                if (area == avoid_area)
    368360                        continue;
    369361               
    370362                mutex_lock(&area->lock);
    371363               
    372                 if (overlaps(addr, count << PAGE_WIDTH,
    373                     area->base, area->pages << PAGE_WIDTH)) {
     364                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    374365                        mutex_unlock(&area->lock);
    375366                        return false;
     
    384375         */
    385376        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    386                 return !overlaps(addr, count << PAGE_WIDTH,
     377                return !overlaps(va, size,
    387378                    KERNEL_ADDRESS_SPACE_START,
    388379                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     
    411402    mem_backend_data_t *backend_data)
    412403{
    413         if ((base % PAGE_SIZE) != 0)
     404        if (base % PAGE_SIZE)
    414405                return NULL;
    415406       
    416         if (size == 0)
     407        if (!size)
    417408                return NULL;
    418        
    419         size_t pages = SIZE2FRAMES(size);
    420409       
    421410        /* Writeable executable areas are not supported. */
     
    425414        mutex_lock(&as->lock);
    426415       
    427         if (!check_area_conflicts(as, base, pages, NULL)) {
     416        if (!check_area_conflicts(as, base, size, NULL)) {
    428417                mutex_unlock(&as->lock);
    429418                return NULL;
     
    437426        area->flags = flags;
    438427        area->attributes = attrs;
    439         area->pages = pages;
     428        area->pages = SIZE2FRAMES(size);
    440429        area->resident = 0;
    441430        area->base = base;
     
    491480                mutex_lock(&area->lock);
    492481               
    493                 if ((area->base <= va) &&
    494                     (va < area->base + (area->pages << PAGE_WIDTH)))
     482                if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
    495483                        return area;
    496484               
     
    508496                mutex_lock(&area->lock);
    509497               
    510                 if (va < area->base + (area->pages << PAGE_WIDTH))
     498                if (va < area->base + area->pages * PAGE_SIZE)
    511499                        return area;
    512500               
     
    573561       
    574562        if (pages < area->pages) {
    575                 uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
     563                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    576564               
    577565                /*
     
    586574                 */
    587575                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    588                     area->base + (pages << PAGE_WIDTH), area->pages - pages);
     576                    area->base + pages * PAGE_SIZE, area->pages - pages);
    589577               
    590578                /*
     
    609597                                size_t i = 0;
    610598                               
    611                                 if (overlaps(ptr, size << PAGE_WIDTH, area->base,
    612                                     pages << PAGE_WIDTH)) {
     599                                if (overlaps(ptr, size * PAGE_SIZE, area->base,
     600                                    pages * PAGE_SIZE)) {
    613601                                       
    614                                         if (ptr + (size << PAGE_WIDTH) <= start_free) {
     602                                        if (ptr + size * PAGE_SIZE <= start_free) {
    615603                                                /*
    616604                                                 * The whole interval fits
     
    644632                                for (; i < size; i++) {
    645633                                        pte_t *pte = page_mapping_find(as, ptr +
    646                                             (i << PAGE_WIDTH));
     634                                            i * PAGE_SIZE);
    647635                                       
    648636                                        ASSERT(pte);
     
    653641                                            (area->backend->frame_free)) {
    654642                                                area->backend->frame_free(area,
    655                                                     ptr + (i << PAGE_WIDTH),
     643                                                    ptr + i * PAGE_SIZE,
    656644                                                    PTE_GET_FRAME(pte));
    657645                                        }
    658646                                       
    659647                                        page_mapping_remove(as, ptr +
    660                                             (i << PAGE_WIDTH));
     648                                            i * PAGE_SIZE);
    661649                                }
    662650                        }
     
    667655                 */
    668656               
    669                 tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
     657                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    670658                    area->pages - pages);
    671659               
     
    674662                 */
    675663                as_invalidate_translation_cache(as, area->base +
    676                     (pages << PAGE_WIDTH), area->pages - pages);
     664                    pages * PAGE_SIZE, area->pages - pages);
    677665                tlb_shootdown_finalize(ipl);
    678666               
     
    683671                 * Check for overlaps with other address space areas.
    684672                 */
    685                 if (!check_area_conflicts(as, address, pages, area)) {
     673                if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
     674                    area)) {
    686675                        mutex_unlock(&area->lock);
    687676                        mutex_unlock(&as->lock);
     
    782771                       
    783772                        for (size = 0; size < (size_t) node->value[i]; size++) {
    784                                 pte_t *pte =
    785                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     773                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
    786774                               
    787775                                ASSERT(pte);
     
    792780                                    (area->backend->frame_free)) {
    793781                                        area->backend->frame_free(area,
    794                                             ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
     782                                            ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
    795783                                }
    796784                               
    797                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     785                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    798786                        }
    799787                }
     
    882870        }
    883871       
    884         size_t src_size = src_area->pages << PAGE_WIDTH;
     872        size_t src_size = src_area->pages * PAGE_SIZE;
    885873        unsigned int src_flags = src_area->flags;
    886874        mem_backend_t *src_backend = src_area->backend;
     
    10881076                       
    10891077                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1090                                 pte_t *pte =
    1091                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     1078                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
    10921079                               
    10931080                                ASSERT(pte);
     
    10981085                               
    10991086                                /* Remove old mapping */
    1100                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     1087                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    11011088                        }
    11021089                }
     
    11441131                               
    11451132                                /* Insert the new mapping */
    1146                                 page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
     1133                                page_mapping_insert(as, ptr + size * PAGE_SIZE,
    11471134                                    old_frame[frame_idx++], page_flags);
    11481135                               
     
    14661453       
    14671454        if (src_area) {
    1468                 size = src_area->pages << PAGE_WIDTH;
     1455                size = src_area->pages * PAGE_SIZE;
    14691456                mutex_unlock(&src_area->lock);
    14701457        } else
     
    15211508                if (page >= right_pg) {
    15221509                        /* Do nothing. */
    1523                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1524                     left_cnt << PAGE_WIDTH)) {
     1510                } else if (overlaps(page, count * PAGE_SIZE, left_pg,
     1511                    left_cnt * PAGE_SIZE)) {
    15251512                        /* The interval intersects with the left interval. */
    15261513                        return false;
    1527                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1528                     right_cnt << PAGE_WIDTH)) {
     1514                } else if (overlaps(page, count * PAGE_SIZE, right_pg,
     1515                    right_cnt * PAGE_SIZE)) {
    15291516                        /* The interval intersects with the right interval. */
    15301517                        return false;
    1531                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1532                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1518                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
     1519                    (page + count * PAGE_SIZE == right_pg)) {
    15331520                        /*
    15341521                         * The interval can be added by merging the two already
     
    15381525                        btree_remove(&area->used_space, right_pg, leaf);
    15391526                        goto success;
    1540                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1527                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    15411528                        /*
    15421529                         * The interval can be added by simply growing the left
     
    15451532                        node->value[node->keys - 1] += count;
    15461533                        goto success;
    1547                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1534                } else if (page + count * PAGE_SIZE == right_pg) {
    15481535                        /*
    15491536                         * The interval can be addded by simply moving base of
     
    15721559                 */
    15731560               
    1574                 if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1575                     right_cnt << PAGE_WIDTH)) {
     1561                if (overlaps(page, count * PAGE_SIZE, right_pg,
     1562                    right_cnt * PAGE_SIZE)) {
    15761563                        /* The interval intersects with the right interval. */
    15771564                        return false;
    1578                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1565                } else if (page + count * PAGE_SIZE == right_pg) {
    15791566                        /*
    15801567                         * The interval can be added by moving the base of the
     
    16111598                if (page < left_pg) {
    16121599                        /* Do nothing. */
    1613                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1614                     left_cnt << PAGE_WIDTH)) {
     1600                } else if (overlaps(page, count * PAGE_SIZE, left_pg,
     1601                    left_cnt * PAGE_SIZE)) {
    16151602                        /* The interval intersects with the left interval. */
    16161603                        return false;
    1617                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1618                     right_cnt << PAGE_WIDTH)) {
     1604                } else if (overlaps(page, count * PAGE_SIZE, right_pg,
     1605                    right_cnt * PAGE_SIZE)) {
    16191606                        /* The interval intersects with the right interval. */
    16201607                        return false;
    1621                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1622                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1608                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
     1609                    (page + count * PAGE_SIZE == right_pg)) {
    16231610                        /*
    16241611                         * The interval can be added by merging the two already
     
    16281615                        btree_remove(&area->used_space, right_pg, node);
    16291616                        goto success;
    1630                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1617                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16311618                        /*
    16321619                         * The interval can be added by simply growing the left
     
    16351622                        leaf->value[leaf->keys - 1] += count;
    16361623                        goto success;
    1637                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1624                } else if (page + count * PAGE_SIZE == right_pg) {
    16381625                        /*
    16391626                         * The interval can be addded by simply moving base of
     
    16621649                 */
    16631650               
    1664                 if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1665                     left_cnt << PAGE_WIDTH)) {
     1651                if (overlaps(page, count * PAGE_SIZE, left_pg,
     1652                    left_cnt * PAGE_SIZE)) {
    16661653                        /* The interval intersects with the left interval. */
    16671654                        return false;
    1668                 } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
     1655                } else if (left_pg + left_cnt * PAGE_SIZE == page) {
    16691656                        /*
    16701657                         * The interval can be added by growing the left
     
    17011688                         */
    17021689                       
    1703                         if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1704                             left_cnt << PAGE_WIDTH)) {
     1690                        if (overlaps(page, count * PAGE_SIZE, left_pg,
     1691                            left_cnt * PAGE_SIZE)) {
    17051692                                /*
    17061693                                 * The interval intersects with the left
     
    17081695                                 */
    17091696                                return false;
    1710                         } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1711                             right_cnt << PAGE_WIDTH)) {
     1697                        } else if (overlaps(page, count * PAGE_SIZE, right_pg,
     1698                            right_cnt * PAGE_SIZE)) {
    17121699                                /*
    17131700                                 * The interval intersects with the right
     
    17151702                                 */
    17161703                                return false;
    1717                         } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1718                             (page + (count << PAGE_WIDTH) == right_pg)) {
     1704                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
     1705                            (page + count * PAGE_SIZE == right_pg)) {
    17191706                                /*
    17201707                                 * The interval can be added by merging the two
     
    17241711                                btree_remove(&area->used_space, right_pg, leaf);
    17251712                                goto success;
    1726                         } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1713                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    17271714                                /*
    17281715                                 * The interval can be added by simply growing
     
    17311718                                leaf->value[i - 1] += count;
    17321719                                goto success;
    1733                         } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1720                        } else if (page + count * PAGE_SIZE == right_pg) {
    17341721                                /*
    17351722                                 * The interval can be addded by simply moving
     
    17971784                        for (i = 0; i < leaf->keys; i++) {
    17981785                                if (leaf->key[i] == page) {
    1799                                         leaf->key[i] += count << PAGE_WIDTH;
     1786                                        leaf->key[i] += count * PAGE_SIZE;
    18001787                                        leaf->value[i] -= count;
    18011788                                        goto success;
     
    18121799                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18131800               
    1814                 if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1815                     count << PAGE_WIDTH)) {
    1816                         if (page + (count << PAGE_WIDTH) ==
    1817                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1801                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
     1802                    count * PAGE_SIZE)) {
     1803                        if (page + count * PAGE_SIZE ==
     1804                            left_pg + left_cnt * PAGE_SIZE) {
    18181805                                /*
    18191806                                 * The interval is contained in the rightmost
     
    18241811                                node->value[node->keys - 1] -= count;
    18251812                                goto success;
    1826                         } else if (page + (count << PAGE_WIDTH) <
    1827                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1813                        } else if (page + count * PAGE_SIZE <
     1814                            left_pg + left_cnt*PAGE_SIZE) {
    18281815                                /*
    18291816                                 * The interval is contained in the rightmost
     
    18331820                                 * new interval.
    18341821                                 */
    1835                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1836                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1822                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1823                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    18371824                                node->value[node->keys - 1] -= count + new_cnt;
    18381825                                btree_insert(&area->used_space, page +
    1839                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1826                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    18401827                                goto success;
    18411828                        }
     
    18501837                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    18511838               
    1852                 if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1853                     count << PAGE_WIDTH)) {
    1854                         if (page + (count << PAGE_WIDTH) ==
    1855                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1839                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
     1840                    count * PAGE_SIZE)) {
     1841                        if (page + count * PAGE_SIZE ==
     1842                            left_pg + left_cnt * PAGE_SIZE) {
    18561843                                /*
    18571844                                 * The interval is contained in the rightmost
     
    18611848                                leaf->value[leaf->keys - 1] -= count;
    18621849                                goto success;
    1863                         } else if (page + (count << PAGE_WIDTH) < left_pg +
    1864                             (left_cnt << PAGE_WIDTH)) {
     1850                        } else if (page + count * PAGE_SIZE < left_pg +
     1851                            left_cnt * PAGE_SIZE) {
    18651852                                /*
    18661853                                 * The interval is contained in the rightmost
     
    18701857                                 * interval.
    18711858                                 */
    1872                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1873                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1859                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1860                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    18741861                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    18751862                                btree_insert(&area->used_space, page +
    1876                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1863                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    18771864                                goto success;
    18781865                        }
     
    18961883                         * to (i - 1) and i.
    18971884                         */
    1898                         if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
    1899                             count << PAGE_WIDTH)) {
    1900                                 if (page + (count << PAGE_WIDTH) ==
    1901                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1885                        if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
     1886                            count * PAGE_SIZE)) {
     1887                                if (page + count * PAGE_SIZE ==
     1888                                    left_pg + left_cnt*PAGE_SIZE) {
    19021889                                        /*
    19031890                                         * The interval is contained in the
     
    19081895                                        leaf->value[i - 1] -= count;
    19091896                                        goto success;
    1910                                 } else if (page + (count << PAGE_WIDTH) <
    1911                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1897                                } else if (page + count * PAGE_SIZE <
     1898                                    left_pg + left_cnt * PAGE_SIZE) {
    19121899                                        /*
    19131900                                         * The interval is contained in the
     
    19181905                                         */
    19191906                                        size_t new_cnt = ((left_pg +
    1920                                             (left_cnt << PAGE_WIDTH)) -
    1921                                             (page + (count << PAGE_WIDTH))) >>
     1907                                            left_cnt * PAGE_SIZE) -
     1908                                            (page + count * PAGE_SIZE)) >>
    19221909                                            PAGE_WIDTH;
    19231910                                        leaf->value[i - 1] -= count + new_cnt;
    19241911                                        btree_insert(&area->used_space, page +
    1925                                             (count << PAGE_WIDTH), (void *) new_cnt,
     1912                                            count * PAGE_SIZE, (void *) new_cnt,
    19261913                                            leaf);
    19271914                                        goto success;
     
    19721959{
    19731960        return (sysarg_t) as_area_destroy(AS, address);
    1974 }
    1975 
    1976 /** Return pointer to unmapped address space area
    1977  *
    1978  * @param base Lowest address bound.
    1979  * @param size Requested size of the allocation.
    1980  *
    1981  * @return Pointer to the beginning of unmapped address space area.
    1982  *
    1983  */
    1984 sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
    1985 {
    1986         if (size == 0)
    1987                 return 0;
    1988        
    1989         /*
    1990          * Make sure we allocate from page-aligned
    1991          * address. Check for possible overflow in
    1992          * each step.
    1993          */
    1994        
    1995         size_t pages = SIZE2FRAMES(size);
    1996         uintptr_t ret = 0;
    1997        
    1998         /*
    1999          * Find the lowest unmapped address aligned on the sz
    2000          * boundary, not smaller than base and of the required size.
    2001          */
    2002        
    2003         mutex_lock(&AS->lock);
    2004        
    2005         /* First check the base address itself */
    2006         uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
    2007         if ((addr >= base) &&
    2008             (check_area_conflicts(AS, addr, pages, NULL)))
    2009                 ret = addr;
    2010        
    2011         /* Eventually check the addresses behind each area */
    2012         link_t *cur;
    2013         for (cur = AS->as_area_btree.leaf_head.next;
    2014             (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
    2015             cur = cur->next) {
    2016                 btree_node_t *node =
    2017                     list_get_instance(cur, btree_node_t, leaf_link);
    2018                
    2019                 btree_key_t i;
    2020                 for (i = 0; (ret == 0) && (i < node->keys); i++) {
    2021                         as_area_t *area = (as_area_t *) node->value[i];
    2022                        
    2023                         mutex_lock(&area->lock);
    2024                        
    2025                         uintptr_t addr =
    2026                             ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
    2027                             PAGE_SIZE);
    2028                        
    2029                         if ((addr >= base) && (addr >= area->base) &&
    2030                             (check_area_conflicts(AS, addr, pages, area)))
    2031                                 ret = addr;
    2032                        
    2033                         mutex_unlock(&area->lock);
    2034                 }
    2035         }
    2036        
    2037         mutex_unlock(&AS->lock);
    2038        
    2039         return (sysarg_t) ret;
    20401961}
    20411962
     
    21062027        mutex_lock(&as->lock);
    21072028       
    2108         /* Print out info about address space areas */
     2029        /* print out info about address space areas */
    21092030        link_t *cur;
    21102031        for (cur = as->as_area_btree.leaf_head.next;
  • kernel/generic/src/syscall/syscall.c

    r0b37882 rae6f303  
    143143        (syshandler_t) sys_as_area_change_flags,
    144144        (syshandler_t) sys_as_area_destroy,
    145         (syshandler_t) sys_as_get_unmapped_area,
    146145       
    147146        /* IPC related syscalls. */
  • uspace/lib/c/generic/as.c

    r0b37882 rae6f303  
    4040#include <bitops.h>
    4141#include <malloc.h>
    42 #include "private/libc.h"
     42
     43/** Last position allocated by as_get_mappable_page */
     44static uintptr_t last_allocated = 0;
    4345
    4446/** Create address space area.
     
    101103}
    102104
    103 /** Return pointer to unmapped address space area
     105/** Return pointer to some unmapped area, where fits new as_area
    104106 *
    105107 * @param size Requested size of the allocation.
    106108 *
    107  * @return Pointer to the beginning of unmapped address space area.
     109 * @return pointer to the beginning
    108110 *
    109111 */
    110112void *as_get_mappable_page(size_t size)
    111113{
    112         return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
    113             (sysarg_t) __entry, (sysarg_t) size);
     114        if (size == 0)
     115                return NULL;
     116       
     117        size_t sz = 1 << (fnzb(size - 1) + 1);
     118        if (last_allocated == 0)
     119                last_allocated = get_max_heap_addr();
     120       
     121        /*
     122         * Make sure we allocate from naturally aligned address.
     123         */
     124        uintptr_t res = ALIGN_UP(last_allocated, sz);
     125        last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
     126       
     127        return ((void *) res);
    114128}
    115129
  • uspace/lib/c/generic/malloc.c

    r0b37882 rae6f303  
    4747#include "private/malloc.h"
    4848
    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  */
     49/* Magic used in heap headers. */
     50#define HEAP_BLOCK_HEAD_MAGIC  0xBEEF0101
     51
     52/* Magic used in heap footers. */
     53#define HEAP_BLOCK_FOOT_MAGIC  0xBEEF0202
     54
     55/** Allocation alignment (this also covers the alignment of fields
     56    in the heap header and footer) */
    6457#define BASE_ALIGN  16
    6558
    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  *
     59/**
     60 * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures
     61 */
     62#define MAX_HEAP_SIZE  (sizeof(uintptr_t) << 28)
     63
     64/**
     65 *
     66 */
     67#define STRUCT_OVERHEAD  (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
     68
     69/**
     70 * Calculate real size of a heap block (with header and footer)
    7471 */
    7572#define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
    7673
    77 /** Calculate net size of a heap block.
    78  *
    79  * Subtract header and footer size.
    80  *
     74/**
     75 * Calculate net size of a heap block (without header and footer)
    8176 */
    8277#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  */
    105 typedef 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;
    12278
    12379/** Header of a heap block
     
    13187        bool free;
    13288       
    133         /** Heap area this block belongs to */
    134         heap_area_t *area;
    135        
    13689        /* A magic value to detect overwrite of heap header */
    13790        uint32_t magic;
     
    149102} heap_block_foot_t;
    150103
    151 /** First heap area */
    152 static heap_area_t *first_heap_area = NULL;
    153 
    154 /** Last heap area */
    155 static heap_area_t *last_heap_area = NULL;
    156 
    157 /** Next heap block to examine (next fit algorithm) */
    158 static heap_block_head_t *next = NULL;
     104/** Linker heap symbol */
     105extern char _heap;
    159106
    160107/** Futex for thread-safe heap manipulation */
    161108static futex_t malloc_futex = FUTEX_INITIALIZER;
    162109
     110/** Address of heap start */
     111static void *heap_start = 0;
     112
     113/** Address of heap end */
     114static void *heap_end = 0;
     115
     116/** Maximum heap size */
     117static size_t max_heap_size = (size_t) -1;
     118
     119/** Current number of pages of heap area */
     120static size_t heap_pages = 0;
     121
    163122/** Initialize a heap block
    164123 *
    165  * Fill in the structures related to a heap block.
     124 * Fills in the structures related to a heap block.
    166125 * Should be called only inside the critical section.
    167126 *
     
    169128 * @param size Size of the block including the header and the footer.
    170129 * @param free Indication of a free block.
    171  * @param area Heap area the block belongs to.
    172  *
    173  */
    174 static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
     130 *
     131 */
     132static void block_init(void *addr, size_t size, bool free)
    175133{
    176134        /* Calculate the position of the header and the footer */
    177135        heap_block_head_t *head = (heap_block_head_t *) addr;
     136        heap_block_foot_t *foot =
     137            (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));
    178138       
    179139        head->size = size;
    180140        head->free = free;
    181         head->area = area;
    182141        head->magic = HEAP_BLOCK_HEAD_MAGIC;
    183        
    184         heap_block_foot_t *foot = BLOCK_FOOT(head);
    185142       
    186143        foot->size = size;
     
    203160        assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
    204161       
    205         heap_block_foot_t *foot = BLOCK_FOOT(head);
     162        heap_block_foot_t *foot =
     163            (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t));
    206164       
    207165        assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
     
    209167}
    210168
    211 /** Check a heap area structure
    212  *
    213  * @param addr Address of the heap area.
    214  *
    215  */
    216 static 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  */
    232 static bool area_create(size_t size)
    233 {
    234         void *start = as_get_mappable_page(size);
    235         if (start == NULL)
     169/** Increase the heap area size
     170 *
     171 * Should be called only inside the critical section.
     172 *
     173 * @param size Number of bytes to grow the heap by.
     174 *
     175 */
     176static bool grow_heap(size_t size)
     177{
     178        if (size == 0)
    236179                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)
     180
     181        if ((heap_start + size < heap_start) || (heap_end + size < heap_end))
    244182                return false;
    245183       
    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  */
    276 static bool area_grow(heap_area_t *area, size_t size)
    277 {
    278         if (size == 0)
     184        size_t heap_size = (size_t) (heap_end - heap_start);
     185       
     186        if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size))
     187                return false;
     188       
     189        size_t pages = (size - 1) / PAGE_SIZE + 1;
     190       
     191        if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0)
     192            == EOK) {
     193                void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) +
     194                    (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN);
     195                block_init(heap_end, end - heap_end, true);
     196                heap_pages += pages;
     197                heap_end = end;
    279198                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)
    292                 return false;
    293        
    294         /* Resize the address space area */
    295         int ret = as_area_resize(area->start, asize, 0);
    296         if (ret != EOK)
    297                 return false;
    298        
    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  */
    313 static bool heap_grow(size_t size)
    314 {
    315         if (size == 0)
    316                 return true;
    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  */
    334 static void heap_shrink(void)
    335 {
    336         next = NULL;
     199        }
     200       
     201        return false;
     202}
     203
     204/** Decrease the heap area
     205 *
     206 * Should be called only inside the critical section.
     207 *
     208 * @param size Number of bytes to shrink the heap by.
     209 *
     210 */
     211static void shrink_heap(void)
     212{
     213        // TODO
    337214}
    338215
     
    346223void __malloc_init(void)
    347224{
    348         if (!area_create(PAGE_SIZE))
     225        if (!as_area_create((void *) &_heap, PAGE_SIZE,
     226            AS_AREA_WRITE | AS_AREA_READ))
    349227                abort();
     228       
     229        heap_pages = 1;
     230        heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);
     231        heap_end =
     232            (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);
     233       
     234        /* Make the entire area one large block. */
     235        block_init(heap_start, heap_end - heap_start, true);
     236}
     237
     238/** Get maximum heap address
     239 *
     240 */
     241uintptr_t get_max_heap_addr(void)
     242{
     243        futex_down(&malloc_futex);
     244       
     245        if (max_heap_size == (size_t) -1)
     246                max_heap_size =
     247                    max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);
     248       
     249        uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;
     250       
     251        futex_up(&malloc_futex);
     252       
     253        return max_heap_addr;
    350254}
    351255
     
    369273                /* Block big enough -> split. */
    370274                void *next = ((void *) cur) + size;
    371                 block_init(next, cur->size - size, true, cur->area);
    372                 block_init(cur, size, false, cur->area);
     275                block_init(next, cur->size - size, true);
     276                block_init(cur, size, false);
    373277        } else {
    374278                /* Block too small -> use as is. */
     
    377281}
    378282
    379 /** Allocate memory from heap area starting from given block
     283/** Allocate a memory block
    380284 *
    381285 * Should be called only inside the critical section.
    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  */
    395 static 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)) {
     286 *
     287 * @param size  The size of the block to allocate.
     288 * @param align Memory address alignment.
     289 *
     290 * @return the address of the block or NULL when not enough memory.
     291 *
     292 */
     293static void *malloc_internal(const size_t size, const size_t align)
     294{
     295        if (align == 0)
     296                return NULL;
     297       
     298        size_t falign = lcm(align, BASE_ALIGN);
     299        size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
     300       
     301        bool grown = false;
     302        void *result;
     303       
     304loop:
     305        result = NULL;
     306        heap_block_head_t *cur = (heap_block_head_t *) heap_start;
     307       
     308        while ((result == NULL) && ((void *) cur < heap_end)) {
    405309                block_check(cur);
    406                
    407                 /* Finish searching on the final block */
    408                 if ((final_block != NULL) && (cur == final_block))
    409                         break;
    410310               
    411311                /* Try to find a block that is free and large enough. */
    412312                if ((cur->free) && (cur->size >= real_size)) {
    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);
     313                        /* We have found a suitable block.
     314                           Check for alignment properties. */
     315                        void *addr = ((void *) cur) + sizeof(heap_block_head_t);
     316                        void *aligned = (void *) ALIGN_UP(addr, falign);
    421317                       
    422318                        if (addr == aligned) {
    423319                                /* Exact block start including alignment. */
    424320                                split_mark(cur, real_size);
    425                                
    426                                 next = cur;
    427                                 return addr;
     321                                result = addr;
    428322                        } else {
    429323                                /* Block start has to be aligned */
     
    431325                               
    432326                                if (cur->size >= real_size + excess) {
    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));
     327                                        /* The current block is large enough to fit
     328                                           data in including alignment */
     329                                        if ((void *) cur > heap_start) {
     330                                                /* There is a block before the current block.
     331                                                   This previous block can be enlarged to compensate
     332                                                   for the alignment excess */
     333                                                heap_block_foot_t *prev_foot =
     334                                                    ((void *) cur) - sizeof(heap_block_foot_t);
    445335                                               
    446                                                 heap_block_head_t *prev_head = (heap_block_head_t *)
    447                                                     ((void *) cur - prev_foot->size);
     336                                                heap_block_head_t *prev_head =
     337                                                    (heap_block_head_t *) (((void *) cur) - prev_foot->size);
    448338                                               
    449339                                                block_check(prev_head);
     
    452342                                                heap_block_head_t *next_head = ((void *) cur) + excess;
    453343                                               
    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);
     344                                                if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) {
     345                                                        /* The previous block is not free and there is enough
     346                                                           space to fill in a new free block between the previous
     347                                                           and current block */
     348                                                        block_init(cur, excess, true);
    463349                                                } else {
    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);
     350                                                        /* The previous block is free (thus there is no need to
     351                                                           induce additional fragmentation to the heap) or the
     352                                                           excess is small, thus just enlarge the previous block */
     353                                                        block_init(prev_head, prev_head->size + excess, prev_head->free);
    473354                                                }
    474355                                               
    475                                                 block_init(next_head, reduced_size, true, area);
     356                                                block_init(next_head, reduced_size, true);
    476357                                                split_mark(next_head, real_size);
    477                                                
    478                                                 next = next_head;
    479                                                 return aligned;
     358                                                result = aligned;
     359                                                cur = next_head;
    480360                                        } else {
    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                                                  */
     361                                                /* The current block is the first block on the heap.
     362                                                   We have to make sure that the alignment excess
     363                                                   is large enough to fit a new free block just
     364                                                   before the current block */
    488365                                                while (excess < STRUCT_OVERHEAD) {
    489366                                                        aligned += falign;
     
    494371                                                if (cur->size >= real_size + excess) {
    495372                                                        size_t reduced_size = cur->size - excess;
    496                                                         cur = (heap_block_head_t *)
    497                                                             (AREA_FIRST_BLOCK(area) + excess);
     373                                                        cur = (heap_block_head_t *) (heap_start + excess);
    498374                                                       
    499                                                         block_init((void *) AREA_FIRST_BLOCK(area), excess,
    500                                                             true, area);
    501                                                         block_init(cur, reduced_size, true, area);
     375                                                        block_init(heap_start, excess, true);
     376                                                        block_init(cur, reduced_size, true);
    502377                                                        split_mark(cur, real_size);
    503                                                        
    504                                                         next = cur;
    505                                                         return aligned;
     378                                                        result = aligned;
    506379                                                }
    507380                                        }
     
    509382                        }
    510383                }
    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  */
    526 static 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        
    539 loop:
    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;
     384               
     385                /* Advance to the next block. */
     386                cur = (heap_block_head_t *) (((void *) cur) + cur->size);
     387        }
     388       
     389        if ((result == NULL) && (!grown)) {
     390                if (grow_heap(real_size)) {
     391                        grown = true;
    569392                        goto loop;
    570393                }
    571394        }
    572395       
    573         return NULL;
     396        return result;
    574397}
    575398
     
    650473            (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    651474       
     475        assert((void *) head >= heap_start);
     476        assert((void *) head < heap_end);
     477       
    652478        block_check(head);
    653479        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);
    660480       
    661481        void *ptr = NULL;
     
    667487                /* Shrink */
    668488                if (orig_size - real_size >= STRUCT_OVERHEAD) {
    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);
     489                        /* Split the original block to a full block
     490                           and a trailing free block */
     491                        block_init((void *) head, real_size, false);
    674492                        block_init((void *) head + real_size,
    675                             orig_size - real_size, true, area);
    676                         heap_shrink();
     493                            orig_size - real_size, true);
     494                        shrink_heap();
    677495                }
    678496               
    679497                ptr = ((void *) head) + sizeof(heap_block_head_t);
    680498        } else {
    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                  */
     499                /* Look at the next block. If it is free and the size is
     500                   sufficient then merge the two. Otherwise just allocate
     501                   a new block, copy the original data into it and
     502                   free the original block. */
    687503                heap_block_head_t *next_head =
    688504                    (heap_block_head_t *) (((void *) head) + head->size);
    689505               
    690                 if (((void *) next_head < area->end) &&
     506                if (((void *) next_head < heap_end) &&
    691507                    (head->size + next_head->size >= real_size) &&
    692508                    (next_head->free)) {
    693509                        block_check(next_head);
    694                         block_init(head, head->size + next_head->size, false, area);
     510                        block_init(head, head->size + next_head->size, false);
    695511                        split_mark(head, real_size);
    696512                       
    697513                        ptr = ((void *) head) + sizeof(heap_block_head_t);
    698                         next = NULL;
    699514                } else
    700515                        reloc = true;
     
    727542            = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    728543       
     544        assert((void *) head >= heap_start);
     545        assert((void *) head < heap_end);
     546       
    729547        block_check(head);
    730548        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);
    737549       
    738550        /* Mark the block itself as free. */
     
    743555            = (heap_block_head_t *) (((void *) head) + head->size);
    744556       
    745         if ((void *) next_head < area->end) {
     557        if ((void *) next_head < heap_end) {
    746558                block_check(next_head);
    747559                if (next_head->free)
    748                         block_init(head, head->size + next_head->size, true, area);
     560                        block_init(head, head->size + next_head->size, true);
    749561        }
    750562       
    751563        /* Look at the previous block. If it is free, merge the two. */
    752         if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
     564        if ((void *) head > heap_start) {
    753565                heap_block_foot_t *prev_foot =
    754566                    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
     
    760572               
    761573                if (prev_head->free)
    762                         block_init(prev_head, prev_head->size + head->size, true,
    763                             area);
    764         }
    765        
    766         heap_shrink();
     574                        block_init(prev_head, prev_head->size + head->size, true);
     575        }
     576       
     577        shrink_heap();
    767578       
    768579        futex_up(&malloc_futex);
  • uspace/lib/c/generic/private/libc.h

    r0b37882 rae6f303  
    3636#define LIBC_PRIVATE_LIBC_H_
    3737
    38 extern void __entry(void);
     38extern int main(int, char *[]);
    3939extern void __main(void *) __attribute__((noreturn));
    40 extern int main(int, char *[]);
    4140
    4241#endif
  • uspace/lib/c/include/malloc.h

    r0b37882 rae6f303  
    3838#include <sys/types.h>
    3939
     40extern uintptr_t get_max_heap_addr(void);
     41
    4042extern void *malloc(const size_t size)
    4143    __attribute__((malloc));
Note: See TracChangeset for help on using the changeset viewer.