sched: implement various ways to end tasks and threads
This commit is contained in:
@@ -68,6 +68,7 @@ extern kern_status_t sys_task_config_set(
|
|||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
extern kern_status_t sys_thread_start(kern_handle_t thread);
|
extern kern_status_t sys_thread_start(kern_handle_t thread);
|
||||||
|
extern kern_status_t sys_thread_exit(void);
|
||||||
extern kern_status_t sys_thread_config_get(
|
extern kern_status_t sys_thread_config_get(
|
||||||
kern_handle_t thread,
|
kern_handle_t thread,
|
||||||
kern_config_key_t key,
|
kern_config_key_t key,
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ static inline void task_unref(struct task *task)
|
|||||||
{
|
{
|
||||||
object_unref(&task->t_base);
|
object_unref(&task->t_base);
|
||||||
}
|
}
|
||||||
|
extern void task_exit(int status);
|
||||||
extern kern_status_t task_add_child(struct task *parent, struct task *child);
|
extern kern_status_t task_add_child(struct task *parent, struct task *child);
|
||||||
extern kern_status_t task_add_channel(
|
extern kern_status_t task_add_channel(
|
||||||
struct task *task,
|
struct task *task,
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ extern kern_status_t thread_init_user(
|
|||||||
size_t nr_args);
|
size_t nr_args);
|
||||||
extern int thread_priority(struct thread *thr);
|
extern int thread_priority(struct thread *thr);
|
||||||
extern void thread_awaken(struct thread *thr);
|
extern void thread_awaken(struct thread *thr);
|
||||||
|
extern void thread_exit(void);
|
||||||
|
extern void thread_join(struct thread *thread, unsigned long *irq_flags);
|
||||||
|
extern void thread_kill(struct thread *thread);
|
||||||
extern void idle(void);
|
extern void idle(void);
|
||||||
extern struct thread *create_kernel_thread(void (*fn)(void));
|
extern struct thread *create_kernel_thread(void (*fn)(void));
|
||||||
extern struct thread *create_idle_thread(void);
|
extern struct thread *create_idle_thread(void);
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ SYSCALL_GATE task_config_get SYS_TASK_CONFIG_GET 4
|
|||||||
SYSCALL_GATE task_config_set SYS_TASK_CONFIG_SET 4
|
SYSCALL_GATE task_config_set SYS_TASK_CONFIG_SET 4
|
||||||
|
|
||||||
SYSCALL_GATE thread_start SYS_THREAD_START 1
|
SYSCALL_GATE thread_start SYS_THREAD_START 1
|
||||||
|
SYSCALL_GATE thread_exit SYS_THREAD_EXIT 0
|
||||||
SYSCALL_GATE thread_config_get SYS_THREAD_CONFIG_GET 4
|
SYSCALL_GATE thread_config_get SYS_THREAD_CONFIG_GET 4
|
||||||
SYSCALL_GATE thread_config_set SYS_THREAD_CONFIG_SET 4
|
SYSCALL_GATE thread_config_set SYS_THREAD_CONFIG_SET 4
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ extern kern_status_t task_config_set(
|
|||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
extern kern_status_t thread_start(kern_handle_t thread);
|
extern kern_status_t thread_start(kern_handle_t thread);
|
||||||
|
extern kern_status_t thread_exit(void);
|
||||||
extern kern_status_t thread_config_get(
|
extern kern_status_t thread_config_get(
|
||||||
kern_handle_t thread,
|
kern_handle_t thread,
|
||||||
kern_config_key_t key,
|
kern_config_key_t key,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef MANGO_SIGNAL_H_
|
#ifndef MANGO_SIGNAL_H_
|
||||||
#define MANGO_SIGNAL_H_
|
#define MANGO_SIGNAL_H_
|
||||||
|
|
||||||
|
#define THREAD_SIGNAL_STOPPED 0x01u
|
||||||
|
|
||||||
#define CHANNEL_SIGNAL_MSG_RECEIVED 0x01u
|
#define CHANNEL_SIGNAL_MSG_RECEIVED 0x01u
|
||||||
|
|
||||||
#define VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED 0x01u
|
#define VM_CONTROLLER_SIGNAL_REQUEST_RECEIVED 0x01u
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#define SYS_TASK_CONFIG_GET 0x2Au
|
#define SYS_TASK_CONFIG_GET 0x2Au
|
||||||
#define SYS_TASK_CONFIG_SET 0x2Bu
|
#define SYS_TASK_CONFIG_SET 0x2Bu
|
||||||
#define SYS_THREAD_START 0x0Cu
|
#define SYS_THREAD_START 0x0Cu
|
||||||
|
#define SYS_THREAD_EXIT 0x2Eu
|
||||||
#define SYS_THREAD_CONFIG_GET 0x2Cu
|
#define SYS_THREAD_CONFIG_GET 0x2Cu
|
||||||
#define SYS_THREAD_CONFIG_SET 0x2Du
|
#define SYS_THREAD_CONFIG_SET 0x2Du
|
||||||
#define SYS_VM_OBJECT_CREATE 0x0Du
|
#define SYS_VM_OBJECT_CREATE 0x0Du
|
||||||
|
|||||||
78
sched/task.c
78
sched/task.c
@@ -222,13 +222,13 @@ kern_status_t task_add_channel(
|
|||||||
{
|
{
|
||||||
channel->c_id = id;
|
channel->c_id = id;
|
||||||
|
|
||||||
if (!task->b_channels.b_root) {
|
if (!task->t_channels.b_root) {
|
||||||
task->b_channels.b_root = &channel->c_node;
|
task->t_channels.b_root = &channel->c_node;
|
||||||
btree_insert_fixup(&task->b_channels, &channel->c_node);
|
btree_insert_fixup(&task->t_channels, &channel->c_node);
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct btree_node *cur = task->b_channels.b_root;
|
struct btree_node *cur = task->t_channels.b_root;
|
||||||
while (1) {
|
while (1) {
|
||||||
struct channel *cur_node
|
struct channel *cur_node
|
||||||
= BTREE_CONTAINER(struct channel, c_node, cur);
|
= BTREE_CONTAINER(struct channel, c_node, cur);
|
||||||
@@ -255,7 +255,7 @@ kern_status_t task_add_channel(
|
|||||||
cur = next;
|
cur = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
btree_insert_fixup(&task->b_channels, &channel->c_node);
|
btree_insert_fixup(&task->t_channels, &channel->c_node);
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ BTREE_DEFINE_SIMPLE_GET(
|
|||||||
|
|
||||||
struct channel *task_get_channel(struct task *task, unsigned int id)
|
struct channel *task_get_channel(struct task *task, unsigned int id)
|
||||||
{
|
{
|
||||||
return get_channel_with_id(&task->b_channels, id);
|
return get_channel_with_id(&task->t_channels, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct task *task_from_tid(tid_t id)
|
struct task *task_from_tid(tid_t id)
|
||||||
@@ -280,6 +280,72 @@ struct task *task_from_tid(tid_t id)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void task_exit(int status)
|
||||||
|
{
|
||||||
|
struct task *self = current_task();
|
||||||
|
unsigned long flags;
|
||||||
|
task_lock_irqsave(self, &flags);
|
||||||
|
struct task *parent = self->t_parent;
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
task_unlock_irqrestore(self, flags);
|
||||||
|
task_lock_irqsave(parent, &flags);
|
||||||
|
task_lock(self);
|
||||||
|
queue_delete(&parent->t_children, &self->t_child_entry);
|
||||||
|
task_unlock(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct thread *cur_thread = current_thread();
|
||||||
|
|
||||||
|
self->t_state = TASK_STOPPED;
|
||||||
|
cur_thread->tr_state = THREAD_STOPPED;
|
||||||
|
|
||||||
|
struct queue_entry *cur = queue_first(&self->t_threads);
|
||||||
|
while (cur) {
|
||||||
|
struct queue_entry *next = queue_next(cur);
|
||||||
|
struct thread *thread
|
||||||
|
= QUEUE_CONTAINER(struct thread, tr_parent_entry, cur);
|
||||||
|
|
||||||
|
if (thread == cur_thread) {
|
||||||
|
cur = next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_lock(thread);
|
||||||
|
thread_kill(thread);
|
||||||
|
queue_delete(&self->t_threads, cur);
|
||||||
|
thread_unlock(thread);
|
||||||
|
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_unref(&self->t_address_space->s_base);
|
||||||
|
spin_lock_t *handles_lock = &self->t_handles_lock;
|
||||||
|
struct handle_table *handles = self->t_handles;
|
||||||
|
spin_lock(&self->t_handles_lock);
|
||||||
|
|
||||||
|
pmap_switch(get_kernel_pmap());
|
||||||
|
pmap_destroy(self->t_pmap);
|
||||||
|
|
||||||
|
task_unlock(self);
|
||||||
|
handle_table_destroy(handles);
|
||||||
|
|
||||||
|
printk("thread %s[%u.%u] killed",
|
||||||
|
self->t_name,
|
||||||
|
self->t_id,
|
||||||
|
cur_thread->tr_id);
|
||||||
|
printk("task %s[%u] killed (%u, %u)",
|
||||||
|
self->t_name,
|
||||||
|
self->t_id,
|
||||||
|
self->t_base.ob_refcount,
|
||||||
|
self->t_base.ob_handles);
|
||||||
|
spin_unlock_irqrestore(handles_lock, flags);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
schedule(SCHED_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kern_status_t task_open_handle(
|
kern_status_t task_open_handle(
|
||||||
struct task *task,
|
struct task *task,
|
||||||
struct object *obj,
|
struct object *obj,
|
||||||
|
|||||||
@@ -65,9 +65,6 @@ kern_status_t thread_init_user(
|
|||||||
const uintptr_t *args,
|
const uintptr_t *args,
|
||||||
size_t nr_args)
|
size_t nr_args)
|
||||||
{
|
{
|
||||||
thr->tr_id = thr->tr_parent->t_next_thread_id++;
|
|
||||||
|
|
||||||
thr->tr_prio = PRIO_NORMAL;
|
|
||||||
thr->tr_state = THREAD_READY;
|
thr->tr_state = THREAD_READY;
|
||||||
thr->tr_quantum_target = default_quantum();
|
thr->tr_quantum_target = default_quantum();
|
||||||
|
|
||||||
@@ -144,6 +141,55 @@ void thread_awaken(struct thread *thr)
|
|||||||
rq_unlock(rq, flags);
|
rq_unlock(rq, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void thread_exit(void)
|
||||||
|
{
|
||||||
|
struct thread *self = current_thread();
|
||||||
|
unsigned long flags;
|
||||||
|
thread_lock_irqsave(self, &flags);
|
||||||
|
self->tr_state = THREAD_STOPPED;
|
||||||
|
object_assert_signal(&self->tr_base, THREAD_SIGNAL_STOPPED);
|
||||||
|
printk("thread %s[%u.%u] exited",
|
||||||
|
self->tr_parent->t_name,
|
||||||
|
self->tr_parent->t_id,
|
||||||
|
self->tr_id);
|
||||||
|
thread_unlock_irqrestore(self, flags);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
schedule(SCHED_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_join(struct thread *thread, unsigned long *irq_flags)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
if (thread->tr_state == THREAD_STOPPED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_wait_signal(
|
||||||
|
&thread->tr_base,
|
||||||
|
THREAD_SIGNAL_STOPPED,
|
||||||
|
irq_flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_kill(struct thread *thread)
|
||||||
|
{
|
||||||
|
thread->tr_state = THREAD_STOPPED;
|
||||||
|
if (thread->tr_rq) {
|
||||||
|
unsigned long flags;
|
||||||
|
rq_lock(thread->tr_rq, &flags);
|
||||||
|
rq_remove_thread(thread->tr_rq, thread);
|
||||||
|
rq_unlock(thread->tr_rq, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_assert_signal(&thread->tr_base, THREAD_SIGNAL_STOPPED);
|
||||||
|
printk("thread %s[%u.%u] killed",
|
||||||
|
thread->tr_parent->t_name,
|
||||||
|
thread->tr_parent->t_id,
|
||||||
|
thread->tr_id);
|
||||||
|
}
|
||||||
|
|
||||||
struct thread *create_kernel_thread(void (*fn)(void))
|
struct thread *create_kernel_thread(void (*fn)(void))
|
||||||
{
|
{
|
||||||
struct task *kernel = kernel_task();
|
struct task *kernel = kernel_task();
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ static const virt_addr_t syscall_table[] = {
|
|||||||
SYSCALL_TABLE_ENTRY(TASK_CREATE_THREAD, task_create_thread),
|
SYSCALL_TABLE_ENTRY(TASK_CREATE_THREAD, task_create_thread),
|
||||||
SYSCALL_TABLE_ENTRY(TASK_GET_ADDRESS_SPACE, task_get_address_space),
|
SYSCALL_TABLE_ENTRY(TASK_GET_ADDRESS_SPACE, task_get_address_space),
|
||||||
SYSCALL_TABLE_ENTRY(THREAD_START, thread_start),
|
SYSCALL_TABLE_ENTRY(THREAD_START, thread_start),
|
||||||
|
SYSCALL_TABLE_ENTRY(THREAD_EXIT, thread_exit),
|
||||||
SYSCALL_TABLE_ENTRY(THREAD_CONFIG_GET, thread_config_get),
|
SYSCALL_TABLE_ENTRY(THREAD_CONFIG_GET, thread_config_get),
|
||||||
SYSCALL_TABLE_ENTRY(THREAD_CONFIG_SET, thread_config_set),
|
SYSCALL_TABLE_ENTRY(THREAD_CONFIG_SET, thread_config_set),
|
||||||
SYSCALL_TABLE_ENTRY(VM_OBJECT_CREATE, vm_object_create),
|
SYSCALL_TABLE_ENTRY(VM_OBJECT_CREATE, vm_object_create),
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#include <kernel/printk.h>
|
#include <kernel/printk.h>
|
||||||
#include <kernel/sched.h>
|
#include <kernel/sched.h>
|
||||||
#include <kernel/task.h>
|
#include <kernel/task.h>
|
||||||
|
#include <kernel/thread.h>
|
||||||
|
|
||||||
kern_status_t sys_kern_log(const char *s)
|
kern_status_t sys_kern_log(const char *s)
|
||||||
{
|
{
|
||||||
struct task *task = current_task();
|
struct task *task = current_task();
|
||||||
printk("%s[%d]: %s", task->t_name, task->t_id, s);
|
struct thread *thread = current_thread();
|
||||||
|
printk("%s[%d.%d]: %s", task->t_name, task->t_id, thread->tr_id, s);
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,8 @@ extern kern_status_t sys_task_exit(int status)
|
|||||||
{
|
{
|
||||||
struct task *self = current_task();
|
struct task *self = current_task();
|
||||||
printk("%s[%d]: task_exit(%d)", self->t_name, self->t_id, status);
|
printk("%s[%d]: task_exit(%d)", self->t_name, self->t_id, status);
|
||||||
while (1) {
|
task_exit(status);
|
||||||
milli_sleep(5000);
|
return KERN_FATAL_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
return KERN_UNIMPLEMENTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t sys_task_self(kern_handle_t *out)
|
kern_status_t sys_task_self(kern_handle_t *out)
|
||||||
@@ -179,6 +176,7 @@ kern_status_t sys_task_create_thread(
|
|||||||
&target_handle,
|
&target_handle,
|
||||||
&out_handle);
|
&out_handle);
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
|
object_unref(target_obj);
|
||||||
task_unlock_irqrestore(self, flags);
|
task_unlock_irqrestore(self, flags);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -198,10 +196,11 @@ kern_status_t sys_task_create_thread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_init_user(thread, ip, sp, args, nr_args);
|
thread_init_user(thread, ip, sp, args, nr_args);
|
||||||
target_handle->h_object = &thread->thr_base;
|
target_handle->h_object = &thread->tr_base;
|
||||||
object_add_handle(&thread->thr_base);
|
object_add_handle(&thread->tr_base);
|
||||||
|
|
||||||
task_unlock_irqrestore(target, flags);
|
task_unlock_irqrestore(target, flags);
|
||||||
|
object_unref(target_obj);
|
||||||
|
|
||||||
*out_thread = out_handle;
|
*out_thread = out_handle;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
@@ -288,6 +287,13 @@ kern_status_t sys_thread_start(kern_handle_t thread_handle)
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t sys_thread_exit(void)
|
||||||
|
{
|
||||||
|
thread_exit();
|
||||||
|
/* unreachable */
|
||||||
|
return KERN_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
kern_status_t sys_thread_config_get(
|
kern_status_t sys_thread_config_get(
|
||||||
kern_handle_t thread_handle,
|
kern_handle_t thread_handle,
|
||||||
kern_config_key_t key,
|
kern_config_key_t key,
|
||||||
|
|||||||
Reference in New Issue
Block a user