Files
magenta/syscall/handle.c
T

159 lines
3.0 KiB
C

#include <kernel/sched.h>
#include <kernel/syscall.h>
kern_status_t sys_kern_handle_close(kern_handle_t handle)
{
struct task *self = get_current_task();
kern_status_t status = task_close_handle(self, handle);
put_current_task(self);
return status;
}
kern_status_t sys_kern_handle_transfer(
kern_handle_t src_task_handle,
kern_handle_t src_handle,
kern_handle_t dest_task_handle,
kern_handle_t dest_handle,
unsigned int mode,
kern_handle_t *out_handle)
{
switch (mode) {
case HANDLE_TRANSFER_MOVE:
case HANDLE_TRANSFER_COPY:
break;
default:
return KERN_INVALID_ARGUMENT;
}
struct task *self = get_current_task();
if (out_handle
&& !validate_access_w(self, out_handle, sizeof *out_handle)) {
put_current_task(self);
return KERN_MEMORY_FAULT;
}
unsigned long flags;
task_lock_irqsave(self, &flags);
struct object *src_object = NULL;
struct task *src_task = NULL;
struct task *dest_task = NULL;
kern_status_t status = KERN_OK;
struct object *obj = NULL;
handle_flags_t handle_flags = 0;
if (src_task_handle != KERN_HANDLE_INVALID) {
status = task_resolve_handle(
self,
src_task_handle,
&obj,
&handle_flags);
if (status != KERN_OK) {
task_unlock_irqrestore(self, flags);
goto cleanup;
}
src_task = task_cast(obj);
if (!src_task) {
status = KERN_INVALID_ARGUMENT;
goto cleanup;
}
} else {
src_task = self;
}
if (dest_task_handle != KERN_HANDLE_INVALID) {
status = task_resolve_handle(
self,
dest_task_handle,
&obj,
&handle_flags);
if (status != KERN_OK) {
task_unlock_irqrestore(self, flags);
goto cleanup;
}
dest_task = task_cast(obj);
if (!dest_task) {
status = KERN_INVALID_ARGUMENT;
goto cleanup;
}
} else {
dest_task = self;
}
status = task_resolve_handle(
self,
src_handle,
&src_object,
&handle_flags);
if (status != KERN_OK) {
goto cleanup;
}
task_unlock_irqrestore(self, flags);
struct handle *dest = NULL;
task_lock_irqsave(dest_task, &flags);
status = handle_table_alloc_handle(
dest_task->t_handles,
dest_handle,
&dest,
&dest_handle);
task_unlock_irqrestore(dest_task, flags);
if (status != KERN_OK) {
goto cleanup;
}
if (mode == HANDLE_TRANSFER_MOVE) {
object_ref(src_object);
task_lock_irqsave(src_task, &flags);
handle_table_free_handle(src_task->t_handles, src_handle);
task_unlock_irqrestore(src_task, flags);
}
dest->h_object = src_object;
dest->h_flags = handle_flags;
if (out_handle) {
*out_handle = dest_handle;
}
put_current_task(self);
return KERN_OK;
cleanup:
if (src_task && src_task_handle != KERN_HANDLE_INVALID) {
object_unref(&src_task->t_base);
}
if (dest_task && dest_task_handle != KERN_HANDLE_INVALID) {
object_unref(&dest_task->t_base);
}
if (src_object) {
object_unref(src_object);
}
put_current_task(self);
return status;
}
kern_status_t sys_kern_handle_control(
kern_handle_t task,
kern_handle_t handle,
uint32_t set_mask,
uint32_t clear_mask,
uint32_t *out_flags)
{
return KERN_UNIMPLEMENTED;
}