Changeset da1bafb in mainline for kernel/generic/src/mm


Ignore:
Timestamp:
2010-05-24T18:57:31Z (16 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0095368
Parents:
666f492
Message:

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
Location:
kernel/generic/src/mm
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/as.c

    r666f492 rda1bafb  
    3333/**
    3434 * @file
    35  * @brief       Address space related functions.
     35 * @brief Address space related functions.
    3636 *
    3737 * This file contains address space manipulation functions.
     
    8686 * Each architecture decides what functions will be used to carry out
    8787 * address space operations such as creating or locking page tables.
     88 *
    8889 */
    8990as_operations_t *as_operations = NULL;
     
    9192/**
    9293 * Slab for as_t objects.
     94 *
    9395 */
    9496static slab_cache_t *as_slab;
     
    100102 * - as->asid for each as of the as_t type
    101103 * - asids_allocated counter
     104 *
    102105 */
    103106SPINLOCK_INITIALIZE(asidlock);
     
    106109 * This list contains address spaces that are not active on any
    107110 * processor and that have valid ASID.
     111 *
    108112 */
    109113LIST_INITIALIZE(inactive_as_with_asid_head);
     
    112116as_t *AS_KERNEL = NULL;
    113117
    114 static int area_flags_to_page_flags(int);
     118static unsigned int area_flags_to_page_flags(unsigned int);
    115119static as_area_t *find_area_and_lock(as_t *, uintptr_t);
    116120static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *);
    117121static void sh_info_remove_reference(share_info_t *);
    118122
    119 static int as_constructor(void *obj, int flags)
     123static int as_constructor(void *obj, unsigned int flags)
    120124{
    121125        as_t *as = (as_t *) obj;
    122         int rc;
    123 
     126       
    124127        link_initialize(&as->inactive_as_with_asid_link);
    125128        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    126129       
    127         rc = as_constructor_arch(as, flags);
     130        int rc = as_constructor_arch(as, flags);
    128131       
    129132        return rc;
    130133}
    131134
    132 static int as_destructor(void *obj)
     135static size_t as_destructor(void *obj)
    133136{
    134137        as_t *as = (as_t *) obj;
    135 
    136138        return as_destructor_arch(as);
    137139}
     
    141143{
    142144        as_arch_init();
    143 
     145       
    144146        as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
    145147            as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
     
    157159/** Create address space.
    158160 *
    159  * @param flags         Flags that influence the way in wich the address space
    160  *                      is created.
    161  */
    162 as_t *as_create(int flags)
    163 {
    164         as_t *as;
    165 
    166         as = (as_t *) slab_alloc(as_slab, 0);
     161 * @param flags Flags that influence the way in wich the address
     162 *              space is created.
     163 *
     164 */
     165as_t *as_create(unsigned int flags)
     166{
     167        as_t *as = (as_t *) slab_alloc(as_slab, 0);
    167168        (void) as_create_arch(as, 0);
    168169       
     
    176177        atomic_set(&as->refcount, 0);
    177178        as->cpu_refcount = 0;
     179       
    178180#ifdef AS_PAGE_TABLE
    179181        as->genarch.page_table = page_table_create(flags);
     
    192194 * We know that we don't hold any spinlock.
    193195 *
    194  * @param as            Address space to be destroyed.
     196 * @param as Address space to be destroyed.
     197 *
    195198 */
    196199void as_destroy(as_t *as)
    197200{
    198         ipl_t ipl;
    199         bool cond;
    200201        DEADLOCK_PROBE_INIT(p_asidlock);
    201202
     
    214215         * disabled to prevent nested context switches. We also depend on the
    215216         * fact that so far no spinlocks are held.
     217         *
    216218         */
    217219        preemption_disable();
    218         ipl = interrupts_read();
     220        ipl_t ipl = interrupts_read();
     221       
    219222retry:
    220223        interrupts_disable();
     
    224227                goto retry;
    225228        }
    226         preemption_enable();    /* Interrupts disabled, enable preemption */
    227         if (as->asid != ASID_INVALID && as != AS_KERNEL) {
     229       
     230        /* Interrupts disabled, enable preemption */
     231        preemption_enable();
     232       
     233        if ((as->asid != ASID_INVALID) && (as != AS_KERNEL)) {
    228234                if (as->cpu_refcount == 0)
    229235                        list_remove(&as->inactive_as_with_asid_link);
     236               
    230237                asid_put(as->asid);
    231238        }
     239       
    232240        spinlock_unlock(&asidlock);
    233 
     241       
    234242        /*
    235243         * Destroy address space areas of the address space.
    236244         * The B+tree must be walked carefully because it is
    237245         * also being destroyed.
    238          */     
    239         for (cond = true; cond; ) {
    240                 btree_node_t *node;
    241 
     246         *
     247         */
     248        bool cond = true;
     249        while (cond) {
    242250                ASSERT(!list_empty(&as->as_area_btree.leaf_head));
    243                 node = list_get_instance(as->as_area_btree.leaf_head.next,
     251               
     252                btree_node_t *node =
     253                    list_get_instance(as->as_area_btree.leaf_head.next,
    244254                    btree_node_t, leaf_link);
    245 
    246                 if ((cond = node->keys)) {
     255               
     256                if ((cond = node->keys))
    247257                        as_area_destroy(as, node->key[0]);
    248                 }
    249         }
    250 
     258        }
     259       
    251260        btree_destroy(&as->as_area_btree);
     261       
    252262#ifdef AS_PAGE_TABLE
    253263        page_table_destroy(as->genarch.page_table);
     
    255265        page_table_destroy(NULL);
    256266#endif
    257 
     267       
    258268        interrupts_restore(ipl);
    259 
     269       
    260270        slab_free(as_slab, as);
    261271}
     
    266276 * space.
    267277 *
    268  * @param a             Address space to be held.
     278 * @param as Address space to be held.
     279 *
    269280 */
    270281void as_hold(as_t *as)
     
    278289 * space.
    279290 *
    280  * @param a             Address space to be released.
     291 * @param asAddress space to be released.
     292 *
    281293 */
    282294void as_release(as_t *as)
     
    290302 * The created address space area is added to the target address space.
    291303 *
    292  * @param as            Target address space.
    293  * @param flags         Flags of the area memory.
    294  * @param size          Size of area.
    295  * @param base          Base address of area.
    296  * @param attrs         Attributes of the area.
    297  * @param backend       Address space area backend. NULL if no backend is used.
    298  * @param backend_data  NULL or a pointer to an array holding two void *.
    299  *
    300  * @return              Address space area on success or NULL on failure.
    301  */
    302 as_area_t *
    303 as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs,
    304     mem_backend_t *backend, mem_backend_data_t *backend_data)
    305 {
    306         ipl_t ipl;
    307         as_area_t *a;
    308        
     304 * @param as           Target address space.
     305 * @param flags        Flags of the area memory.
     306 * @param size         Size of area.
     307 * @param base         Base address of area.
     308 * @param attrs        Attributes of the area.
     309 * @param backend      Address space area backend. NULL if no backend is used.
     310 * @param backend_data NULL or a pointer to an array holding two void *.
     311 *
     312 * @return Address space area on success or NULL on failure.
     313 *
     314 */
     315as_area_t *as_area_create(as_t *as, unsigned int flags, size_t size,
     316    uintptr_t base, unsigned int attrs, mem_backend_t *backend,
     317    mem_backend_data_t *backend_data)
     318{
    309319        if (base % PAGE_SIZE)
    310320                return NULL;
    311 
     321       
    312322        if (!size)
    313323                return NULL;
    314 
     324       
    315325        /* Writeable executable areas are not supported. */
    316326        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    317327                return NULL;
    318328       
    319         ipl = interrupts_disable();
     329        ipl_t ipl = interrupts_disable();
    320330        mutex_lock(&as->lock);
    321331       
     
    326336        }
    327337       
    328         a = (as_area_t *) malloc(sizeof(as_area_t), 0);
    329 
    330         mutex_initialize(&a->lock, MUTEX_PASSIVE);
    331        
    332         a->as = as;
    333         a->flags = flags;
    334         a->attributes = attrs;
    335         a->pages = SIZE2FRAMES(size);
    336         a->base = base;
    337         a->sh_info = NULL;
    338         a->backend = backend;
     338        as_area_t *area = (as_area_t *) malloc(sizeof(as_area_t), 0);
     339       
     340        mutex_initialize(&area->lock, MUTEX_PASSIVE);
     341       
     342        area->as = as;
     343        area->flags = flags;
     344        area->attributes = attrs;
     345        area->pages = SIZE2FRAMES(size);
     346        area->base = base;
     347        area->sh_info = NULL;
     348        area->backend = backend;
     349       
    339350        if (backend_data)
    340                 a->backend_data = *backend_data;
     351                area->backend_data = *backend_data;
    341352        else
    342                 memsetb(&a->backend_data, sizeof(a->backend_data), 0);
    343 
    344         btree_create(&a->used_space);
    345        
    346         btree_insert(&as->as_area_btree, base, (void *) a, NULL);
    347 
     353                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
     354       
     355        btree_create(&area->used_space);
     356        btree_insert(&as->as_area_btree, base, (void *) area, NULL);
     357       
    348358        mutex_unlock(&as->lock);
    349359        interrupts_restore(ipl);
    350 
    351         return a;
     360       
     361        return area;
    352362}
    353363
    354364/** Find address space area and change it.
    355365 *
    356  * @param as            Address space.
    357  * @param address       Virtual address belonging to the area to be changed.
    358  *                      Must be page-aligned.
    359  * @param size          New size of the virtual memory block starting at
    360  *                      address.
    361  * @param flags         Flags influencing the remap operation. Currently unused.
    362  *
    363  * @return              Zero on success or a value from @ref errno.h otherwise.
    364  */
    365 int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags)
    366 {
    367         as_area_t *area;
    368         ipl_t ipl;
    369         size_t pages;
    370        
    371         ipl = interrupts_disable();
     366 * @param as      Address space.
     367 * @param address Virtual address belonging to the area to be changed.
     368 *                Must be page-aligned.
     369 * @param size    New size of the virtual memory block starting at
     370 *                address.
     371 * @param flags   Flags influencing the remap operation. Currently unused.
     372 *
     373 * @return Zero on success or a value from @ref errno.h otherwise.
     374 *
     375 */
     376int as_area_resize(as_t *as, uintptr_t address, size_t size, unsigned int flags)
     377{
     378        ipl_t ipl = interrupts_disable();
    372379        mutex_lock(&as->lock);
    373380       
    374381        /*
    375382         * Locate the area.
    376          */
    377         area = find_area_and_lock(as, address);
     383         *
     384         */
     385        as_area_t *area = find_area_and_lock(as, address);
    378386        if (!area) {
    379387                mutex_unlock(&as->lock);
     
    381389                return ENOENT;
    382390        }
    383 
     391       
    384392        if (area->backend == &phys_backend) {
    385393                /*
    386394                 * Remapping of address space areas associated
    387395                 * with memory mapped devices is not supported.
     396                 *
    388397                 */
    389398                mutex_unlock(&area->lock);
     
    392401                return ENOTSUP;
    393402        }
     403       
    394404        if (area->sh_info) {
    395405                /*
    396                  * Remapping of shared address space areas 
     406                 * Remapping of shared address space areas
    397407                 * is not supported.
     408                 *
    398409                 */
    399410                mutex_unlock(&area->lock);
     
    402413                return ENOTSUP;
    403414        }
    404 
    405         pages = SIZE2FRAMES((address - area->base) + size);
     415       
     416        size_t pages = SIZE2FRAMES((address - area->base) + size);
    406417        if (!pages) {
    407418                /*
    408419                 * Zero size address space areas are not allowed.
     420                 *
    409421                 */
    410422                mutex_unlock(&area->lock);
     
    415427       
    416428        if (pages < area->pages) {
    417                 bool cond;
    418429                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    419 
     430               
    420431                /*
    421432                 * Shrinking the area.
    422433                 * No need to check for overlaps.
    423                  */
    424 
     434                 *
     435                 */
     436               
    425437                page_table_lock(as, false);
    426 
     438               
    427439                /*
    428440                 * Start TLB shootdown sequence.
     441                 *
    429442                 */
    430443                tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
    431444                    pages * PAGE_SIZE, area->pages - pages);
    432 
     445               
    433446                /*
    434447                 * Remove frames belonging to used space starting from
     
    437450                 * is also the right way to remove part of the used_space
    438451                 * B+tree leaf list.
    439                  */             
    440                 for (cond = true; cond;) {
    441                         btree_node_t *node;
    442                
     452                 *
     453                 */
     454                bool cond = true;
     455                while (cond) {
    443456                        ASSERT(!list_empty(&area->used_space.leaf_head));
    444                         node =
     457                       
     458                        btree_node_t *node =
    445459                            list_get_instance(area->used_space.leaf_head.prev,
    446460                            btree_node_t, leaf_link);
     461                       
    447462                        if ((cond = (bool) node->keys)) {
    448                                 uintptr_t b = node->key[node->keys - 1];
    449                                 size_t c =
     463                                uintptr_t ptr = node->key[node->keys - 1];
     464                                size_t size =
    450465                                    (size_t) node->value[node->keys - 1];
    451                                 unsigned int i = 0;
    452                        
    453                                 if (overlaps(b, c * PAGE_SIZE, area->base,
     466                                size_t i = 0;
     467                               
     468                                if (overlaps(ptr, size * PAGE_SIZE, area->base,
    454469                                    pages * PAGE_SIZE)) {
    455470                                       
    456                                         if (b + c * PAGE_SIZE <= start_free) {
     471                                        if (ptr + size * PAGE_SIZE <= start_free) {
    457472                                                /*
    458473                                                 * The whole interval fits
    459474                                                 * completely in the resized
    460475                                                 * address space area.
     476                                                 *
    461477                                                 */
    462478                                                break;
    463479                                        }
    464                
     480                                       
    465481                                        /*
    466482                                         * Part of the interval corresponding
    467483                                         * to b and c overlaps with the resized
    468484                                         * address space area.
     485                                         *
    469486                                         */
    470                
    471                                         cond = false;   /* we are almost done */
    472                                         i = (start_free - b) >> PAGE_WIDTH;
     487                                       
     488                                        /* We are almost done */
     489                                        cond = false;
     490                                        i = (start_free - ptr) >> PAGE_WIDTH;
    473491                                        if (!used_space_remove(area, start_free,
    474                                             c - i))
    475                                                 panic("Cannot remove used "
    476                                                     "space.");
     492                                            size - i))
     493                                                panic("Cannot remove used space.");
    477494                                } else {
    478495                                        /*
     
    480497                                         * completely removed.
    481498                                         */
    482                                         if (!used_space_remove(area, b, c))
    483                                                 panic("Cannot remove used "
    484                                                     "space.");
     499                                        if (!used_space_remove(area, ptr, size))
     500                                                panic("Cannot remove used space.");
    485501                                }
    486                        
    487                                 for (; i < c; i++) {
    488                                         pte_t *pte;
    489                        
    490                                         pte = page_mapping_find(as, b +
     502                               
     503                                for (; i < size; i++) {
     504                                        pte_t *pte = page_mapping_find(as, ptr +
    491505                                            i * PAGE_SIZE);
    492                                         ASSERT(pte && PTE_VALID(pte) &&
    493                                             PTE_PRESENT(pte));
    494                                         if (area->backend &&
    495                                             area->backend->frame_free) {
     506                                       
     507                                        ASSERT(pte);
     508                                        ASSERT(PTE_VALID(pte));
     509                                        ASSERT(PTE_PRESENT(pte));
     510                                       
     511                                        if ((area->backend) &&
     512                                            (area->backend->frame_free)) {
    496513                                                area->backend->frame_free(area,
    497                                                     b + i * PAGE_SIZE,
     514                                                    ptr + i * PAGE_SIZE,
    498515                                                    PTE_GET_FRAME(pte));
    499516                                        }
    500                                         page_mapping_remove(as, b +
     517                                       
     518                                        page_mapping_remove(as, ptr +
    501519                                            i * PAGE_SIZE);
    502520                                }
    503521                        }
    504522                }
    505 
     523               
    506524                /*
    507525                 * Finish TLB shootdown sequence.
    508                  */
    509 
     526                 *
     527                 */
     528               
    510529                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    511530                    area->pages - pages);
    512 
     531               
    513532                /*
    514533                 * Invalidate software translation caches (e.g. TSB on sparc64).
     534                 *
    515535                 */
    516536                as_invalidate_translation_cache(as, area->base +
    517537                    pages * PAGE_SIZE, area->pages - pages);
    518538                tlb_shootdown_finalize();
    519 
     539               
    520540                page_table_unlock(as, false);
    521                
    522541        } else {
    523542                /*
    524543                 * Growing the area.
    525544                 * Check for overlaps with other address space areas.
     545                 *
    526546                 */
    527547                if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    528548                    area)) {
    529549                        mutex_unlock(&area->lock);
    530                         mutex_unlock(&as->lock);               
     550                        mutex_unlock(&as->lock);
    531551                        interrupts_restore(ipl);
    532552                        return EADDRNOTAVAIL;
    533553                }
    534         } 
    535 
     554        }
     555       
    536556        area->pages = pages;
    537557       
     
    539559        mutex_unlock(&as->lock);
    540560        interrupts_restore(ipl);
    541 
     561       
    542562        return 0;
    543563}
     
    545565/** Destroy address space area.
    546566 *
    547  * @param as            Address space.
    548  * @param address       Address within the area to be deleted.
    549  *
    550  * @return              Zero on success or a value from @ref errno.h on failure.
     567 * @param as      Address space.
     568 * @param address Address within the area to be deleted.
     569 *
     570 * @return Zero on success or a value from @ref errno.h on failure.
     571 *
    551572 */
    552573int as_area_destroy(as_t *as, uintptr_t address)
    553574{
    554         as_area_t *area;
    555         uintptr_t base;
    556         link_t *cur;
    557         ipl_t ipl;
    558 
    559         ipl = interrupts_disable();
     575        ipl_t ipl = interrupts_disable();
    560576        mutex_lock(&as->lock);
    561 
    562         area = find_area_and_lock(as, address);
     577       
     578        as_area_t *area = find_area_and_lock(as, address);
    563579        if (!area) {
    564580                mutex_unlock(&as->lock);
     
    566582                return ENOENT;
    567583        }
    568 
    569         base = area->base;
    570 
     584       
     585        uintptr_t base = area->base;
     586       
    571587        page_table_lock(as, false);
    572 
     588       
    573589        /*
    574590         * Start TLB shootdown sequence.
    575591         */
    576592        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
    577 
     593       
    578594        /*
    579595         * Visit only the pages mapped by used_space B+tree.
    580596         */
     597        link_t *cur;
    581598        for (cur = area->used_space.leaf_head.next;
    582599            cur != &area->used_space.leaf_head; cur = cur->next) {
    583600                btree_node_t *node;
    584                 unsigned int i;
     601                btree_key_t i;
    585602               
    586603                node = list_get_instance(cur, btree_node_t, leaf_link);
    587604                for (i = 0; i < node->keys; i++) {
    588                         uintptr_t b = node->key[i];
    589                         size_t j;
    590                         pte_t *pte;
     605                        uintptr_t ptr = node->key[i];
     606                        size_t size;
    591607                       
    592                         for (j = 0; j < (size_t) node->value[i]; j++) {
    593                                 pte = page_mapping_find(as, b + j * PAGE_SIZE);
    594                                 ASSERT(pte && PTE_VALID(pte) &&
    595                                     PTE_PRESENT(pte));
    596                                 if (area->backend &&
    597                                     area->backend->frame_free) {
    598                                         area->backend->frame_free(area, b +
    599                                             j * PAGE_SIZE, PTE_GET_FRAME(pte));
     608                        for (size = 0; size < (size_t) node->value[i]; size++) {
     609                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     610                               
     611                                ASSERT(pte);
     612                                ASSERT(PTE_VALID(pte));
     613                                ASSERT(PTE_PRESENT(pte));
     614                               
     615                                if ((area->backend) &&
     616                                    (area->backend->frame_free)) {
     617                                        area->backend->frame_free(area,
     618                                            ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
    600619                                }
    601                                 page_mapping_remove(as, b + j * PAGE_SIZE);                             
     620                               
     621                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    602622                        }
    603623                }
    604624        }
    605 
     625       
    606626        /*
    607627         * Finish TLB shootdown sequence.
    608          */
    609 
     628         *
     629         */
     630       
    610631        tlb_invalidate_pages(as->asid, area->base, area->pages);
    611 
     632       
    612633        /*
    613634         * Invalidate potential software translation caches (e.g. TSB on
    614635         * sparc64).
     636         *
    615637         */
    616638        as_invalidate_translation_cache(as, area->base, area->pages);
    617639        tlb_shootdown_finalize();
    618 
     640       
    619641        page_table_unlock(as, false);
    620642       
    621643        btree_destroy(&area->used_space);
    622 
     644       
    623645        area->attributes |= AS_AREA_ATTR_PARTIAL;
    624646       
    625647        if (area->sh_info)
    626648                sh_info_remove_reference(area->sh_info);
    627                
     649       
    628650        mutex_unlock(&area->lock);
    629 
     651       
    630652        /*
    631653         * Remove the empty area from address space.
     654         *
    632655         */
    633656        btree_remove(&as->as_area_btree, base, NULL);
     
    647670 * sh_info of the source area. The process of duplicating the
    648671 * mapping is done through the backend share function.
    649  * 
    650  * @param src_as        Pointer to source address space.
    651  * @param src_base      Base address of the source address space area.
    652  * @param acc_size      Expected size of the source area.
    653  * @param dst_as        Pointer to destination address space.
    654  * @param dst_base      Target base address.
     672 *
     673 * @param src_as         Pointer to source address space.
     674 * @param src_base       Base address of the source address space area.
     675 * @param acc_size       Expected size of the source area.
     676 * @param dst_as         Pointer to destination address space.
     677 * @param dst_base       Target base address.
    655678 * @param dst_flags_mask Destination address space area flags mask.
    656679 *
    657  * @return              Zero on success or ENOENT if there is no such task or if
    658  *                      there is no such address space area, EPERM if there was
    659  *                      a problem in accepting the area or ENOMEM if there was a
    660  *                      problem in allocating destination address space area.
    661  *                      ENOTSUP is returned if the address space area backend
    662  *                      does not support sharing.
     680 * @return Zero on success.
     681 * @return ENOENT if there is no such task or such address space.
     682 * @return EPERM if there was a problem in accepting the area.
     683 * @return ENOMEM if there was a problem in allocating destination
     684 *         address space area.
     685 * @return ENOTSUP if the address space area backend does not support
     686 *         sharing.
     687 *
    663688 */
    664689int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
    665     as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
    666 {
    667         ipl_t ipl;
    668         int src_flags;
    669         size_t src_size;
    670         as_area_t *src_area, *dst_area;
    671         share_info_t *sh_info;
    672         mem_backend_t *src_backend;
    673         mem_backend_data_t src_backend_data;
    674        
    675         ipl = interrupts_disable();
     690    as_t *dst_as, uintptr_t dst_base, unsigned int dst_flags_mask)
     691{
     692        ipl_t ipl = interrupts_disable();
    676693        mutex_lock(&src_as->lock);
    677         src_area = find_area_and_lock(src_as, src_base);
     694        as_area_t *src_area = find_area_and_lock(src_as, src_base);
    678695        if (!src_area) {
    679696                /*
    680697                 * Could not find the source address space area.
     698                 *
    681699                 */
    682700                mutex_unlock(&src_as->lock);
     
    684702                return ENOENT;
    685703        }
    686 
    687         if (!src_area->backend || !src_area->backend->share) {
     704       
     705        if ((!src_area->backend) || (!src_area->backend->share)) {
    688706                /*
    689707                 * There is no backend or the backend does not
    690708                 * know how to share the area.
     709                 *
    691710                 */
    692711                mutex_unlock(&src_area->lock);
     
    696715        }
    697716       
    698         src_size = src_area->pages * PAGE_SIZE;
    699         src_flags = src_area->flags;
    700         src_backend = src_area->backend;
    701         src_backend_data = src_area->backend_data;
    702 
     717        size_t src_size = src_area->pages * PAGE_SIZE;
     718        unsigned int src_flags = src_area->flags;
     719        mem_backend_t *src_backend = src_area->backend;
     720        mem_backend_data_t src_backend_data = src_area->backend_data;
     721       
    703722        /* Share the cacheable flag from the original mapping */
    704723        if (src_flags & AS_AREA_CACHEABLE)
    705724                dst_flags_mask |= AS_AREA_CACHEABLE;
    706 
    707         if (src_size != acc_size ||
    708             (src_flags & dst_flags_mask) != dst_flags_mask) {
     725       
     726        if ((src_size != acc_size) ||
     727            ((src_flags & dst_flags_mask) != dst_flags_mask)) {
    709728                mutex_unlock(&src_area->lock);
    710729                mutex_unlock(&src_as->lock);
     
    712731                return EPERM;
    713732        }
    714 
     733       
    715734        /*
    716735         * Now we are committed to sharing the area.
    717736         * First, prepare the area for sharing.
    718737         * Then it will be safe to unlock it.
    719          */
    720         sh_info = src_area->sh_info;
     738         *
     739         */
     740        share_info_t *sh_info = src_area->sh_info;
    721741        if (!sh_info) {
    722742                sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
     
    725745                btree_create(&sh_info->pagemap);
    726746                src_area->sh_info = sh_info;
     747               
    727748                /*
    728749                 * Call the backend to setup sharing.
     750                 *
    729751                 */
    730752                src_area->backend->share(src_area);
     
    734756                mutex_unlock(&sh_info->lock);
    735757        }
    736 
     758       
    737759        mutex_unlock(&src_area->lock);
    738760        mutex_unlock(&src_as->lock);
    739 
     761       
    740762        /*
    741763         * Create copy of the source address space area.
     
    745767         * The flags of the source area are masked against dst_flags_mask
    746768         * to support sharing in less privileged mode.
    747          */
    748         dst_area = as_area_create(dst_as, dst_flags_mask, src_size, dst_base,
    749             AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
     769         *
     770         */
     771        as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
     772            dst_base, AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
    750773        if (!dst_area) {
    751774                /*
     
    757780                return ENOMEM;
    758781        }
    759 
     782       
    760783        /*
    761784         * Now the destination address space area has been
    762785         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    763786         * attribute and set the sh_info.
    764          */     
    765         mutex_lock(&dst_as->lock);     
     787         *
     788         */
     789        mutex_lock(&dst_as->lock);
    766790        mutex_lock(&dst_area->lock);
    767791        dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
    768792        dst_area->sh_info = sh_info;
    769793        mutex_unlock(&dst_area->lock);
    770         mutex_unlock(&dst_as->lock);   
    771 
     794        mutex_unlock(&dst_as->lock);
     795       
    772796        interrupts_restore(ipl);
    773797       
     
    779803 * The address space area must be locked prior to this call.
    780804 *
    781  * @param area          Address space area.
    782  * @param access        Access mode.
    783  *
    784  * @return              False if access violates area's permissions, true
    785  *                      otherwise.
     805 * @param area   Address space area.
     806 * @param access Access mode.
     807 *
     808 * @return False if access violates area's permissions, true
     809 *         otherwise.
     810 *
    786811 */
    787812bool as_area_check_access(as_area_t *area, pf_access_t access)
     
    792817                [PF_ACCESS_EXEC] = AS_AREA_EXEC
    793818        };
    794 
     819       
    795820        if (!(area->flags & flagmap[access]))
    796821                return false;
     
    813838 *
    814839 */
    815 int as_area_change_flags(as_t *as, int flags, uintptr_t address)
    816 {
    817         as_area_t *area;
    818         link_t *cur;
    819         ipl_t ipl;
    820         int page_flags;
    821         uintptr_t *old_frame;
    822         size_t frame_idx;
    823         size_t used_pages;
    824        
     840int as_area_change_flags(as_t *as, unsigned int flags, uintptr_t address)
     841{
    825842        /* Flags for the new memory mapping */
    826         page_flags = area_flags_to_page_flags(flags);
    827 
    828         ipl = interrupts_disable();
     843        unsigned int page_flags = area_flags_to_page_flags(flags);
     844       
     845        ipl_t ipl = interrupts_disable();
    829846        mutex_lock(&as->lock);
    830 
    831         area = find_area_and_lock(as, address);
     847       
     848        as_area_t *area = find_area_and_lock(as, address);
    832849        if (!area) {
    833850                mutex_unlock(&as->lock);
     
    835852                return ENOENT;
    836853        }
    837 
     854       
    838855        if ((area->sh_info) || (area->backend != &anon_backend)) {
    839856                /* Copying shared areas not supported yet */
     
    844861                return ENOTSUP;
    845862        }
    846 
     863       
    847864        /*
    848865         * Compute total number of used pages in the used_space B+tree
    849          */
    850         used_pages = 0;
    851 
     866         *
     867         */
     868        size_t used_pages = 0;
     869        link_t *cur;
     870       
    852871        for (cur = area->used_space.leaf_head.next;
    853872            cur != &area->used_space.leaf_head; cur = cur->next) {
    854                 btree_node_t *node;
    855                 unsigned int i;
    856                
    857                 node = list_get_instance(cur, btree_node_t, leaf_link);
    858                 for (i = 0; i < node->keys; i++) {
     873                btree_node_t *node
     874                    = list_get_instance(cur, btree_node_t, leaf_link);
     875                btree_key_t i;
     876               
     877                for (i = 0; i < node->keys; i++)
    859878                        used_pages += (size_t) node->value[i];
    860                 }
    861         }
    862 
     879        }
     880       
    863881        /* An array for storing frame numbers */
    864         old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
    865 
     882        uintptr_t *old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     883       
    866884        page_table_lock(as, false);
    867 
     885       
    868886        /*
    869887         * Start TLB shootdown sequence.
     888         *
    870889         */
    871890        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
    872 
     891       
    873892        /*
    874893         * Remove used pages from page tables and remember their frame
    875894         * numbers.
    876          */
    877         frame_idx = 0;
    878 
     895         *
     896         */
     897        size_t frame_idx = 0;
     898       
    879899        for (cur = area->used_space.leaf_head.next;
    880900            cur != &area->used_space.leaf_head; cur = cur->next) {
    881                 btree_node_t *node;
    882                 unsigned int i;
    883                
    884                 node = list_get_instance(cur, btree_node_t, leaf_link);
     901                btree_node_t *node
     902                    = list_get_instance(cur, btree_node_t, leaf_link);
     903                btree_key_t i;
     904               
    885905                for (i = 0; i < node->keys; i++) {
    886                         uintptr_t b = node->key[i];
    887                         size_t j;
    888                         pte_t *pte;
     906                        uintptr_t ptr = node->key[i];
     907                        size_t size;
    889908                       
    890                         for (j = 0; j < (size_t) node->value[i]; j++) {
    891                                 pte = page_mapping_find(as, b + j * PAGE_SIZE);
    892                                 ASSERT(pte && PTE_VALID(pte) &&
    893                                     PTE_PRESENT(pte));
     909                        for (size = 0; size < (size_t) node->value[i]; size++) {
     910                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     911                               
     912                                ASSERT(pte);
     913                                ASSERT(PTE_VALID(pte));
     914                                ASSERT(PTE_PRESENT(pte));
     915                               
    894916                                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
    895 
     917                               
    896918                                /* Remove old mapping */
    897                                 page_mapping_remove(as, b + j * PAGE_SIZE);
     919                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    898920                        }
    899921                }
    900922        }
    901 
     923       
    902924        /*
    903925         * Finish TLB shootdown sequence.
    904          */
    905 
     926         *
     927         */
     928       
    906929        tlb_invalidate_pages(as->asid, area->base, area->pages);
    907930       
     
    909932         * Invalidate potential software translation caches (e.g. TSB on
    910933         * sparc64).
     934         *
    911935         */
    912936        as_invalidate_translation_cache(as, area->base, area->pages);
    913937        tlb_shootdown_finalize();
    914 
     938       
    915939        page_table_unlock(as, false);
    916 
     940       
    917941        /*
    918942         * Set the new flags.
    919943         */
    920944        area->flags = flags;
    921 
     945       
    922946        /*
    923947         * Map pages back in with new flags. This step is kept separate
     
    926950         */
    927951        frame_idx = 0;
    928 
     952       
    929953        for (cur = area->used_space.leaf_head.next;
    930954            cur != &area->used_space.leaf_head; cur = cur->next) {
    931                 btree_node_t *node;
    932                 unsigned int i;
    933                
    934                 node = list_get_instance(cur, btree_node_t, leaf_link);
     955                btree_node_t *node
     956                    = list_get_instance(cur, btree_node_t, leaf_link);
     957                btree_key_t i;
     958               
    935959                for (i = 0; i < node->keys; i++) {
    936                         uintptr_t b = node->key[i];
    937                         size_t j;
     960                        uintptr_t ptr = node->key[i];
     961                        size_t size;
    938962                       
    939                         for (j = 0; j < (size_t) node->value[i]; j++) {
     963                        for (size = 0; size < (size_t) node->value[i]; size++) {
    940964                                page_table_lock(as, false);
    941 
     965                               
    942966                                /* Insert the new mapping */
    943                                 page_mapping_insert(as, b + j * PAGE_SIZE,
     967                                page_mapping_insert(as, ptr + size * PAGE_SIZE,
    944968                                    old_frame[frame_idx++], page_flags);
    945 
     969                               
    946970                                page_table_unlock(as, false);
    947971                        }
    948972                }
    949973        }
    950 
     974       
    951975        free(old_frame);
    952 
     976       
    953977        mutex_unlock(&area->lock);
    954978        mutex_unlock(&as->lock);
    955979        interrupts_restore(ipl);
    956 
     980       
    957981        return 0;
    958982}
    959 
    960983
    961984/** Handle page fault within the current address space.
     
    967990 * Interrupts are assumed disabled.
    968991 *
    969  * @param page          Faulting page.
    970  * @param access        Access mode that caused the page fault (i.e.
    971  *                      read/write/exec).
    972  * @param istate        Pointer to the interrupted state.
    973  *
    974  * @return              AS_PF_FAULT on page fault, AS_PF_OK on success or
    975  *                      AS_PF_DEFER if the fault was caused by copy_to_uspace()
    976  *                      or copy_from_uspace().
     992 * @param page   Faulting page.
     993 * @param access Access mode that caused the page fault (i.e.
     994 *               read/write/exec).
     995 * @param istate Pointer to the interrupted state.
     996 *
     997 * @return AS_PF_FAULT on page fault.
     998 * @return AS_PF_OK on success.
     999 * @return AS_PF_DEFER if the fault was caused by copy_to_uspace()
     1000 *         or copy_from_uspace().
     1001 *
    9771002 */
    9781003int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    9791004{
    980         pte_t *pte;
    981         as_area_t *area;
    982        
    9831005        if (!THREAD)
    9841006                return AS_PF_FAULT;
     
    9881010       
    9891011        mutex_lock(&AS->lock);
    990         area = find_area_and_lock(AS, page);
     1012        as_area_t *area = find_area_and_lock(AS, page);
    9911013        if (!area) {
    9921014                /*
    9931015                 * No area contained mapping for 'page'.
    9941016                 * Signal page fault to low-level handler.
     1017                 *
    9951018                 */
    9961019                mutex_unlock(&AS->lock);
    9971020                goto page_fault;
    9981021        }
    999 
     1022       
    10001023        if (area->attributes & AS_AREA_ATTR_PARTIAL) {
    10011024                /*
     
    10051028                mutex_unlock(&area->lock);
    10061029                mutex_unlock(&AS->lock);
    1007                 goto page_fault;               
    1008         }
    1009 
    1010         if (!area->backend || !area->backend->page_fault) {
     1030                goto page_fault;
     1031        }
     1032       
     1033        if ((!area->backend) || (!area->backend->page_fault)) {
    10111034                /*
    10121035                 * The address space area is not backed by any backend
    10131036                 * or the backend cannot handle page faults.
     1037                 *
    10141038                 */
    10151039                mutex_unlock(&area->lock);
    10161040                mutex_unlock(&AS->lock);
    1017                 goto page_fault;               
    1018         }
    1019 
     1041                goto page_fault;
     1042        }
     1043       
    10201044        page_table_lock(AS, false);
    10211045       
     
    10231047         * To avoid race condition between two page faults on the same address,
    10241048         * we need to make sure the mapping has not been already inserted.
    1025          */
     1049         *
     1050         */
     1051        pte_t *pte;
    10261052        if ((pte = page_mapping_find(AS, page))) {
    10271053                if (PTE_PRESENT(pte)) {
     
    10391065        /*
    10401066         * Resort to the backend page fault handler.
     1067         *
    10411068         */
    10421069        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    10511078        mutex_unlock(&AS->lock);
    10521079        return AS_PF_OK;
    1053 
     1080       
    10541081page_fault:
    10551082        if (THREAD->in_copy_from_uspace) {
     
    10641091                return AS_PF_FAULT;
    10651092        }
    1066 
     1093       
    10671094        return AS_PF_DEFER;
    10681095}
     
    10761103 * When this function is enetered, no spinlocks may be held.
    10771104 *
    1078  * @param old           Old address space or NULL.
    1079  * @param new           New address space.
     1105 * @param old Old address space or NULL.
     1106 * @param new New address space.
     1107 *
    10801108 */
    10811109void as_switch(as_t *old_as, as_t *new_as)
     
    10831111        DEADLOCK_PROBE_INIT(p_asidlock);
    10841112        preemption_disable();
     1113       
    10851114retry:
    10861115        (void) interrupts_disable();
    10871116        if (!spinlock_trylock(&asidlock)) {
    1088                 /* 
     1117                /*
    10891118                 * Avoid deadlock with TLB shootdown.
    10901119                 * We can enable interrupts here because
    10911120                 * preemption is disabled. We should not be
    10921121                 * holding any other lock.
     1122                 *
    10931123                 */
    10941124                (void) interrupts_enable();
     
    10971127        }
    10981128        preemption_enable();
    1099 
     1129       
    11001130        /*
    11011131         * First, take care of the old address space.
    1102          */     
     1132         */
    11031133        if (old_as) {
    11041134                ASSERT(old_as->cpu_refcount);
    1105                 if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
     1135               
     1136                if ((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
    11061137                        /*
    11071138                         * The old address space is no longer active on
     
    11091140                         * list of inactive address spaces with assigned
    11101141                         * ASID.
     1142                         *
    11111143                         */
    11121144                        ASSERT(old_as->asid != ASID_INVALID);
     1145                       
    11131146                        list_append(&old_as->inactive_as_with_asid_link,
    11141147                            &inactive_as_with_asid_head);
    11151148                }
    1116 
     1149               
    11171150                /*
    11181151                 * Perform architecture-specific tasks when the address space
    11191152                 * is being removed from the CPU.
     1153                 *
    11201154                 */
    11211155                as_deinstall_arch(old_as);
    11221156        }
    1123 
     1157       
    11241158        /*
    11251159         * Second, prepare the new address space.
     1160         *
    11261161         */
    11271162        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    11311166                        new_as->asid = asid_get();
    11321167        }
     1168       
    11331169#ifdef AS_PAGE_TABLE
    11341170        SET_PTL0_ADDRESS(new_as->genarch.page_table);
     
    11381174         * Perform architecture-specific steps.
    11391175         * (e.g. write ASID to hardware register etc.)
     1176         *
    11401177         */
    11411178        as_install_arch(new_as);
    1142 
     1179       
    11431180        spinlock_unlock(&asidlock);
    11441181       
     
    11481185/** Convert address space area flags to page flags.
    11491186 *
    1150  * @param aflags        Flags of some address space area.
    1151  *
    1152  * @return              Flags to be passed to page_mapping_insert().
    1153  */
    1154 int area_flags_to_page_flags(int aflags)
    1155 {
    1156         int flags;
    1157 
    1158         flags = PAGE_USER | PAGE_PRESENT;
     1187 * @param aflags Flags of some address space area.
     1188 *
     1189 * @return Flags to be passed to page_mapping_insert().
     1190 *
     1191 */
     1192unsigned int area_flags_to_page_flags(unsigned int aflags)
     1193{
     1194        unsigned int flags = PAGE_USER | PAGE_PRESENT;
    11591195       
    11601196        if (aflags & AS_AREA_READ)
     
    11691205        if (aflags & AS_AREA_CACHEABLE)
    11701206                flags |= PAGE_CACHEABLE;
    1171                
     1207       
    11721208        return flags;
    11731209}
     
    11781214 * Interrupts must be disabled.
    11791215 *
    1180  * @param a             Address space area.
    1181  *
    1182  * @return              Flags to be used in page_mapping_insert().
    1183  */
    1184 int as_area_get_flags(as_area_t *a)
    1185 {
    1186         return area_flags_to_page_flags(a->flags);
     1216 * @param area Address space area.
     1217 *
     1218 * @return Flags to be used in page_mapping_insert().
     1219 *
     1220 */
     1221unsigned int as_area_get_flags(as_area_t *area)
     1222{
     1223        return area_flags_to_page_flags(area->flags);
    11871224}
    11881225
     
    11921229 * table.
    11931230 *
    1194  * @param flags         Flags saying whether the page table is for the kernel
    1195  *                      address space.
    1196  *
    1197  * @return              First entry of the page table.
    1198  */
    1199 pte_t *page_table_create(int flags)
     1231 * @param flags Flags saying whether the page table is for the kernel
     1232 *              address space.
     1233 *
     1234 * @return First entry of the page table.
     1235 *
     1236 */
     1237pte_t *page_table_create(unsigned int flags)
    12001238{
    12011239        ASSERT(as_operations);
     
    12091247 * Destroy page table in architecture specific way.
    12101248 *
    1211  * @param page_table    Physical address of PTL0.
     1249 * @param page_table Physical address of PTL0.
     1250 *
    12121251 */
    12131252void page_table_destroy(pte_t *page_table)
     
    12231262 * This function should be called before any page_mapping_insert(),
    12241263 * page_mapping_remove() and page_mapping_find().
    1225  * 
     1264 *
    12261265 * Locking order is such that address space areas must be locked
    12271266 * prior to this call. Address space can be locked prior to this
    12281267 * call in which case the lock argument is false.
    12291268 *
    1230  * @param as            Address space.
    1231  * @param lock          If false, do not attempt to lock as->lock.
     1269 * @param as   Address space.
     1270 * @param lock If false, do not attempt to lock as->lock.
     1271 *
    12321272 */
    12331273void page_table_lock(as_t *as, bool lock)
     
    12411281/** Unlock page table.
    12421282 *
    1243  * @param as            Address space.
    1244  * @param unlock        If false, do not attempt to unlock as->lock.
     1283 * @param as     Address space.
     1284 * @param unlock If false, do not attempt to unlock as->lock.
     1285 *
    12451286 */
    12461287void page_table_unlock(as_t *as, bool unlock)
     
    12571298 * The address space must be locked and interrupts must be disabled.
    12581299 *
    1259  * @param as            Address space.
    1260  * @param va            Virtual address.
    1261  *
    1262  * @return              Locked address space area containing va on success or
    1263  *                      NULL on failure.
     1300 * @param as Address space.
     1301 * @param va Virtual address.
     1302 *
     1303 * @return Locked address space area containing va on success or
     1304 *         NULL on failure.
     1305 *
    12641306 */
    12651307as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
    12661308{
    1267         as_area_t *a;
    1268         btree_node_t *leaf, *lnode;
    1269         unsigned int i;
    1270        
    1271         a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    1272         if (a) {
     1309        btree_node_t *leaf;
     1310        as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     1311        if (area) {
    12731312                /* va is the base address of an address space area */
    1274                 mutex_lock(&a->lock);
    1275                 return a;
     1313                mutex_lock(&area->lock);
     1314                return area;
    12761315        }
    12771316       
     
    12801319         * to find out whether this is a miss or va belongs to an address
    12811320         * space area found there.
     1321         *
    12821322         */
    12831323       
    12841324        /* First, search the leaf node itself. */
     1325        btree_key_t i;
     1326       
    12851327        for (i = 0; i < leaf->keys; i++) {
    1286                 a = (as_area_t *) leaf->value[i];
    1287                 mutex_lock(&a->lock);
    1288                 if ((a->base <= va) && (va < a->base + a->pages * PAGE_SIZE)) {
    1289                         return a;
    1290                 }
    1291                 mutex_unlock(&a->lock);
    1292         }
    1293 
     1328                area = (as_area_t *) leaf->value[i];
     1329               
     1330                mutex_lock(&area->lock);
     1331               
     1332                if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
     1333                        return area;
     1334               
     1335                mutex_unlock(&area->lock);
     1336        }
     1337       
    12941338        /*
    12951339         * Second, locate the left neighbour and test its last record.
    12961340         * Because of its position in the B+tree, it must have base < va.
    1297          */
    1298         lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     1341         *
     1342         */
     1343        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    12991344        if (lnode) {
    1300                 a = (as_area_t *) lnode->value[lnode->keys - 1];
    1301                 mutex_lock(&a->lock);
    1302                 if (va < a->base + a->pages * PAGE_SIZE) {
    1303                         return a;
    1304                 }
    1305                 mutex_unlock(&a->lock);
    1306         }
    1307 
     1345                area = (as_area_t *) lnode->value[lnode->keys - 1];
     1346               
     1347                mutex_lock(&area->lock);
     1348               
     1349                if (va < area->base + area->pages * PAGE_SIZE)
     1350                        return area;
     1351               
     1352                mutex_unlock(&area->lock);
     1353        }
     1354       
    13081355        return NULL;
    13091356}
     
    13131360 * The address space must be locked and interrupts must be disabled.
    13141361 *
    1315  * @param as            Address space.
    1316  * @param va            Starting virtual address of the area being tested.
    1317  * @param size          Size of the area being tested.
    1318  * @param avoid_area    Do not touch this area.
    1319  *
    1320  * @return              True if there is no conflict, false otherwise.
    1321  */
    1322 bool
    1323 check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area)
    1324 {
    1325         as_area_t *a;
    1326         btree_node_t *leaf, *node;
    1327         unsigned int i;
    1328        
     1362 * @param as         Address space.
     1363 * @param va         Starting virtual address of the area being tested.
     1364 * @param size       Size of the area being tested.
     1365 * @param avoid_area Do not touch this area.
     1366 *
     1367 * @return True if there is no conflict, false otherwise.
     1368 *
     1369 */
     1370bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
     1371    as_area_t *avoid_area)
     1372{
    13291373        /*
    13301374         * We don't want any area to have conflicts with NULL page.
     1375         *
    13311376         */
    13321377        if (overlaps(va, size, NULL, PAGE_SIZE))
     
    13391384         * record in the left neighbour, the leftmost record in the right
    13401385         * neighbour and all records in the leaf node itself.
    1341          */
    1342        
    1343         if ((a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf))) {
    1344                 if (a != avoid_area)
     1386         *
     1387         */
     1388        btree_node_t *leaf;
     1389        as_area_t *area =
     1390            (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     1391        if (area) {
     1392                if (area != avoid_area)
    13451393                        return false;
    13461394        }
    13471395       
    13481396        /* First, check the two border cases. */
    1349         if ((node = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf))) {
    1350                 a = (as_area_t *) node->value[node->keys - 1];
    1351                 mutex_lock(&a->lock);
    1352                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1353                         mutex_unlock(&a->lock);
     1397        btree_node_t *node =
     1398            btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     1399        if (node) {
     1400                area = (as_area_t *) node->value[node->keys - 1];
     1401               
     1402                mutex_lock(&area->lock);
     1403               
     1404                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     1405                        mutex_unlock(&area->lock);
    13541406                        return false;
    13551407                }
    1356                 mutex_unlock(&a->lock);
    1357         }
     1408               
     1409                mutex_unlock(&area->lock);
     1410        }
     1411       
    13581412        node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    13591413        if (node) {
    1360                 a = (as_area_t *) node->value[0];
    1361                 mutex_lock(&a->lock);
    1362                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1363                         mutex_unlock(&a->lock);
     1414                area = (as_area_t *) node->value[0];
     1415               
     1416                mutex_lock(&area->lock);
     1417               
     1418                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     1419                        mutex_unlock(&area->lock);
    13641420                        return false;
    13651421                }
    1366                 mutex_unlock(&a->lock);
     1422               
     1423                mutex_unlock(&area->lock);
    13671424        }
    13681425       
    13691426        /* Second, check the leaf node. */
     1427        btree_key_t i;
    13701428        for (i = 0; i < leaf->keys; i++) {
    1371                 a = (as_area_t *) leaf->value[i];
    1372        
    1373                 if (a == avoid_area)
     1429                area = (as_area_t *) leaf->value[i];
     1430               
     1431                if (area == avoid_area)
    13741432                        continue;
    1375        
    1376                 mutex_lock(&a->lock);
    1377                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1378                         mutex_unlock(&a->lock);
     1433               
     1434                mutex_lock(&area->lock);
     1435               
     1436                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     1437                        mutex_unlock(&area->lock);
    13791438                        return false;
    13801439                }
    1381                 mutex_unlock(&a->lock);
    1382         }
    1383 
     1440               
     1441                mutex_unlock(&area->lock);
     1442        }
     1443       
    13841444        /*
    13851445         * So far, the area does not conflict with other areas.
    13861446         * Check if it doesn't conflict with kernel address space.
    1387          */     
     1447         *
     1448         */
    13881449        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    1389                 return !overlaps(va, size, 
     1450                return !overlaps(va, size,
    13901451                    KERNEL_ADDRESS_SPACE_START,
    13911452                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    13921453        }
    1393 
     1454       
    13941455        return true;
    13951456}
     
    13971458/** Return size of the address space area with given base.
    13981459 *
    1399  * @param base          Arbitrary address insede the address space area.
    1400  *
    1401  * @return              Size of the address space area in bytes or zero if it
    1402  *                      does not exist.
     1460 * @param base Arbitrary address insede the address space area.
     1461 *
     1462 * @return Size of the address space area in bytes or zero if it
     1463 *         does not exist.
     1464 *
    14031465 */
    14041466size_t as_area_get_size(uintptr_t base)
    14051467{
    1406         ipl_t ipl;
    1407         as_area_t *src_area;
    14081468        size_t size;
    1409 
    1410         ipl = interrupts_disable();
    1411         src_area = find_area_and_lock(AS, base);
     1469       
     1470        ipl_t ipl = interrupts_disable();
     1471        as_area_t *src_area = find_area_and_lock(AS, base);
     1472       
    14121473        if (src_area) {
    14131474                size = src_area->pages * PAGE_SIZE;
    14141475                mutex_unlock(&src_area->lock);
    1415         } else {
     1476        } else
    14161477                size = 0;
    1417         }
     1478       
    14181479        interrupts_restore(ipl);
    14191480        return size;
     
    14241485 * The address space area must be already locked.
    14251486 *
    1426  * @param a             Address space area.
    1427  * @param page          First page to be marked.
    1428  * @param count         Number of page to be marked.
    1429  *
    1430  * @return              Zero on failure and non-zero on success.
    1431  */
    1432 int used_space_insert(as_area_t *a, uintptr_t page, size_t count)
    1433 {
    1434         btree_node_t *leaf, *node;
    1435         size_t pages;
    1436         unsigned int i;
    1437 
     1487 * @param area  Address space area.
     1488 * @param page  First page to be marked.
     1489 * @param count Number of page to be marked.
     1490 *
     1491 * @return Zero on failure and non-zero on success.
     1492 *
     1493 */
     1494int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
     1495{
    14381496        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    14391497        ASSERT(count);
    1440 
    1441         pages = (size_t) btree_search(&a->used_space, page, &leaf);
     1498       
     1499        btree_node_t *leaf;
     1500        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
    14421501        if (pages) {
    14431502                /*
    14441503                 * We hit the beginning of some used space.
     1504                 *
    14451505                 */
    14461506                return 0;
    14471507        }
    1448 
     1508       
    14491509        if (!leaf->keys) {
    1450                 btree_insert(&a->used_space, page, (void *) count, leaf);
     1510                btree_insert(&area->used_space, page, (void *) count, leaf);
    14511511                return 1;
    14521512        }
    1453 
    1454         node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
     1513       
     1514        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
    14551515        if (node) {
    14561516                uintptr_t left_pg = node->key[node->keys - 1];
     
    14631523                 * somewhere between the rightmost interval of
    14641524                 * the left neigbour and the first interval of the leaf.
    1465                  */
    1466                  
     1525                 *
     1526                 */
     1527               
    14671528                if (page >= right_pg) {
    14681529                        /* Do nothing. */
     
    14741535                    right_cnt * PAGE_SIZE)) {
    14751536                        /* The interval intersects with the right interval. */
    1476                         return 0;                       
     1537                        return 0;
    14771538                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    14781539                    (page + count * PAGE_SIZE == right_pg)) {
     
    14801541                         * The interval can be added by merging the two already
    14811542                         * present intervals.
     1543                         *
    14821544                         */
    14831545                        node->value[node->keys - 1] += count + right_cnt;
    1484                         btree_remove(&a->used_space, right_pg, leaf);
    1485                         return 1; 
     1546                        btree_remove(&area->used_space, right_pg, leaf);
     1547                        return 1;
    14861548                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    1487                         /* 
     1549                        /*
    14881550                         * The interval can be added by simply growing the left
    14891551                         * interval.
     1552                         *
    14901553                         */
    14911554                        node->value[node->keys - 1] += count;
     
    14961559                         * the right interval down and increasing its size
    14971560                         * accordingly.
     1561                         *
    14981562                         */
    14991563                        leaf->value[0] += count;
     
    15041568                         * The interval is between both neigbouring intervals,
    15051569                         * but cannot be merged with any of them.
     1570                         *
    15061571                         */
    1507                         btree_insert(&a->used_space, page, (void *) count,
     1572                        btree_insert(&area->used_space, page, (void *) count,
    15081573                            leaf);
    15091574                        return 1;
     
    15121577                uintptr_t right_pg = leaf->key[0];
    15131578                size_t right_cnt = (size_t) leaf->value[0];
    1514        
     1579               
    15151580                /*
    15161581                 * Investigate the border case in which the left neighbour does
    15171582                 * not exist but the interval fits from the left.
    1518                  */
    1519                  
     1583                 *
     1584                 */
     1585               
    15201586                if (overlaps(page, count * PAGE_SIZE, right_pg,
    15211587                    right_cnt * PAGE_SIZE)) {
     
    15271593                         * right interval down and increasing its size
    15281594                         * accordingly.
     1595                         *
    15291596                         */
    15301597                        leaf->key[0] = page;
     
    15351602                         * The interval doesn't adjoin with the right interval.
    15361603                         * It must be added individually.
     1604                         *
    15371605                         */
    1538                         btree_insert(&a->used_space, page, (void *) count,
     1606                        btree_insert(&area->used_space, page, (void *) count,
    15391607                            leaf);
    15401608                        return 1;
    15411609                }
    15421610        }
    1543 
    1544         node = btree_leaf_node_right_neighbour(&a->used_space, leaf);
     1611       
     1612        node = btree_leaf_node_right_neighbour(&area->used_space, leaf);
    15451613        if (node) {
    15461614                uintptr_t left_pg = leaf->key[leaf->keys - 1];
     
    15531621                 * somewhere between the leftmost interval of
    15541622                 * the right neigbour and the last interval of the leaf.
    1555                  */
    1556 
     1623                 *
     1624                 */
     1625               
    15571626                if (page < left_pg) {
    15581627                        /* Do nothing. */
     
    15641633                    right_cnt * PAGE_SIZE)) {
    15651634                        /* The interval intersects with the right interval. */
    1566                         return 0;                       
     1635                        return 0;
    15671636                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    15681637                    (page + count * PAGE_SIZE == right_pg)) {
     
    15701639                         * The interval can be added by merging the two already
    15711640                         * present intervals.
    1572                          * */
     1641                         *
     1642                         */
    15731643                        leaf->value[leaf->keys - 1] += count + right_cnt;
    1574                         btree_remove(&a->used_space, right_pg, node);
    1575                         return 1; 
     1644                        btree_remove(&area->used_space, right_pg, node);
     1645                        return 1;
    15761646                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    15771647                        /*
    15781648                         * The interval can be added by simply growing the left
    15791649                         * interval.
    1580                          * */
     1650                         *
     1651                         */
    15811652                        leaf->value[leaf->keys - 1] +=  count;
    15821653                        return 1;
     
    15861657                         * the right interval down and increasing its size
    15871658                         * accordingly.
     1659                         *
    15881660                         */
    15891661                        node->value[0] += count;
     
    15941666                         * The interval is between both neigbouring intervals,
    15951667                         * but cannot be merged with any of them.
     1668                         *
    15961669                         */
    1597                         btree_insert(&a->used_space, page, (void *) count,
     1670                        btree_insert(&area->used_space, page, (void *) count,
    15981671                            leaf);
    15991672                        return 1;
     
    16021675                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    16031676                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1604        
     1677               
    16051678                /*
    16061679                 * Investigate the border case in which the right neighbour
    16071680                 * does not exist but the interval fits from the right.
    1608                  */
    1609                  
     1681                 *
     1682                 */
     1683               
    16101684                if (overlaps(page, count * PAGE_SIZE, left_pg,
    16111685                    left_cnt * PAGE_SIZE)) {
     
    16161690                         * The interval can be added by growing the left
    16171691                         * interval.
     1692                         *
    16181693                         */
    16191694                        leaf->value[leaf->keys - 1] += count;
     
    16231698                         * The interval doesn't adjoin with the left interval.
    16241699                         * It must be added individually.
     1700                         *
    16251701                         */
    1626                         btree_insert(&a->used_space, page, (void *) count,
     1702                        btree_insert(&area->used_space, page, (void *) count,
    16271703                            leaf);
    16281704                        return 1;
     
    16341710         * only between two other intervals of the leaf. The two border cases
    16351711         * were already resolved.
    1636          */
     1712         *
     1713         */
     1714        btree_key_t i;
    16371715        for (i = 1; i < leaf->keys; i++) {
    16381716                if (page < leaf->key[i]) {
     
    16411719                        size_t left_cnt = (size_t) leaf->value[i - 1];
    16421720                        size_t right_cnt = (size_t) leaf->value[i];
    1643 
     1721                       
    16441722                        /*
    16451723                         * The interval fits between left_pg and right_pg.
     1724                         *
    16461725                         */
    1647 
     1726                       
    16481727                        if (overlaps(page, count * PAGE_SIZE, left_pg,
    16491728                            left_cnt * PAGE_SIZE)) {
     
    16511730                                 * The interval intersects with the left
    16521731                                 * interval.
     1732                                 *
    16531733                                 */
    16541734                                return 0;
     
    16581738                                 * The interval intersects with the right
    16591739                                 * interval.
     1740                                 *
    16601741                                 */
    1661                                 return 0;                       
     1742                                return 0;
    16621743                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    16631744                            (page + count * PAGE_SIZE == right_pg)) {
     
    16651746                                 * The interval can be added by merging the two
    16661747                                 * already present intervals.
     1748                                 *
    16671749                                 */
    16681750                                leaf->value[i - 1] += count + right_cnt;
    1669                                 btree_remove(&a->used_space, right_pg, leaf);
    1670                                 return 1; 
     1751                                btree_remove(&area->used_space, right_pg, leaf);
     1752                                return 1;
    16711753                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16721754                                /*
    16731755                                 * The interval can be added by simply growing
    16741756                                 * the left interval.
     1757                                 *
    16751758                                 */
    16761759                                leaf->value[i - 1] += count;
     
    16781761                        } else if (page + count * PAGE_SIZE == right_pg) {
    16791762                                /*
    1680                                 * The interval can be addded by simply moving
     1763                                * The interval can be addded by simply moving
    16811764                                 * base of the right interval down and
    16821765                                 * increasing its size accordingly.
    1683                                  */
     1766                                 *
     1767                                 */
    16841768                                leaf->value[i] += count;
    16851769                                leaf->key[i] = page;
     
    16901774                                 * intervals, but cannot be merged with any of
    16911775                                 * them.
     1776                                 *
    16921777                                 */
    1693                                 btree_insert(&a->used_space, page,
     1778                                btree_insert(&area->used_space, page,
    16941779                                    (void *) count, leaf);
    16951780                                return 1;
     
    16971782                }
    16981783        }
    1699 
     1784       
    17001785        panic("Inconsistency detected while adding %" PRIs " pages of used "
    17011786            "space at %p.", count, page);
     
    17061791 * The address space area must be already locked.
    17071792 *
    1708  * @param a             Address space area.
    1709  * @param page          First page to be marked.
    1710  * @param count         Number of page to be marked.
    1711  *
    1712  * @return              Zero on failure and non-zero on success.
    1713  */
    1714 int used_space_remove(as_area_t *a, uintptr_t page, size_t count)
    1715 {
    1716         btree_node_t *leaf, *node;
    1717         size_t pages;
    1718         unsigned int i;
    1719 
     1793 * @param area  Address space area.
     1794 * @param page  First page to be marked.
     1795 * @param count Number of page to be marked.
     1796 *
     1797 * @return Zero on failure and non-zero on success.
     1798 *
     1799 */
     1800int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
     1801{
    17201802        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    17211803        ASSERT(count);
    1722 
    1723         pages = (size_t) btree_search(&a->used_space, page, &leaf);
     1804       
     1805        btree_node_t *leaf;
     1806        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
    17241807        if (pages) {
    17251808                /*
    17261809                 * We are lucky, page is the beginning of some interval.
     1810                 *
    17271811                 */
    17281812                if (count > pages) {
    17291813                        return 0;
    17301814                } else if (count == pages) {
    1731                         btree_remove(&a->used_space, page, leaf);
     1815                        btree_remove(&area->used_space, page, leaf);
    17321816                        return 1;
    17331817                } else {
     
    17351819                         * Find the respective interval.
    17361820                         * Decrease its size and relocate its start address.
     1821                         *
    17371822                         */
     1823                        btree_key_t i;
    17381824                        for (i = 0; i < leaf->keys; i++) {
    17391825                                if (leaf->key[i] == page) {
     
    17461832                }
    17471833        }
    1748 
    1749         node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
    1750         if (node && page < leaf->key[0]) {
     1834       
     1835        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
     1836        if ((node) && (page < leaf->key[0])) {
    17511837                uintptr_t left_pg = node->key[node->keys - 1];
    17521838                size_t left_cnt = (size_t) node->value[node->keys - 1];
    1753 
     1839               
    17541840                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    17551841                    count * PAGE_SIZE)) {
     
    17611847                                 * removed by updating the size of the bigger
    17621848                                 * interval.
     1849                                 *
    17631850                                 */
    17641851                                node->value[node->keys - 1] -= count;
     
    17661853                        } else if (page + count * PAGE_SIZE <
    17671854                            left_pg + left_cnt*PAGE_SIZE) {
    1768                                 size_t new_cnt;
    1769                                
    17701855                                /*
    17711856                                 * The interval is contained in the rightmost
     
    17741859                                 * the original interval and also inserting a
    17751860                                 * new interval.
     1861                                 *
    17761862                                 */
    1777                                 new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1863                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    17781864                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    17791865                                node->value[node->keys - 1] -= count + new_cnt;
    1780                                 btree_insert(&a->used_space, page +
     1866                                btree_insert(&area->used_space, page +
    17811867                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    17821868                                return 1;
     
    17841870                }
    17851871                return 0;
    1786         } else if (page < leaf->key[0]) {
     1872        } else if (page < leaf->key[0])
    17871873                return 0;
    1788         }
    17891874       
    17901875        if (page > leaf->key[leaf->keys - 1]) {
    17911876                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    17921877                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1793 
     1878               
    17941879                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    17951880                    count * PAGE_SIZE)) {
    1796                         if (page + count * PAGE_SIZE == 
     1881                        if (page + count * PAGE_SIZE ==
    17971882                            left_pg + left_cnt * PAGE_SIZE) {
    17981883                                /*
     
    18001885                                 * interval of the leaf and can be removed by
    18011886                                 * updating the size of the bigger interval.
     1887                                 *
    18021888                                 */
    18031889                                leaf->value[leaf->keys - 1] -= count;
     
    18051891                        } else if (page + count * PAGE_SIZE < left_pg +
    18061892                            left_cnt * PAGE_SIZE) {
    1807                                 size_t new_cnt;
    1808                                
    18091893                                /*
    18101894                                 * The interval is contained in the rightmost
     
    18131897                                 * original interval and also inserting a new
    18141898                                 * interval.
     1899                                 *
    18151900                                 */
    1816                                 new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1901                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    18171902                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    18181903                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    1819                                 btree_insert(&a->used_space, page +
     1904                                btree_insert(&area->used_space, page +
    18201905                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    18211906                                return 1;
     
    18231908                }
    18241909                return 0;
    1825         }       
     1910        }
    18261911       
    18271912        /*
     
    18291914         * Now the interval can be only between intervals of the leaf.
    18301915         */
     1916        btree_key_t i;
    18311917        for (i = 1; i < leaf->keys - 1; i++) {
    18321918                if (page < leaf->key[i]) {
    18331919                        uintptr_t left_pg = leaf->key[i - 1];
    18341920                        size_t left_cnt = (size_t) leaf->value[i - 1];
    1835 
     1921                       
    18361922                        /*
    18371923                         * Now the interval is between intervals corresponding
     
    18471933                                         * be removed by updating the size of
    18481934                                         * the bigger interval.
     1935                                         *
    18491936                                         */
    18501937                                        leaf->value[i - 1] -= count;
     
    18521939                                } else if (page + count * PAGE_SIZE <
    18531940                                    left_pg + left_cnt * PAGE_SIZE) {
    1854                                         size_t new_cnt;
    1855                                
    18561941                                        /*
    18571942                                         * The interval is contained in the
     
    18611946                                         * also inserting a new interval.
    18621947                                         */
    1863                                         new_cnt = ((left_pg +
     1948                                        size_t new_cnt = ((left_pg +
    18641949                                            left_cnt * PAGE_SIZE) -
    18651950                                            (page + count * PAGE_SIZE)) >>
    18661951                                            PAGE_WIDTH;
    18671952                                        leaf->value[i - 1] -= count + new_cnt;
    1868                                         btree_insert(&a->used_space, page +
     1953                                        btree_insert(&area->used_space, page +
    18691954                                            count * PAGE_SIZE, (void *) new_cnt,
    18701955                                            leaf);
     
    18751960                }
    18761961        }
    1877 
     1962       
    18781963error:
    18791964        panic("Inconsistency detected while removing %" PRIs " pages of used "
     
    18851970 * If the reference count drops to 0, the sh_info is deallocated.
    18861971 *
    1887  * @param sh_info       Pointer to address space area share info.
     1972 * @param sh_info Pointer to address space area share info.
     1973 *
    18881974 */
    18891975void sh_info_remove_reference(share_info_t *sh_info)
    18901976{
    18911977        bool dealloc = false;
    1892 
     1978       
    18931979        mutex_lock(&sh_info->lock);
    18941980        ASSERT(sh_info->refcount);
     1981       
    18951982        if (--sh_info->refcount == 0) {
    18961983                dealloc = true;
     
    19031990                for (cur = sh_info->pagemap.leaf_head.next;
    19041991                    cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
    1905                         btree_node_t *node;
    1906                         unsigned int i;
     1992                        btree_node_t *node
     1993                            = list_get_instance(cur, btree_node_t, leaf_link);
     1994                        btree_key_t i;
    19071995                       
    1908                         node = list_get_instance(cur, btree_node_t, leaf_link);
    1909                         for (i = 0; i < node->keys; i++)
     1996                        for (i = 0; i < node->keys; i++)
    19101997                                frame_free((uintptr_t) node->value[i]);
    19111998                }
     
    19252012
    19262013/** Wrapper for as_area_create(). */
    1927 unative_t sys_as_area_create(uintptr_t address, size_t size, int flags)
     2014unative_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
    19282015{
    19292016        if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
     
    19352022
    19362023/** Wrapper for as_area_resize(). */
    1937 unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags)
     2024unative_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
    19382025{
    19392026        return (unative_t) as_area_resize(AS, address, size, 0);
     
    19412028
    19422029/** Wrapper for as_area_change_flags(). */
    1943 unative_t sys_as_area_change_flags(uintptr_t address, int flags)
     2030unative_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
    19442031{
    19452032        return (unative_t) as_area_change_flags(AS, flags, address);
     
    19542041/** Get list of adress space areas.
    19552042 *
    1956  * @param as            Address space.
    1957  * @param obuf          Place to save pointer to returned buffer.
    1958  * @param osize         Place to save size of returned buffer.
     2043 * @param as    Address space.
     2044 * @param obuf  Place to save pointer to returned buffer.
     2045 * @param osize Place to save size of returned buffer.
     2046 *
    19592047 */
    19602048void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
    19612049{
    1962         ipl_t ipl;
    1963         size_t area_cnt, area_idx, i;
     2050        ipl_t ipl = interrupts_disable();
     2051        mutex_lock(&as->lock);
     2052       
     2053        /* First pass, count number of areas. */
     2054       
     2055        size_t area_cnt = 0;
    19642056        link_t *cur;
    1965 
    1966         as_area_info_t *info;
    1967         size_t isize;
    1968 
    1969         ipl = interrupts_disable();
    1970         mutex_lock(&as->lock);
    1971 
    1972         /* First pass, count number of areas. */
    1973 
    1974         area_cnt = 0;
    1975 
     2057       
    19762058        for (cur = as->as_area_btree.leaf_head.next;
    19772059            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1978                 btree_node_t *node;
    1979 
    1980                 node = list_get_instance(cur, btree_node_t, leaf_link);
     2060                btree_node_t *node =
     2061                    list_get_instance(cur, btree_node_t, leaf_link);
    19812062                area_cnt += node->keys;
    19822063        }
    1983 
    1984         isize = area_cnt * sizeof(as_area_info_t);
    1985         info = malloc(isize, 0);
    1986 
     2064       
     2065        size_t isize = area_cnt * sizeof(as_area_info_t);
     2066        as_area_info_t *info = malloc(isize, 0);
     2067       
    19872068        /* Second pass, record data. */
    1988 
    1989         area_idx = 0;
    1990 
     2069       
     2070        size_t area_idx = 0;
     2071       
    19912072        for (cur = as->as_area_btree.leaf_head.next;
    19922073            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1993                 btree_node_t *node;
    1994 
    1995                 node = list_get_instance(cur, btree_node_t, leaf_link);
    1996 
     2074                btree_node_t *node =
     2075                    list_get_instance(cur, btree_node_t, leaf_link);
     2076                btree_key_t i;
     2077               
    19972078                for (i = 0; i < node->keys; i++) {
    19982079                        as_area_t *area = node->value[i];
    1999 
     2080                       
    20002081                        ASSERT(area_idx < area_cnt);
    20012082                        mutex_lock(&area->lock);
    2002 
     2083                       
    20032084                        info[area_idx].start_addr = area->base;
    20042085                        info[area_idx].size = FRAMES2SIZE(area->pages);
    20052086                        info[area_idx].flags = area->flags;
    20062087                        ++area_idx;
    2007 
     2088                       
    20082089                        mutex_unlock(&area->lock);
    20092090                }
    20102091        }
    2011 
     2092       
    20122093        mutex_unlock(&as->lock);
    20132094        interrupts_restore(ipl);
    2014 
     2095       
    20152096        *obuf = info;
    20162097        *osize = isize;
    20172098}
    20182099
    2019 
    20202100/** Print out information about address space.
    20212101 *
    2022  * @param as            Address space.
     2102 * @param as Address space.
     2103 *
    20232104 */
    20242105void as_print(as_t *as)
    20252106{
    2026         ipl_t ipl;
    2027        
    2028         ipl = interrupts_disable();
     2107        ipl_t ipl = interrupts_disable();
    20292108        mutex_lock(&as->lock);
    20302109       
     
    20332112        for (cur = as->as_area_btree.leaf_head.next;
    20342113            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2035                 btree_node_t *node;
    2036                
    2037                 node = list_get_instance(cur, btree_node_t, leaf_link);
    2038                
    2039                 unsigned int i;
     2114                btree_node_t *node
     2115                    = list_get_instance(cur, btree_node_t, leaf_link);
     2116                btree_key_t i;
     2117               
    20402118                for (i = 0; i < node->keys; i++) {
    20412119                        as_area_t *area = node->value[i];
    2042                
     2120                       
    20432121                        mutex_lock(&area->lock);
    20442122                        printf("as_area: %p, base=%p, pages=%" PRIs
  • kernel/generic/src/mm/frame.c

    r666f492 rda1bafb  
    6666 * available.
    6767 */
    68 mutex_t mem_avail_mtx;
    69 condvar_t mem_avail_cv;
    70 size_t mem_avail_req = 0;  /**< Number of frames requested. */
    71 size_t mem_avail_gen = 0;  /**< Generation counter. */
     68static mutex_t mem_avail_mtx;
     69static condvar_t mem_avail_cv;
     70static size_t mem_avail_req = 0;  /**< Number of frames requested. */
     71static size_t mem_avail_gen = 0;  /**< Generation counter. */
    7272
    7373/********************/
     
    171171        return total;
    172172}
    173 #endif
     173#endif /* CONFIG_DEBUG */
    174174
    175175/** Find a zone with a given frames.
     
    199199                if (i >= zones.count)
    200200                        i = 0;
     201               
    201202        } while (i != hint);
    202203       
     
    242243                if (i >= zones.count)
    243244                        i = 0;
     245               
    244246        } while (i != hint);
    245247       
     
    296298                index = (frame_index(zone, frame)) +
    297299                    (1 << frame->buddy_order);
    298         } else {        /* is_right */
     300        } else {  /* is_right */
    299301                index = (frame_index(zone, frame)) -
    300302                    (1 << frame->buddy_order);
     
    673675bool zone_merge(size_t z1, size_t z2)
    674676{
    675         ipl_t ipl = interrupts_disable();
    676         spinlock_lock(&zones.lock);
     677        irq_spinlock_lock(&zones.lock, true);
    677678       
    678679        bool ret = true;
     
    744745       
    745746errout:
    746         spinlock_unlock(&zones.lock);
    747         interrupts_restore(ipl);
     747        irq_spinlock_unlock(&zones.lock, true);
    748748       
    749749        return ret;
     
    777777 *
    778778 */
    779 static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, size_t count, zone_flags_t flags)
     779static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start,
     780    size_t count, zone_flags_t flags)
    780781{
    781782        zone->base = start;
     
    841842 *
    842843 */
    843 size_t zone_create(pfn_t start, size_t count, pfn_t confframe, zone_flags_t flags)
    844 {
    845         ipl_t ipl = interrupts_disable();
    846         spinlock_lock(&zones.lock);
     844size_t zone_create(pfn_t start, size_t count, pfn_t confframe,
     845    zone_flags_t flags)
     846{
     847        irq_spinlock_lock(&zones.lock, true);
    847848       
    848849        if (zone_flags_available(flags)) {  /* Create available zone */
     
    889890                size_t znum = zones_insert_zone(start, count);
    890891                if (znum == (size_t) -1) {
    891                         spinlock_unlock(&zones.lock);
    892                         interrupts_restore(ipl);
     892                        irq_spinlock_unlock(&zones.lock, true);
    893893                        return (size_t) -1;
    894894                }
     
    905905                }
    906906               
    907                 spinlock_unlock(&zones.lock);
    908                 interrupts_restore(ipl);
     907                irq_spinlock_unlock(&zones.lock, true);
    909908               
    910909                return znum;
     
    914913        size_t znum = zones_insert_zone(start, count);
    915914        if (znum == (size_t) -1) {
    916                 spinlock_unlock(&zones.lock);
    917                 interrupts_restore(ipl);
     915                irq_spinlock_unlock(&zones.lock, true);
    918916                return (size_t) -1;
    919917        }
    920918        zone_construct(&zones.info[znum], NULL, start, count, flags);
    921919       
    922         spinlock_unlock(&zones.lock);
    923         interrupts_restore(ipl);
     920        irq_spinlock_unlock(&zones.lock, true);
    924921       
    925922        return znum;
     
    933930void frame_set_parent(pfn_t pfn, void *data, size_t hint)
    934931{
    935         ipl_t ipl = interrupts_disable();
    936         spinlock_lock(&zones.lock);
     932        irq_spinlock_lock(&zones.lock, true);
    937933       
    938934        size_t znum = find_zone(pfn, 1, hint);
     
    943939            pfn - zones.info[znum].base)->parent = data;
    944940       
    945         spinlock_unlock(&zones.lock);
    946         interrupts_restore(ipl);
     941        irq_spinlock_unlock(&zones.lock, true);
    947942}
    948943
    949944void *frame_get_parent(pfn_t pfn, size_t hint)
    950945{
    951         ipl_t ipl = interrupts_disable();
    952         spinlock_lock(&zones.lock);
     946        irq_spinlock_lock(&zones.lock, true);
    953947       
    954948        size_t znum = find_zone(pfn, 1, hint);
     
    959953            pfn - zones.info[znum].base)->parent;
    960954       
    961         spinlock_unlock(&zones.lock);
    962         interrupts_restore(ipl);
     955        irq_spinlock_unlock(&zones.lock, true);
    963956       
    964957        return res;
     
    977970{
    978971        size_t size = ((size_t) 1) << order;
    979         ipl_t ipl;
    980972        size_t hint = pzone ? (*pzone) : 0;
    981973       
    982974loop:
    983         ipl = interrupts_disable();
    984         spinlock_lock(&zones.lock);
     975        irq_spinlock_lock(&zones.lock, true);
    985976       
    986977        /*
     
    993984           if it does not help, reclaim all */
    994985        if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
    995                 spinlock_unlock(&zones.lock);
    996                 interrupts_restore(ipl);
    997                
     986                irq_spinlock_unlock(&zones.lock, true);
    998987                size_t freed = slab_reclaim(0);
    999                
    1000                 ipl = interrupts_disable();
    1001                 spinlock_lock(&zones.lock);
     988                irq_spinlock_lock(&zones.lock, true);
    1002989               
    1003990                if (freed > 0)
     
    1006993               
    1007994                if (znum == (size_t) -1) {
    1008                         spinlock_unlock(&zones.lock);
    1009                         interrupts_restore(ipl);
    1010                        
     995                        irq_spinlock_unlock(&zones.lock, true);
    1011996                        freed = slab_reclaim(SLAB_RECLAIM_ALL);
    1012                        
    1013                         ipl = interrupts_disable();
    1014                         spinlock_lock(&zones.lock);
     997                        irq_spinlock_lock(&zones.lock, true);
    1015998                       
    1016999                        if (freed > 0)
     
    10221005        if (znum == (size_t) -1) {
    10231006                if (flags & FRAME_ATOMIC) {
    1024                         spinlock_unlock(&zones.lock);
    1025                         interrupts_restore(ipl);
     1007                        irq_spinlock_unlock(&zones.lock, true);
    10261008                        return NULL;
    10271009                }
     
    10311013#endif
    10321014               
    1033                 spinlock_unlock(&zones.lock);
    1034                 interrupts_restore(ipl);
    1035 
     1015                irq_spinlock_unlock(&zones.lock, true);
     1016               
    10361017                if (!THREAD)
    10371018                        panic("Cannot wait for memory to become available.");
     
    10691050            + zones.info[znum].base;
    10701051       
    1071         spinlock_unlock(&zones.lock);
    1072         interrupts_restore(ipl);
     1052        irq_spinlock_unlock(&zones.lock, true);
    10731053       
    10741054        if (pzone)
     
    10921072void frame_free(uintptr_t frame)
    10931073{
    1094         ipl_t ipl = interrupts_disable();
    1095         spinlock_lock(&zones.lock);
     1074        irq_spinlock_lock(&zones.lock, true);
    10961075       
    10971076        /*
     
    11051084        zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
    11061085       
    1107         spinlock_unlock(&zones.lock);
    1108         interrupts_restore(ipl);
     1086        irq_spinlock_unlock(&zones.lock, true);
    11091087       
    11101088        /*
     
    11321110void frame_reference_add(pfn_t pfn)
    11331111{
    1134         ipl_t ipl = interrupts_disable();
    1135         spinlock_lock(&zones.lock);
     1112        irq_spinlock_lock(&zones.lock, true);
    11361113       
    11371114        /*
     
    11441121        zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
    11451122       
    1146         spinlock_unlock(&zones.lock);
    1147         interrupts_restore(ipl);
    1148 }
    1149 
    1150 /** Mark given range unavailable in frame zones. */
     1123        irq_spinlock_unlock(&zones.lock, true);
     1124}
     1125
     1126/** Mark given range unavailable in frame zones.
     1127 *
     1128 */
    11511129void frame_mark_unavailable(pfn_t start, size_t count)
    11521130{
    1153         ipl_t ipl = interrupts_disable();
    1154         spinlock_lock(&zones.lock);
     1131        irq_spinlock_lock(&zones.lock, true);
    11551132       
    11561133        size_t i;
     
    11641141        }
    11651142       
    1166         spinlock_unlock(&zones.lock);
    1167         interrupts_restore(ipl);
    1168 }
    1169 
    1170 /** Initialize physical memory management. */
     1143        irq_spinlock_unlock(&zones.lock, true);
     1144}
     1145
     1146/** Initialize physical memory management.
     1147 *
     1148 */
    11711149void frame_init(void)
    11721150{
    11731151        if (config.cpu_active == 1) {
    11741152                zones.count = 0;
    1175                 spinlock_initialize(&zones.lock, "zones.lock");
     1153                irq_spinlock_initialize(&zones.lock, "frame.zones.lock");
    11761154                mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
    11771155                condvar_initialize(&mem_avail_cv);
     
    12041182}
    12051183
    1206 /** Return total size of all zones. */
     1184/** Return total size of all zones.
     1185 *
     1186 */
    12071187uint64_t zones_total_size(void)
    12081188{
    1209         ipl_t ipl = interrupts_disable();
    1210         spinlock_lock(&zones.lock);
     1189        irq_spinlock_lock(&zones.lock, true);
    12111190       
    12121191        uint64_t total = 0;
     
    12151194                total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    12161195       
    1217         spinlock_unlock(&zones.lock);
    1218         interrupts_restore(ipl);
     1196        irq_spinlock_unlock(&zones.lock, true);
    12191197       
    12201198        return total;
     
    12291207        ASSERT(free != NULL);
    12301208       
    1231         ipl_t ipl = interrupts_disable();
    1232         spinlock_lock(&zones.lock);
     1209        irq_spinlock_lock(&zones.lock, true);
    12331210       
    12341211        *total = 0;
     
    12481225        }
    12491226       
    1250         spinlock_unlock(&zones.lock);
    1251         interrupts_restore(ipl);
    1252 }
    1253 
    1254 /** Prints list of zones. */
     1227        irq_spinlock_unlock(&zones.lock, true);
     1228}
     1229
     1230/** Prints list of zones.
     1231 *
     1232 */
    12551233void zones_print_list(void)
    12561234{
     
    12781256        size_t i;
    12791257        for (i = 0;; i++) {
    1280                 ipl_t ipl = interrupts_disable();
    1281                 spinlock_lock(&zones.lock);
     1258                irq_spinlock_lock(&zones.lock, true);
    12821259               
    12831260                if (i >= zones.count) {
    1284                         spinlock_unlock(&zones.lock);
    1285                         interrupts_restore(ipl);
     1261                        irq_spinlock_unlock(&zones.lock, true);
    12861262                        break;
    12871263                }
     
    12931269                size_t busy_count = zones.info[i].busy_count;
    12941270               
    1295                 spinlock_unlock(&zones.lock);
    1296                 interrupts_restore(ipl);
     1271                irq_spinlock_unlock(&zones.lock, true);
    12971272               
    12981273                bool available = zone_flags_available(flags);
     
    13281303void zone_print_one(size_t num)
    13291304{
    1330         ipl_t ipl = interrupts_disable();
    1331         spinlock_lock(&zones.lock);
     1305        irq_spinlock_lock(&zones.lock, true);
    13321306        size_t znum = (size_t) -1;
    13331307       
     
    13411315       
    13421316        if (znum == (size_t) -1) {
    1343                 spinlock_unlock(&zones.lock);
    1344                 interrupts_restore(ipl);
     1317                irq_spinlock_unlock(&zones.lock, true);
    13451318                printf("Zone not found.\n");
    13461319                return;
     
    13531326        size_t busy_count = zones.info[i].busy_count;
    13541327       
    1355         spinlock_unlock(&zones.lock);
    1356         interrupts_restore(ipl);
     1328        irq_spinlock_unlock(&zones.lock, true);
    13571329       
    13581330        bool available = zone_flags_available(flags);
  • kernel/generic/src/mm/page.c

    r666f492 rda1bafb  
    3333/**
    3434 * @file
    35  * @brief       Virtual Address Translation subsystem.
     35 * @brief Virtual Address Translation subsystem.
    3636 *
    3737 * This file contains code for creating, destroying and searching
     
    3939 * Functions here are mere wrappers that call the real implementation.
    4040 * They however, define the single interface.
     41 *
    4142 */
    4243
     
    5556 * will do an implicit serialization by virtue of running the TLB shootdown
    5657 * interrupt handler.
     58 *
    5759 */
    5860
     
    8385 * of page boundaries.
    8486 *
    85  * @param s             Address of the structure.
    86  * @param size          Size of the structure.
     87 * @param addr Address of the structure.
     88 * @param size Size of the structure.
     89 *
    8790 */
    88 void map_structure(uintptr_t s, size_t size)
     91void map_structure(uintptr_t addr, size_t size)
    8992{
    90         int i, cnt, length;
    91 
    92         length = size + (s - (s & ~(PAGE_SIZE - 1)));
    93         cnt = length / PAGE_SIZE + (length % PAGE_SIZE > 0);
    94 
     93        size_t length = size + (addr - (addr & ~(PAGE_SIZE - 1)));
     94        size_t cnt = length / PAGE_SIZE + (length % PAGE_SIZE > 0);
     95       
     96        size_t i;
    9597        for (i = 0; i < cnt; i++)
    96                 page_mapping_insert(AS_KERNEL, s + i * PAGE_SIZE,
    97                     s + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE);
    98 
     98                page_mapping_insert(AS_KERNEL, addr + i * PAGE_SIZE,
     99                    addr + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE);
     100       
    99101        /* Repel prefetched accesses to the old mapping. */
    100102        memory_barrier();
     
    108110 * The page table must be locked and interrupts must be disabled.
    109111 *
    110  * @param as            Address space to wich page belongs.
    111  * @param page          Virtual address of the page to be mapped.
    112  * @param frame         Physical address of memory frame to which the mapping is
    113  *                      done.
    114  * @param flags         Flags to be used for mapping.
     112 * @param as    Address space to wich page belongs.
     113 * @param page  Virtual address of the page to be mapped.
     114 * @param frame Physical address of memory frame to which the mapping is
     115 *              done.
     116 * @param flags Flags to be used for mapping.
     117 *
    115118 */
    116 void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags)
     119void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame,
     120    unsigned int flags)
    117121{
    118122        ASSERT(page_mapping_operations);
     
    133137 * The page table must be locked and interrupts must be disabled.
    134138 *
    135  * @param as            Address space to wich page belongs.
    136  * @param page          Virtual address of the page to be demapped.
     139 * @param as   Address space to wich page belongs.
     140 * @param page Virtual address of the page to be demapped.
     141 *
    137142 */
    138143void page_mapping_remove(as_t *as, uintptr_t page)
     
    142147       
    143148        page_mapping_operations->mapping_remove(as, page);
    144 
     149       
    145150        /* Repel prefetched accesses to the old mapping. */
    146151        memory_barrier();
     
    153158 * The page table must be locked and interrupts must be disabled.
    154159 *
    155  * @param as            Address space to wich page belongs.
    156  * @param page          Virtual page.
     160 * @param as   Address space to wich page belongs.
     161 * @param page Virtual page.
    157162 *
    158  * @return              NULL if there is no such mapping; requested mapping
    159  *                      otherwise.
     163 * @return NULL if there is no such mapping; requested mapping
     164 *         otherwise.
     165 *
    160166 */
    161167pte_t *page_mapping_find(as_t *as, uintptr_t page)
     
    163169        ASSERT(page_mapping_operations);
    164170        ASSERT(page_mapping_operations->mapping_find);
    165 
     171       
    166172        return page_mapping_operations->mapping_find(as, page);
    167173}
  • kernel/generic/src/mm/slab.c

    r666f492 rda1bafb  
    3333/**
    3434 * @file
    35  * @brief       Slab allocator.
     35 * @brief Slab allocator.
    3636 *
    3737 * The slab allocator is closely modelled after OpenSolaris slab allocator.
     
    5050 *
    5151 * The slab allocator supports per-CPU caches ('magazines') to facilitate
    52  * good SMP scaling. 
     52 * good SMP scaling.
    5353 *
    5454 * When a new object is being allocated, it is first checked, if it is
     
    6565 * thrashing when somebody is allocating/deallocating 1 item at the magazine
    6666 * size boundary. LIFO order is enforced, which should avoid fragmentation
    67  * as much as possible. 
    68  * 
     67 * as much as possible.
     68 *
    6969 * Every cache contains list of full slabs and list of partially full slabs.
    7070 * Empty slabs are immediately freed (thrashing will be avoided because
    71  * of magazines). 
     71 * of magazines).
    7272 *
    7373 * The slab information structure is kept inside the data area, if possible.
     
    9595 *
    9696 * @todo
    97  * it might be good to add granularity of locks even to slab level,
     97 * It might be good to add granularity of locks even to slab level,
    9898 * we could then try_spinlock over all partial slabs and thus improve
    99  * scalability even on slab level
     99 * scalability even on slab level.
     100 *
    100101 */
    101102
     
    114115#include <macros.h>
    115116
    116 SPINLOCK_INITIALIZE(slab_cache_lock);
     117IRQ_SPINLOCK_STATIC_INITIALIZE(slab_cache_lock);
    117118static LIST_INITIALIZE(slab_cache_list);
    118119
    119120/** Magazine cache */
    120121static slab_cache_t mag_cache;
     122
    121123/** Cache for cache descriptors */
    122124static slab_cache_t slab_cache_cache;
     125
    123126/** Cache for external slab descriptors
    124127 * This time we want per-cpu cache, so do not make it static
     
    128131 */
    129132static slab_cache_t *slab_extern_cache;
     133
    130134/** Caches for malloc */
    131135static slab_cache_t *malloc_caches[SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1];
     136
    132137static const char *malloc_names[] =  {
    133138        "malloc-16",
     
    154159/** Slab descriptor */
    155160typedef struct {
    156         slab_cache_t *cache;    /**< Pointer to parent cache. */
    157         link_t link;            /**< List of full/partial slabs. */
    158         void *start;            /**< Start address of first available item. */
    159         size_t available;       /**< Count of available items in this slab. */
    160         size_t nextavail;       /**< The index of next available item. */
     161        slab_cache_t *cache;  /**< Pointer to parent cache. */
     162        link_t link;          /**< List of full/partial slabs. */
     163        void *start;          /**< Start address of first available item. */
     164        size_t available;     /**< Count of available items in this slab. */
     165        size_t nextavail;     /**< The index of next available item. */
    161166} slab_t;
    162167
    163168#ifdef CONFIG_DEBUG
    164 static int _slab_initialized = 0;
     169static unsigned int _slab_initialized = 0;
    165170#endif
    166171
    167172/**************************************/
    168173/* Slab allocation functions          */
    169 
    170 /**
    171  * Allocate frames for slab space and initialize
    172  *
    173  */
    174 static slab_t *slab_space_alloc(slab_cache_t *cache, int flags)
    175 {
    176         void *data;
     174/**************************************/
     175
     176/** Allocate frames for slab space and initialize
     177 *
     178 */
     179static slab_t *slab_space_alloc(slab_cache_t *cache, unsigned int flags)
     180{
     181       
     182       
     183        size_t zone = 0;
     184       
     185        void *data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
     186        if (!data) {
     187                return NULL;
     188        }
     189       
    177190        slab_t *slab;
    178191        size_t fsize;
    179         unsigned int i;
    180         size_t zone = 0;
    181        
    182         data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
    183         if (!data) {
    184                 return NULL;
    185         }
     192       
    186193        if (!(cache->flags & SLAB_CACHE_SLINSIDE)) {
    187194                slab = slab_alloc(slab_extern_cache, flags);
     
    196203       
    197204        /* Fill in slab structures */
    198         for (i = 0; i < ((unsigned int) 1 << cache->order); i++)
     205        size_t i;
     206        for (i = 0; i < ((size_t) 1 << cache->order); i++)
    199207                frame_set_parent(ADDR2PFN(KA2PA(data)) + i, slab, zone);
    200 
     208       
    201209        slab->start = data;
    202210        slab->available = cache->objects;
    203211        slab->nextavail = 0;
    204212        slab->cache = cache;
    205 
     213       
    206214        for (i = 0; i < cache->objects; i++)
    207                 *((int *) (slab->start + i*cache->size)) = i + 1;
    208 
     215                *((size_t *) (slab->start + i * cache->size)) = i + 1;
     216       
    209217        atomic_inc(&cache->allocated_slabs);
    210218        return slab;
    211219}
    212220
    213 /**
    214  * Deallocate space associated with slab
     221/** Deallocate space associated with slab
    215222 *
    216223 * @return number of freed frames
     224 *
    217225 */
    218226static size_t slab_space_free(slab_cache_t *cache, slab_t *slab)
    219227{
    220228        frame_free(KA2PA(slab->start));
    221         if (! (cache->flags & SLAB_CACHE_SLINSIDE))
     229        if (!(cache->flags & SLAB_CACHE_SLINSIDE))
    222230                slab_free(slab_extern_cache, slab);
    223 
     231       
    224232        atomic_dec(&cache->allocated_slabs);
    225233       
    226         return 1 << cache->order;
     234        return (1 << cache->order);
    227235}
    228236
    229237/** Map object to slab structure */
    230 static slab_t * obj2slab(void *obj)
     238static slab_t *obj2slab(void *obj)
    231239{
    232240        return (slab_t *) frame_get_parent(ADDR2PFN(KA2PA(obj)), 0);
    233241}
    234242
    235 /**************************************/
     243/******************/
    236244/* Slab functions */
    237 
    238 
    239 /**
    240  * Return object to slab and call a destructor
     245/******************/
     246
     247/** Return object to slab and call a destructor
    241248 *
    242249 * @param slab If the caller knows directly slab of the object, otherwise NULL
    243250 *
    244251 * @return Number of freed pages
     252 *
    245253 */
    246254static size_t slab_obj_destroy(slab_cache_t *cache, void *obj, slab_t *slab)
    247255{
    248         int freed = 0;
    249 
    250256        if (!slab)
    251257                slab = obj2slab(obj);
    252 
     258       
    253259        ASSERT(slab->cache == cache);
    254 
     260       
     261        size_t freed = 0;
     262       
    255263        if (cache->destructor)
    256264                freed = cache->destructor(obj);
     
    258266        spinlock_lock(&cache->slablock);
    259267        ASSERT(slab->available < cache->objects);
    260 
    261         *((int *)obj) = slab->nextavail;
     268       
     269        *((size_t *) obj) = slab->nextavail;
    262270        slab->nextavail = (obj - slab->start) / cache->size;
    263271        slab->available++;
    264 
     272       
    265273        /* Move it to correct list */
    266274        if (slab->available == cache->objects) {
     
    268276                list_remove(&slab->link);
    269277                spinlock_unlock(&cache->slablock);
    270 
     278               
    271279                return freed + slab_space_free(cache, slab);
    272 
    273280        } else if (slab->available == 1) {
    274281                /* It was in full, move to partial */
     
    276283                list_prepend(&slab->link, &cache->partial_slabs);
    277284        }
     285       
    278286        spinlock_unlock(&cache->slablock);
    279287        return freed;
    280288}
    281289
    282 /**
    283  * Take new object from slab or create new if needed
     290/** Take new object from slab or create new if needed
    284291 *
    285292 * @return Object address or null
     293 *
    286294 */
    287295static void *slab_obj_create(slab_cache_t *cache, int flags)
    288296{
     297        spinlock_lock(&cache->slablock);
     298       
    289299        slab_t *slab;
    290         void *obj;
    291 
    292         spinlock_lock(&cache->slablock);
    293 
     300       
    294301        if (list_empty(&cache->partial_slabs)) {
    295                 /* Allow recursion and reclaiming
     302                /*
     303                 * Allow recursion and reclaiming
    296304                 * - this should work, as the slab control structures
    297305                 *   are small and do not need to allocate with anything
    298306                 *   other than frame_alloc when they are allocating,
    299307                 *   that's why we should get recursion at most 1-level deep
     308                 *
    300309                 */
    301310                spinlock_unlock(&cache->slablock);
     
    303312                if (!slab)
    304313                        return NULL;
     314               
    305315                spinlock_lock(&cache->slablock);
    306316        } else {
     
    309319                list_remove(&slab->link);
    310320        }
    311         obj = slab->start + slab->nextavail * cache->size;
    312         slab->nextavail = *((int *)obj);
     321       
     322        void *obj = slab->start + slab->nextavail * cache->size;
     323        slab->nextavail = *((size_t *) obj);
    313324        slab->available--;
    314 
     325       
    315326        if (!slab->available)
    316327                list_prepend(&slab->link, &cache->full_slabs);
    317328        else
    318329                list_prepend(&slab->link, &cache->partial_slabs);
    319 
     330       
    320331        spinlock_unlock(&cache->slablock);
    321 
    322         if (cache->constructor && cache->constructor(obj, flags)) {
     332       
     333        if ((cache->constructor) && (cache->constructor(obj, flags))) {
    323334                /* Bad, bad, construction failed */
    324335                slab_obj_destroy(cache, obj, slab);
    325336                return NULL;
    326337        }
     338       
    327339        return obj;
    328340}
    329341
    330 /**************************************/
     342/****************************/
    331343/* CPU-Cache slab functions */
    332 
    333 /**
    334  * Finds a full magazine in cache, takes it from list
    335  * and returns it
    336  *
    337  * @param first If true, return first, else last mag
    338  */
    339 static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, int first)
     344/****************************/
     345
     346/** Find a full magazine in cache, take it from list and return it
     347 *
     348 * @param first If true, return first, else last mag.
     349 *
     350 */
     351static slab_magazine_t *get_mag_from_cache(slab_cache_t *cache, bool first)
    340352{
    341353        slab_magazine_t *mag = NULL;
    342354        link_t *cur;
    343 
     355       
    344356        spinlock_lock(&cache->maglock);
    345357        if (!list_empty(&cache->magazines)) {
     
    348360                else
    349361                        cur = cache->magazines.prev;
     362               
    350363                mag = list_get_instance(cur, slab_magazine_t, link);
    351364                list_remove(&mag->link);
    352365                atomic_dec(&cache->magazine_counter);
    353366        }
     367       
    354368        spinlock_unlock(&cache->maglock);
    355369        return mag;
    356370}
    357371
    358 /** Prepend magazine to magazine list in cache */
     372/** Prepend magazine to magazine list in cache
     373 *
     374 */
    359375static void put_mag_to_cache(slab_cache_t *cache, slab_magazine_t *mag)
    360376{
    361377        spinlock_lock(&cache->maglock);
    362 
     378       
    363379        list_prepend(&mag->link, &cache->magazines);
    364380        atomic_inc(&cache->magazine_counter);
     
    367383}
    368384
    369 /**
    370  * Free all objects in magazine and free memory associated with magazine
     385/** Free all objects in magazine and free memory associated with magazine
    371386 *
    372387 * @return Number of freed pages
     388 *
    373389 */
    374390static size_t magazine_destroy(slab_cache_t *cache, slab_magazine_t *mag)
    375391{
    376         unsigned int i;
     392        size_t i;
    377393        size_t frames = 0;
    378 
     394       
    379395        for (i = 0; i < mag->busy; i++) {
    380396                frames += slab_obj_destroy(cache, mag->objs[i], NULL);
     
    383399       
    384400        slab_free(&mag_cache, mag);
    385 
     401       
    386402        return frames;
    387403}
    388404
    389 /**
    390  * Find full magazine, set it as current and return it
     405/** Find full magazine, set it as current and return it
    391406 *
    392407 * Assume cpu_magazine lock is held
     408 *
    393409 */
    394410static slab_magazine_t *get_full_current_mag(slab_cache_t *cache)
    395411{
    396         slab_magazine_t *cmag, *lastmag, *newmag;
    397 
    398         cmag = cache->mag_cache[CPU->id].current;
    399         lastmag = cache->mag_cache[CPU->id].last;
     412        slab_magazine_t *cmag = cache->mag_cache[CPU->id].current;
     413        slab_magazine_t *lastmag = cache->mag_cache[CPU->id].last;
     414       
    400415        if (cmag) { /* First try local CPU magazines */
    401416                if (cmag->busy)
    402417                        return cmag;
    403 
    404                 if (lastmag && lastmag->busy) {
     418               
     419                if ((lastmag) && (lastmag->busy)) {
    405420                        cache->mag_cache[CPU->id].current = lastmag;
    406421                        cache->mag_cache[CPU->id].last = cmag;
     
    408423                }
    409424        }
     425       
    410426        /* Local magazines are empty, import one from magazine list */
    411         newmag = get_mag_from_cache(cache, 1);
     427        slab_magazine_t *newmag = get_mag_from_cache(cache, 1);
    412428        if (!newmag)
    413429                return NULL;
    414 
     430       
    415431        if (lastmag)
    416432                magazine_destroy(cache, lastmag);
    417 
     433       
    418434        cache->mag_cache[CPU->id].last = cmag;
    419435        cache->mag_cache[CPU->id].current = newmag;
     436       
    420437        return newmag;
    421438}
    422439
    423 /**
    424  * Try to find object in CPU-cache magazines
     440/** Try to find object in CPU-cache magazines
    425441 *
    426442 * @return Pointer to object or NULL if not available
     443 *
    427444 */
    428445static void *magazine_obj_get(slab_cache_t *cache)
    429446{
    430         slab_magazine_t *mag;
    431         void *obj;
    432 
    433447        if (!CPU)
    434448                return NULL;
    435 
     449       
    436450        spinlock_lock(&cache->mag_cache[CPU->id].lock);
    437 
    438         mag = get_full_current_mag(cache);
     451       
     452        slab_magazine_t *mag = get_full_current_mag(cache);
    439453        if (!mag) {
    440454                spinlock_unlock(&cache->mag_cache[CPU->id].lock);
    441455                return NULL;
    442456        }
    443         obj = mag->objs[--mag->busy];
     457       
     458        void *obj = mag->objs[--mag->busy];
    444459        spinlock_unlock(&cache->mag_cache[CPU->id].lock);
     460       
    445461        atomic_dec(&cache->cached_objs);
    446462       
     
    448464}
    449465
    450 /**
    451  * Assure that the current magazine is empty, return pointer to it, or NULL if
    452  * no empty magazine is available and cannot be allocated
     466/** Assure that the current magazine is empty, return pointer to it,
     467 * or NULL if no empty magazine is available and cannot be allocated
    453468 *
    454469 * Assume mag_cache[CPU->id].lock is held
    455470 *
    456  * We have 2 magazines bound to processor.
    457  * First try the current.
    458  *  If full, try the last.
    459  *   If full, put to magazines list.
    460  *   allocate new, exchange last & current
     471 * We have 2 magazines bound to processor.
     472 * First try the current.
     473 * If full, try the last.
     474 * If full, put to magazines list.
    461475 *
    462476 */
    463477static slab_magazine_t *make_empty_current_mag(slab_cache_t *cache)
    464478{
    465         slab_magazine_t *cmag,*lastmag,*newmag;
    466 
    467         cmag = cache->mag_cache[CPU->id].current;
    468         lastmag = cache->mag_cache[CPU->id].last;
    469 
     479        slab_magazine_t *cmag = cache->mag_cache[CPU->id].current;
     480        slab_magazine_t *lastmag = cache->mag_cache[CPU->id].last;
     481       
    470482        if (cmag) {
    471483                if (cmag->busy < cmag->size)
    472484                        return cmag;
    473                 if (lastmag && lastmag->busy < lastmag->size) {
     485               
     486                if ((lastmag) && (lastmag->busy < lastmag->size)) {
    474487                        cache->mag_cache[CPU->id].last = cmag;
    475488                        cache->mag_cache[CPU->id].current = lastmag;
     
    477490                }
    478491        }
     492       
    479493        /* current | last are full | nonexistent, allocate new */
    480         /* We do not want to sleep just because of caching */
    481         /* Especially we do not want reclaiming to start, as
    482          * this would deadlock */
    483         newmag = slab_alloc(&mag_cache, FRAME_ATOMIC | FRAME_NO_RECLAIM);
     494       
     495        /*
     496         * We do not want to sleep just because of caching,
     497         * especially we do not want reclaiming to start, as
     498         * this would deadlock.
     499         *
     500         */
     501        slab_magazine_t *newmag = slab_alloc(&mag_cache,
     502            FRAME_ATOMIC | FRAME_NO_RECLAIM);
    484503        if (!newmag)
    485504                return NULL;
     505       
    486506        newmag->size = SLAB_MAG_SIZE;
    487507        newmag->busy = 0;
    488 
     508       
    489509        /* Flush last to magazine list */
    490510        if (lastmag)
    491511                put_mag_to_cache(cache, lastmag);
    492 
     512       
    493513        /* Move current as last, save new as current */
    494         cache->mag_cache[CPU->id].last = cmag; 
    495         cache->mag_cache[CPU->id].current = newmag;     
    496 
     514        cache->mag_cache[CPU->id].last = cmag;
     515        cache->mag_cache[CPU->id].current = newmag;
     516       
    497517        return newmag;
    498518}
    499519
    500 /**
    501  * Put object into CPU-cache magazine
    502  *
    503  * @return 0 - success, -1 - could not get memory
     520/** Put object into CPU-cache magazine
     521 *
     522 * @return 0 on success, -1 on no memory
     523 *
    504524 */
    505525static int magazine_obj_put(slab_cache_t *cache, void *obj)
    506526{
    507         slab_magazine_t *mag;
    508 
    509527        if (!CPU)
    510528                return -1;
    511 
     529       
    512530        spinlock_lock(&cache->mag_cache[CPU->id].lock);
    513 
    514         mag = make_empty_current_mag(cache);
     531       
     532        slab_magazine_t *mag = make_empty_current_mag(cache);
    515533        if (!mag) {
    516534                spinlock_unlock(&cache->mag_cache[CPU->id].lock);
     
    519537       
    520538        mag->objs[mag->busy++] = obj;
    521 
     539       
    522540        spinlock_unlock(&cache->mag_cache[CPU->id].lock);
     541       
    523542        atomic_inc(&cache->cached_objs);
     543       
    524544        return 0;
    525545}
    526546
    527 
    528 /**************************************/
     547/************************/
    529548/* Slab cache functions */
    530 
    531 /** Return number of objects that fit in certain cache size */
    532 static unsigned int comp_objects(slab_cache_t *cache)
     549/************************/
     550
     551/** Return number of objects that fit in certain cache size
     552 *
     553 */
     554static size_t comp_objects(slab_cache_t *cache)
    533555{
    534556        if (cache->flags & SLAB_CACHE_SLINSIDE)
    535                 return ((PAGE_SIZE << cache->order) - sizeof(slab_t)) /
    536                     cache->size;
    537         else 
     557                return ((PAGE_SIZE << cache->order)
     558                    - sizeof(slab_t)) / cache->size;
     559        else
    538560                return (PAGE_SIZE << cache->order) / cache->size;
    539561}
    540562
    541 /** Return wasted space in slab */
    542 static unsigned int badness(slab_cache_t *cache)
    543 {
    544         unsigned int objects;
    545         unsigned int ssize;
    546 
    547         objects = comp_objects(cache);
    548         ssize = PAGE_SIZE << cache->order;
     563/** Return wasted space in slab
     564 *
     565 */
     566static size_t badness(slab_cache_t *cache)
     567{
     568        size_t objects = comp_objects(cache);
     569        size_t ssize = PAGE_SIZE << cache->order;
     570       
    549571        if (cache->flags & SLAB_CACHE_SLINSIDE)
    550572                ssize -= sizeof(slab_t);
     573       
    551574        return ssize - objects * cache->size;
    552575}
    553576
    554 /**
    555  * Initialize mag_cache structure in slab cache
     577/** Initialize mag_cache structure in slab cache
     578 *
    556579 */
    557580static bool make_magcache(slab_cache_t *cache)
    558581{
    559         unsigned int i;
    560        
    561582        ASSERT(_slab_initialized >= 2);
    562 
     583       
    563584        cache->mag_cache = malloc(sizeof(slab_mag_cache_t) * config.cpu_count,
    564585            FRAME_ATOMIC);
    565586        if (!cache->mag_cache)
    566587                return false;
    567 
     588       
     589        size_t i;
    568590        for (i = 0; i < config.cpu_count; i++) {
    569591                memsetb(&cache->mag_cache[i], sizeof(cache->mag_cache[i]), 0);
    570592                spinlock_initialize(&cache->mag_cache[i].lock,
    571                     "slab_maglock_cpu");
    572         }
     593                    "slab.cache.mag_cache[].lock");
     594        }
     595       
    573596        return true;
    574597}
    575598
    576 /** Initialize allocated memory as a slab cache */
     599/** Initialize allocated memory as a slab cache
     600 *
     601 */
    577602static void _slab_cache_create(slab_cache_t *cache, const char *name,
    578     size_t size, size_t align, int (*constructor)(void *obj, int kmflag),
    579     int (*destructor)(void *obj), int flags)
    580 {
    581         int pages;
    582         ipl_t ipl;
    583 
     603    size_t size, size_t align, int (*constructor)(void *obj,
     604    unsigned int kmflag), size_t (*destructor)(void *obj), unsigned int flags)
     605{
    584606        memsetb(cache, sizeof(*cache), 0);
    585607        cache->name = name;
    586 
     608       
    587609        if (align < sizeof(unative_t))
    588610                align = sizeof(unative_t);
     611       
    589612        size = ALIGN_UP(size, align);
    590                
     613       
    591614        cache->size = size;
    592 
    593615        cache->constructor = constructor;
    594616        cache->destructor = destructor;
    595617        cache->flags = flags;
    596 
     618       
    597619        list_initialize(&cache->full_slabs);
    598620        list_initialize(&cache->partial_slabs);
    599621        list_initialize(&cache->magazines);
    600         spinlock_initialize(&cache->slablock, "slab_lock");
    601         spinlock_initialize(&cache->maglock, "slab_maglock");
     622       
     623        spinlock_initialize(&cache->slablock, "slab.cache.slablock");
     624        spinlock_initialize(&cache->maglock, "slab.cache.maglock");
     625       
    602626        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    603627                (void) make_magcache(cache);
    604 
     628       
    605629        /* Compute slab sizes, object counts in slabs etc. */
    606630        if (cache->size < SLAB_INSIDE_SIZE)
    607631                cache->flags |= SLAB_CACHE_SLINSIDE;
    608 
     632       
    609633        /* Minimum slab order */
    610         pages = SIZE2FRAMES(cache->size);
     634        size_t pages = SIZE2FRAMES(cache->size);
     635       
    611636        /* We need the 2^order >= pages */
    612637        if (pages == 1)
     
    614639        else
    615640                cache->order = fnzb(pages - 1) + 1;
    616 
    617         while (badness(cache) > SLAB_MAX_BADNESS(cache)) {
     641       
     642        while (badness(cache) > SLAB_MAX_BADNESS(cache))
    618643                cache->order += 1;
    619         }
     644       
    620645        cache->objects = comp_objects(cache);
     646       
    621647        /* If info fits in, put it inside */
    622648        if (badness(cache) > sizeof(slab_t))
    623649                cache->flags |= SLAB_CACHE_SLINSIDE;
    624 
     650       
    625651        /* Add cache to cache list */
    626         ipl = interrupts_disable();
    627         spinlock_lock(&slab_cache_lock);
    628 
     652        irq_spinlock_lock(&slab_cache_lock, true);
    629653        list_append(&cache->link, &slab_cache_list);
    630 
    631         spinlock_unlock(&slab_cache_lock);
    632         interrupts_restore(ipl);
    633 }
    634 
    635 /** Create slab cache */
     654        irq_spinlock_unlock(&slab_cache_lock, true);
     655}
     656
     657/** Create slab cache
     658 *
     659 */
    636660slab_cache_t *slab_cache_create(const char *name, size_t size, size_t align,
    637     int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
    638     int flags)
    639 {
    640         slab_cache_t *cache;
    641 
    642         cache = slab_alloc(&slab_cache_cache, 0);
     661    int (*constructor)(void *obj, unsigned int kmflag),
     662    size_t (*destructor)(void *obj), unsigned int flags)
     663{
     664        slab_cache_t *cache = slab_alloc(&slab_cache_cache, 0);
    643665        _slab_cache_create(cache, name, size, align, constructor, destructor,
    644666            flags);
     667       
    645668        return cache;
    646669}
    647670
    648 /**
    649  * Reclaim space occupied by objects that are already free
     671/** Reclaim space occupied by objects that are already free
    650672 *
    651673 * @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing
     674 *
    652675 * @return Number of freed pages
    653  */
    654 static size_t _slab_reclaim(slab_cache_t *cache, int flags)
    655 {
    656         unsigned int i;
     676 *
     677 */
     678static size_t _slab_reclaim(slab_cache_t *cache, unsigned int flags)
     679{
     680        if (cache->flags & SLAB_CACHE_NOMAGAZINE)
     681                return 0; /* Nothing to do */
     682       
     683        /*
     684         * We count up to original magazine count to avoid
     685         * endless loop
     686         */
     687        atomic_count_t magcount = atomic_get(&cache->magazine_counter);
     688       
    657689        slab_magazine_t *mag;
    658690        size_t frames = 0;
    659         int magcount;
    660        
    661         if (cache->flags & SLAB_CACHE_NOMAGAZINE)
    662                 return 0; /* Nothing to do */
    663 
    664         /* We count up to original magazine count to avoid
    665          * endless loop
    666          */
    667         magcount = atomic_get(&cache->magazine_counter);
    668         while (magcount-- && (mag=get_mag_from_cache(cache, 0))) {
    669                 frames += magazine_destroy(cache,mag);
    670                 if (!(flags & SLAB_RECLAIM_ALL) && frames)
     691       
     692        while ((magcount--) && (mag = get_mag_from_cache(cache, 0))) {
     693                frames += magazine_destroy(cache, mag);
     694                if ((!(flags & SLAB_RECLAIM_ALL)) && (frames))
    671695                        break;
    672696        }
     
    675699                /* Free cpu-bound magazines */
    676700                /* Destroy CPU magazines */
     701                size_t i;
    677702                for (i = 0; i < config.cpu_count; i++) {
    678703                        spinlock_lock(&cache->mag_cache[i].lock);
    679 
     704                       
    680705                        mag = cache->mag_cache[i].current;
    681706                        if (mag)
     
    687712                                frames += magazine_destroy(cache, mag);
    688713                        cache->mag_cache[i].last = NULL;
    689 
     714                       
    690715                        spinlock_unlock(&cache->mag_cache[i].lock);
    691716                }
    692717        }
    693 
     718       
    694719        return frames;
    695720}
    696721
    697 /** Check that there are no slabs and remove cache from system  */
     722/** Check that there are no slabs and remove cache from system
     723 *
     724 */
    698725void slab_cache_destroy(slab_cache_t *cache)
    699726{
    700         ipl_t ipl;
    701 
    702         /* First remove cache from link, so that we don't need
     727        /*
     728         * First remove cache from link, so that we don't need
    703729         * to disable interrupts later
     730         *
    704731         */
    705 
    706         ipl = interrupts_disable();
    707         spinlock_lock(&slab_cache_lock);
    708 
     732        irq_spinlock_lock(&slab_cache_lock, true);
    709733        list_remove(&cache->link);
    710 
    711         spinlock_unlock(&slab_cache_lock);
    712         interrupts_restore(ipl);
    713 
    714         /* Do not lock anything, we assume the software is correct and
    715          * does not touch the cache when it decides to destroy it */
     734        irq_spinlock_unlock(&slab_cache_lock, true);
     735       
     736        /*
     737         * Do not lock anything, we assume the software is correct and
     738         * does not touch the cache when it decides to destroy it
     739         *
     740         */
    716741       
    717742        /* Destroy all magazines */
    718743        _slab_reclaim(cache, SLAB_RECLAIM_ALL);
    719 
     744       
    720745        /* All slabs must be empty */
    721         if (!list_empty(&cache->full_slabs) ||
    722             !list_empty(&cache->partial_slabs))
     746        if ((!list_empty(&cache->full_slabs)) ||
     747            (!list_empty(&cache->partial_slabs)))
    723748                panic("Destroying cache that is not empty.");
    724 
     749       
    725750        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    726751                free(cache->mag_cache);
     752       
    727753        slab_free(&slab_cache_cache, cache);
    728754}
    729755
    730 /** Allocate new object from cache - if no flags given, always returns memory */
    731 void *slab_alloc(slab_cache_t *cache, int flags)
    732 {
    733         ipl_t ipl;
     756/** Allocate new object from cache - if no flags given, always returns memory
     757 *
     758 */
     759void *slab_alloc(slab_cache_t *cache, unsigned int flags)
     760{
     761        /* Disable interrupts to avoid deadlocks with interrupt handlers */
     762        ipl_t ipl = interrupts_disable();
     763       
    734764        void *result = NULL;
    735765       
    736         /* Disable interrupts to avoid deadlocks with interrupt handlers */
    737         ipl = interrupts_disable();
    738 
    739         if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) {
     766        if (!(cache->flags & SLAB_CACHE_NOMAGAZINE))
    740767                result = magazine_obj_get(cache);
    741         }
     768       
    742769        if (!result)
    743770                result = slab_obj_create(cache, flags);
    744 
     771       
    745772        interrupts_restore(ipl);
    746 
     773       
    747774        if (result)
    748775                atomic_inc(&cache->allocated_objs);
    749 
     776       
    750777        return result;
    751778}
    752779
    753 /** Return object to cache, use slab if known  */
     780/** Return object to cache, use slab if known
     781 *
     782 */
    754783static void _slab_free(slab_cache_t *cache, void *obj, slab_t *slab)
    755784{
    756         ipl_t ipl;
    757 
    758         ipl = interrupts_disable();
    759 
     785        ipl_t ipl = interrupts_disable();
     786       
    760787        if ((cache->flags & SLAB_CACHE_NOMAGAZINE) ||
    761             magazine_obj_put(cache, obj)) {
     788            (magazine_obj_put(cache, obj)))
    762789                slab_obj_destroy(cache, obj, slab);
    763 
    764         }
     790       
    765791        interrupts_restore(ipl);
    766792        atomic_dec(&cache->allocated_objs);
    767793}
    768794
    769 /** Return slab object to cache */
     795/** Return slab object to cache
     796 *
     797 */
    770798void slab_free(slab_cache_t *cache, void *obj)
    771799{
     
    773801}
    774802
    775 /* Go through all caches and reclaim what is possible */
    776 size_t slab_reclaim(int flags)
    777 {
    778         slab_cache_t *cache;
     803/** Go through all caches and reclaim what is possible
     804 *
     805 * Interrupts must be disabled before calling this function,
     806 * otherwise  memory allocation from interrupts can deadlock.
     807 *
     808 */
     809size_t slab_reclaim(unsigned int flags)
     810{
     811        irq_spinlock_lock(&slab_cache_lock, false);
     812       
     813        size_t frames = 0;
    779814        link_t *cur;
    780         size_t frames = 0;
    781 
    782         spinlock_lock(&slab_cache_lock);
    783 
    784         /* TODO: Add assert, that interrupts are disabled, otherwise
    785          * memory allocation from interrupts can deadlock.
    786          */
    787 
    788815        for (cur = slab_cache_list.next; cur != &slab_cache_list;
    789816            cur = cur->next) {
    790                 cache = list_get_instance(cur, slab_cache_t, link);
     817                slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
    791818                frames += _slab_reclaim(cache, flags);
    792819        }
    793 
    794         spinlock_unlock(&slab_cache_lock);
    795 
     820       
     821        irq_spinlock_unlock(&slab_cache_lock, false);
     822       
    796823        return frames;
    797824}
    798825
    799 
    800 /* Print list of slabs */
     826/* Print list of slabs
     827 *
     828 */
    801829void slab_print_list(void)
    802830{
    803         int skip = 0;
    804 
    805         printf("slab name        size     pages  obj/pg slabs  cached allocated"
     831        printf("slab name        size     pages  obj/pg   slabs  cached allocated"
    806832            " ctl\n");
    807         printf("---------------- -------- ------ ------ ------ ------ ---------"
     833        printf("---------------- -------- ------ -------- ------ ------ ---------"
    808834            " ---\n");
    809 
     835       
     836        size_t skip = 0;
    810837        while (true) {
    811                 slab_cache_t *cache;
    812                 link_t *cur;
    813                 ipl_t ipl;
    814                 int i;
    815 
    816838                /*
    817839                 * We must not hold the slab_cache_lock spinlock when printing
     
    836858                 * statistics.
    837859                 */
    838 
    839                 ipl = interrupts_disable();
    840                 spinlock_lock(&slab_cache_lock);
    841 
     860               
     861                irq_spinlock_lock(&slab_cache_lock, true);
     862               
     863                link_t *cur;
     864                size_t i;
    842865                for (i = 0, cur = slab_cache_list.next;
    843                     i < skip && cur != &slab_cache_list;
    844                     i++, cur = cur->next)
    845                         ;
    846 
     866                    (i < skip) && (cur != &slab_cache_list);
     867                    i++, cur = cur->next);
     868               
    847869                if (cur == &slab_cache_list) {
    848                         spinlock_unlock(&slab_cache_lock);
    849                         interrupts_restore(ipl);
     870                        irq_spinlock_unlock(&slab_cache_lock, true);
    850871                        break;
    851872                }
    852 
     873               
    853874                skip++;
    854 
    855                 cache = list_get_instance(cur, slab_cache_t, link);
    856 
     875               
     876                slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
     877               
    857878                const char *name = cache->name;
    858879                uint8_t order = cache->order;
    859880                size_t size = cache->size;
    860                 unsigned int objects = cache->objects;
     881                size_t objects = cache->objects;
    861882                long allocated_slabs = atomic_get(&cache->allocated_slabs);
    862883                long cached_objs = atomic_get(&cache->cached_objs);
    863884                long allocated_objs = atomic_get(&cache->allocated_objs);
    864                 int flags = cache->flags;
    865                
    866                 spinlock_unlock(&slab_cache_lock);
    867                 interrupts_restore(ipl);
    868                
    869                 printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n",
     885                unsigned int flags = cache->flags;
     886               
     887                irq_spinlock_unlock(&slab_cache_lock, true);
     888               
     889                printf("%-16s %8" PRIs " %6u %8" PRIs " %6ld %6ld %9ld %-3s\n",
    870890                    name, size, (1 << order), objects, allocated_slabs,
    871891                    cached_objs, allocated_objs,
     
    876896void slab_cache_init(void)
    877897{
    878         int i, size;
    879 
    880898        /* Initialize magazine cache */
    881899        _slab_cache_create(&mag_cache, "slab_magazine",
     
    883901            sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE |
    884902            SLAB_CACHE_SLINSIDE);
     903       
    885904        /* Initialize slab_cache cache */
    886905        _slab_cache_create(&slab_cache_cache, "slab_cache",
    887906            sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL,
    888907            SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
     908       
    889909        /* Initialize external slab cache */
    890910        slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0,
    891911            NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED);
    892 
     912       
    893913        /* Initialize structures for malloc */
     914        size_t i;
     915        size_t size;
     916       
    894917        for (i = 0, size = (1 << SLAB_MIN_MALLOC_W);
    895918            i < (SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1);
     
    898921                    NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    899922        }
     923       
    900924#ifdef CONFIG_DEBUG
    901925        _slab_initialized = 1;
     
    906930 *
    907931 * Kernel calls this function, when it knows the real number of
    908  * processors.
    909  * Allocate slab for cpucache and enable it on all existing
    910  * slabs that are SLAB_CACHE_MAGDEFERRED
     932 * processors. Allocate slab for cpucache and enable it on all
     933 * existing slabs that are SLAB_CACHE_MAGDEFERRED
     934 *
    911935 */
    912936void slab_enable_cpucache(void)
    913937{
    914         link_t *cur;
    915         slab_cache_t *s;
    916 
    917938#ifdef CONFIG_DEBUG
    918939        _slab_initialized = 2;
    919940#endif
    920 
    921         spinlock_lock(&slab_cache_lock);
    922        
     941       
     942        irq_spinlock_lock(&slab_cache_lock, false);
     943       
     944        link_t *cur;
    923945        for (cur = slab_cache_list.next; cur != &slab_cache_list;
    924             cur = cur->next){
    925                 s = list_get_instance(cur, slab_cache_t, link);
    926                 if ((s->flags & SLAB_CACHE_MAGDEFERRED) !=
     946            cur = cur->next) {
     947                slab_cache_t *slab = list_get_instance(cur, slab_cache_t, link);
     948                if ((slab->flags & SLAB_CACHE_MAGDEFERRED) !=
    927949                    SLAB_CACHE_MAGDEFERRED)
    928950                        continue;
    929                 (void) make_magcache(s);
    930                 s->flags &= ~SLAB_CACHE_MAGDEFERRED;
    931         }
    932 
    933         spinlock_unlock(&slab_cache_lock);
    934 }
    935 
    936 /**************************************/
    937 /* kalloc/kfree functions             */
    938 void *malloc(unsigned int size, int flags)
     951               
     952                (void) make_magcache(slab);
     953                slab->flags &= ~SLAB_CACHE_MAGDEFERRED;
     954        }
     955       
     956        irq_spinlock_unlock(&slab_cache_lock, false);
     957}
     958
     959void *malloc(size_t size, unsigned int flags)
    939960{
    940961        ASSERT(_slab_initialized);
     
    943964        if (size < (1 << SLAB_MIN_MALLOC_W))
    944965                size = (1 << SLAB_MIN_MALLOC_W);
    945 
    946         int idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
    947 
     966       
     967        uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
     968       
    948969        return slab_alloc(malloc_caches[idx], flags);
    949970}
    950971
    951 void *realloc(void *ptr, unsigned int size, int flags)
     972void *realloc(void *ptr, size_t size, unsigned int flags)
    952973{
    953974        ASSERT(_slab_initialized);
     
    959980                if (size < (1 << SLAB_MIN_MALLOC_W))
    960981                        size = (1 << SLAB_MIN_MALLOC_W);
    961                 int idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
     982                uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
    962983               
    963984                new_ptr = slab_alloc(malloc_caches[idx], flags);
     
    9801001        if (!ptr)
    9811002                return;
    982 
     1003       
    9831004        slab_t *slab = obj2slab(ptr);
    9841005        _slab_free(slab->cache, ptr, slab);
  • kernel/generic/src/mm/tlb.c

    r666f492 rda1bafb  
    3333/**
    3434 * @file
    35  * @brief       Generic TLB shootdown algorithm.
     35 * @brief Generic TLB shootdown algorithm.
    3636 *
    3737 * The algorithm implemented here is based on the CMU TLB shootdown
     
    5353#include <cpu.h>
    5454
    55 /**
    56  * This lock is used for synchronisation between sender and
    57  * recipients of TLB shootdown message. It must be acquired
    58  * before CPU structure lock.
    59  */
    60 SPINLOCK_INITIALIZE(tlblock);
    61 
    6255void tlb_init(void)
    6356{
     
    6659
    6760#ifdef CONFIG_SMP
     61
     62/**
     63 * This lock is used for synchronisation between sender and
     64 * recipients of TLB shootdown message. It must be acquired
     65 * before CPU structure lock.
     66 *
     67 */
     68IRQ_SPINLOCK_STATIC_INITIALIZE(tlblock);
    6869
    6970/** Send TLB shootdown message.
     
    7879 * @param page Virtual page address, if required by type.
    7980 * @param count Number of pages, if required by type.
     81 *
    8082 */
    8183void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid,
    8284    uintptr_t page, size_t count)
    8385{
    84         unsigned int i;
    85 
    86         CPU->tlb_active = 0;
    87         spinlock_lock(&tlblock);
     86        CPU->tlb_active = false;
     87        irq_spinlock_lock(&tlblock, false);
    8888       
     89        size_t i;
    8990        for (i = 0; i < config.cpu_count; i++) {
    9091                cpu_t *cpu;
     
    9293                if (i == CPU->id)
    9394                        continue;
    94 
     95               
    9596                cpu = &cpus[i];
    96                 spinlock_lock(&cpu->lock);
     97                irq_spinlock_lock(&cpu->lock, false);
    9798                if (cpu->tlb_messages_count == TLB_MESSAGE_QUEUE_LEN) {
    9899                        /*
     
    115116                        cpu->tlb_messages[idx].count = count;
    116117                }
    117                 spinlock_unlock(&cpu->lock);
     118                irq_spinlock_unlock(&cpu->lock, false);
    118119        }
    119120       
    120121        tlb_shootdown_ipi_send();
    121 
    122 busy_wait:     
     122       
     123busy_wait:
    123124        for (i = 0; i < config.cpu_count; i++)
    124125                if (cpus[i].tlb_active)
     
    126127}
    127128
    128 /** Finish TLB shootdown sequence. */
     129/** Finish TLB shootdown sequence.
     130 *
     131 */
    129132void tlb_shootdown_finalize(void)
    130133{
    131         spinlock_unlock(&tlblock);
    132         CPU->tlb_active = 1;
     134        irq_spinlock_unlock(&tlblock, false);
     135        CPU->tlb_active = true;
    133136}
    134137
     
    138141}
    139142
    140 /** Receive TLB shootdown message. */
     143/** Receive TLB shootdown message.
     144 *
     145 */
    141146void tlb_shootdown_ipi_recv(void)
    142147{
    143         tlb_invalidate_type_t type;
    144         asid_t asid;
    145         uintptr_t page;
    146         size_t count;
    147         unsigned int i;
    148        
    149148        ASSERT(CPU);
    150149       
    151         CPU->tlb_active = 0;
    152         spinlock_lock(&tlblock);
    153         spinlock_unlock(&tlblock);
     150        CPU->tlb_active = false;
     151        irq_spinlock_lock(&tlblock, false);
     152        irq_spinlock_unlock(&tlblock, false);
    154153       
    155         spinlock_lock(&CPU->lock);
     154        irq_spinlock_lock(&CPU->lock, false);
    156155        ASSERT(CPU->tlb_messages_count <= TLB_MESSAGE_QUEUE_LEN);
    157 
     156       
     157        size_t i;
    158158        for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) {
    159                 type = CPU->tlb_messages[i].type;
    160                 asid = CPU->tlb_messages[i].asid;
    161                 page = CPU->tlb_messages[i].page;
    162                 count = CPU->tlb_messages[i].count;
    163 
     159                tlb_invalidate_type_t type = CPU->tlb_messages[i].type;
     160                asid_t asid = CPU->tlb_messages[i].asid;
     161                uintptr_t page = CPU->tlb_messages[i].page;
     162                size_t count = CPU->tlb_messages[i].count;
     163               
    164164                switch (type) {
    165165                case TLB_INVL_ALL:
     
    170170                        break;
    171171                case TLB_INVL_PAGES:
    172                         ASSERT(count);
     172                        ASSERT(count);
    173173                        tlb_invalidate_pages(asid, page, count);
    174174                        break;
     
    177177                        break;
    178178                }
     179               
    179180                if (type == TLB_INVL_ALL)
    180181                        break;
    181182        }
    182183       
    183         spinlock_unlock(&CPU->lock);
    184         CPU->tlb_active = 1;
     184        irq_spinlock_unlock(&CPU->lock, false);
     185        CPU->tlb_active = true;
    185186}
    186187
Note: See TracChangeset for help on using the changeset viewer.