Changeset 252127e in mainline
- Timestamp:
- 2006-04-03T22:15:56Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b26db0c
- Parents:
- b9b14a83
- Location:
- generic
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/include/adt/btree.h
rb9b14a83 r252127e 84 84 extern void *btree_search(btree_t *t, __native key, btree_node_t **leaf_node); 85 85 86 extern btree_node_t *btree_node_left_sibling(btree_t *t, btree_node_t *node); 87 extern btree_node_t *btree_node_right_sibling(btree_t *t, btree_node_t *node); 88 86 89 extern void btree_print(btree_t *t); 87 90 #endif -
generic/include/mm/as.h
rb9b14a83 r252127e 37 37 #include <synch/spinlock.h> 38 38 #include <adt/list.h> 39 #include <adt/btree.h> 39 40 40 41 /** Defined to be true if user address space and kernel address space shadow each other. */ … … 64 65 struct as_area { 65 66 SPINLOCK_DECLARE(lock); 66 link_t link;67 67 int flags; 68 68 count_t pages; /**< Size of this area in multiples of PAGE_SIZE. */ … … 86 86 count_t refcount; 87 87 88 link_t as_area_head; 88 /** B+-tree of address space areas. */ 89 btree_t as_area_btree; 89 90 90 91 /** Page table pointer. Constant on architectures that use global page hash table. */ -
generic/src/adt/btree.c
rb9b14a83 r252127e 341 341 } 342 342 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 */ 350 btree_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 */ 366 btree_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 343 375 /** Initialize B-tree node. 344 376 * -
generic/src/mm/as.c
rb9b14a83 r252127e 49 49 #include <config.h> 50 50 #include <adt/list.h> 51 #include <adt/btree.h> 51 52 #include <panic.h> 52 53 #include <arch/asm.h> … … 95 96 link_initialize(&as->inactive_as_with_asid_link); 96 97 spinlock_initialize(&as->lock, "as_lock"); 97 list_initialize(&as->as_area_head);98 btree_create(&as->as_area_btree); 98 99 99 100 if (flags & FLAG_AS_KERNEL) … … 154 155 spinlock_initialize(&a->lock, "as_area_lock"); 155 156 156 link_initialize(&a->link);157 157 a->flags = flags; 158 158 a->pages = SIZE2FRAMES(size); 159 159 a->base = base; 160 160 161 list_append(&a->link, &as->as_area_head);161 btree_insert(&as->as_area_btree, base, (void *) a, NULL); 162 162 163 163 spinlock_unlock(&as->lock); … … 446 446 447 447 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 455 448 if (pages < area->pages) { 456 449 int i; … … 458 451 /* 459 452 * Shrinking the area. 453 * No need to check for overlaps. 460 454 */ 461 455 for (i = pages; i < area->pages; i++) { … … 487 481 tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages); 488 482 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 } 489 494 } 490 495 … … 509 514 as_area_t *find_area_and_lock(as_t *as, __address va) 510 515 { 511 link_t *cur;512 516 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 */ 516 523 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)) { 519 538 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 } 521 553 spinlock_unlock(&a->lock); 522 554 } … … 538 570 bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area) 539 571 { 540 link_t *cur;541 572 as_area_t *a; 573 btree_node_t *leaf, *node; 574 int i; 542 575 543 576 /* … … 547 580 return false; 548 581 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 554 619 if (a == avoid_area) 555 620 continue; 556 621 557 622 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 } 562 627 spinlock_unlock(&a->lock); 563 564 if (overlaps(va, size, a_start, a_size))565 return false;566 567 628 } 568 629
Note:
See TracChangeset
for help on using the changeset viewer.