Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3155 → Rev 3156

/branches/dynload/kernel/generic/src/mm/as.c
791,7 → 791,9
link_t *cur;
ipl_t ipl;
int page_flags;
uintptr_t old_frame;
uintptr_t *old_frame;
index_t frame_idx;
count_t used_pages;
 
/* Flags for the new memory mapping */
page_flags = area_flags_to_page_flags(flags);
818,13 → 820,35
base = area->base;
 
/*
* Compute total number of used pages in the used_space B+tree
*/
used_pages = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
used_pages += (count_t) node->value[i];
}
}
 
/* An array for storing frame numbers */
old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
 
/*
* Start TLB shootdown sequence.
*/
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
 
/*
* Visit only the pages mapped by used_space B+tree.
* Remove used pages from page tables and remember their frame
* numbers.
*/
frame_idx = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
841,13 → 865,10
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
PTE_PRESENT(pte));
old_frame = PTE_GET_FRAME(pte);
old_frame[frame_idx++] = PTE_GET_FRAME(pte);
 
/* Remove old mapping and insert the new one */
/* Remove old mapping */
page_mapping_remove(as, b + j * PAGE_SIZE);
page_mapping_insert(as, b + j * PAGE_SIZE,
old_frame, page_flags);
 
page_table_unlock(as, false);
}
}
864,7 → 885,38
*/
as_invalidate_translation_cache(as, area->base, area->pages);
tlb_shootdown_finalize();
 
/*
* Map pages back in with new flags. This step is kept separate
* so that there's no instant when the memory area could be
* accesed with both the old and the new flags at once.
*/
frame_idx = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
 
/* Insert the new mapping */
page_mapping_insert(as, b + j * PAGE_SIZE,
old_frame[frame_idx++], page_flags);
 
page_table_unlock(as, false);
}
}
}
 
free(old_frame);
 
mutex_unlock(&area->lock);
mutex_unlock(&as->lock);
interrupts_restore(ipl);