Kernel code interrupted by Timer

Peter Teoh htmldeveloper at gmail.com
Sat Feb 9 11:13:21 EST 2013


On Sat, Feb 9, 2013 at 8:07 PM, anish kumar <anish198519851985 at gmail.com>wrote:

> Thanks Frederic.
> On Sat, 2013-02-09 at 08:44 +0100, Frederic Weisbecker wrote:
> > 2013/2/8 Gaurav Jain <gjainroorkee at gmail.com>:
> > > What happens if the kernel executing in some process context (let's say
> > > executing a time-consuming syscall) gets interrupted by the Timer -
> which is
> > > apparently allowed in 2.6 onwards kernels.
> > >
> > > My understanding is that once the interrupt handler is done executing,
> we
> > > should switch back to where the kernel code was executing.
> >
> > Exactly. At the end of the interrupt, the state of the processor
> > (register values) as it was before being interrupted is restored.
> >
> > > Specifically, the
> > > interrupt handler for the Timer interrupt should not schedule some
> other
> > > task since that might leave kernel data in an inconsistent state -
> kernel
> > > didn't finish doing whatever it was doing when interrupted.
> > >
> > > So, does the Timer interrupt handler include such a policy for the
> above
> > > case?
> >
> > In the case you have CONFIG_PREEMPT and it's the turn for some other
> > task to be scheduled, the function preempt_schedule_irq() is called
> > right before the irq return to the interrupted code. If the irq
> > interrupted preemptible code (code that was not under a
> > preempt_disable() section) then the scheduler may well schedule
> > another task.
> However if the code is under preempt_disable() when irq happened then it
> won't choose any other task and will come back immediately to the task
> which was preempted by the irq handler.
>
> I think what you are referring is below code:
>
> __irq_svc:
>         svc_entry
>         irq_handler
>
> #ifdef CONFIG_PREEMPT
>         get_thread_info tsk
>         ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
>         ldr     r0, [tsk, #TI_FLAGS]            @ get flags
>         teq     r8, #0                          @ if preempt count != 0
>         movne   r0, #0                          @ force flags to 0
>         tst     r0, #_TIF_NEED_RESCHED
>         blne    svc_preempt
> #endif
>
> #ifdef CONFIG_PREEMPT
> svc_preempt:
>         mov     r8, lr
> 1:      bl      preempt_schedule_irq            @ irq en/disable is done
> inside
>         ldr     r0, [tsk, #TI_FLAGS]            @ get new tasks TI_FLAGS
>         tst     r0, #_TIF_NEED_RESCHED
>         moveq   pc, r8                          @ go again
>         b       1b
> #endif
>
>
> /*
>  * this is the entry point to schedule() from kernel preemption
>  * off of irq context.
>  * Note, that this is called and return with irqs disabled. This will
>  * protect us against recursive calling from irq.
>  */
> asmlinkage void __sched preempt_schedule_irq(void)
> {
>         struct thread_info *ti = current_thread_info();
>
>         /* Catch callers which need to be fixed */
>         BUG_ON(ti->preempt_count || !irqs_disabled());
>
>         user_exit();
>         do {
>                 add_preempt_count(PREEMPT_ACTIVE);
>                 local_irq_enable();
>                 __schedule();
>                 local_irq_disable();
>                 sub_preempt_count(PREEMPT_ACTIVE);
>
>                 /*
>                  * Check again in case we missed a preemption
> opportunity
>                  * between schedule and now.
>                  */
>                 barrier();
>         } while (need_resched());
> }
>
> >
> > It may indeed sound suprising that we schedule from an interrupt but
> It is really *surprising* that we do scheduling from interrupt context.
> Doesn't Do's and Don't of scheduling from interrupt context apply here?
>

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.

for example, calling from here:

https://lkml.org/lkml/2012/5/2/298

so definitely this preempt_schedule_irq() calling from irq mode is rare -
at least for x86.

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
"y".


>
> So how does the regular call to schedule() occur when task(process) time
> slice is over?
> > it's actually fine. Later on, the scheduler restores the previous task
> > to the middle of preempt_schedule_irq() and the irq completes its
> Sorry didn't understand this sentence i.e. "scheduler restores the
> previous task to the middle of preempt_schedule_irq()".
> > return to what it interrupted. The state of the processor prior to the
> > interrupt is stored on the task stack. So we can restore that anytime.
> > Note if the irq interrupted userspace, it can do about the same thing,
> > except it calls schedule() directly instead of preempt_schedule_irq().
> >
> > _______________________________________________
> > Kernelnewbies mailing list
> > Kernelnewbies at kernelnewbies.org
> > http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>
>
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>



-- 
Regards,
Peter Teoh
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20130210/7b26666b/attachment.html 


More information about the Kernelnewbies mailing list