kernel: add functions for moving sets of handles between tasks
This commit is contained in:
124
kernel/handle.c
124
kernel/handle.c
@@ -185,5 +185,129 @@ struct handle *handle_table_get_handle(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tab->t_handles.t_handle_list[handle_index].h_object) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return &tab->t_handles.t_handle_list[handle_index];
|
return &tab->t_handles.t_handle_list[handle_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct handle_list_iterator {
|
||||||
|
struct handle_list *it_list;
|
||||||
|
size_t it_list_count;
|
||||||
|
size_t it_list_ptr;
|
||||||
|
|
||||||
|
kern_handle_t *it_handles;
|
||||||
|
size_t it_nr_handles;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handle_list_iterator_begin(
|
||||||
|
struct handle_list_iterator *it,
|
||||||
|
struct handle_list *list,
|
||||||
|
size_t list_count)
|
||||||
|
{
|
||||||
|
memset(it, 0x0, sizeof *it);
|
||||||
|
it->it_list = list;
|
||||||
|
it->it_list_count = list_count;
|
||||||
|
|
||||||
|
while (it->it_list_ptr < list_count) {
|
||||||
|
if (list[it->it_list_ptr].l_nr_handles > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->it_list_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->it_list_ptr >= list_count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->it_handles = list[it->it_list_ptr].l_handles;
|
||||||
|
it->it_nr_handles = list[it->it_list_ptr].l_nr_handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_list_iterator_seek(
|
||||||
|
struct handle_list_iterator *it,
|
||||||
|
size_t nr_handles)
|
||||||
|
{
|
||||||
|
if (nr_handles > it->it_nr_handles) {
|
||||||
|
nr_handles = it->it_nr_handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr_handles < it->it_nr_handles) {
|
||||||
|
it->it_handles += nr_handles;
|
||||||
|
it->it_nr_handles -= nr_handles;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->it_list_ptr++;
|
||||||
|
while (it->it_list_ptr < it->it_list_count) {
|
||||||
|
if (it->it_list[it->it_list_ptr].l_nr_handles > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->it_list_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->it_list_ptr >= it->it_list_count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->it_handles = it->it_list[it->it_list_ptr].l_handles;
|
||||||
|
it->it_nr_handles = it->it_list[it->it_list_ptr].l_nr_handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t handle_list_transfer(
|
||||||
|
struct handle_table *dest_table,
|
||||||
|
struct handle_list *dest_list,
|
||||||
|
size_t dest_list_count,
|
||||||
|
struct handle_table *src_table,
|
||||||
|
const struct handle_list *src_list,
|
||||||
|
size_t src_list_count)
|
||||||
|
{
|
||||||
|
struct handle_list_iterator src, dest;
|
||||||
|
handle_list_iterator_begin(
|
||||||
|
&src,
|
||||||
|
(struct handle_list *)src_list,
|
||||||
|
src_list_count);
|
||||||
|
handle_list_iterator_begin(&dest, dest_list, dest_list_count);
|
||||||
|
|
||||||
|
while (src.it_nr_handles && dest.it_nr_handles) {
|
||||||
|
size_t to_copy = MIN(src.it_nr_handles, dest.it_nr_handles);
|
||||||
|
for (size_t i = 0; i < to_copy; i++) {
|
||||||
|
kern_handle_t handle_v = src.it_handles[i];
|
||||||
|
struct handle *handle
|
||||||
|
= handle_table_get_handle(src_table, handle_v);
|
||||||
|
if (!handle) {
|
||||||
|
return KERN_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object *obj = object_ref(handle->h_object);
|
||||||
|
handle_flags_t flags = handle->h_flags;
|
||||||
|
|
||||||
|
handle_table_free_handle(src_table, handle_v);
|
||||||
|
|
||||||
|
struct handle *dest_slot = NULL;
|
||||||
|
kern_status_t status = handle_table_alloc_handle(
|
||||||
|
dest_table,
|
||||||
|
&dest_slot,
|
||||||
|
&handle_v);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest_slot->h_object = obj;
|
||||||
|
dest_slot->h_flags = flags;
|
||||||
|
|
||||||
|
object_add_handle(obj);
|
||||||
|
object_unref(obj);
|
||||||
|
|
||||||
|
dest.it_handles[i] = handle_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_list_iterator_seek(&src, to_copy);
|
||||||
|
handle_list_iterator_seek(&dest, to_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user