Re: A question about cpu_idle()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>>> On 10/22/2009 at 12:30 AM, in message
<a0e7fce50910212130h385cdbe1ucbb4fe00233eb0bb@xxxxxxxxxxxxxx>, yi li
<liyi.dev@xxxxxxxxx> wrote: 
> On Wed, Oct 21, 2009 at 12:47 PM, Gregory Haskins <ghaskins@xxxxxxxxxx> wrote:
>>>>> On 10/20/2009 at 11:07 PM, in message
>> <a0e7fce50910202007l587d2cfcu91b455ff0486110b@xxxxxxxxxxxxxx>, yi li
>> <liyi.dev@xxxxxxxxx> wrote:
>>> Hi RT users,
>>>
>>> While reading patch-2.6.31.4-rt14, there is a patch for cpu_idle()
>>> which I cannot understand.
>>>
>>> Could anyone kindly enough to tell me what is patch used for?
>>
>> Hi Yi,
>>
>> I believe that logic is ensuring that the task is put to sleep instead of 
> simply being preempted.  The difference is that a preemption leaves the task 
> on the RQ, whereas calling schedule() may or may not leave the caller on the 
> RQ, depending on the status of current->state.  The 
> local_irq_disable+__preempt_enable_no_resched dance is a way of legally 
> calling schedule() while effectively preventing preemption (since 
> interrupts-off also disables preemption).  The difference is that its legal 
> to call __schedule() with interrupts off, but you can't with 
> preempt_disable().
>>
>> Long story short, the enable_no_resched() + schedule() pattern is only ever 
> used when you want to make sure the task fully sleeps.  However without this 
> patch to disable interrupts, the original code appears racy and thus probably 
> had issues achieving its intended goal.
>>
>> HTH,
>> -Greg
>>
> 
> Thanks Greg for the kind reply.
> 
> But due to my limited knowledge on PREEMPT_RT, I still not fully understand.
> 
> Given schedule() is defined as:
> 
> asmlinkage void __sched schedule(void)
> {
> need_resched:
> 	local_irq_disable();
> 	__schedule();
> 	local_irq_enable();
> 
> 	if (need_resched())
> 		goto need_resched;
> }
> 
> Comparing bellow two code sequences:
> 
> 1)
> preempt_enable_no_resched();
> schedule();
> preempt_disable();
> 
> 
> 2)
> local_irq_disable();
> __preempt_enable_no_resched();
> __schedule();
> preempt_disable();
> local_irq_enable();
> 
> It seems to me, the main difference is to change the order of
> "preempt_enable_no_sched() / local_irq_disable()":
> i.e, from:
> 
> "preempt_enable_no_sched();
> /* Yi: will some race condition happens here? */

This is exactly right.  In a preemptible kernel (which includes standard mainline PREEMPT as well as PREEMPT_RT) we technically may preempt at this point.  Normally a preempt_enable() will induce a type of "voluntary" preemption point when the preempt-disable count goes to zero.  The "no_sched()" variant disables this voluntary reschedule, but it does nothing to prevent an _involuntary_ preemption (such as a RESCHEDULE interprocessor-interrupt (IPI) sent from another core).

>  local_irq_disable();
> __schedule();"
> 
> to:
> 
> "local_irq_disable(); /* Yi: disables irq effectively disables preemption?

Yes, that is right.  irq_disable is a effective superset of preempt-disable() in this context because it also blocks those RESCHED_IPI events from being received.  Of course, disabling interrupts also has other side effects since it also disables *all* interrupts (like timers, etc) so it should be used sparingly.  In this case, we are simply bridging the preempt_enable_no_resched() and schedule() to make sure it is truly an atomic transition to a sleep state, so its use is justified.

I hope this helps, and feel free to ask any more questions you wish.
-Greg
 
> */
> preempt_enable_no_sched();
> __schedule();"
> 
> Regards,
> -Yi
> 
>>>
>>>
>>> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
>>> index ebefb54..c8d0ece 100644
>>> --- a/arch/x86/kernel/process_64.c
>>> +++ b/arch/x86/kernel/process_64.c
>>> @@ -152,9 +152,11 @@ void cpu_idle(void)
>>>                 }
>>>
>>>                 tick_nohz_restart_sched_tick();
>>> -               preempt_enable_no_resched();
>>> -               schedule();
>>> +               local_irq_disable();
>>> +               __preempt_enable_no_resched();
>>> +               __schedule();
>>>                 preempt_disable();
>>> +               local_irq_enable();
>>>         }
>>>  }
>>>
>>> Regards,
>>> -Yi
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in
>>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>>


--
To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux