Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2087 → Rev 2086

/trunk/kernel/generic/src/mm/as.c
93,10 → 93,7
*/
static slab_cache_t *as_slab;
 
/**
* This lock protects inactive_as_with_asid_head list. It must be acquired
* before as_t mutex.
*/
/** This lock protects inactive_as_with_asid_head list. It must be acquired before as_t mutex. */
SPINLOCK_INITIALIZE(inactive_as_with_asid_lock);
 
/**
110,8 → 107,7
 
static int area_flags_to_page_flags(int aflags);
static as_area_t *find_area_and_lock(as_t *as, uintptr_t va);
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
as_area_t *avoid_area);
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area);
static void sh_info_remove_reference(share_info_t *sh_info);
 
static int as_constructor(void *obj, int flags)
140,7 → 136,7
as_arch_init();
as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
AS_KERNEL = as_create(FLAG_AS_KERNEL);
if (!AS_KERNEL)
175,8 → 171,8
 
/** Destroy adress space.
*
* When there are no tasks referencing this address space (i.e. its refcount is
* zero), the address space can be destroyed.
* When there are no tasks referencing this address space (i.e. its refcount is zero),
* the address space can be destroyed.
*/
void as_destroy(as_t *as)
{
207,8 → 203,7
btree_node_t *node;
 
ASSERT(!list_empty(&as->as_area_btree.leaf_head));
node = list_get_instance(as->as_area_btree.leaf_head.next,
btree_node_t, leaf_link);
node = list_get_instance(as->as_area_btree.leaf_head.next, btree_node_t, leaf_link);
 
if ((cond = node->keys)) {
as_area_destroy(as, node->key[0]);
277,8 → 272,7
if (backend_data)
a->backend_data = *backend_data;
else
memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data),
0);
memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data), 0);
 
btree_create(&a->used_space);
293,8 → 287,7
/** Find address space area and change it.
*
* @param as Address space.
* @param address Virtual address belonging to the area to be changed. Must be
* page-aligned.
* @param address Virtual address belonging to the area to be changed. Must be page-aligned.
* @param size New size of the virtual memory block starting at address.
* @param flags Flags influencing the remap operation. Currently unused.
*
363,8 → 356,7
/*
* Start TLB shootdown sequence.
*/
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base +
pages * PAGE_SIZE, area->pages - pages);
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
 
/*
* Remove frames belonging to used space starting from
377,47 → 369,37
btree_node_t *node;
ASSERT(!list_empty(&area->used_space.leaf_head));
node =
list_get_instance(area->used_space.leaf_head.prev,
btree_node_t, leaf_link);
node = list_get_instance(area->used_space.leaf_head.prev, btree_node_t, leaf_link);
if ((cond = (bool) node->keys)) {
uintptr_t b = node->key[node->keys - 1];
count_t c =
(count_t) node->value[node->keys - 1];
count_t c = (count_t) node->value[node->keys - 1];
int i = 0;
if (overlaps(b, c * PAGE_SIZE, area->base,
pages*PAGE_SIZE)) {
if (overlaps(b, c*PAGE_SIZE, area->base, pages*PAGE_SIZE)) {
if (b + c * PAGE_SIZE <= start_free) {
if (b + c*PAGE_SIZE <= start_free) {
/*
* The whole interval fits
* completely in the resized
* address space area.
* The whole interval fits completely
* in the resized address space area.
*/
break;
}
/*
* Part of the interval corresponding
* to b and c overlaps with the resized
* address space area.
* Part of the interval corresponding to b and c
* overlaps with the resized address space area.
*/
cond = false; /* we are almost done */
i = (start_free - b) >> PAGE_WIDTH;
if (!used_space_remove(area, start_free,
c - i))
panic("Could not remove used "
"space.\n");
if (!used_space_remove(area, start_free, c - i))
panic("Could not remove used space.\n");
} else {
/*
* The interval of used space can be
* completely removed.
* The interval of used space can be completely removed.
*/
if (!used_space_remove(area, b, c))
panic("Could not remove used "
"space.\n");
panic("Could not remove used space.\n");
}
for (; i < c; i++) {
424,18 → 406,13
pte_t *pte;
page_table_lock(as, false);
pte = page_mapping_find(as, b +
i * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
PTE_PRESENT(pte));
if (area->backend &&
area->backend->frame_free) {
pte = page_mapping_find(as, b + i*PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte));
if (area->backend && area->backend->frame_free) {
area->backend->frame_free(area,
b + i * PAGE_SIZE,
PTE_GET_FRAME(pte));
b + i*PAGE_SIZE, PTE_GET_FRAME(pte));
}
page_mapping_remove(as, b +
i * PAGE_SIZE);
page_mapping_remove(as, b + i*PAGE_SIZE);
page_table_unlock(as, false);
}
}
444,22 → 421,19
/*
* Finish TLB shootdown sequence.
*/
tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
area->pages - pages);
tlb_invalidate_pages(as->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
tlb_shootdown_finalize();
/*
* Invalidate software translation caches (e.g. TSB on sparc64).
*/
as_invalidate_translation_cache(as, area->base +
pages * PAGE_SIZE, area->pages - pages);
as_invalidate_translation_cache(as, area->base + pages*PAGE_SIZE, area->pages - pages);
} else {
/*
* Growing the area.
* Check for overlaps with other address space areas.
*/
if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
area)) {
if (!check_area_conflicts(as, address, pages * PAGE_SIZE, area)) {
mutex_unlock(&area->lock);
mutex_unlock(&as->lock);
interrupts_restore(ipl);
510,8 → 484,7
/*
* Visit only the pages mapped by used_space B+tree.
*/
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
for (cur = area->used_space.leaf_head.next; cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
int i;
523,15 → 496,13
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
PTE_PRESENT(pte));
if (area->backend &&
area->backend->frame_free) {
area->backend->frame_free(area, b +
j * PAGE_SIZE, PTE_GET_FRAME(pte));
pte = page_mapping_find(as, b + j*PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte));
if (area->backend && area->backend->frame_free) {
area->backend->frame_free(area,
b + j*PAGE_SIZE, PTE_GET_FRAME(pte));
}
page_mapping_remove(as, b + j * PAGE_SIZE);
page_mapping_remove(as, b + j*PAGE_SIZE);
page_table_unlock(as, false);
}
}
544,8 → 515,7
tlb_shootdown_finalize();
/*
* Invalidate potential software translation caches (e.g. TSB on
* sparc64).
* Invalidate potential software translation caches (e.g. TSB on sparc64).
*/
as_invalidate_translation_cache(as, area->base, area->pages);
635,8 → 605,7
if (src_flags & AS_AREA_CACHEABLE)
dst_flags_mask |= AS_AREA_CACHEABLE;
 
