Changeset 7e4e532 in mainline


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.

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • arch/ia32/include/mm/asid.h

    rbb68433 r7e4e532  
    3838typedef int asid_t;
    3939
    40 #define ASID_MAX_ARCH           0
     40#define ASID_MAX_ARCH           3
    4141
    42 #define asid_install(as)
     42#define asid_get()              (ASID_START+1)
    4343
    4444#endif
  • arch/ia64/src/mm/frame.c

    rbb68433 r7e4e532  
    4444       
    4545        /*
    46         * Workaround to prevent slab allocator from allocating frame 0.
    47         * Remove the following statement when the kernel is no longer
     46        * Workaround to prevent slab allocator from allocating frame 0.
     47        * Remove the following statement when the kernel is no longer
    4848         * identity mapped.
    49         */
     49        */
    5050        frame_mark_unavailable(0, 1);
    5151
  • arch/ppc32/include/mm/asid.h

    rbb68433 r7e4e532  
    3232typedef int asid_t;
    3333
    34 #define ASID_MAX_ARCH   0
     34#define ASID_MAX_ARCH   3
    3535
    36 #define asid_install(as)
     36#define asid_get()      (ASID_START+1)
    3737
    3838#endif
  • arch/sparc64/src/mm/frame.c

    rbb68433 r7e4e532  
    3434void frame_arch_init(void)
    3535{
    36         zone_create(0, config.memory_size >> FRAME_WIDTH, ADDR2PFN(ALIGN_UP(config.base + config.kernel_size, FRAME_SIZE)), 0);
     36        zone_create(0, config.memory_size >> FRAME_WIDTH, 1, 0);
    3737
    3838        /*
  • genarch/src/mm/asid.c

    rbb68433 r7e4e532  
    4444 * a while.
    4545 *
     46 * This code depends on the fact that ASIDS_ALLOCABLE
     47 * is greater than number of supported CPUs (i.e. the
     48 * amount of concurently active address spaces).
     49 *
    4650 * Architectures that don't have hardware support for address
    4751 * spaces do not compile with this file.
     
    5862
    5963/**
    60  * asidlock protects both the asids_allocated counter
    61  * and the list of address spaces that were already
    62  * assigned ASID.
     64 * asidlock protects the asids_allocated counter.
    6365 */
    6466SPINLOCK_INITIALIZE(asidlock);
     
    6668static count_t asids_allocated = 0;
    6769
    68 /**
    69  * List of address spaces with assigned ASID.
    70  * When the system runs short of allocable
    71  * ASIDS, inactive address spaces are guaranteed
    72  * to be at the beginning of the list.
    73  */
    74 LIST_INITIALIZE(as_with_asid_head);
    75 
    76 
    7770/** Allocate free address space identifier.
    7871 *
    79  * This code depends on the fact that ASIDS_ALLOCABLE
    80  * is greater than number of supported CPUs.
     72 * Interrupts must be disabled and as_lock must be held
     73 * prior to this call
    8174 *
    8275 * @return New ASID.
     
    8477asid_t asid_get(void)
    8578{
    86         ipl_t ipl;
    8779        asid_t asid;
    8880        link_t *tmp;
     
    9385         */
    9486       
    95         ipl = interrupts_disable();
    9687        spinlock_lock(&asidlock);
    9788        if (asids_allocated == ASIDS_ALLOCABLE) {
     
    10798                 * inactive address space.
    10899                 */
    109                 tmp = as_with_asid_head.next;
    110                 ASSERT(tmp != &as_with_asid_head);
     100                ASSERT(!list_empty(&inactive_as_with_asid_head));
     101                tmp = inactive_as_with_asid_head.next;
    111102                list_remove(tmp);
    112103               
    113                 as = list_get_instance(tmp, as_t, as_with_asid_link);
     104                as = list_get_instance(tmp, as_t, inactive_as_with_asid_link);
    114105                spinlock_lock(&as->lock);
    115106
     
    146137       
    147138        spinlock_unlock(&asidlock);
    148         interrupts_restore(ipl);
    149139       
    150140        return asid;
     
    171161        interrupts_restore(ipl);
    172162}
    173 
    174 /** Install ASID.
    175  *
    176  * This function is to be executed on each address space switch.
    177  *
    178  * @param as Address space.
    179  */
    180 void asid_install(as_t *as)
    181 {
    182         ipl_t ipl;
    183        
    184         ipl = interrupts_disable();
    185         spinlock_lock(&asidlock);
    186         spinlock_lock(&as->lock);
    187        
    188         if (as->asid != ASID_KERNEL) {
    189                 if (as->asid != ASID_INVALID) {
    190                         /*
    191                          * This address space has valid ASID.
    192                          * Remove 'as' from the list of address spaces
    193                          * with assigned ASID, so that it can be later
    194                          * appended to the tail of the same list.
    195                          * This is to prevent stealing of ASIDs from
    196                          * recently installed address spaces.
    197                          */
    198                         list_remove(&as->as_with_asid_link);
    199                 } else {
    200                         spinlock_unlock(&as->lock);
    201                         spinlock_unlock(&asidlock);
    202        
    203                         /*
    204                          * This address space doesn't have ASID assigned.
    205                          * It was stolen or the address space is being
    206                          * installed for the first time.
    207                          * Allocate new ASID for it.
    208                          */
    209                         as->asid = asid_get();
    210                         spinlock_lock(&asidlock);
    211                         spinlock_lock(&as->lock);
    212                 }
    213        
    214                 /*
    215                  * Now it is sure that 'as' has ASID.
    216                  * It is therefore appended to the list
    217                  * of address spaces from which it can
    218                  * be stolen.
    219                  */
    220                 list_append(&as->as_with_asid_link, &as_with_asid_head);
    221         }
    222        
    223         spinlock_unlock(&as->lock);
    224         spinlock_unlock(&asidlock);
    225         interrupts_restore(ipl);
    226 }
  • genarch/src/mm/page_ht.c

    rbb68433 r7e4e532  
    170170
    171171        if (!hash_table_find(&page_ht, key)) {
    172                 t = (pte_t *) malloc(sizeof(pte_t));
     172                t = (pte_t *) malloc(sizeof(pte_t), FRAME_ATOMIC);
    173173                ASSERT(t != NULL);
    174174       
  • generic/include/mm/as.h

    rbb68433 r7e4e532  
    7777struct as {
    7878        /** Protected by asidlock. Must be acquired before as->lock. */
    79         link_t as_with_asid_link;
     79        link_t inactive_as_with_asid_link;
    8080
    8181        SPINLOCK_DECLARE(lock);
     82
     83        /** Number of processors on wich is this address space active. */
     84        count_t refcount;
     85
    8286        link_t as_area_head;
    8387
     
    97101extern as_operations_t *as_operations;
    98102
     103extern spinlock_t as_lock;
     104extern link_t inactive_as_with_asid_head;
     105
    99106extern void as_init(void);
    100107extern as_t *as_create(int flags);
     
    102109extern void as_set_mapping(as_t *as, __address page, __address frame);
    103110extern int as_page_fault(__address page);
    104 extern void as_install(as_t *m);
     111extern void as_switch(as_t *old, as_t *new);
    105112
    106113/* Interface to be implemented by architectures. */
  • generic/include/mm/asid.h

    rbb68433 r7e4e532  
    4646
    4747extern spinlock_t asidlock;
    48 extern link_t as_with_asid_head;
    4948
     49#ifndef asid_get
    5050extern asid_t asid_get(void);
     51#endif /* !def asid_get */
    5152extern void asid_put(asid_t asid);
    5253
  • 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
  • generic/src/proc/scheduler.c

    rbb68433 r7e4e532  
    328328                         * Replace the old one with the new one.
    329329                         */
    330                         as_install(as2);
     330                        as_switch(as1, as2);
    331331                }
    332332                TASK = THREAD->task;   
     
    336336
    337337        #ifdef SCHEDULER_VERBOSE
    338         printf("cpu%d: tid %d (priority=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, CPU->nrdy);
     338        printf("cpu%d: tid %d (priority=%d,ticks=%d,nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks, atomic_get(&CPU->nrdy));
    339339        #endif 
    340340
Note: See TracChangeset for help on using the changeset viewer.