Usually, when processes want to wait some events that are not available, we can put them into sleep and wake up them later when the events occur.
The familiar codes below fulfil this task:
while (!events) {
DEFINE_WAIT(wait);
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if (!events)
schedule();
finish_wait(&q, &wait);
}
Imagine that in a preemptive kernel there exists two processes in which process A is a producer and process B is a consumer. Process B is executing the codes above, waiting for the some datas produced by process A become valid.
Now, I think process B will lost the wake-up chance if the executing path of two processes is as below.
- Process B checks event in
while
statement, and now it is return false. - Process B executes
DEFIN_WAIT(wait)
. - Process A produces some datas just after process B finished executing
DEFIN_WAIT(wait)
and before executingprepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
. - Process B executes
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
. - Process B is preempted by other process just before it executes
if (!events)
.
Because of the state of process B now is TASK_INTERRUPTIBLE
, it won't be schedule to CPU again. So, I think, Process B will never be waken....
Your final verdict is wrong: preemption does not work with task state. So, even in
TASK_INTERRUPTIBLE
state preempted task can gain CPU again.See, e.g this or that.