Linux内核计时器功能在什么上下文中运行? [英] What context does a Linux kernel timer function runs in?

查看:147
本文介绍了Linux内核计时器功能在什么上下文中运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用add_timer API创建的计时器到期并且在计时器结构上分配的功能运行时,它在什么情况下运行?是中断上下文还是某些内核进程上下文?

When a timer created with the add_timer API expires and the function assigned at the timer structure runs, in what context does it run? Is it interrupt context or some kernel process context?

推荐答案

它当然是在中断上下文中,更确切地说,在softirq上下文中,请参见下文(kernel/timer.c):

It is of course in interrupt context, more precisely, in softirq context, see below (kernel/timer.c):

static inline void __run_timers(struct tvec_base *base)
{
        struct timer_list *timer;

        spin_lock_irq(&base->lock);
        while (time_after_eq(jiffies, base->timer_jiffies)) {
                struct list_head work_list;
                struct list_head *head = &work_list;
                int index = base->timer_jiffies & TVR_MASK;

                /*
                 * Cascade timers:
                 */
                if (!index &&
                        (!cascade(base, &base->tv2, INDEX(0))) &&
                                (!cascade(base, &base->tv3, INDEX(1))) &&
                                        !cascade(base, &base->tv4, INDEX(2)))
                        cascade(base, &base->tv5, INDEX(3));
                ++base->timer_jiffies;
                list_replace_init(base->tv1.vec + index, &work_list);
                while (!list_empty(head)) {
                        void (*fn)(unsigned long);
                        unsigned long data;
                        bool irqsafe;

                        timer = list_first_entry(head, struct timer_list,entry);
                        fn = timer->function;
                        data = timer->data;
                        irqsafe = tbase_get_irqsafe(timer->base);

                        timer_stats_account_timer(timer);

                        base->running_timer = timer;
                        detach_expired_timer(timer, base);

                        if (irqsafe) {
                                spin_unlock(&base->lock);
                                call_timer_fn(timer, fn, data); // <=========== HERE
                                spin_lock(&base->lock);
                        } else {
                                spin_unlock_irq(&base->lock);
                                call_timer_fn(timer, fn, data); // <============ HERE
                                spin_lock_irq(&base->lock);
                        }
                }
        }
        base->running_timer = NULL;
        spin_unlock_irq(&base->lock);
}


/*
 * This function runs timers and the timer-tq in bottom half context.
 */
static void run_timer_softirq(struct softirq_action *h)
{
        struct tvec_base *base = __this_cpu_read(tvec_bases);

        hrtimer_run_pending();

        if (time_after_eq(jiffies, base->timer_jiffies))
                __run_timers(base);
}

void __init init_timers(void)
{
        int err;

        /* ensure there are enough low bits for flags in timer->base pointer */
        BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK);

        err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
                               (void *)(long)smp_processor_id());
        init_timer_stats();

        BUG_ON(err != NOTIFY_OK);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq); // <============= HERE
}

这篇关于Linux内核计时器功能在什么上下文中运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