Re: Kernel code interrupted by Timer

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

 





On Sat, Feb 9, 2013 at 8:07 PM, anish kumar <anish198519851985@xxxxxxxxx> wrote:
Thanks Frederic.
On Sat, 2013-02-09 at 08:44 +0100, Frederic Weisbecker wrote:
> 2013/2/8 Gaurav Jain <gjainroorkee@xxxxxxxxx>:
> > 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@xxxxxxxxxxxxxxxxx
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies



_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies



--
Regards,
Peter Teoh
_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux