Changeset 0b37882 in mainline for kernel


Ignore:
Timestamp:
2011-02-03T21:14:23Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
17aca1c, 6a343bdf, cf2af94
Parents:
d88218b (diff), ae6f303 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

memory management work

  • implement as_get_mappable_page() as a new syscall (SYS_AS_GET_UNMAPPED_AREA), the kernel has a full knowledge of the address space areas, there is no need to duplicate this management in uspace)
  • make sure all address space/address space area manipulating functions use proper page alignment on base addresses and sizes (discrepancy with respect to this caused inconsistent behaviour, although no fatal bugs were probably present)
  • add forgotten tests (area != avoid) to check_area_conflicts()
  • unify size/page conversions (use always use bitwise shifts by PAGE_WIDTH)
  • new uspace heap allocator
    • basic next fit algorithm for better scalability (there is still space for optimizations)
    • support for multiple discontinuous heap areas (inspired by Jiri Tlach's implementation in lp:~jiri-tlach/helenos/nommu, but independent)
    • the "_heap" linker script symbol has been removed, the initial heap area is allocated according to as_get_mappable_page() (which uses the address of entry as the lower bound of the address space area base)
    • the hardwired 1 GB (4 GB respectivelly) heap size limit has been removed
    • the heap areas can be freely intermixed with other address space areas (e.g. mapped physical memory of devices, shared memory, etc.), the address space holes can be reused later (but still merging of adjunct address space areas is missing)
  • minor cstyle changes
Location:
kernel/generic
Files:
4 edited

Legend:

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

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

    rd88218b r0b37882  
    5959        SYS_AS_AREA_CHANGE_FLAGS,
    6060        SYS_AS_AREA_DESTROY,
     61        SYS_AS_GET_UNMAPPED_AREA,
    6162       
    6263        SYS_IPC_CALL_SYNC_FAST,
  • kernel/generic/src/mm/as.c

    rd88218b r0b37882  
    7171#include <memstr.h>
    7272#include <macros.h>
     73#include <bitops.h>
    7374#include <arch.h>
    7475#include <errno.h>
     
    288289/** Check area conflicts with other areas.
    289290 *
    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.
     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.
    294295 *
    295296 * @return True if there is no conflict, false otherwise.
    296297 *
    297298 */
    298 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
    299     as_area_t *avoid_area)
    300 {
     299NO_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);
    301303        ASSERT(mutex_locked(&as->lock));
    302304       
     
    304306         * We don't want any area to have conflicts with NULL page.
    305307         */
    306         if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
     308        if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
    307309                return false;
    308310       
     
    316318        btree_node_t *leaf;
    317319        as_area_t *area =
    318             (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     320            (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
    319321        if (area) {
    320                 if (area != avoid_area)
     322                if (area != avoid)
    321323                        return false;
    322324        }
     
    328330                area = (as_area_t *) node->value[node->keys - 1];
    329331               
    330                 mutex_lock(&area->lock);
    331                
    332                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     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                       
    333341                        mutex_unlock(&area->lock);
    334                         return false;
    335                 }
    336                
    337                 mutex_unlock(&area->lock);
     342                }
    338343        }
    339344       
     
    342347                area = (as_area_t *) node->value[0];
    343348               
    344                 mutex_lock(&area->lock);
    345                
    346                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     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                       
    347358                        mutex_unlock(&area->lock);
    348                         return false;
    349                 }
    350                
    351                 mutex_unlock(&area->lock);
     359                }
    352360        }
    353361       
     
    357365                area = (as_area_t *) leaf->value[i];
    358366               
    359                 if (area == avoid_area)
     367                if (area == avoid)
    360368                        continue;
    361369               
    362370                mutex_lock(&area->lock);
    363371               
    364                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     372                if (overlaps(addr, count << PAGE_WIDTH,
     373                    area->base, area->pages << PAGE_WIDTH)) {
    365374                        mutex_unlock(&area->lock);
    366375                        return false;
     
    375384         */
    376385        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    377                 return !overlaps(va, size,
     386                return !overlaps(addr, count << PAGE_WIDTH,
    378387                    KERNEL_ADDRESS_SPACE_START,
    379388                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     
    402411    mem_backend_data_t *backend_data)
    403412{
    404         if (base % PAGE_SIZE)
     413        if ((base % PAGE_SIZE) != 0)
    405414                return NULL;
    406415       
    407         if (!size)
     416        if (size == 0)
    408417                return NULL;
     418       
     419        size_t pages = SIZE2FRAMES(size);
    409420       
    410421        /* Writeable executable areas are not supported. */
     
    414425        mutex_lock(&as->lock);
    415426       
    416         if (!check_area_conflicts(as, base, size, NULL)) {
     427        if (!check_area_conflicts(as, base, pages, NULL)) {
    417428                mutex_unlock(&as->lock);
    418429                return NULL;
     
    426437        area->flags = flags;
    427438        area->attributes = attrs;
    428         area->pages = SIZE2FRAMES(size);
     439        area->pages = pages;
    429440        area->resident = 0;
    430441        area->base = base;
     
    480491                mutex_lock(&area->lock);
    481492               
    482                 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
     493                if ((area->base <= va) &&
     494                    (va < area->base + (area->pages << PAGE_WIDTH)))
    483495                        return area;
    484496               
     
    496508                mutex_lock(&area->lock);
    497509               
    498                 if (va < area->base + area->pages * PAGE_SIZE)
     510                if (va < area->base + (area->pages << PAGE_WIDTH))
    499511                        return area;
    500512               
     
    561573       
    562574        if (pages < area->pages) {
    563                 uintptr_t start_free = area->base + pages * PAGE_SIZE;
     575                uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
    564576               
    565577                /*
     
    574586                 */
    575587                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    576                     area->base + pages * PAGE_SIZE, area->pages - pages);
     588                    area->base + (pages << PAGE_WIDTH), area->pages - pages);
    577589               
    578590                /*
     
    597609                                size_t i = 0;
    598610                               
    599                                 if (overlaps(ptr, size * PAGE_SIZE, area->base,
    600                                     pages * PAGE_SIZE)) {
     611                                if (overlaps(ptr, size << PAGE_WIDTH, area->base,
     612                                    pages << PAGE_WIDTH)) {
    601613                                       
    602                                         if (ptr + size * PAGE_SIZE <= start_free) {
     614                                        if (ptr + (size << PAGE_WIDTH) <= start_free) {
    603615                                                /*
    604616                                                 * The whole interval fits
     
    632644                                for (; i < size; i++) {
    633645                                        pte_t *pte = page_mapping_find(as, ptr +
    634                                             i * PAGE_SIZE);
     646                                            (i << PAGE_WIDTH));
    635647                                       
    636648                                        ASSERT(pte);
     
    641653                                            (area->backend->frame_free)) {
    642654                                                area->backend->frame_free(area,
    643                                                     ptr + i * PAGE_SIZE,
     655                                                    ptr + (i << PAGE_WIDTH),
    644656                                                    PTE_GET_FRAME(pte));
    645657                                        }
    646658                                       
    647659                                        page_mapping_remove(as, ptr +
    648                                             i * PAGE_SIZE);
     660                                            (i << PAGE_WIDTH));
    649661                                }
    650662                        }
     
    655667                 */
    656668               
    657                 tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
     669                tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
    658670                    area->pages - pages);
    659671               
     
    662674                 */
    663675                as_invalidate_translation_cache(as, area->base +
    664                     pages * PAGE_SIZE, area->pages - pages);
     676                    (pages << PAGE_WIDTH), area->pages - pages);
    665677                tlb_shootdown_finalize(ipl);
    666678               
     
    671683                 * Check for overlaps with other address space areas.
    672684                 */
    673                 if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    674                     area)) {
     685                if (!check_area_conflicts(as, address, pages, area)) {
    675686                        mutex_unlock(&area->lock);
    676687                        mutex_unlock(&as->lock);
     
    771782                       
    772783                        for (size = 0; size < (size_t) node->value[i]; size++) {
    773                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     784                                pte_t *pte =
     785                                    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
    774786                               
    775787                                ASSERT(pte);
     
    780792                                    (area->backend->frame_free)) {
    781793                                        area->backend->frame_free(area,
    782                                             ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
     794                                            ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
    783795                                }
    784796                               
    785                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     797                                page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
    786798                        }
    787799                }
     
    870882        }
    871883       
    872         size_t src_size = src_area->pages * PAGE_SIZE;
     884        size_t src_size = src_area->pages << PAGE_WIDTH;
    873885        unsigned int src_flags = src_area->flags;
    874886        mem_backend_t *src_backend = src_area->backend;
     
    10761088                       
    10771089                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1078                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     1090                                pte_t *pte =
     1091                                    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
    10791092                               
    10801093                                ASSERT(pte);
     
    10851098                               
    10861099                                /* Remove old mapping */
    1087                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     1100                                page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
    10881101                        }
    10891102                }
     
    11311144                               
    11321145                                /* Insert the new mapping */
    1133                                 page_mapping_insert(as, ptr + size * PAGE_SIZE,
     1146                                page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
    11341147                                    old_frame[frame_idx++], page_flags);
    11351148                               
     
    14531466       
    14541467        if (src_area) {
    1455                 size = src_area->pages * PAGE_SIZE;
     1468                size = src_area->pages << PAGE_WIDTH;
    14561469                mutex_unlock(&src_area->lock);
    14571470        } else
     
    15081521                if (page >= right_pg) {
    15091522                        /* Do nothing. */
    1510                 } else if (overlaps(page, count * PAGE_SIZE, left_pg,
    1511                     left_cnt * PAGE_SIZE)) {
     1523                } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1524                    left_cnt << PAGE_WIDTH)) {
    15121525                        /* The interval intersects with the left interval. */
    15131526                        return false;
    1514                 } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1515                     right_cnt * PAGE_SIZE)) {
     1527                } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1528                    right_cnt << PAGE_WIDTH)) {
    15161529                        /* The interval intersects with the right interval. */
    15171530                        return false;
    1518                 } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1519                     (page + count * PAGE_SIZE == right_pg)) {
     1531                } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1532                    (page + (count << PAGE_WIDTH) == right_pg)) {
    15201533                        /*
    15211534                         * The interval can be added by merging the two already
     
    15251538                        btree_remove(&area->used_space, right_pg, leaf);
    15261539                        goto success;
    1527                 } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1540                } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    15281541                        /*
    15291542                         * The interval can be added by simply growing the left
     
    15321545                        node->value[node->keys - 1] += count;
    15331546                        goto success;
    1534                 } else if (page + count * PAGE_SIZE == right_pg) {
     1547                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    15351548                        /*
    15361549                         * The interval can be addded by simply moving base of
     
    15591572                 */
    15601573               
    1561                 if (overlaps(page, count * PAGE_SIZE, right_pg,
    1562                     right_cnt * PAGE_SIZE)) {
     1574                if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1575                    right_cnt << PAGE_WIDTH)) {
    15631576                        /* The interval intersects with the right interval. */
    15641577                        return false;
    1565                 } else if (page + count * PAGE_SIZE == right_pg) {
     1578                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    15661579                        /*
    15671580                         * The interval can be added by moving the base of the
     
    15981611                if (page < left_pg) {
    15991612                        /* Do nothing. */
    1600                 } else if (overlaps(page, count * PAGE_SIZE, left_pg,
    1601                     left_cnt * PAGE_SIZE)) {
     1613                } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1614                    left_cnt << PAGE_WIDTH)) {
    16021615                        /* The interval intersects with the left interval. */
    16031616                        return false;
    1604                 } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1605                     right_cnt * PAGE_SIZE)) {
     1617                } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1618                    right_cnt << PAGE_WIDTH)) {
    16061619                        /* The interval intersects with the right interval. */
    16071620                        return false;
    1608                 } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1609                     (page + count * PAGE_SIZE == right_pg)) {
     1621                } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1622                    (page + (count << PAGE_WIDTH) == right_pg)) {
    16101623                        /*
    16111624                         * The interval can be added by merging the two already
     
    16151628                        btree_remove(&area->used_space, right_pg, node);
    16161629                        goto success;
    1617                 } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1630                } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    16181631                        /*
    16191632                         * The interval can be added by simply growing the left
     
    16221635                        leaf->value[leaf->keys - 1] += count;
    16231636                        goto success;
    1624                 } else if (page + count * PAGE_SIZE == right_pg) {
     1637                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    16251638                        /*
    16261639                         * The interval can be addded by simply moving base of
     
    16491662                 */
    16501663               
    1651                 if (overlaps(page, count * PAGE_SIZE, left_pg,
    1652                     left_cnt * PAGE_SIZE)) {
     1664                if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1665                    left_cnt << PAGE_WIDTH)) {
    16531666                        /* The interval intersects with the left interval. */
    16541667                        return false;
    1655                 } else if (left_pg + left_cnt * PAGE_SIZE == page) {
     1668                } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
    16561669                        /*
    16571670                         * The interval can be added by growing the left
     
    16881701                         */
    16891702                       
    1690                         if (overlaps(page, count * PAGE_SIZE, left_pg,
    1691                             left_cnt * PAGE_SIZE)) {
     1703                        if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1704                            left_cnt << PAGE_WIDTH)) {
    16921705                                /*
    16931706                                 * The interval intersects with the left
     
    16951708                                 */
    16961709                                return false;
    1697                         } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1698                             right_cnt * PAGE_SIZE)) {
     1710                        } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1711                            right_cnt << PAGE_WIDTH)) {
    16991712                                /*
    17001713                                 * The interval intersects with the right
     
    17021715                                 */
    17031716                                return false;
    1704                         } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1705                             (page + count * PAGE_SIZE == right_pg)) {
     1717                        } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1718                            (page + (count << PAGE_WIDTH) == right_pg)) {
    17061719                                /*
    17071720                                 * The interval can be added by merging the two
     
    17111724                                btree_remove(&area->used_space, right_pg, leaf);
    17121725                                goto success;
    1713                         } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1726                        } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    17141727                                /*
    17151728                                 * The interval can be added by simply growing
     
    17181731                                leaf->value[i - 1] += count;
    17191732                                goto success;
    1720                         } else if (page + count * PAGE_SIZE == right_pg) {
     1733                        } else if (page + (count << PAGE_WIDTH) == right_pg) {
    17211734                                /*
    17221735                                 * The interval can be addded by simply moving
     
    17841797                        for (i = 0; i < leaf->keys; i++) {
    17851798                                if (leaf->key[i] == page) {
    1786                                         leaf->key[i] += count * PAGE_SIZE;
     1799                                        leaf->key[i] += count << PAGE_WIDTH;
    17871800                                        leaf->value[i] -= count;
    17881801                                        goto success;
     
    17991812                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18001813               
    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) {
     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)) {
    18051818                                /*
    18061819                                 * The interval is contained in the rightmost
     
    18111824                                node->value[node->keys - 1] -= count;
    18121825                                goto success;
    1813                         } else if (page + count * PAGE_SIZE <
    1814                             left_pg + left_cnt*PAGE_SIZE) {
     1826                        } else if (page + (count << PAGE_WIDTH) <
     1827                            left_pg + (left_cnt << PAGE_WIDTH)) {
    18151828                                /*
    18161829                                 * The interval is contained in the rightmost
     
    18201833                                 * new interval.
    18211834                                 */
    1822                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    1823                                     (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
     1835                                size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
     1836                                    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
    18241837                                node->value[node->keys - 1] -= count + new_cnt;
    18251838                                btree_insert(&area->used_space, page +
    1826                                     count * PAGE_SIZE, (void *) new_cnt, leaf);
     1839                                    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
    18271840                                goto success;
    18281841                        }
     
    18371850                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    18381851               
    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) {
     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)) {
    18431856                                /*
    18441857                                 * The interval is contained in the rightmost
     
    18481861                                leaf->value[leaf->keys - 1] -= count;
    18491862                                goto success;
    1850                         } else if (page + count * PAGE_SIZE < left_pg +
    1851                             left_cnt * PAGE_SIZE) {
     1863                        } else if (page + (count << PAGE_WIDTH) < left_pg +
     1864                            (left_cnt << PAGE_WIDTH)) {
    18521865                                /*
    18531866                                 * The interval is contained in the rightmost
     
    18571870                                 * interval.
    18581871                                 */
    1859                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    1860                                     (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
     1872                                size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
     1873                                    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
    18611874                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    18621875                                btree_insert(&area->used_space, page +
    1863                                     count * PAGE_SIZE, (void *) new_cnt, leaf);
     1876                                    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
    18641877                                goto success;
    18651878                        }
     
    18831896                         * to (i - 1) and i.
    18841897                         */
    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) {
     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)) {
    18891902                                        /*
    18901903                                         * The interval is contained in the
     
    18951908                                        leaf->value[i - 1] -= count;
    18961909                                        goto success;
    1897                                 } else if (page + count * PAGE_SIZE <
    1898                                     left_pg + left_cnt * PAGE_SIZE) {
     1910                                } else if (page + (count << PAGE_WIDTH) <
     1911                                    left_pg + (left_cnt << PAGE_WIDTH)) {
    18991912                                        /*
    19001913                                         * The interval is contained in the
     
    19051918                                         */
    19061919                                        size_t new_cnt = ((left_pg +
    1907                                             left_cnt * PAGE_SIZE) -
    1908                                             (page + count * PAGE_SIZE)) >>
     1920                                            (left_cnt << PAGE_WIDTH)) -
     1921                                            (page + (count << PAGE_WIDTH))) >>
    19091922                                            PAGE_WIDTH;
    19101923                                        leaf->value[i - 1] -= count + new_cnt;
    19111924                                        btree_insert(&area->used_space, page +
    1912                                             count * PAGE_SIZE, (void *) new_cnt,
     1925                                            (count << PAGE_WIDTH), (void *) new_cnt,
    19131926                                            leaf);
    19141927                                        goto success;
     
    19611974}
    19621975
     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 */
     1984sysarg_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;
     2040}
     2041
    19632042/** Get list of adress space areas.
    19642043 *
     
    20272106        mutex_lock(&as->lock);
    20282107       
    2029         /* print out info about address space areas */
     2108        /* Print out info about address space areas */
    20302109        link_t *cur;
    20312110        for (cur = as->as_area_btree.leaf_head.next;
  • kernel/generic/src/syscall/syscall.c

    rd88218b r0b37882  
    143143        (syshandler_t) sys_as_area_change_flags,
    144144        (syshandler_t) sys_as_area_destroy,
     145        (syshandler_t) sys_as_get_unmapped_area,
    145146       
    146147        /* IPC related syscalls. */
Note: See TracChangeset for help on using the changeset viewer.