feat(sched): add observable kernel thread exit
This commit is contained in:
parent
7292b9eb56
commit
624034acb5
@ -152,9 +152,10 @@
|
||||
- 已把 `kernel_thread_create()` 中的线程 id 分配和 run queue 入队纳入 interrupt-safe lock 保护。
|
||||
- 已建立 `sched_irq_exit()`,timer IRQ 只设置 `need_resched`,trap 的 IRQ 返回边界统一消费调度请求。
|
||||
- 已建立最小 DEAD 线程回收路径,调度前会释放非当前 DEAD 线程的内核栈和线程对象。
|
||||
- 已建立统一 `kernel_thread_exit()`/`sched_thread_exit()`,线程入口返回和显式退出都会进入明确退出路径,再由调度安全边界回收非当前 DEAD 线程。
|
||||
- 已在调度私有头中加入 thread state helper,调度核心、线程退出和 wait queue 路径不再直接散写主要状态转换。
|
||||
- 已把调度代码按职责拆分为 `core.c`、`thread.c`、`wait.c`、`idle.c` 和私有 `sched.h`,并把当前阶段自测/演示线程移到 `kernel/selftest/sched.c`。
|
||||
- `scripts/check.sh` 已验证 `timer initialized`、`timer tick=1/2/3`、`scheduler initialized`、`kernel thread selftest ok`、timer 驱动线程轮转、`sched_sleep()`、wait queue wakeup、条件等待和超时等待。
|
||||
- `scripts/check.sh` 已验证 `timer initialized`、`timer tick=1/2/3`、`scheduler initialized`、`kernel thread selftest ok`、timer 驱动线程轮转、`sched_sleep()`、wait queue wakeup、条件等待、超时等待、线程返回退出、显式退出和 DEAD 线程回收。
|
||||
|
||||
后续扩展:
|
||||
|
||||
@ -181,7 +182,7 @@
|
||||
### D. thread lifecycle
|
||||
|
||||
- 为线程退出增加更完整的生命周期状态、引用规则和最终释放约束。
|
||||
- 补充“当前线程不能释放自身内核栈”的文档和自测。
|
||||
- 继续补充“当前线程不能释放自身内核栈”的更严格断言和未来 join/wait 语义。
|
||||
- 为未来 `kthread_stop()`、join/wait 和进程退出保留接口空间。
|
||||
- 回收路径需要覆盖等待队列残留、run queue 残留和 timer sleep 残留。
|
||||
|
||||
|
||||
@ -41,6 +41,7 @@ struct thread {
|
||||
void sched_init(void);
|
||||
struct thread *kernel_thread_create(
|
||||
const char *name, kernel_thread_entry_t entry, void *arg);
|
||||
void kernel_thread_exit(void) __attribute__((noreturn));
|
||||
void sched_start(void) __attribute__((noreturn));
|
||||
void sched_tick(uint64_t tick);
|
||||
void sched_irq_exit(void);
|
||||
|
||||
@ -74,6 +74,7 @@ static inline void thread_set_dead(struct thread *thread)
|
||||
|
||||
void enqueue_thread(struct thread *thread);
|
||||
void sched_reap_dead_threads(void);
|
||||
void sched_thread_exit(void) __attribute__((noreturn));
|
||||
void sched_selftest(void);
|
||||
int sched_idle_create(void);
|
||||
void sched_demo_start(void) __attribute__((noreturn));
|
||||
|
||||
@ -98,6 +98,9 @@ struct thread *kernel_thread_create(
|
||||
|
||||
static void release_thread(struct thread *thread)
|
||||
{
|
||||
early_log_puts("thread reaped ");
|
||||
early_log_puts(thread->name);
|
||||
early_log_puts("\n");
|
||||
kfree(thread->stack_base);
|
||||
kfree(thread);
|
||||
}
|
||||
@ -106,7 +109,10 @@ void sched_reap_dead_threads(void)
|
||||
{
|
||||
struct thread *prev = 0;
|
||||
struct thread *thread = run_queue_head;
|
||||
struct thread *reap_list = 0;
|
||||
uint64_t flags;
|
||||
|
||||
spin_lock_irqsave(&scheduler_lock, &flags);
|
||||
while (thread != 0) {
|
||||
struct thread *next = thread->next;
|
||||
|
||||
@ -121,13 +127,41 @@ void sched_reap_dead_threads(void)
|
||||
run_queue_tail = prev;
|
||||
}
|
||||
|
||||
release_thread(thread);
|
||||
thread->next = reap_list;
|
||||
reap_list = thread;
|
||||
} else {
|
||||
prev = thread;
|
||||
}
|
||||
|
||||
thread = next;
|
||||
}
|
||||
spin_unlock_irqrestore(&scheduler_lock, flags);
|
||||
|
||||
while (reap_list != 0) {
|
||||
struct thread *next = reap_list->next;
|
||||
|
||||
reap_list->next = 0;
|
||||
release_thread(reap_list);
|
||||
reap_list = next;
|
||||
}
|
||||
}
|
||||
|
||||
void sched_thread_exit(void)
|
||||
{
|
||||
if (current_thread == 0) {
|
||||
panic("thread exit without current thread");
|
||||
}
|
||||
|
||||
thread_set_dead(current_thread);
|
||||
|
||||
for (;;) {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_thread_exit(void)
|
||||
{
|
||||
sched_thread_exit();
|
||||
}
|
||||
|
||||
static void thread_trampoline(void)
|
||||
@ -139,9 +173,5 @@ static void thread_trampoline(void)
|
||||
}
|
||||
|
||||
thread->entry(thread->arg);
|
||||
thread_set_dead(thread);
|
||||
|
||||
for (;;) {
|
||||
sched_yield();
|
||||
}
|
||||
kernel_thread_exit();
|
||||
}
|
||||
|
||||
@ -134,6 +134,21 @@ static void timeout_wait_demo_waiter(void *arg)
|
||||
early_log_puts("timeout waiter timed out\n");
|
||||
}
|
||||
|
||||
static void return_exit_demo_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
early_log_puts("return exit thread returning\n");
|
||||
}
|
||||
|
||||
static void explicit_exit_demo_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
early_log_puts("explicit exit thread exiting\n");
|
||||
kernel_thread_exit();
|
||||
}
|
||||
|
||||
void sched_demo_start(void)
|
||||
{
|
||||
struct thread *first = kernel_thread_create(
|
||||
@ -150,10 +165,14 @@ void sched_demo_start(void)
|
||||
"condition-waker", condition_wait_demo_waker, 0);
|
||||
struct thread *timeout_waiter = kernel_thread_create(
|
||||
"timeout-waiter", timeout_wait_demo_waiter, 0);
|
||||
struct thread *return_exit =
|
||||
kernel_thread_create("return-exit", return_exit_demo_thread, 0);
|
||||
struct thread *explicit_exit = kernel_thread_create(
|
||||
"explicit-exit", explicit_exit_demo_thread, 0);
|
||||
|
||||
if (first == 0 || second == 0 || waiter == 0 || waker == 0 ||
|
||||
condition_waiter == 0 || condition_waker == 0 ||
|
||||
timeout_waiter == 0) {
|
||||
timeout_waiter == 0 || return_exit == 0 || explicit_exit == 0) {
|
||||
panic("scheduler demo thread creation failed");
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,12 @@ check_lines build/debug.log \
|
||||
"condition waiter sleeping" \
|
||||
"condition waker sleeping" \
|
||||
"timeout waiter sleeping" \
|
||||
"return exit thread returning" \
|
||||
"explicit exit thread exiting" \
|
||||
"thread reaped worker-a" \
|
||||
"thread reaped worker-b" \
|
||||
"thread reaped return-exit" \
|
||||
"thread reaped explicit-exit" \
|
||||
"preempt thread 1 step=2" \
|
||||
"preempt thread 2 step=2" \
|
||||
"timeout waiter timed out" \
|
||||
@ -71,6 +77,12 @@ check_lines build/serial.log \
|
||||
"condition waiter sleeping" \
|
||||
"condition waker sleeping" \
|
||||
"timeout waiter sleeping" \
|
||||
"return exit thread returning" \
|
||||
"explicit exit thread exiting" \
|
||||
"thread reaped worker-a" \
|
||||
"thread reaped worker-b" \
|
||||
"thread reaped return-exit" \
|
||||
"thread reaped explicit-exit" \
|
||||
"preempt thread 1 step=2" \
|
||||
"preempt thread 2 step=2" \
|
||||
"timeout waiter timed out" \
|
||||
|
||||
Loading…
Reference in New Issue
Block a user