kernel: re-implement sending handles via port messages
This commit is contained in:
143
kernel/handle.c
143
kernel/handle.c
@@ -3,7 +3,9 @@
|
||||
#include <kernel/object.h>
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/util.h>
|
||||
#include <kernel/vm-region.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <mango/types.h>
|
||||
|
||||
/* depth=3 gives a maximum of ~66.6 million handles */
|
||||
#define MAX_TABLE_DEPTH 3
|
||||
@@ -191,3 +193,144 @@ struct handle *handle_table_get_handle(
|
||||
|
||||
return &tab->t_handles.t_handle_list[handle_index];
|
||||
}
|
||||
|
||||
kern_status_t handle_table_transfer(
|
||||
struct vm_region *dst_region,
|
||||
struct handle_table *dst,
|
||||
kern_msg_handle_t *dst_handles,
|
||||
size_t dst_handles_max,
|
||||
struct vm_region *src_region,
|
||||
struct handle_table *src,
|
||||
kern_msg_handle_t *src_handles,
|
||||
size_t src_handles_count)
|
||||
{
|
||||
kern_status_t status = KERN_OK;
|
||||
size_t to_transfer = MIN(dst_handles_max, src_handles_count);
|
||||
|
||||
size_t i = 0;
|
||||
for (size_t i = 0; i < to_transfer; i++) {
|
||||
kern_msg_handle_t src_handle = {0}, dst_handle = {0};
|
||||
virt_addr_t src_handle_addr
|
||||
= (virt_addr_t)src_handles + (i * sizeof src_handle);
|
||||
virt_addr_t dst_handle_addr
|
||||
= (virt_addr_t)dst_handles + (i * sizeof dst_handle);
|
||||
status = vm_region_read_kernel(
|
||||
src_region,
|
||||
src_handle_addr,
|
||||
sizeof src_handle,
|
||||
&src_handle,
|
||||
NULL);
|
||||
|
||||
if (status != KERN_OK) {
|
||||
src_handle.hnd_result = KERN_OK;
|
||||
vm_region_write_kernel(
|
||||
src_region,
|
||||
src_handle_addr,
|
||||
sizeof src_handle,
|
||||
&src_handle,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
struct handle *src_entry
|
||||
= handle_table_get_handle(src, src_handle.hnd_value);
|
||||
struct handle *dst_entry = NULL;
|
||||
kern_handle_t dst_value = KERN_HANDLE_INVALID;
|
||||
|
||||
if (!src_entry) {
|
||||
status = KERN_INVALID_ARGUMENT;
|
||||
src_handle.hnd_result = KERN_OK;
|
||||
vm_region_write_kernel(
|
||||
src_region,
|
||||
src_handle_addr,
|
||||
sizeof src_handle,
|
||||
&src_handle,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (src_handle.hnd_mode) {
|
||||
case KERN_MSG_HANDLE_IGNORE:
|
||||
break;
|
||||
case KERN_MSG_HANDLE_MOVE:
|
||||
status = handle_table_alloc_handle(
|
||||
dst,
|
||||
&dst_entry,
|
||||
&dst_value);
|
||||
if (status != KERN_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst_entry->h_object = src_entry->h_object;
|
||||
dst_entry->h_flags = src_entry->h_flags;
|
||||
object_add_handle(dst_entry->h_object);
|
||||
|
||||
handle_table_free_handle(src, src_handles[i].hnd_value);
|
||||
|
||||
dst_handle.hnd_mode = src_handles[i].hnd_mode;
|
||||
dst_handle.hnd_value = dst_value;
|
||||
dst_handle.hnd_result = KERN_OK;
|
||||
break;
|
||||
case KERN_MSG_HANDLE_COPY:
|
||||
status = handle_table_alloc_handle(
|
||||
dst,
|
||||
&dst_entry,
|
||||
&dst_value);
|
||||
if (status != KERN_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst_entry->h_object = src_entry->h_object;
|
||||
dst_entry->h_flags = src_entry->h_flags;
|
||||
object_add_handle(dst_entry->h_object);
|
||||
|
||||
dst_handle.hnd_mode = src_handles[i].hnd_mode;
|
||||
dst_handle.hnd_value = dst_value;
|
||||
dst_handle.hnd_result = KERN_OK;
|
||||
break;
|
||||
default:
|
||||
status = KERN_INVALID_ARGUMENT;
|
||||
break;
|
||||
}
|
||||
|
||||
src_handle.hnd_result = status;
|
||||
|
||||
vm_region_write_kernel(
|
||||
src_region,
|
||||
src_handle_addr,
|
||||
sizeof src_handle,
|
||||
&src_handle,
|
||||
NULL);
|
||||
vm_region_write_kernel(
|
||||
dst_region,
|
||||
dst_handle_addr,
|
||||
sizeof dst_handle,
|
||||
&dst_handle,
|
||||
NULL);
|
||||
}
|
||||
|
||||
for (; i < src_handles_count; i++) {
|
||||
kern_msg_handle_t handle = {0};
|
||||
virt_addr_t handle_addr
|
||||
= (virt_addr_t)src_handles + (i * sizeof handle);
|
||||
vm_region_read_kernel(
|
||||
src_region,
|
||||
handle_addr,
|
||||
sizeof handle,
|
||||
&handle,
|
||||
NULL);
|
||||
|
||||
if (handle.hnd_mode != KERN_MSG_HANDLE_MOVE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct handle *src_entry
|
||||
= handle_table_get_handle(src, handle.hnd_value);
|
||||
if (src_entry) {
|
||||
object_remove_handle(src_entry->h_object);
|
||||
handle_table_free_handle(src, handle.hnd_value);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user