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,
|
VMO_IN_PLACE = 0x01u,
|
||||||
/* this vm-object is/was attached to a vm-controller */
|
/* this vm-object is/was attached to a vm-controller */
|
||||||
VMO_CONTROLLER = 0x02u,
|
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 */
|
/* these flags are for use with vm_object_get_page */
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
|
|
||||||
/* if the relevant page hasn't been allocated yet, it will be allocated
|
/* 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. */
|
* 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
|
/* 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
|
* 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 missing page. will result in the vm-object being unlocked and
|
||||||
* the current thread sleeping until the request is fulfilled. the
|
* the current thread sleeping until the request is fulfilled. the
|
||||||
* vm-object will be re-locked before the function returns. */
|
* vm-object will be re-locked before the function returns. */
|
||||||
VMO_REQUEST_MISSING_PAGE = 0x08u,
|
VMO_REQUEST_MISSING_PAGE = 0x10u,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vm_object {
|
struct vm_object {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <kernel/sched.h>
|
#include <kernel/sched.h>
|
||||||
#include <kernel/task.h>
|
#include <kernel/task.h>
|
||||||
#include <kernel/util.h>
|
#include <kernel/util.h>
|
||||||
|
#include <kernel/vm-controller.h>
|
||||||
#include <kernel/vm-object.h>
|
#include <kernel/vm-object.h>
|
||||||
#include <mango/status.h>
|
#include <mango/status.h>
|
||||||
|
|
||||||
@@ -721,6 +722,9 @@ kern_status_t address_space_map(
|
|||||||
}
|
}
|
||||||
|
|
||||||
tracek("address_space_map(%zx, %zx)", map_address, length);
|
tracek("address_space_map(%zx, %zx)", map_address, length);
|
||||||
|
if (map_address == 0xc6a55000) {
|
||||||
|
printk("break");
|
||||||
|
}
|
||||||
|
|
||||||
if (!root || !object) {
|
if (!root || !object) {
|
||||||
tracek("null pointer");
|
tracek("null pointer");
|
||||||
@@ -838,7 +842,7 @@ static kern_status_t split_area(
|
|||||||
|
|
||||||
put_entry(&root->s_mappings, right);
|
put_entry(&root->s_mappings, right);
|
||||||
for (size_t i = unmap_base; i < unmap_limit; i += VM_PAGE_SIZE) {
|
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);
|
pmap_remove(root->s_pmap, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,7 +879,7 @@ static kern_status_t left_reduce_area(
|
|||||||
return KERN_OK;
|
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) {
|
for (size_t i = base; i < limit; i += VM_PAGE_SIZE) {
|
||||||
pmap_remove(root->s_pmap, i);
|
pmap_remove(root->s_pmap, i);
|
||||||
}
|
}
|
||||||
@@ -912,7 +916,7 @@ static kern_status_t right_reduce_area(
|
|||||||
return KERN_OK;
|
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) {
|
for (size_t i = base; i < limit; i += VM_PAGE_SIZE) {
|
||||||
pmap_remove(root->s_pmap, i);
|
pmap_remove(root->s_pmap, i);
|
||||||
}
|
}
|
||||||
@@ -930,9 +934,10 @@ static kern_status_t delete_area(
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracek("delete mapping [%zx-%zx]",
|
tracek("delete mapping [%zx-%zx] (%zx bytes)",
|
||||||
mapping->vma_base,
|
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;
|
for (size_t i = mapping->vma_base; i < mapping->vma_limit;
|
||||||
i += VM_PAGE_SIZE) {
|
i += VM_PAGE_SIZE) {
|
||||||
@@ -946,7 +951,23 @@ static kern_status_t delete_area(
|
|||||||
&mapping->vma_object->vo_mappings,
|
&mapping->vma_object->vo_mappings,
|
||||||
&mapping->vma_object_entry);
|
&mapping->vma_object_entry);
|
||||||
mapping->vma_object = NULL;
|
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);
|
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);
|
object_unref(&object->vo_base);
|
||||||
|
|
||||||
/* don't actually delete the mapping yet. that will be done by
|
/* 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);
|
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_ctrl = ctrl;
|
||||||
vmo->vo_key = key;
|
vmo->vo_key = key;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user