From 537242e606d7980e549444395c4bcedea15da431 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 29 Mar 2026 11:47:22 +0100 Subject: [PATCH] kernel: handle: add support for allocating a specific handle value --- include/kernel/handle.h | 1 + kernel/handle.c | 51 ++++++++++++++++++++++++++++++++++++++++- sched/task.c | 7 ++++-- syscall/task.c | 6 +++++ syscall/vm-controller.c | 1 + 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/include/kernel/handle.h b/include/kernel/handle.h index 98715f4..d23d6eb 100644 --- a/include/kernel/handle.h +++ b/include/kernel/handle.h @@ -47,6 +47,7 @@ extern void handle_table_destroy(struct handle_table *tab); extern kern_status_t handle_table_alloc_handle( struct handle_table *tab, + kern_handle_t value, struct handle **out_slot, kern_handle_t *out_handle); extern kern_status_t handle_table_free_handle( diff --git a/kernel/handle.c b/kernel/handle.c index d1d0df9..8195afd 100644 --- a/kernel/handle.c +++ b/kernel/handle.c @@ -109,7 +109,7 @@ static kern_status_t encode_handle_indices( return KERN_OK; } -kern_status_t handle_table_alloc_handle( +static kern_status_t alloc_handle( struct handle_table *tab, struct handle **out_slot, kern_handle_t *out_handle) @@ -164,6 +164,53 @@ kern_status_t handle_table_alloc_handle( return encode_handle_indices(indices, out_handle); } +kern_status_t handle_table_alloc_handle( + struct handle_table *tab, + kern_handle_t value, + struct handle **out_slot, + kern_handle_t *out_handle) +{ + if (value == KERN_HANDLE_INVALID) { + return alloc_handle(tab, out_slot, out_handle); + } + + unsigned int indices[MAX_TABLE_DEPTH]; + if (decode_handle_indices(value, indices) != KERN_OK) { + return KERN_HANDLE_INVALID; + } + + int i; + for (i = 0; i < MAX_TABLE_DEPTH - 1; i++) { + struct handle_table *next + = tab->t_subtables.t_subtable_list[indices[i]]; + if (!next) { + next = handle_table_create(); + tab->t_subtables.t_subtable_list[indices[i]] = next; + } + + if (!next) { + return KERN_NO_MEMORY; + } + + tab = next; + } + + unsigned int handle_index = indices[i]; + bitmap_set(tab->t_handles.t_handle_map, handle_index); + + struct handle *out = &tab->t_handles.t_handle_list[handle_index]; + + if (out->h_object) { + object_unref(out->h_object); + out->h_object = NULL; + out->h_flags = 0; + } + + *out_slot = out; + *out_handle = value; + return KERN_OK; +} + kern_status_t handle_table_free_handle( struct handle_table *tab, kern_handle_t handle) @@ -299,6 +346,7 @@ kern_status_t handle_table_transfer( case KERN_MSG_HANDLE_MOVE: status = handle_table_alloc_handle( dst, + KERN_HANDLE_INVALID, &dst_entry, &dst_value); if (status != KERN_OK) { @@ -318,6 +366,7 @@ kern_status_t handle_table_transfer( case KERN_MSG_HANDLE_COPY: status = handle_table_alloc_handle( dst, + KERN_HANDLE_INVALID, &dst_entry, &dst_value); if (status != KERN_OK) { diff --git a/sched/task.c b/sched/task.c index 504b204..f5e70c2 100644 --- a/sched/task.c +++ b/sched/task.c @@ -352,8 +352,11 @@ kern_status_t task_open_handle( kern_handle_t *out) { struct handle *handle_data = NULL; - kern_status_t status - = handle_table_alloc_handle(task->t_handles, &handle_data, out); + kern_status_t status = handle_table_alloc_handle( + task->t_handles, + KERN_HANDLE_INVALID, + &handle_data, + out); if (status != KERN_OK) { return status; } diff --git a/syscall/task.c b/syscall/task.c index 2b04346..e436d8a 100644 --- a/syscall/task.c +++ b/syscall/task.c @@ -30,6 +30,7 @@ kern_status_t sys_task_self(kern_handle_t *out) kern_handle_t handle; kern_status_t status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &handle_slot, &handle); task_unlock_irqrestore(self, flags); @@ -89,6 +90,7 @@ kern_status_t sys_task_create( kern_handle_t child_handle, space_handle; status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &child_handle_slot, &child_handle); if (status != KERN_OK) { @@ -99,6 +101,7 @@ kern_status_t sys_task_create( status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &space_handle_slot, &space_handle); if (status != KERN_OK) { @@ -175,6 +178,7 @@ kern_status_t sys_task_create_thread( kern_handle_t out_handle; status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &target_handle, &out_handle); if (status != KERN_OK) { @@ -236,6 +240,7 @@ kern_status_t sys_task_get_address_space( status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &handle_slot, &handle); if (status != KERN_OK) { @@ -278,6 +283,7 @@ kern_status_t sys_thread_self(kern_handle_t *out) kern_handle_t handle; kern_status_t status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &handle_slot, &handle); task_unlock_irqrestore(self, flags); diff --git a/syscall/vm-controller.c b/syscall/vm-controller.c index a1c756e..807891a 100644 --- a/syscall/vm-controller.c +++ b/syscall/vm-controller.c @@ -154,6 +154,7 @@ kern_status_t sys_vm_controller_create_object( kern_handle_t out_handle = KERN_HANDLE_INVALID; status = handle_table_alloc_handle( self->t_handles, + KERN_HANDLE_INVALID, &out_slot, &out_handle);