diff options
Diffstat (limited to 'kernel/vm/vmmap.c')
-rw-r--r-- | kernel/vm/vmmap.c | 59 |
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 ); |