if (src_size != acc_size ||
(src_flags & dst_flags_mask) != dst_flags_mask) {
if (src_size != acc_size || (src_flags & dst_flags_mask) != dst_flags_mask) {
mutex_unlock(&src_area->lock);
mutex_unlock(&src_as->lock);
interrupts_restore(ipl);
689,7 → 658,7
* to support sharing in less privileged mode.
*/
dst_area = as_area_create(dst_as, dst_flags_mask, src_size, dst_base,
AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
if (!dst_area) {
/*
* Destination address space area could not be created.
807,8 → 776,8
if ((pte = page_mapping_find(AS, page))) {
if (PTE_PRESENT(pte)) {
if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) ||
(access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) ||
(access == PF_ACCESS_EXEC && PTE_EXECUTABLE(pte))) {
(access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) ||
(access == PF_ACCESS_EXEC && PTE_EXECUTABLE(pte))) {
page_table_unlock(AS, false);
mutex_unlock(&area->lock);
mutex_unlock(&AS->lock);
835,12 → 804,10
page_fault:
if (THREAD->in_copy_from_uspace) {
THREAD->in_copy_from_uspace = false;
istate_set_retaddr(istate,
(uintptr_t) &memcpy_from_uspace_failover_address);
istate_set_retaddr(istate, (uintptr_t) &memcpy_from_uspace_failover_address);
} else if (THREAD->in_copy_to_uspace) {
THREAD->in_copy_to_uspace = false;
istate_set_retaddr(istate,
(uintptr_t) &memcpy_to_uspace_failover_address);
istate_set_retaddr(istate, (uintptr_t) &memcpy_to_uspace_failover_address);
} else {
return AS_PF_FAULT;
}
878,8 → 845,7
* ASID.
*/
ASSERT(old->asid != ASID_INVALID);
list_append(&old->inactive_as_with_asid_link,
&inactive_as_with_asid_head);
list_append(&old->inactive_as_with_asid_link, &inactive_as_with_asid_head);
}
mutex_unlock(&old->lock);
 
895,14 → 861,10
*/
mutex_lock_active(&new->lock);
if ((new->cpu_refcount++ == 0) && (new != AS_KERNEL)) {
if (new->asid != ASID_INVALID) {
if (new->asid != ASID_INVALID)
list_remove(&new->inactive_as_with_asid_link);
} else {
/*
* Defer call to asid_get() until new->lock is released.
*/
needs_asid = true;
}
else
needs_asid = true; /* defer call to asid_get() until new->lock is released */
}
SET_PTL0_ADDRESS(new->page_table);
mutex_unlock(&new->lock);
1044,8 → 1006,7
* @param as Address space.
* @param va Virtual address.
*
* @return Locked address space area containing va on success or NULL on
* failure.
* @return Locked address space area containing va on success or NULL on failure.
*/
as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
{
1080,8 → 1041,7
* Second, locate the left neighbour and test its last record.
* Because of its position in the B+tree, it must have base < va.
*/
lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
if (lnode) {
if ((lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf))) {
a = (as_area_t *) lnode->value[lnode->keys - 1];
mutex_lock(&a->lock);
if (va < a->base + a->pages * PAGE_SIZE) {
1104,8 → 1064,7
*
* @return True if there is no conflict, false otherwise.
*/
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
as_area_t *avoid_area)
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area)
{
as_area_t *a;
btree_node_t *leaf, *node;
1140,8 → 1099,7
}
mutex_unlock(&a->lock);
}
node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
if (node) {
if ((node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf))) {
a = (as_area_t *) node->value[0];
mutex_lock(&a->lock);
if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
1172,8 → 1130,7
*/
if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
return !overlaps(va, size,
KERNEL_ADDRESS_SPACE_START,
KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
KERNEL_ADDRESS_SPACE_START, KERNEL_ADDRESS_SPACE_END-KERNEL_ADDRESS_SPACE_START);
}
 
return true;
1232,10 → 1189,8
 
node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
if (node) {
uintptr_t left_pg = node->key[node->keys - 1];
uintptr_t right_pg = leaf->key[0];
count_t left_cnt = (count_t) node->value[node->keys - 1];
count_t right_cnt = (count_t) leaf->value[0];
uintptr_t left_pg = node->key[node->keys - 1], right_pg = leaf->key[0];
count_t left_cnt = (count_t) node->value[node->keys - 1], right_cnt = (count_t) leaf->value[0];
/*
* Examine the possibility that the interval fits
1245,35 → 1200,25
if (page >= right_pg) {
/* Do nothing. */
} else if (overlaps(page, count * PAGE_SIZE, left_pg,
left_cnt * PAGE_SIZE)) {
} else if (overlaps(page, count*PAGE_SIZE, left_pg, left_cnt*PAGE_SIZE)) {
/* The interval intersects with the left interval. */
return 0;
} else if (overlaps(page, count * PAGE_SIZE, right_pg,
right_cnt * PAGE_SIZE)) {
} else if (overlaps(page, count*PAGE_SIZE, right_pg, right_cnt*PAGE_SIZE)) {
/* The interval intersects with the right interval. */
return 0;
} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
(page + count * PAGE_SIZE == right_pg)) {
/*
* The interval can be added by merging the two already
* present intervals.
*/
} else if ((page == left_pg + left_cnt*PAGE_SIZE) && (page + count*PAGE_SIZE == right_pg)) {
/* The interval can be added by merging the two already present intervals. */
node->value[node->keys - 1] += count + right_cnt;
btree_remove(&a->used_space, right_pg, leaf);
return 1;
} else if (page == left_pg + left_cnt * PAGE_SIZE) {
/*
* The interval can be added by simply growing the left
* interval.
*/
} else if (page == left_pg + left_cnt*PAGE_SIZE) {
/* The interval can be added by simply growing the left interval. */
node->value[node->keys - 1] += count;
return 1;
} else if (page + count * PAGE_SIZE == right_pg) {
} else if (page + count*PAGE_SIZE == right_pg) {
/*
* The interval can be addded by simply moving base of
* the right interval down and increasing its size
* accordingly.
* The interval can be addded by simply moving base of the right
* interval down and increasing its size accordingly.
*/
leaf->value[0] += count;
leaf->key[0] = page;
1283,8 → 1228,7
* The interval is between both neigbouring intervals,
* but cannot be merged with any of them.
*/
btree_insert(&a->used_space, page, (void *) count,
leaf);
btree_insert(&a->used_space, page, (void *) count, leaf);
return 1;
}
} else if (page < leaf->key[0]) {
1292,19 → 1236,17
count_t right_cnt = (count_t) leaf->value[0];
/*
* Investigate the border case in which the left neighbour does
* not exist but the interval fits from the left.
* Investigate the border case in which the left neighbour does not
* exist but the interval fits from the left.
*/
if (overlaps(page, count * PAGE_SIZE, right_pg,
right_cnt * PAGE_SIZE)) {
if (overlaps(page, count*PAGE_SIZE, right_pg, right_cnt*PAGE_SIZE)) {
/* The interval intersects with the right interval. */
return 0;
} else if (page + count * PAGE_SIZE == right_pg) {
} else if (page + count*PAGE_SIZE == right_pg) {
/*
* The interval can be added by moving the base of the
* right interval down and increasing its size
* accordingly.
* The interval can be added by moving the base of the right interval down
* and increasing its size accordingly.
*/
leaf->key[0] = page;
leaf->value[0] += count;
1314,8 → 1256,7
* The interval doesn't adjoin with the right interval.
* It must be added individually.
*/
btree_insert(&a->used_space, page, (void *) count,
leaf);
btree_insert(&a->used_space, page, (void *) count, leaf);
return 1;
}
}
1322,10 → 1263,8
 
node = btree_leaf_node_right_neighbour(&a->used_space, leaf);
if (node) {
uintptr_t left_pg = leaf->key[leaf->keys - 1];
uintptr_t right_pg = node->key[0];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
count_t right_cnt = (count_t) node->value[0];
uintptr_t left_pg = leaf->key[leaf->keys - 1], right_pg = node->key[0];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1], right_cnt = (count_t) node->value[0];
/*
* Examine the possibility that the interval fits
1335,35 → 1274,25
 
if (page < left_pg) {
/* Do nothing. */
} else if (overlaps(page, count * PAGE_SIZE, left_pg,
left_cnt * PAGE_SIZE)) {
} else if (overlaps(page, count*PAGE_SIZE, left_pg, left_cnt*PAGE_SIZE)) {
/* The interval intersects with the left interval. */
return 0;
} else if (overlaps(page, count * PAGE_SIZE, right_pg,
right_cnt * PAGE_SIZE)) {
} else if (overlaps(page, count*PAGE_SIZE, right_pg, right_cnt*PAGE_SIZE)) {
/* The interval intersects with the right interval. */
return 0;
} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
(page + count * PAGE_SIZE == right_pg)) {
/*
* The interval can be added by merging the two already
* present intervals.
* */
} else if ((page == left_pg + left_cnt*PAGE_SIZE) && (page + count*PAGE_SIZE == right_pg)) {
/* The interval can be added by merging the two already present intervals. */
leaf->value[leaf->keys - 1] += count + right_cnt;
btree_remove(&a->used_space, right_pg, node);
return 1;
} else if (page == left_pg + left_cnt * PAGE_SIZE) {
/*
* The interval can be added by simply growing the left
* interval.
* */
} else if (page == left_pg + left_cnt*PAGE_SIZE) {
/* The interval can be added by simply growing the left interval. */
leaf->value[leaf->keys - 1] += count;
return 1;
} else if (page + count * PAGE_SIZE == right_pg) {
} else if (page + count*PAGE_SIZE == right_pg) {
/*
* The interval can be addded by simply moving base of
* the right interval down and increasing its size
* accordingly.
* The interval can be addded by simply moving base of the right
* interval down and increasing its size accordingly.
*/
node->value[0] += count;
node->key[0] = page;
1373,8 → 1302,7
* The interval is between both neigbouring intervals,
* but cannot be merged with any of them.
*/
btree_insert(&a->used_space, page, (void *) count,
leaf);
btree_insert(&a->used_space, page, (void *) count, leaf);
return 1;
}
} else if (page >= leaf->key[leaf->keys - 1]) {
1382,19 → 1310,15
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
/*
* Investigate the border case in which the right neighbour
* does not exist but the interval fits from the right.
* Investigate the border case in which the right neighbour does not
* exist but the interval fits from the right.
*/
if (overlaps(page, count * PAGE_SIZE, left_pg,
left_cnt * PAGE_SIZE)) {
if (overlaps(page, count*PAGE_SIZE, left_pg, left_cnt*PAGE_SIZE)) {
/* The interval intersects with the left interval. */
return 0;
} else if (left_pg + left_cnt * PAGE_SIZE == page) {
/*
* The interval can be added by growing the left
* interval.
*/
} else if (left_pg + left_cnt*PAGE_SIZE == page) {
/* The interval can be added by growing the left interval. */
leaf->value[leaf->keys - 1] += count;
return 1;
} else {
1402,63 → 1326,44
* The interval doesn't adjoin with the left interval.
* It must be added individually.
*/
btree_insert(&a->used_space, page, (void *) count,
leaf);
btree_insert(&a->used_space, page, (void *) count, leaf);
return 1;
}
}
/*
* Note that if the algorithm made it thus far, the interval can fit
* only between two other intervals of the leaf. The two border cases
* were already resolved.
* Note that if the algorithm made it thus far, the interval can fit only
* between two other intervals of the leaf. The two border cases were already
* resolved.
*/
for (i = 1; i < leaf->keys; i++) {
if (page < leaf->key[i]) {
uintptr_t left_pg = leaf->key[i - 1];
uintptr_t right_pg = leaf->key[i];
count_t left_cnt = (count_t) leaf->value[i - 1];
count_t right_cnt = (count_t) leaf->value[i];
uintptr_t left_pg = leaf->key[i - 1], right_pg = leaf->key[i];
count_t left_cnt = (count_t) leaf->value[i - 1], right_cnt = (count_t) leaf->value[i];
 
/*
* The interval fits between left_pg and right_pg.
*/
 
if (overlaps(page, count * PAGE_SIZE, left_pg,
left_cnt * PAGE_SIZE)) {
/*
* The interval intersects with the left
* interval.
*/
if (overlaps(page, count*PAGE_SIZE, left_pg, left_cnt*PAGE_SIZE)) {
/* The interval intersects with the left interval. */
return 0;
} else if (overlaps(page, count * PAGE_SIZE, right_pg,
right_cnt * PAGE_SIZE)) {
/*
* The interval intersects with the right
* interval.
*/
} else if (overlaps(page, count*PAGE_SIZE, right_pg, right_cnt*PAGE_SIZE)) {
/* The interval intersects with the right interval. */
return 0;
} else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
(page + count * PAGE_SIZE == right_pg)) {
/*
* The interval can be added by merging the two
* already present intervals.
*/
} else if ((page == left_pg + left_cnt*PAGE_SIZE) && (page + count*PAGE_SIZE == right_pg)) {
/* The interval can be added by merging the two already present intervals. */
leaf->value[i - 1] += count + right_cnt;
btree_remove(&a->used_space, right_pg, leaf);
return 1;
} else if (page == left_pg + left_cnt * PAGE_SIZE) {
/*
* The interval can be added by simply growing
* the left interval.
*/
} else if (page == left_pg + left_cnt*PAGE_SIZE) {
/* The interval can be added by simply growing the left interval. */
leaf->value[i - 1] += count;
return 1;
} else if (page + count * PAGE_SIZE == right_pg) {
} else if (page + count*PAGE_SIZE == right_pg) {
/*
* The interval can be addded by simply moving
* base of the right interval down and
* increasing its size accordingly.
* The interval can be addded by simply moving base of the right
* interval down and increasing its size accordingly.
*/
leaf->value[i] += count;
leaf->key[i] = page;
1465,19 → 1370,16
return 1;
} else {
/*
* The interval is between both neigbouring
* intervals, but cannot be merged with any of
* them.
* The interval is between both neigbouring intervals,
* but cannot be merged with any of them.
*/
btree_insert(&a->used_space, page,
(void *) count, leaf);
btree_insert(&a->used_space, page, (void *) count, leaf);
return 1;
}
}
}
 
panic("Inconsistency detected while adding %d pages of used space at "
"%p.\n", count, page);
panic("Inconsistency detected while adding %d pages of used space at %p.\n", count, page);
}
 
