Changeset 252127e in mainline


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.

Location:
generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • generic/include/adt/btree.h

    rb9b14a83 r252127e  
    8484extern void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node);
    8585
     86extern btree_node_t *btree_node_left_sibling(btree_t *t, btree_node_t *node);
     87extern btree_node_t *btree_node_right_sibling(btree_t *t, btree_node_t *node);
     88
    8689extern void btree_print(btree_t *t);
    8790#endif
  • generic/include/mm/as.h

    rb9b14a83 r252127e  
    3737#include <synch/spinlock.h>
    3838#include <adt/list.h>
     39#include <adt/btree.h>
    3940
    4041/** Defined to be true if user address space and kernel address space shadow each other. */
     
    6465struct as_area {
    6566        SPINLOCK_DECLARE(lock);
    66         link_t link;
    6767        int flags;
    6868        count_t pages;          /**< Size of this area in multiples of PAGE_SIZE. */
     
    8686        count_t refcount;
    8787
    88         link_t as_area_head;
     88        /** B+-tree of address space areas. */
     89        btree_t as_area_btree;
    8990
    9091        /** Page table pointer. Constant on architectures that use global page hash table. */
  • generic/src/adt/btree.c

    rb9b14a83 r252127e  
    341341}
    342342
     343/** Return pointer to B-tree node's left sibling.
     344 *
     345 * @param t B-tree.
     346 * @param node Node whose left sibling will be returned.
     347 *
     348 * @return Left sibling of the node or NULL if the node does not have the left sibling.
     349 */
     350btree_node_t *btree_node_left_sibling(btree_t *t, btree_node_t *node)
     351{
     352        ASSERT(LEAF_NODE(node));
     353        if (node->leaf_link.prev != &t->leaf_head)
     354                return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
     355        else
     356                return NULL;
     357}
     358
     359/** Return pointer to B-tree node's right sibling.
     360 *
     361 * @param t B-tree.
     362 * @param node Node whose right sibling will be returned.
     363 *
     364 * @return Right sibling of the node or NULL if the node does not have the right sibling.
     365 */
     366btree_node_t *btree_node_right_sibling(btree_t *t, btree_node_t *node)
     367{
     368        ASSERT(LEAF_NODE(node));
     369        if (node->leaf_link.next != &t->leaf_head)
     370                return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
     371        else
     372                return NULL;
     373}
     374
    343375/** Initialize B-tree node.
    344376 *
  • 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.