syscall: add lots of syscalls
This commit is contained in:
202
syscall/task.c
202
syscall/task.c
@@ -1,13 +1,203 @@
|
||||
#include <mango/machine/cpu.h>
|
||||
#include <mango/printk.h>
|
||||
#include <mango/sched.h>
|
||||
#include <kernel/machine/cpu.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/syscall.h>
|
||||
#include <kernel/vm-region.h>
|
||||
|
||||
extern kern_status_t sys_exit(int status)
|
||||
extern kern_status_t sys_task_exit(int status)
|
||||
{
|
||||
printk("sys_exit(%d)", status);
|
||||
while (1) {
|
||||
ml_cpu_pause();
|
||||
printk("sys_exit(%d)", status);
|
||||
milli_sleep(1000);
|
||||
}
|
||||
|
||||
return KERN_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
kern_status_t sys_task_create(
|
||||
kern_handle_t parent_handle,
|
||||
const char *name,
|
||||
size_t name_len,
|
||||
kern_handle_t *out_task,
|
||||
kern_handle_t *out_address_space)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct task *self = current_task();
|
||||
|
||||
if (name_len && !validate_access_r(self, name, name_len)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (!validate_access_w(self, out_task, sizeof *out_task)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (!validate_access_w(
|
||||
self,
|
||||
out_address_space,
|
||||
sizeof *out_address_space)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
struct object *parent_obj;
|
||||
handle_flags_t parent_flags;
|
||||
task_lock_irqsave(self, &flags);
|
||||
kern_status_t status = task_resolve_handle(
|
||||
self,
|
||||
parent_handle,
|
||||
&parent_obj,
|
||||
&parent_flags);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
object_ref(parent_obj);
|
||||
struct task *parent = task_cast(parent_obj);
|
||||
|
||||
struct handle *child_handle_slot = NULL, *space_handle_slot = NULL;
|
||||
kern_handle_t child_handle, space_handle;
|
||||
status = handle_table_alloc_handle(
|
||||
self->t_handles,
|
||||
&child_handle_slot,
|
||||
&child_handle);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = handle_table_alloc_handle(
|
||||
self->t_handles,
|
||||
&space_handle_slot,
|
||||
&space_handle);
|
||||
if (status != KERN_OK) {
|
||||
handle_table_free_handle(self->t_handles, child_handle);
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
task_unlock_irqrestore(self, flags);
|
||||
|
||||
struct task *child = task_create(name, name_len);
|
||||
if (!child) {
|
||||
object_unref(parent_obj);
|
||||
|
||||
task_lock_irqsave(self, &flags);
|
||||
handle_table_free_handle(self->t_handles, child_handle);
|
||||
handle_table_free_handle(self->t_handles, space_handle);
|
||||
task_unlock_irqrestore(self, flags);
|
||||
|
||||
return KERN_NO_MEMORY;
|
||||
}
|
||||
|
||||
task_lock_irqsave(parent, &flags);
|
||||
task_add_child(parent, child);
|
||||
task_unlock_irqrestore(parent, flags);
|
||||
|
||||
child_handle_slot->h_object = &child->t_base;
|
||||
space_handle_slot->h_object = &child->t_address_space->vr_base;
|
||||
|
||||
object_add_handle(&child->t_base);
|
||||
object_add_handle(&child->t_address_space->vr_base);
|
||||
|
||||
object_unref(parent_obj);
|
||||
|
||||
*out_task = child_handle;
|
||||
*out_address_space = space_handle;
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t sys_task_create_thread(
|
||||
kern_handle_t task,
|
||||
virt_addr_t ip,
|
||||
virt_addr_t sp,
|
||||
uintptr_t *args,
|
||||
size_t nr_args,
|
||||
kern_handle_t *out_thread)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct task *self = current_task();
|
||||
|
||||
if (!validate_access_r(self, args, nr_args * sizeof(uintptr_t))) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
if (!validate_access_w(self, out_thread, sizeof *out_thread)) {
|
||||
return KERN_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
struct object *target_obj;
|
||||
handle_flags_t target_flags;
|
||||
task_lock_irqsave(self, &flags);
|
||||
kern_status_t status
|
||||
= task_resolve_handle(self, task, &target_obj, &target_flags);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
object_ref(target_obj);
|
||||
struct task *target = task_cast(target_obj);
|
||||
|
||||
struct handle *target_handle = NULL;
|
||||
kern_handle_t out_handle;
|
||||
status = handle_table_alloc_handle(
|
||||
self->t_handles,
|
||||
&target_handle,
|
||||
&out_handle);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
task_unlock_irqrestore(self, flags);
|
||||
task_lock_irqsave(target, &flags);
|
||||
|
||||
struct thread *thread = task_create_thread(target);
|
||||
if (!thread) {
|
||||
object_unref(target_obj);
|
||||
task_unlock_irqrestore(target, flags);
|
||||
|
||||
task_lock_irqsave(self, &flags);
|
||||
handle_table_free_handle(self->t_handles, out_handle);
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return KERN_NO_MEMORY;
|
||||
}
|
||||
|
||||
thread_init_user(thread, ip, sp, args, nr_args);
|
||||
target_handle->h_object = &thread->thr_base;
|
||||
object_add_handle(&thread->thr_base);
|
||||
|
||||
task_unlock_irqrestore(target, flags);
|
||||
|
||||
*out_thread = out_handle;
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t sys_thread_start(kern_handle_t thread_handle)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct task *self = current_task();
|
||||
|
||||
struct object *thread_obj;
|
||||
handle_flags_t thread_flags;
|
||||
task_lock_irqsave(self, &flags);
|
||||
kern_status_t status = task_resolve_handle(
|
||||
self,
|
||||
thread_handle,
|
||||
&thread_obj,
|
||||
&thread_flags);
|
||||
if (status != KERN_OK) {
|
||||
task_unlock_irqrestore(self, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
object_ref(thread_obj);
|
||||
struct thread *thread = thread_cast(thread_obj);
|
||||
task_unlock_irqrestore(self, flags);
|
||||
|
||||
schedule_thread_on_cpu(thread);
|
||||
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user