/** Mark portion of address space area as unused.
1516,7 → 1418,7
*/
for (i = 0; i < leaf->keys; i++) {
if (leaf->key[i] == page) {
leaf->key[i] += count * PAGE_SIZE;
leaf->key[i] += count*PAGE_SIZE;
leaf->value[i] -= count;
return 1;
}
1530,34 → 1432,27
uintptr_t left_pg = node->key[node->keys - 1];
count_t left_cnt = (count_t) node->value[node->keys - 1];
 
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
if (page + count * PAGE_SIZE ==
left_pg + left_cnt * PAGE_SIZE) {
if (overlaps(left_pg, left_cnt*PAGE_SIZE, page, count*PAGE_SIZE)) {
if (page + count*PAGE_SIZE == left_pg + left_cnt*PAGE_SIZE) {
/*
* The interval is contained in the rightmost
* interval of the left neighbour and can be
* removed by updating the size of the bigger
* interval.
* The interval is contained in the rightmost interval
* of the left neighbour and can be removed by
* updating the size of the bigger interval.
*/
node->value[node->keys - 1] -= count;
return 1;
} else if (page + count * PAGE_SIZE <
left_pg + left_cnt*PAGE_SIZE) {
} else if (page + count*PAGE_SIZE < left_pg + left_cnt*PAGE_SIZE) {
count_t new_cnt;
/*
* The interval is contained in the rightmost
* interval of the left neighbour but its
* removal requires both updating the size of
* the original interval and also inserting a
* new interval.
* The interval is contained in the rightmost interval
* of the left neighbour but its removal requires
* both updating the size of the original interval and
* also inserting a new interval.
*/
new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
(page + count*PAGE_SIZE)) >> PAGE_WIDTH;
new_cnt = ((left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
node->value[node->keys - 1] -= count + new_cnt;
btree_insert(&a->used_space, page +
count * PAGE_SIZE, (void *) new_cnt, leaf);
btree_insert(&a->used_space, page + count*PAGE_SIZE, (void *) new_cnt, leaf);
return 1;
}
}
1570,33 → 1465,27
uintptr_t left_pg = leaf->key[leaf->keys - 1];
count_t left_cnt = (count_t) leaf->value[leaf->keys - 1];
 
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
if (page + count * PAGE_SIZE ==
left_pg + left_cnt * PAGE_SIZE) {
if (overlaps(left_pg, left_cnt*PAGE_SIZE, page, count*PAGE_SIZE)) {
if (page + count*PAGE_SIZE == left_pg + left_cnt*PAGE_SIZE) {
/*
* The interval is contained in the rightmost
* interval of the leaf and can be removed by
* updating the size of the bigger interval.
* The interval is contained in the rightmost interval
* of the leaf and can be removed by updating the size
* of the bigger interval.
*/
leaf->value[leaf->keys - 1] -= count;
return 1;
} else if (page + count * PAGE_SIZE < left_pg +
left_cnt * PAGE_SIZE) {
} else if (page + count*PAGE_SIZE < left_pg + left_cnt*PAGE_SIZE) {
count_t new_cnt;
/*
* The interval is contained in the rightmost
* interval of the leaf but its removal
* requires both updating the size of the
* original interval and also inserting a new
* interval.
* The interval is contained in the rightmost interval
* of the leaf but its removal requires both updating
* the size of the original interval and
* also inserting a new interval.
*/
new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
(page + count * PAGE_SIZE)) >> PAGE_WIDTH;
new_cnt = ((left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
leaf->value[leaf->keys - 1] -= count + new_cnt;
btree_insert(&a->used_space, page +
count * PAGE_SIZE, (void *) new_cnt, leaf);
btree_insert(&a->used_space, page + count*PAGE_SIZE, (void *) new_cnt, leaf);
return 1;
}
}
1613,40 → 1502,29
count_t left_cnt = (count_t) leaf->value[i - 1];
 
/*
* Now the interval is between intervals corresponding
* to (i - 1) and i.
* Now the interval is between intervals corresponding to (i - 1) and i.
*/
if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
count * PAGE_SIZE)) {
if (page + count * PAGE_SIZE ==
left_pg + left_cnt*PAGE_SIZE) {
if (overlaps(left_pg, left_cnt*PAGE_SIZE, page, count*PAGE_SIZE)) {
if (page + count*PAGE_SIZE == left_pg + left_cnt*PAGE_SIZE) {
/*
* The interval is contained in the
* interval (i - 1) of the leaf and can
* be removed by updating the size of
* the bigger interval.
* The interval is contained in the interval (i - 1)
* of the leaf and can be removed by updating the size
* of the bigger interval.
*/
leaf->value[i - 1] -= count;
return 1;
} else if (page + count * PAGE_SIZE <
left_pg + left_cnt * PAGE_SIZE) {
} else if (page + count*PAGE_SIZE < left_pg + left_cnt*PAGE_SIZE) {
count_t new_cnt;
/*
* The interval is contained in the
* interval (i - 1) of the leaf but its
* removal requires both updating the
* size of the original interval and
* The interval is contained in the interval (i - 1)
* of the leaf but its removal requires both updating
* the size of the original interval and
* also inserting a new interval.
*/
new_cnt = ((left_pg +
left_cnt * PAGE_SIZE) -
(page + count * PAGE_SIZE)) >>
PAGE_WIDTH;
new_cnt = ((left_pg + left_cnt*PAGE_SIZE) - (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
leaf->value[i - 1] -= count + new_cnt;
btree_insert(&a->used_space, page +
count * PAGE_SIZE, (void *) new_cnt,
leaf);
btree_insert(&a->used_space, page + count*PAGE_SIZE, (void *) new_cnt, leaf);
return 1;
}
}
1655,8 → 1533,7
}
 
error:
panic("Inconsistency detected while removing %d pages of used space "
"from %p.\n", count, page);
panic("Inconsistency detected while removing %d pages of used space from %p.\n", count, page);
}
 
/** Remove reference to address space area share info.
1679,8 → 1556,7
* Now walk carefully the pagemap B+tree and free/remove
* reference from all frames found there.
*/
for (cur = sh_info->pagemap.leaf_head.next;
cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
for (cur = sh_info->pagemap.leaf_head.next; cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
btree_node_t *node;
int i;
1705,8 → 1581,7
/** Wrapper for as_area_create(). */
unative_t sys_as_area_create(uintptr_t address, size_t size, int flags)
{
if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
AS_AREA_ATTR_NONE, &anon_backend, NULL))
if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address, AS_AREA_ATTR_NONE, &anon_backend, NULL))
return (unative_t) address;
else
return (unative_t) -1;
1737,12 → 1612,9
/* print out info about address space areas */
link_t *cur;
for (cur = as->as_area_btree.leaf_head.next;
cur != &as->as_area_btree.leaf_head; cur = cur->next) {
btree_node_t *node;
for (cur = as->as_area_btree.leaf_head.next; cur != &as->as_area_btree.leaf_head; cur = cur->next) {
btree_node_t *node = list_get_instance(cur, btree_node_t, leaf_link);
node = list_get_instance(cur, btree_node_t, leaf_link);
int i;
for (i = 0; i < node->keys; i++) {
as_area_t *area = node->value[i];
1749,8 → 1621,7
mutex_lock(&area->lock);
printf("as_area: %p, base=%p, pages=%d (%p - %p)\n",
area, area->base, area->pages, area->base,
area->base + area->pages*PAGE_SIZE);
area, area->base, area->pages, area->base, area->base + area->pages*PAGE_SIZE);
mutex_unlock(&area->lock);
}
}