Skip to contentSkip to conversation

wake_up vs. wake_up_sync

DISCUSSION Manfred Spraul 3 participants 5 messages Jun 27, 2001

lore
Share & tools
lore
#0 lore raw
Quoted 6 lines

I'm having trouble understanding the difference between these. Synchronous apparently causes try_to_wake_up() to NOT call reschedule_idle() but I'm uncertain what reschedule_idle() is doing. I assume it just looks for an idle CPU and makes that CPU reschedule.

What is the purpose of wake_up_sync?

Avoid the reschedule_idle() call - it's quite costly, and it could cause processes jumping from one cpu to another.

Quoted 3 lines

Why would you want to prevent
reschedule_idle()?

If one process runs, wakes up another process and _knows_ that it's going to sleep immediately after the wake_up it doesn't need the
reschedule_idle: the current cpu will be idle soon, the scheduler doesn't need to find another cpu for the woken up thread.

I think the pipe code is the only user of _sync right now - pipes cause an incredible amount of task switches.

--
Manfred

#1 lore raw
Quoted 7 lines · Manfred Spraul
Quoted 3 lines

Why would you want to prevent
reschedule_idle()?

If one process runs, wakes up another process and _knows_ that it's going to sleep immediately after the wake_up it doesn't need the
reschedule_idle: the current cpu will be idle soon, the scheduler doesn't need to find another cpu for the woken up thread.

I'm curious. How does the caller of wake_up_sync know that the current cpu will soon be idle. Does it assume that there are no other tasks on the runqueue waiting for a CPU? If there are other tasks on the runqueue, isn't it possible that another task has a higher goodness value than the task being awakened. In such a case, isn't is possible that the awakened task could sit on the runqueue (waiting for a CPU) while tasks with a lower goodness value are allowed to run?

Signature · 2 lines
Mike Kravetz                                 [email protected]
IBM Linux Technology Center
#2 lore raw
In reply to Manfred Spraul

Does reschedule_idle() ever cause the current CPU to get scheduled? That is, if someone calls wake_up() and wakes up a higher-priority process could reschedule_idle() potentially immediately switch the current CPU to that higher-priority process?

Because this is NOT what I want to happen (it would produce a deadlock in this particular situation). Having other CPUs get scheduled is ok, but having the process that called wake_up() get kicked out would be very bad. In that case I suppose I will have to use wake_up_sync().

Would the following be an appropriate solution?

{
    wake_up_sync(&wq->q);

    /* Potential deadlock situation */
    user_unlock(&wq->lock);

    /* Potential for deadlock has passed */
    reschedule_idle();
}

Thanks,
Scott

Quoted 24 lines · Manfred Spraul
Quoted 7 lines

I'm having trouble understanding the difference between these. Synchronous apparently causes try_to_wake_up() to NOT call reschedule_idle() but I'm uncertain what reschedule_idle() is doing. I assume it just looks for an idle CPU and makes that CPU reschedule.

What is the purpose of wake_up_sync?

Avoid the reschedule_idle() call - it's quite costly, and it could cause processes jumping from one cpu to another.

Quoted 3 lines

Why would you want to prevent
reschedule_idle()?

If one process runs, wakes up another process and _knows_ that it's going to sleep immediately after the wake_up it doesn't need the
reschedule_idle: the current cpu will be idle soon, the scheduler doesn't need to find another cpu for the woken up thread.

I think the pipe code is the only user of _sync right now - pipes cause an incredible amount of task switches.

--
Manfred

#3 lore raw
In reply to Manfred Spraul
Quoted 4 lines · Scott Long

Does reschedule_idle() ever cause the current CPU to get scheduled? That is, if someone calls wake_up() and wakes up a higher-priority process could reschedule_idle() potentially immediately switch the current CPU to that higher-priority process?

No. reschedule_idle() never directly performs a 'task to task' context switch itself. Instead, it simply marks a currently running task to indicate that a reschedule is needed on that task's CPU. No task context switch will occur until schedule() is run on that CPU.

Signature · 2 lines
Mike Kravetz                                 [email protected]
IBM Linux Technology Center
#4 lore raw
In reply to Manfred Spraul
Quoted 10 lines · Mike Kravetz
Quoted 7 lines · Manfred Spraul
Quoted 3 lines

Why would you want to prevent
reschedule_idle()?

If one process runs, wakes up another process and _knows_ that it's going to sleep immediately after the wake_up it doesn't need the
reschedule_idle: the current cpu will be idle soon, the scheduler doesn't need to find another cpu for the woken up thread.

Quoted 9 lines

I'm curious. How does the caller of wake_up_sync know that the current cpu will soon be idle. Does it assume that there are no other tasks on the runqueue waiting for a CPU? If there are other tasks on the runqueue, isn't it possible that another task has a higher goodness value than the task being awakened. In such a case, isn't is possible that the awakened task could sit on the runqueue (waiting for a CPU) while tasks with a lower goodness value are allowed to run?

I found one combination where that could happen:

process.thread
A.1: highest priority, runs on cpu0
B.1: lowest priority, runs on cpu1
A.2: another thread of process A, priority PROC_CHANGE_PENALTY+PRIORITY(B.1)+1, sleeping. B.2: same priority as A.2, sleeping, same process as B.1

A.1:

{
	wake_up("A.2");
/* nothing happens: preemption_goodness is 0 since B.1 has both
PROC_CHANGE_PENALTY and the += 1 from 'same mm'
*/
	wake_up_sync("B.2");
	schedule();
/* schedule selects A.2 instead of B.2 due to the += 1 from 'same mm'.
BUG: B.2 should replace B.1 on cpu1. The preemption_goodness is 1.

*/

IMHO obscure and very rare.

But I just found a bigger problem:
If wake_up_sync wakes up more than 1 process then cpus could remain in cpu_idle() although processes are on the runqueue without cpus.

--
Manfred