Changeset 7e4e532 in mainline for generic/src/mm/as.c


Ignore:
Timestamp:
2006-02-08T23:37:38Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
874878a
Parents:
bb68433
Message:

Reimplement ASID stealing logic.
This time, hopefully, with correct synchronization.

File:
1 edited

Legend:

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

    rbb68433 r7e4e532  
    5757as_operations_t *as_operations = NULL;
    5858
     59/** Address space lock. It protects inactive_as_with_asid_head. */
     60SPINLOCK_INITIALIZE(as_lock);
     61
     62/**
     63 * This list contains address spaces that are not active on any
     64 * processor and that have valid ASID.
     65 */
     66LIST_INITIALIZE(inactive_as_with_asid_head);
     67
    5968/** Kernel address space. */
    6069as_t *AS_KERNEL = NULL;
     
    8089
    8190        as = (as_t *) malloc(sizeof(as_t), 0);
    82 
    83         list_initialize(&as->as_with_asid_link);
     91        link_initialize(&as->inactive_as_with_asid_link);
    8492        spinlock_initialize(&as->lock, "as_lock");
    8593        list_initialize(&as->as_area_head);
     
    9098                as->asid = ASID_INVALID;
    9199       
     100        as->refcount = 0;
    92101        as->page_table = page_table_create(flags);
    93102
     
    268277}
    269278
    270 /** Install address space on CPU.
    271  *
    272  * @param as Address space.
    273  */
    274 void as_install(as_t *as)
     279/** Switch address spaces.
     280 *
     281 * @param old Old address space or NULL.
     282 * @param new New address space.
     283 */
     284void as_switch(as_t *old, as_t *new)
    275285{
    276286        ipl_t ipl;
    277        
    278         asid_install(as);
     287        bool needs_asid = false;
    279288       
    280289        ipl = interrupts_disable();
    281         spinlock_lock(&as->lock);
    282         SET_PTL0_ADDRESS(as->page_table);
    283         spinlock_unlock(&as->lock);
     290        spinlock_lock(&as_lock);
     291
     292        /*
     293         * First, take care of the old address space.
     294         */     
     295        if (old) {
     296                spinlock_lock(&old->lock);
     297                ASSERT(old->refcount);
     298                if((--old->refcount == 0) && (old != AS_KERNEL)) {
     299                        /*
     300                         * The old address space is no longer active on
     301                         * any processor. It can be appended to the
     302                         * list of inactive address spaces with assigned
     303                         * ASID.
     304                         */
     305                         ASSERT(old->asid != ASID_INVALID);
     306                         list_append(&old->inactive_as_with_asid_link, &inactive_as_with_asid_head);
     307                }
     308                spinlock_unlock(&old->lock);
     309        }
     310
     311        /*
     312         * Second, prepare the new address space.
     313         */
     314        spinlock_lock(&new->lock);
     315        if ((new->refcount++ == 0) && (new != AS_KERNEL)) {
     316                if (new->asid != ASID_INVALID)
     317                        list_remove(&new->inactive_as_with_asid_link);
     318                else
     319                        needs_asid = true;      /* defer call to asid_get() until new->lock is released */
     320        }
     321        SET_PTL0_ADDRESS(new->page_table);
     322        spinlock_unlock(&new->lock);
     323
     324        if (needs_asid) {
     325                /*
     326                 * Allocation of new ASID was deferred
     327                 * until now in order to avoid deadlock.
     328                 */
     329                asid_t asid;
     330               
     331                asid = asid_get();
     332                spinlock_lock(&new->lock);
     333                new->asid = asid;
     334                spinlock_unlock(&new->lock);
     335        }
     336        spinlock_unlock(&as_lock);
    284337        interrupts_restore(ipl);
    285 
     338       
    286339        /*
    287340         * Perform architecture-specific steps.
    288341         * (e.g. write ASID to hardware register etc.)
    289342         */
    290         as_install_arch(as);
    291        
    292         AS = as;
     343        as_install_arch(new);
     344       
     345        AS = new;
    293346}
    294347
Note: See TracChangeset for help on using the changeset viewer.