Changeset 252127e in mainline for generic/src/mm/as.c


Ignore:
Timestamp:
2006-04-03T22:15:56Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b26db0c
Parents:
b9b14a83
Message:

Deploy B+tree in address space area management.
Change as_remap() to check for conflicts with other address space areas only when the area in question grows.

File:
1 edited

Legend:

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

    rb9b14a83 r252127e  
    4949#include <config.h>
    5050#include <adt/list.h>
     51#include <adt/btree.h>
    5152#include <panic.h>
    5253#include <arch/asm.h>
     
    9596        link_initialize(&as->inactive_as_with_asid_link);
    9697        spinlock_initialize(&as->lock, "as_lock");
    97         list_initialize(&as->as_area_head);
     98        btree_create(&as->as_area_btree);
    9899       
    99100        if (flags & FLAG_AS_KERNEL)
     
    154155        spinlock_initialize(&a->lock, "as_area_lock");
    155156       
    156         link_initialize(&a->link);                     
    157157        a->flags = flags;
    158158        a->pages = SIZE2FRAMES(size);
    159159        a->base = base;
    160160       
    161         list_append(&a->link, &as->as_area_head);
     161        btree_insert(&as->as_area_btree, base, (void *) a, NULL);
    162162
    163163        spinlock_unlock(&as->lock);
     
    446446
    447447        pages = SIZE2FRAMES((address - area->base) + size);
    448         if (!check_area_conflicts(as, address, pages * PAGE_SIZE, area)) {
    449                 spinlock_unlock(&area->lock);
    450                 spinlock_unlock(&as->lock);             
    451                 interrupts_restore(ipl);
    452                 return (__address) -1;
    453         }
    454 
    455448        if (pages < area->pages) {
    456449                int i;
     
    458451                /*
    459452                 * Shrinking the area.
     453                 * No need to check for overlaps.
    460454                 */
    461455                for (i = pages; i < area->pages; i++) {
     
    487481                tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
    488482                tlb_shootdown_finalize();
     483        } else {
     484                /*
     485                 * Growing the area.
     486                 * Check for overlaps with other address space areas.
     487                 */
     488                if (!check_area_conflicts(as, address, pages * PAGE_SIZE, area)) {
     489                        spinlock_unlock(&area->lock);
     490                        spinlock_unlock(&as->lock);             
     491                        interrupts_restore(ipl);
     492                        return (__address) -1;
     493                }
    489494        }
    490495
     
    509514as_area_t *find_area_and_lock(as_t *as, __address va)
    510515{
    511         link_t *cur;
    512516        as_area_t *a;
    513        
    514         for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
    515                 a = list_get_instance(cur, as_area_t, link);
     517        btree_node_t *leaf, *lnode;
     518        int i;
     519       
     520        a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     521        if (a) {
     522                /* va is the base address of an address space area */
    516523                spinlock_lock(&a->lock);
    517 
    518                 if ((va >= a->base) && (va < a->base + a->pages * PAGE_SIZE))
     524                return a;
     525        }
     526       
     527        /*
     528         * Search the leaf node and the righmost record of its left sibling
     529         * to find out whether this is a miss or va belongs to an address
     530         * space area found there.
     531         */
     532       
     533        /* First, search the leaf node itself. */
     534        for (i = 0; i < leaf->keys; i++) {
     535                a = (as_area_t *) leaf->value[i];
     536                spinlock_lock(&a->lock);
     537                if ((a->base <= va) && (va < a->base + a->pages * PAGE_SIZE)) {
    519538                        return a;
    520                
     539                }
     540                spinlock_unlock(&a->lock);
     541        }
     542
     543        /*
     544         * Second, locate the left sibling and test its last record.
     545         * Because of its position in the B+-tree, it must have base < va.
     546         */
     547        if ((lnode = btree_node_left_sibling(&as->as_area_btree, leaf))) {
     548                a = (as_area_t *) lnode->value[lnode->keys - 1];
     549                spinlock_lock(&a->lock);
     550                if (va < a->base + a->pages * PAGE_SIZE) {
     551                        return a;
     552                }
    521553                spinlock_unlock(&a->lock);
    522554        }
     
    538570bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area)
    539571{
    540         link_t *cur;
    541572        as_area_t *a;
     573        btree_node_t *leaf, *node;
     574        int i;
    542575       
    543576        /*
     
    547580                return false;
    548581       
    549         for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
    550                 __address a_start;
    551                 size_t a_size;
    552        
    553                 a = list_get_instance(cur, as_area_t, link);
     582        /*
     583         * The leaf node is found in O(log n), where n is proportional to
     584         * the number of address space areas belonging to as.
     585         * The check for conflicts is then attempted on the rightmost
     586         * record in the left sibling, the leftmost record in the right
     587         * sibling and all records in the leaf node itself.
     588         */
     589       
     590        if ((a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf))) {
     591                if (a != avoid_area)
     592                        return false;
     593        }
     594       
     595        /* First, check the two border cases. */
     596        if ((node = btree_node_left_sibling(&as->as_area_btree, leaf))) {
     597                a = (as_area_t *) node->value[node->keys - 1];
     598                spinlock_lock(&a->lock);
     599                if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
     600                        spinlock_unlock(&a->lock);
     601                        return false;
     602                }
     603                spinlock_unlock(&a->lock);
     604        }
     605        if ((node = btree_node_right_sibling(&as->as_area_btree, leaf))) {
     606                a = (as_area_t *) node->value[0];
     607                spinlock_lock(&a->lock);
     608                if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
     609                        spinlock_unlock(&a->lock);
     610                        return false;
     611                }
     612                spinlock_unlock(&a->lock);
     613        }
     614       
     615        /* Second, check the leaf node. */
     616        for (i = 0; i < leaf->keys; i++) {
     617                a = (as_area_t *) leaf->value[i];
     618       
    554619                if (a == avoid_area)
    555620                        continue;
    556                        
     621       
    557622                spinlock_lock(&a->lock);
    558 
    559                 a_start = a->base;
    560                 a_size = a->pages * PAGE_SIZE;
    561 
     623                if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
     624                        spinlock_unlock(&a->lock);
     625                        return false;
     626                }
    562627                spinlock_unlock(&a->lock);
    563 
    564                 if (overlaps(va, size, a_start, a_size))
    565                         return false;           
    566 
    567628        }
    568629
Note: See TracChangeset for help on using the changeset viewer.