vm: object: add prefetch function to fetch missing pages

This commit is contained in:
2026-04-30 19:09:41 +01:00
parent 607efa961f
commit d63c2dbd12
3 changed files with 78 additions and 9 deletions
+10
View File
@@ -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,
+40 -8
View File
@@ -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);
if (status != KERN_OK) {
task_unlock_irqrestore(self, irq_flags);
put_current_task(self);
if (status != KERN_OK) {
return status;
}
struct vm_object *vmo = vm_object_cast(obj);
if (!vmo) {
put_current_task(self);
object_unref(obj);
return KERN_INVALID_ARGUMENT;
}
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);
put_current_task(self);
}
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);
if (status != KERN_OK) {
task_unlock_irqrestore(self, irq_flags);
put_current_task(self);
if (status != KERN_OK) {
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);
+27
View File
@@ -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,