<br><br><div class="gmail_quote">On Sat, Feb 9, 2013 at 8:07 PM, anish kumar <span dir="ltr">&lt;<a href="mailto:anish198519851985@gmail.com" target="_blank">anish198519851985@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Thanks Frederic.<br>
<div>On Sat, 2013-02-09 at 08:44 +0100, Frederic Weisbecker wrote:<br>
&gt; 2013/2/8 Gaurav Jain &lt;<a href="mailto:gjainroorkee@gmail.com" target="_blank">gjainroorkee@gmail.com</a>&gt;:<br>
&gt; &gt; What happens if the kernel executing in some process context (let&#39;s say<br>
&gt; &gt; executing a time-consuming syscall) gets interrupted by the Timer - which is<br>
&gt; &gt; apparently allowed in 2.6 onwards kernels.<br>
&gt; &gt;<br>
&gt; &gt; My understanding is that once the interrupt handler is done executing, we<br>
&gt; &gt; should switch back to where the kernel code was executing.<br>
&gt;<br>
&gt; Exactly. At the end of the interrupt, the state of the processor<br>
&gt; (register values) as it was before being interrupted is restored.<br>
&gt;<br>
&gt; &gt; Specifically, the<br>
&gt; &gt; interrupt handler for the Timer interrupt should not schedule some other<br>
&gt; &gt; task since that might leave kernel data in an inconsistent state - kernel<br>
&gt; &gt; didn&#39;t finish doing whatever it was doing when interrupted.<br>
&gt; &gt;<br>
&gt; &gt; So, does the Timer interrupt handler include such a policy for the above<br>
&gt; &gt; case?<br>
&gt;<br>
&gt; In the case you have CONFIG_PREEMPT and it&#39;s the turn for some other<br>
&gt; task to be scheduled, the function preempt_schedule_irq() is called<br>
&gt; right before the irq return to the interrupted code. If the irq<br>
&gt; interrupted preemptible code (code that was not under a<br>
&gt; preempt_disable() section) then the scheduler may well schedule<br>
&gt; another task.<br>
</div>However if the code is under preempt_disable() when irq happened then it<br>
won&#39;t choose any other task and will come back immediately to the task<br>
which was preempted by the irq handler.<br>
<br>
I think what you are referring is below code:<br>
<br>
__irq_svc:<br>
        svc_entry<br>
        irq_handler<br>
<br>
#ifdef CONFIG_PREEMPT<br>
        get_thread_info tsk<br>
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count<br>
        ldr     r0, [tsk, #TI_FLAGS]            @ get flags<br>
        teq     r8, #0                          @ if preempt count != 0<br>
        movne   r0, #0                          @ force flags to 0<br>
        tst     r0, #_TIF_NEED_RESCHED<br>
        blne    svc_preempt<br>
#endif<br>
<br>
#ifdef CONFIG_PREEMPT<br>
svc_preempt:<br>
        mov     r8, lr<br>
1:      bl      preempt_schedule_irq            @ irq en/disable is done<br>
inside<br>
        ldr     r0, [tsk, #TI_FLAGS]            @ get new tasks TI_FLAGS<br>
        tst     r0, #_TIF_NEED_RESCHED<br>
        moveq   pc, r8                          @ go again<br>
        b       1b<br>
#endif<br>
<br>
<br>
/*<br>
 * this is the entry point to schedule() from kernel preemption<br>
 * off of irq context.<br>
 * Note, that this is called and return with irqs disabled. This will<br>
 * protect us against recursive calling from irq.<br>
 */<br>
asmlinkage void __sched preempt_schedule_irq(void)<br>
{<br>
        struct thread_info *ti = current_thread_info();<br>
<br>
        /* Catch callers which need to be fixed */<br>
        BUG_ON(ti-&gt;preempt_count || !irqs_disabled());<br>
<br>
        user_exit();<br>
        do {<br>
                add_preempt_count(PREEMPT_ACTIVE);<br>
                local_irq_enable();<br>
                __schedule();<br>
                local_irq_disable();<br>
                sub_preempt_count(PREEMPT_ACTIVE);<br>
<br>
                /*<br>
                 * Check again in case we missed a preemption<br>
opportunity<br>
                 * between schedule and now.<br>
                 */<br>
                barrier();<br>
        } while (need_resched());<br>
<div>}<br>
<br>
&gt;<br>
&gt; It may indeed sound suprising that we schedule from an interrupt but<br>
</div>It is really *surprising* that we do scheduling from interrupt context.<br>
Doesn&#39;t Do&#39;s and Don&#39;t of scheduling from interrupt context apply here?<br></blockquote><div><br></div><div>A search in the entire subtree of arch/x86/ and including all its subdirectories, (for 3.2.0 kernel) return only TWO result where preempt_schedule_irq is called:   kernel/entry_64.S and kernel/entry_32.S.   And the called is in fact resume_kernel(),   ie, it is NOT called from timer interrupt, but from wakeup context of the CPU, and is only executed ONCE upon waking up from hibernation.   </div>
<div><br></div><div>for example, calling from here:</div><div><br></div><div><a href="https://lkml.org/lkml/2012/5/2/298">https://lkml.org/lkml/2012/5/2/298</a></div>
<div><br></div><div>so definitely this preempt_schedule_irq() calling from irq mode is rare - at least for x86.</div><div><br></div><div>but the code u have shown above is for ARM, i tried to understand it, but could not comment much....except that it CONFIG_PREEMPT is still very popular: out of 121 of different ARM boards, about 46 still need it to be &quot;y&quot;.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
So how does the regular call to schedule() occur when task(process) time<br>
slice is over?<br>
<div>&gt; it&#39;s actually fine. Later on, the scheduler restores the previous task<br>
&gt; to the middle of preempt_schedule_irq() and the irq completes its<br>
</div>Sorry didn&#39;t understand this sentence i.e. &quot;scheduler restores the<br>
previous task to the middle of preempt_schedule_irq()&quot;.<br>
<div><div>&gt; return to what it interrupted. The state of the processor prior to the<br>
&gt; interrupt is stored on the task stack. So we can restore that anytime.<br>
&gt; Note if the irq interrupted userspace, it can do about the same thing,<br>
&gt; except it calls schedule() directly instead of preempt_schedule_irq().<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Kernelnewbies mailing list<br>
&gt; <a href="mailto:Kernelnewbies@kernelnewbies.org" target="_blank">Kernelnewbies@kernelnewbies.org</a><br>
&gt; <a href="http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies" target="_blank">http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies</a><br>
<br>
<br>
<br>
_______________________________________________<br>
Kernelnewbies mailing list<br>
<a href="mailto:Kernelnewbies@kernelnewbies.org" target="_blank">Kernelnewbies@kernelnewbies.org</a><br>
<a href="http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies" target="_blank">http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>Regards,<br>Peter Teoh