vm: controller: add an auto-detach flag for vm-objects
This commit is contained in:
@@ -14,19 +14,25 @@ enum vm_object_flags {
|
||||
VMO_IN_PLACE = 0x01u,
|
||||
/* this vm-object is/was attached to a vm-controller */
|
||||
VMO_CONTROLLER = 0x02u,
|
||||
/* when a vm-object is attached to a controller, and the ref-count of
|
||||
* the object falls to one (i.e. the last reference is the handle to
|
||||
* the object held by the server that created it), the object will
|
||||
* be detached, allowing the server to close the last handle to the
|
||||
* object and dispose of it. */
|
||||
VMO_AUTO_DETACH = 0x04u,
|
||||
|
||||
/* these flags are for use with vm_object_get_page */
|
||||
/**************************************************/
|
||||
|
||||
/* if the relevant page hasn't been allocated yet, it will be allocated
|
||||
* and returned. if this flag isn't specified, NULL will be returned. */
|
||||
VMO_ALLOCATE_MISSING_PAGE = 0x04u,
|
||||
VMO_ALLOCATE_MISSING_PAGE = 0x08u,
|
||||
/* if the vm-object is attached to a vm-controller, and the relevant
|
||||
* page is uncommitted, send a request to the vm-controller to provide
|
||||
* the missing page. will result in the vm-object being unlocked and
|
||||
* the current thread sleeping until the request is fulfilled. the
|
||||
* vm-object will be re-locked before the function returns. */
|
||||
VMO_REQUEST_MISSING_PAGE = 0x08u,
|
||||
VMO_REQUEST_MISSING_PAGE = 0x10u,
|
||||
};
|
||||
|
||||
struct vm_object {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/task.h>
|
||||
#include <kernel/util.h>
|
||||
#include <kernel/vm-controller.h>
|
||||
#include <kernel/vm-object.h>
|
||||
#include <mango/status.h>
|
||||
|
||||
@@ -721,6 +722,9 @@ kern_status_t address_space_map(
|
||||
}
|
||||
|
||||
tracek("address_space_map(%zx, %zx)", map_address, length);
|
||||
if (map_address == 0xc6a55000) {
|
||||
printk("break");
|
||||
}
|
||||
|
||||
if (!root || !object) {
|
||||
tracek("null pointer");
|
||||
@@ -838,7 +842,7 @@ static kern_status_t split_area(
|
||||
|
||||
put_entry(&root->s_mappings, right);
|
||||
for (size_t i = unmap_base; i < unmap_limit; i += VM_PAGE_SIZE) {
|
||||
tracek("unmapping %zx", i);
|
||||
tracek("pmap_remove %zx", i);
|
||||
pmap_remove(root->s_pmap, i);
|
||||
}
|
||||
|
||||
@@ -875,7 +879,7 @@ static kern_status_t left_reduce_area(
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
tracek(" unmapping %zx-%zx (%zx bytes)", base, base + length, length);
|
||||
tracek(" pmap_remove %zx-%zx (%zx bytes)", base, base + length, length);
|
||||
for (size_t i = base; i < limit; i += VM_PAGE_SIZE) {
|
||||
pmap_remove(root->s_pmap, i);
|
||||
}
|
||||
@@ -912,7 +916,7 @@ static kern_status_t right_reduce_area(
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
tracek(" unmapping %zx-%zx (%zx bytes)", base, base + length, length);
|
||||
tracek(" pmap_remove %zx-%zx (%zx bytes)", base, base + length, length);
|
||||
for (size_t i = base; i < limit; i += VM_PAGE_SIZE) {
|
||||
pmap_remove(root->s_pmap, i);
|
||||
}
|
||||
@@ -930,9 +934,10 @@ static kern_status_t delete_area(
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
tracek("delete mapping [%zx-%zx]",
|
||||
tracek("delete mapping [%zx-%zx] (%zx bytes)",
|
||||
mapping->vma_base,
|
||||
mapping->vma_limit);
|
||||
mapping->vma_limit,
|
||||
mapping->vma_limit - mapping->vma_base);
|
||||
|
||||
for (size_t i = mapping->vma_base; i < mapping->vma_limit;
|
||||
i += VM_PAGE_SIZE) {
|
||||
@@ -946,7 +951,23 @@ static kern_status_t delete_area(
|
||||
&mapping->vma_object->vo_mappings,
|
||||
&mapping->vma_object_entry);
|
||||
mapping->vma_object = NULL;
|
||||
/* if the object is attached to a controller and the ref-count is 2,
|
||||
* then the only other remaining reference to this object is held by
|
||||
* the controller. */
|
||||
struct vm_controller *ctrl = object->vo_ctrl;
|
||||
bool detach = ctrl != NULL && object->vo_base.ob_refcount == 2
|
||||
&& (object->vo_flags & VMO_AUTO_DETACH);
|
||||
vm_object_unlock_irqrestore(object, flags);
|
||||
|
||||
if (detach) {
|
||||
/* TODO find a better way to achieve this, and/or give the
|
||||
* server that created the object more control over when it
|
||||
* should be detached */
|
||||
vm_controller_lock_irqsave(ctrl, &flags);
|
||||
vm_controller_detach_object(ctrl, object);
|
||||
vm_controller_unlock_irqrestore(ctrl, flags);
|
||||
}
|
||||
|
||||
object_unref(&object->vo_base);
|
||||
|
||||
/* don't actually delete the mapping yet. that will be done by
|
||||
|
||||
@@ -198,7 +198,8 @@ kern_status_t vm_controller_create_object(
|
||||
|
||||
object_ref(&ctrl->vc_base);
|
||||
|
||||
vmo->vo_flags |= VMO_CONTROLLER;
|
||||
/* TODO expose the VMO_AUTO_DETACH flag to userspace */
|
||||
vmo->vo_flags |= VMO_CONTROLLER | VMO_AUTO_DETACH;
|
||||
vmo->vo_ctrl = ctrl;
|
||||
vmo->vo_key = key;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user