sched: implement various ways to end tasks and threads

This commit is contained in:
2026-03-18 21:07:43 +00:00
parent e03b2e07d0
commit 4551e7b2e6
12 changed files with 148 additions and 17 deletions

View File

@@ -222,13 +222,13 @@ kern_status_t task_add_channel(
{
channel->c_id = id;
if (!task->b_channels.b_root) {
task->b_channels.b_root = &channel->c_node;
btree_insert_fixup(&task->b_channels, &channel->c_node);
if (!task->t_channels.b_root) {
task->t_channels.b_root = &channel->c_node;
btree_insert_fixup(&task->t_channels, &channel->c_node);
return KERN_OK;
}
struct btree_node *cur = task->b_channels.b_root;
struct btree_node *cur = task->t_channels.b_root;
while (1) {
struct channel *cur_node
= BTREE_CONTAINER(struct channel, c_node, cur);
@@ -255,7 +255,7 @@ kern_status_t task_add_channel(
cur = next;
}
btree_insert_fixup(&task->b_channels, &channel->c_node);
btree_insert_fixup(&task->t_channels, &channel->c_node);
return KERN_OK;
}
@@ -268,7 +268,7 @@ BTREE_DEFINE_SIMPLE_GET(
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)
@@ -280,6 +280,72 @@ struct task *task_from_tid(tid_t id)
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(
struct task *task,
struct object *obj,

View File

@@ -65,9 +65,6 @@ kern_status_t thread_init_user(
const uintptr_t *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_quantum_target = default_quantum();
@@ -144,6 +141,55 @@ void thread_awaken(struct thread *thr)
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 task *kernel = kernel_task();