Changeset 252127e in mainline for generic/src/mm/as.c
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.