Ignore:
File:
1 edited

Legend:

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

    r336db295 rc964521  
    11/*
    2  * Copyright (c) 2001-2006 Jakub Jermar
     2 * Copyright (c) 2010 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    7575#include <config.h>
    7676#include <align.h>
    77 #include <arch/types.h>
     77#include <typedefs.h>
    7878#include <syscall/copy.h>
    7979#include <arch/interrupt.h>
     
    152152         * reference count never drops to zero.
    153153         */
    154         atomic_set(&AS_KERNEL->refcount, 1);
     154        as_hold(AS_KERNEL);
    155155}
    156156
     
    200200        DEADLOCK_PROBE_INIT(p_asidlock);
    201201
     202        ASSERT(as != AS);
    202203        ASSERT(atomic_get(&as->refcount) == 0);
    203204       
    204205        /*
    205          * Since there is no reference to this area,
    206          * it is safe not to lock its mutex.
     206         * Since there is no reference to this address space, it is safe not to
     207         * lock its mutex.
    207208         */
    208209
     
    225226        preemption_enable();    /* Interrupts disabled, enable preemption */
    226227        if (as->asid != ASID_INVALID && as != AS_KERNEL) {
    227                 if (as != AS && as->cpu_refcount == 0)
     228                if (as->cpu_refcount == 0)
    228229                        list_remove(&as->inactive_as_with_asid_link);
    229230                asid_put(as->asid);
     
    258259
    259260        slab_free(as_slab, as);
     261}
     262
     263/** Hold a reference to an address space.
     264 *
     265 * Holding a reference to an address space prevents destruction of that address
     266 * space.
     267 *
     268 * @param a             Address space to be held.
     269 */
     270void as_hold(as_t *as)
     271{
     272        atomic_inc(&as->refcount);
     273}
     274
     275/** Release a reference to an address space.
     276 *
     277 * The last one to release a reference to an address space destroys the address
     278 * space.
     279 *
     280 * @param a             Address space to be released.
     281 */
     282void as_release(as_t *as)
     283{
     284        if (atomic_predec(&as->refcount) == 0)
     285                as_destroy(as);
    260286}
    261287
     
    396422                 * No need to check for overlaps.
    397423                 */
     424
     425                page_table_lock(as, false);
    398426
    399427                /*
     
    460488                                        pte_t *pte;
    461489                       
    462                                         page_table_lock(as, false);
    463490                                        pte = page_mapping_find(as, b +
    464491                                            i * PAGE_SIZE);
     
    473500                                        page_mapping_remove(as, b +
    474501                                            i * PAGE_SIZE);
    475                                         page_table_unlock(as, false);
    476502                                }
    477503                        }
     
    484510                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    485511                    area->pages - pages);
     512
    486513                /*
    487514                 * Invalidate software translation caches (e.g. TSB on sparc64).
     
    490517                    pages * PAGE_SIZE, area->pages - pages);
    491518                tlb_shootdown_finalize();
     519
     520                page_table_unlock(as, false);
    492521               
    493522        } else {
     
    539568
    540569        base = area->base;
     570
     571        page_table_lock(as, false);
    541572
    542573        /*
     
    560591                       
    561592                        for (j = 0; j < (size_t) node->value[i]; j++) {
    562                                 page_table_lock(as, false);
    563593                                pte = page_mapping_find(as, b + j * PAGE_SIZE);
    564594                                ASSERT(pte && PTE_VALID(pte) &&
     
    570600                                }
    571601                                page_mapping_remove(as, b + j * PAGE_SIZE);                             
    572                                 page_table_unlock(as, false);
    573602                        }
    574603                }
     
    580609
    581610        tlb_invalidate_pages(as->asid, area->base, area->pages);
     611
    582612        /*
    583613         * Invalidate potential software translation caches (e.g. TSB on
     
    586616        as_invalidate_translation_cache(as, area->base, area->pages);
    587617        tlb_shootdown_finalize();
     618
     619        page_table_unlock(as, false);
    588620       
    589621        btree_destroy(&area->used_space);
     
    784816{
    785817        as_area_t *area;
    786         uintptr_t base;
    787818        link_t *cur;
    788819        ipl_t ipl;
     
    813844                return ENOTSUP;
    814845        }
    815 
    816         base = area->base;
    817846
    818847        /*
     
    834863        /* An array for storing frame numbers */
    835864        old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     865
     866        page_table_lock(as, false);
    836867
    837868        /*
     
    858889                       
    859890                        for (j = 0; j < (size_t) node->value[i]; j++) {
    860                                 page_table_lock(as, false);
    861891                                pte = page_mapping_find(as, b + j * PAGE_SIZE);
    862892                                ASSERT(pte && PTE_VALID(pte) &&
     
    866896                                /* Remove old mapping */
    867897                                page_mapping_remove(as, b + j * PAGE_SIZE);
    868                                 page_table_unlock(as, false);
    869898                        }
    870899                }
     
    883912        as_invalidate_translation_cache(as, area->base, area->pages);
    884913        tlb_shootdown_finalize();
     914
     915        page_table_unlock(as, false);
    885916
    886917        /*
     
    952983        if (!THREAD)
    953984                return AS_PF_FAULT;
    954                
    955         ASSERT(AS);
    956 
     985       
     986        if (!AS)
     987                return AS_PF_FAULT;
     988       
    957989        mutex_lock(&AS->lock);
    958         area = find_area_and_lock(AS, page);   
     990        area = find_area_and_lock(AS, page);
    959991        if (!area) {
    960992                /*
Note: See TracChangeset for help on using the changeset viewer.