vm: object: add prefetch function to fetch missing pages
This commit is contained in:
@@ -98,6 +98,16 @@ extern kern_status_t vm_object_attach_cow(
|
||||
struct vm_object *vmo,
|
||||
unsigned long *irq_flags);
|
||||
|
||||
/* prefetch any missing pages in the specified range of a vm-object.
|
||||
* any lazy-allocated pages will be allocated.
|
||||
* any missing pages will be requested from the vm-controller, if one is
|
||||
* attached. */
|
||||
extern kern_status_t vm_object_prefetch(
|
||||
struct vm_object *vo,
|
||||
off_t offset,
|
||||
size_t length,
|
||||
unsigned long *irq_flags);
|
||||
|
||||
extern struct vm_page *vm_object_get_page(
|
||||
struct vm_object *vo,
|
||||
off_t offset,
|
||||
|
||||
+41
-9
@@ -58,20 +58,31 @@ kern_status_t sys_vm_object_read(
|
||||
|
||||
struct object *obj = NULL;
|
||||
handle_flags_t flags = 0;
|
||||
unsigned long irq_flags = 0;
|
||||
task_lock_irqsave(self, &irq_flags);
|
||||
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
|
||||
task_unlock_irqrestore(self, irq_flags);
|
||||
put_current_task(self);
|
||||
|
||||
if (status != KERN_OK) {
|
||||
put_current_task(self);
|
||||
return status;
|
||||
}
|
||||
|
||||
struct vm_object *vmo = vm_object_cast(obj);
|
||||
if (!vmo) {
|
||||
put_current_task(self);
|
||||
object_unref(obj);
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
status = vm_object_read(vmo, dst, offset, count, nr_read);
|
||||
put_current_task(self);
|
||||
vm_object_lock_irqsave(vmo, &irq_flags);
|
||||
status = vm_object_prefetch(vmo, offset, count, &irq_flags);
|
||||
if (status == KERN_OK) {
|
||||
status = vm_object_read(vmo, dst, offset, count, nr_read);
|
||||
}
|
||||
|
||||
vm_object_unlock_irqrestore(vmo, irq_flags);
|
||||
object_unref(obj);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -97,20 +108,25 @@ kern_status_t sys_vm_object_write(
|
||||
|
||||
struct object *obj = NULL;
|
||||
handle_flags_t flags = 0;
|
||||
unsigned long irq_flags = 0;
|
||||
task_lock_irqsave(self, &irq_flags);
|
||||
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
|
||||
task_unlock_irqrestore(self, irq_flags);
|
||||
put_current_task(self);
|
||||
|
||||
if (status != KERN_OK) {
|
||||
put_current_task(self);
|
||||
return status;
|
||||
}
|
||||
|
||||
struct vm_object *vmo = vm_object_cast(obj);
|
||||
if (!vmo) {
|
||||
put_current_task(self);
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
vm_object_lock_irqsave(vmo, &irq_flags);
|
||||
status = vm_object_write(vmo, src, offset, count, nr_written);
|
||||
put_current_task(self);
|
||||
vm_object_unlock_irqrestore(vmo, irq_flags);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -162,13 +178,28 @@ kern_status_t sys_vm_object_copy(
|
||||
put_current_task(self);
|
||||
|
||||
struct vm_object *dst_vmo = vm_object_cast(dst_obj);
|
||||
if (!dst_vmo) {
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
struct vm_object *src_vmo = vm_object_cast(src_obj);
|
||||
if (!dst_vmo || !src_vmo) {
|
||||
object_unref(src_obj);
|
||||
if (!src_vmo) {
|
||||
object_unref(dst_obj);
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
unsigned long irq_flags = 0;
|
||||
vm_object_lock_irqsave(src_vmo, &irq_flags);
|
||||
status = vm_object_prefetch(src_vmo, src_offset, count, &irq_flags);
|
||||
vm_object_unlock_irqrestore(src_vmo, irq_flags);
|
||||
|
||||
if (status != KERN_OK) {
|
||||
object_unref(src_obj);
|
||||
object_unref(dst_obj);
|
||||
return status;
|
||||
}
|
||||
|
||||
vm_object_lock_pair_irqsave(src_vmo, dst_vmo, &irq_flags);
|
||||
status = vm_object_copy(
|
||||
dst_vmo,
|
||||
dst_offset,
|
||||
@@ -176,6 +207,7 @@ kern_status_t sys_vm_object_copy(
|
||||
src_offset,
|
||||
count,
|
||||
nr_copied);
|
||||
vm_object_unlock_pair_irqrestore(src_vmo, dst_vmo, irq_flags);
|
||||
|
||||
object_unref(src_obj);
|
||||
object_unref(dst_obj);
|
||||
|
||||
@@ -516,6 +516,33 @@ static kern_status_t request_page(
|
||||
return status;
|
||||
}
|
||||
|
||||
kern_status_t vm_object_prefetch(
|
||||
struct vm_object *vo,
|
||||
off_t offset,
|
||||
size_t length,
|
||||
unsigned long *irq_flags)
|
||||
{
|
||||
offset &= ~VM_PAGE_MASK;
|
||||
if (length & VM_PAGE_MASK) {
|
||||
length &= ~VM_PAGE_MASK;
|
||||
length += VM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
for (off_t i = offset; i < offset + length; i += VM_PAGE_SIZE) {
|
||||
struct vm_page *pg = vm_object_get_page(
|
||||
vo,
|
||||
i,
|
||||
VMO_ALLOCATE_MISSING_PAGE | VMO_REQUEST_MISSING_PAGE,
|
||||
irq_flags);
|
||||
if (!pg) {
|
||||
/* TODO get error code from vm_object_get_page */
|
||||
return KERN_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
struct vm_page *vm_object_get_page(
|
||||
struct vm_object *vo,
|
||||
off_t offset,
|
||||
|
||||
Reference in New Issue
Block a user