Fix race condition in wait_for_termination

If preempted, it was possible for a process to be waiting forever
This commit is contained in:
Baptiste Wicht 2016-07-03 15:59:54 +02:00
parent 1c3af14f35
commit 27dc7e25a0

View File

@ -26,6 +26,7 @@
#include "mutex.hpp" #include "mutex.hpp"
#include "kernel_utils.hpp" #include "kernel_utils.hpp"
#include "logging.hpp" #include "logging.hpp"
#include "int_lock.hpp"
//Provided by task_switch.s //Provided by task_switch.s
extern "C" { extern "C" {
@ -690,23 +691,35 @@ void scheduler::sbrk(size_t inc){
} }
void scheduler::await_termination(pid_t pid){ void scheduler::await_termination(pid_t pid){
int_lock lock;
while(true){ while(true){
lock.acquire();
bool found = false; bool found = false;
for(auto& process : pcb){ for(auto& process : pcb){
if(process.process.ppid == current_pid && process.process.pid == pid){ if(process.process.ppid == current_pid && process.process.pid == pid){
if(process.state == process_state::KILLED){ if(process.state == process_state::KILLED){
lock.release();
return; return;
} }
found = true; found = true;
break;
} }
} }
// The process may have already been cleaned, we can simply return
if(!found){ if(!found){
lock.release();
return; return;
} }
logging::logf(logging::log_level::DEBUG, "Process %u waits for %u\n", current_pid, pid);
pcb[current_pid].state = process_state::WAITING; pcb[current_pid].state = process_state::WAITING;
lock.release();
reschedule(); reschedule();
} }
} }
@ -726,6 +739,7 @@ void scheduler::kill_current_process(){
unblock_process(gc_pid); unblock_process(gc_pid);
pcb[current_pid].state = scheduler::process_state::KILLED; pcb[current_pid].state = scheduler::process_state::KILLED;
logging::logf(logging::log_level::DEBUG, "Found%u\n", static_cast<uint8_t>(pcb[current_pid].state));
//Run another process //Run another process
reschedule(); reschedule();