diff --git a/kernel/include/process.hpp b/kernel/include/process.hpp index bba1ada0..8071dabb 100644 --- a/kernel/include/process.hpp +++ b/kernel/include/process.hpp @@ -30,7 +30,8 @@ enum class process_state : char { RUNNING = 3, BLOCKED = 4, SLEEPING= 5, - KILLED = 6 + WAITING = 6, + KILLED = 7 }; struct segment_t { diff --git a/kernel/include/scheduler.hpp b/kernel/include/scheduler.hpp index 34da4ab8..91ae485b 100644 --- a/kernel/include/scheduler.hpp +++ b/kernel/include/scheduler.hpp @@ -27,6 +27,7 @@ void init(); int64_t exec(const std::string& path); void kill_current_process(); +void await_termination(pid_t pid); void tick(); void reschedule(); diff --git a/kernel/src/scheduler.cpp b/kernel/src/scheduler.cpp index 24ec56c5..12a46983 100644 --- a/kernel/src/scheduler.cpp +++ b/kernel/src/scheduler.cpp @@ -384,7 +384,7 @@ void start(){ void scheduler::init(){ //Create the idle task create_idle_task(); - create_init_task(); + //create_init_task(); } int64_t scheduler::exec(const std::string& file){ @@ -414,21 +414,48 @@ int64_t scheduler::exec(const std::string& file){ } } +void scheduler::await_termination(pid_t pid){ + while(true){ + bool found = false; + for(auto& process : pcb){ + if(process.process.ppid == current_pid && process.process.pid == pid){ + if(process.state == process_state::KILLED){ + return; + } + + found = true; + } + } + + if(!found){ + return; + } + + pcb[current_pid].state = process_state::WAITING; + reschedule(); + } +} + void scheduler::kill_current_process(){ if(DEBUG_SCHEDULER){ k_printf("Kill %u\n", current_pid); } + //Notify parent if waiting + auto ppid = pcb[current_pid].process.ppid; + for(auto& process : pcb){ + if(process.process.pid == ppid && process.state == process_state::WAITING){ + unblock_process(process.process.pid); + } + } + //TODO At this point, memory should be released //TODO The process should also be removed from the run queue pcb[current_pid].state = scheduler::process_state::KILLED; - current_pid = (current_pid + 1) % scheduler::MAX_PROCESS; - - //Select the next process and switch to it - auto index = select_next_process(); - switch_to_process(index); + //Run another process + reschedule(); } void scheduler::tick(){ @@ -512,7 +539,7 @@ void scheduler::block_process(pid_t pid){ void scheduler::unblock_process(pid_t pid){ thor_assert(pid < scheduler::MAX_PROCESS, "pid out of bounds"); - thor_assert(pcb[pid].state == process_state::BLOCKED, "Can only block BLOCKED processes"); + thor_assert(pcb[pid].state == process_state::BLOCKED || pcb[pid].state == process_state::WAITING, "Can only unblock BLOCKED/WAITING processes"); if(DEBUG_SCHEDULER){ k_printf("Unblock process %u\n", pid); diff --git a/kernel/src/system_calls.cpp b/kernel/src/system_calls.cpp index 56a1a047..750baf2c 100644 --- a/kernel/src/system_calls.cpp +++ b/kernel/src/system_calls.cpp @@ -47,7 +47,7 @@ void sc_exec(interrupt::syscall_regs* regs){ void sc_await_termination(interrupt::syscall_regs* regs){ auto pid = regs->rbx; - //TODO Implement + scheduler::await_termination(pid); } } //End of anonymous namespace