aboutsummaryrefslogtreecommitdiff
path: root/kernel/vm/vmmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/vm/vmmap.c')
-rw-r--r--kernel/vm/vmmap.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/kernel/vm/vmmap.c b/kernel/vm/vmmap.c
index fd99c55..8789371 100644
--- a/kernel/vm/vmmap.c
+++ b/kernel/vm/vmmap.c
@@ -172,21 +172,35 @@ ssize_t vmmap_find_range(vmmap_t *map, size_t npages, int dir)
// case 1: dir is VMMAP_DIR_LOHI
if (dir == VMMAP_DIR_LOHI)
{
- // iterate over the page numbers
+ // iterate over the page numbers, going from low to high
+ // determine the continguous range of free virtual pages
+
+ int start, end = 0;
size_t vfn = ADDR_TO_PN(USER_MEM_LOW);
- while (vfn <= ADDR_TO_PN(USER_MEM_HIGH) - npages)
+ while (vfn <= ADDR_TO_PN(USER_MEM_HIGH))
{
// Lookup the vmarea for this page number
- vmarea_t *vma = vmmap_lookup(map, vfn);
-
- // if the vmarea is NULL, return the page number
+ vmarea_t *vma = vmmap_lookup(map, vfn++);
if (vma == NULL)
{
- return vfn;
+ // if unmapped, document this
+ end = vfn;
+ if (start == 0)
+ {
+ start = vfn;
+ }
+ }
+ else
+ {
+ // if mapped, start over
+ start, end = 0;
}
- // if the vmarea is not NULL, set the page number to the end of the vmarea
- vfn = vma->vma_end;
+ // if the range exists, return the start
+ if (end == npages)
+ {
+ return start;
+ }
}
}
@@ -194,20 +208,28 @@ ssize_t vmmap_find_range(vmmap_t *map, size_t npages, int dir)
else if (dir == VMMAP_DIR_HILO)
{
// iterate over the page numbers
- size_t vfn = ADDR_TO_PN(USER_MEM_HIGH) - npages;
+ int contig = 0;
+ size_t vfn = ADDR_TO_PN(USER_MEM_HIGH);
while (vfn >= ADDR_TO_PN(USER_MEM_LOW))
{
// Lookup the vmarea for this page number
- vmarea_t *vma = vmmap_lookup(map, vfn);
-
- // if the vmarea is NULL, return the page number
+ vmarea_t *vma = vmmap_lookup(map, --vfn);
if (vma == NULL)
{
- return vfn;
+ // if unmapped, increment the contig
+ contig++;
+ }
+ else
+ {
+ // if mapped, reset the contig
+ contig = 0;
}
- // if the vmarea is not NULL, set the page number to the start of the vmarea
- vfn = vma->vma_start - npages;
+ // if there are n contiguous pages, return the current vfn
+ if (contig == npages)
+ {
+ return vfn;
+ }
}
}
@@ -448,6 +470,7 @@ long vmmap_map(vmmap_t *map, vnode_t *file, size_t lopage, size_t npages,
mobj_t *shadow_obj = shadow_create(new_vmarea->vma_obj);
mobj_unlock(new_vmarea->vma_obj);
mobj_unlock(shadow_obj); // unlock the shadow object before use
+ mobj_put(&new_vmarea->vma_obj); // put the original object
if (shadow_obj == NULL)
{
vmarea_free(new_vmarea);
@@ -674,7 +697,7 @@ long vmmap_read(vmmap_t *map, const void *vaddr, void *buf, size_t count)
size_t vfn = ADDR_TO_PN(vaddr);
size_t end_vfn = ADDR_TO_PN(vaddr + count);
size_t bytes_read = 0;
- while (vfn < end_vfn)
+ while (vfn <= end_vfn)
{
// Lookup the vmarea for this page number
vmarea_t *vma = vmmap_lookup(map, vfn);
@@ -697,7 +720,7 @@ long vmmap_read(vmmap_t *map, const void *vaddr, void *buf, size_t count)
void *cursor = (void *)(bytes_read + vaddr);
size_t bytes_this_iteration = MIN(PAGE_SIZE - PAGE_OFFSET(cursor), count - bytes_read);
memcpy(
- buf + bytes_read,
+ (void *) buf + bytes_read,
(void *)pf->pf_addr + PAGE_OFFSET(cursor),
bytes_this_iteration
);
@@ -768,7 +791,7 @@ long vmmap_write(vmmap_t *map, void *vaddr, const void *buf, size_t count)
size_t bytes_this_iteration = MIN(PAGE_SIZE - PAGE_OFFSET(cursor), count - bytes_written);
memcpy(
(void *)pf->pf_addr + PAGE_OFFSET(cursor),
- buf + bytes_written,
+ (void *)buf + bytes_written,
bytes_this_iteration
);