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:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user