diff --git a/include/process/scheduler.h b/include/process/scheduler.h index 800532f..9c00cf3 100644 --- a/include/process/scheduler.h +++ b/include/process/scheduler.h @@ -27,6 +27,7 @@ void scheduler_remove_task(task_struct_t* task); // 스케줄러 통계 uint32_t scheduler_get_total_tasks(void); void scheduler_print_status(void); +void scheduler_reap_terminated_tasks(void); // ✅ IRQ 기반 스케줄러 핸들러 // 인터럽트 프레임 구조체는 scheduler.c에 정의됨 diff --git a/include/process/task.h b/include/process/task.h index 25215da..0f78c0e 100644 --- a/include/process/task.h +++ b/include/process/task.h @@ -37,6 +37,7 @@ typedef struct task_struct { void task_init(void); task_struct_t* task_create(const char* name, void (*entry_point)(void), uint32_t priority); void task_destroy(task_struct_t* task); +void task_exit(void) __attribute__((noreturn)); task_struct_t* task_get_current(void); void task_set_current(task_struct_t* task); uint32_t task_get_next_pid(void); diff --git a/src/kernel.c b/src/kernel.c index 1e73528..82e3d31 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -15,6 +15,13 @@ static void hlt_loop(void) { for(;;) __asm__ __volatile__("hlt"); } +static void kernel_idle_loop(void) { + for (;;) { + scheduler_reap_terminated_tasks(); + __asm__ __volatile__("sti; hlt"); + } +} + static void console_putu32(uint32_t v) { char buf[11]; int idx = 0; @@ -279,7 +286,7 @@ void kernel_main(uint32_t magic, void* mbinfo) { console_puts("[SCHEDULER] Output should cycle through 1, 2, and 3.\n"); idt_enable_interrupts(); - hlt_loop(); + kernel_idle_loop(); } // Test: Put string diff --git a/src/process/scheduler.c b/src/process/scheduler.c index 4d14425..4c37e8c 100644 --- a/src/process/scheduler.c +++ b/src/process/scheduler.c @@ -1,5 +1,6 @@ #include "process/scheduler.h" #include "process/task.h" +#include "arch/x86/idt.h" #include "drivers/console/console.h" #include @@ -16,8 +17,11 @@ struct interrupt_frame { // 라운드 로빈 큐 static task_struct_t* ready_queue_head = NULL; static task_struct_t* ready_queue_tail = NULL; +static task_struct_t* terminated_queue_head = NULL; +static task_struct_t* terminated_queue_tail = NULL; static task_struct_t* current_task = NULL; static uint32_t total_tasks = 0; +static uint32_t terminated_tasks = 0; static uint32_t scheduler_ticks = 0; static void scheduler_enqueue_task(task_struct_t* task) { @@ -57,12 +61,56 @@ static task_struct_t* scheduler_dequeue_task(void) { return task; } +static void scheduler_enqueue_terminated_task(task_struct_t* task) { + if (!task || task->pid == 0) { + return; + } + + task->next = NULL; + task->prev = terminated_queue_tail; + + if (terminated_queue_tail) { + terminated_queue_tail->next = task; + } else { + terminated_queue_head = task; + } + + terminated_queue_tail = task; + terminated_tasks++; +} + +static task_struct_t* scheduler_dequeue_terminated_task(void) { + task_struct_t* task = terminated_queue_head; + if (!task) { + return NULL; + } + + terminated_queue_head = task->next; + if (terminated_queue_head) { + terminated_queue_head->prev = NULL; + } else { + terminated_queue_tail = NULL; + } + + task->next = NULL; + task->prev = NULL; + + if (terminated_tasks > 0) { + terminated_tasks--; + } + + return task; +} + void scheduler_init(void) { console_puts("[SCHEDULER] Initializing round-robin scheduler...\n"); ready_queue_head = NULL; ready_queue_tail = NULL; + terminated_queue_head = NULL; + terminated_queue_tail = NULL; total_tasks = 0; + terminated_tasks = 0; scheduler_ticks = 0; // 현재 태스크는 커널 태스크 @@ -154,6 +202,20 @@ uint32_t scheduler_get_total_tasks(void) { return total_tasks; } +void scheduler_reap_terminated_tasks(void) { + for (;;) { + idt_disable_interrupts(); + task_struct_t* task = scheduler_dequeue_terminated_task(); + idt_enable_interrupts(); + + if (!task) { + return; + } + + task_destroy(task); + } +} + void scheduler_print_status(void) { console_puts("[SCHEDULER] Status:\n"); console_puts(" Total tasks in ready queue: "); @@ -207,6 +269,20 @@ void scheduler_print_status(void) { while (idx--) console_putc(buf[idx]); } console_puts("\n"); + + console_puts(" Terminated tasks pending cleanup: "); + count = terminated_tasks; + idx = 0; + if (count == 0) { + console_putc('0'); + } else { + while (count > 0 && idx < 11) { + buf[idx++] = (char)('0' + (count % 10)); + count /= 10; + } + while (idx--) console_putc(buf[idx]); + } + console_puts("\n"); // Ready 큐의 모든 태스크 출력 if (ready_queue_head) { @@ -272,6 +348,8 @@ uint32_t scheduler_irq_handler(void* frame_ptr) { if (old_task->pid != 0) { scheduler_enqueue_task(old_task); } + } else if (old_task->state == TASK_TERMINATED) { + scheduler_enqueue_terminated_task(old_task); } // 다음 태스크 선택 diff --git a/src/process/task.c b/src/process/task.c index 551bb2b..1f44ea8 100644 --- a/src/process/task.c +++ b/src/process/task.c @@ -23,14 +23,7 @@ static void task_entry_trampoline(void) { current->entry_point(); } - if (current) { - current->state = TASK_TERMINATED; - current->time_remaining = 0; - } - - for (;;) { - __asm__ __volatile__("sti; hlt"); - } + task_exit(); } task_struct_t* task_get_kernel_task(void) { @@ -70,6 +63,19 @@ uint32_t task_get_next_pid(void) { return next_pid++; } +void task_exit(void) { + task_struct_t* current = scheduler_get_current_task(); + + if (current && current->pid != 0) { + current->state = TASK_TERMINATED; + current->time_remaining = 0; + } + + for (;;) { + __asm__ __volatile__("sti; hlt"); + } +} + task_struct_t* task_create(const char* name, void (*entry_point)(void), uint32_t priority) { // PCB 할당 task_struct_t* task = (task_struct_t*)kmalloc(sizeof(task_struct_t)); @@ -178,6 +184,10 @@ void task_destroy(task_struct_t* task) { if (!task) { return; } + + if (task->pid == 0 || task == scheduler_get_current_task()) { + return; + } console_puts("[TASK] Destroying task PID "); uint32_t pid = task->pid;