vm: region: improve locking rules and semantics; implement region killing
the rules around acquiring locks have been strictly defined and
implemented, and general lock usage has been improved, to fix and
prevent several different issues.
a vm-region is now destroyed in two separate steps:
1. it is "killed": all mappings are unmapped and deleted, the
region is removed from its parent, and the region and all of
its sub-regions are marked as "dead", preventing any
further actions from being performed with the region.
2. it is "destroyed": the vm-region object is de-allocated when
the last reference/handle is closed. the references that this
region holds to any sub-regions are also released, meaning
these regions may also be de-allocated too.
This commit is contained in:
@@ -63,6 +63,7 @@ kern_status_t sys_vm_region_create(
|
||||
|
||||
object_ref(obj);
|
||||
task_unlock_irqrestore(self, flags);
|
||||
vm_region_lock_irqsave(parent_region, &flags);
|
||||
|
||||
struct vm_region *child = NULL;
|
||||
status = vm_region_create(
|
||||
@@ -73,6 +74,7 @@ kern_status_t sys_vm_region_create(
|
||||
region_len,
|
||||
prot,
|
||||
&child);
|
||||
vm_region_unlock_irqrestore(parent_region, flags);
|
||||
object_unref(obj);
|
||||
|
||||
if (status != KERN_OK) {
|
||||
@@ -92,6 +94,39 @@ kern_status_t sys_vm_region_create(
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t sys_vm_region_kill(kern_handle_t region_handle)
|
||||
{
|
||||
struct task *self = current_task();
|
||||
|
||||
unsigned long flags;
|
||||
task_lock_irqsave(self, &flags);
|
||||
|
||||
struct object *obj = NULL;
|
||||
handle_flags_t handle_flags = 0;
|
||||
kern_status_t status
|
||||
= task_resolve_handle(self, region_handle, &obj, &handle_flags);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
struct vm_region *region = vm_region_cast(obj);
|
||||
if (!region) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
object_ref(obj);
|
||||
task_unlock_irqrestore(self, flags);
|
||||
|
||||
vm_region_lock_irqsave(region, &flags);
|
||||
status = vm_region_kill(region, &flags);
|
||||
vm_region_unlock_irqrestore(region, flags);
|
||||
object_unref(obj);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
kern_status_t sys_vm_region_read(
|
||||
kern_handle_t region_handle,
|
||||
void *dst,
|
||||
|
||||
Reference in New Issue
Block a user