idle(): recheck runq just before cpu status check

There is a problem which causes wait4(2) hang when wait4(2) called by a
process races with its child process termination.
This is a quick fix for this problem. See idle().

refs #271
This commit is contained in:
NAKAMURA Gou
2014-10-14 20:08:03 +09:00
parent 758796bb69
commit d2cb890cdd

View File

@@ -1789,6 +1789,38 @@ static void idle(void)
while (1) {
schedule();
cpu_disable_interrupt();
/*
* XXX: KLUDGE: It is desirable to be resolved in schedule().
*
* There is a problem which causes wait4(2) hang when
* wait4(2) called by a process races with its child process
* termination. This is a quick fix for this problem.
*
* The problem occurrd in the following sequence.
* 1) The parent process called schedule() from sys_wait4() to
* wait for an event generated by the child process.
* 2) schedule() resumed the idle process because there was no
* runnable process in run queue.
* 3) At the moment, the child process began to end. It set
* the parent process runnable, and sent an interrupt to
* the parent process's cpu. But this interrupt had no
* effect because the parent process's cpu had not halted.
* 4) The idle process was resumed, and halted for waiting for
* the interrupt that had already been handled.
*/
if (v->status == CPU_STATUS_IDLE) {
long s;
struct process *p;
s = ihk_mc_spinlock_lock(&v->runq_lock);
list_for_each_entry(p, &v->runq, sched_list) {
if (p->status == PS_RUNNING) {
v->status = CPU_STATUS_RUNNING;
break;
}
}
ihk_mc_spinlock_unlock(&v->runq_lock, s);
}
if (v->status == CPU_STATUS_IDLE) {
cpu_safe_halt();
}