linux时间子系统 - 动态任务

1. 动态任务的切换


系统初期是在periodic模式,在周期性函数调用update_process_times过程中,会进行动态任务的切换,具体是在函数hrtimer_run_queues中进行

linux时间子系统 - 动态任务_第1张图片

2. 低精度模式下的动态任务


2.1 切换到低精度动态任务

static void tick_nohz_switch_to_nohz(void)
{
    struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
    ktime_t next;

    if (!tick_nohz_enabled)
        return;

    if (tick_switch_to_oneshot(tick_nohz_handler))
        return;

    /*
     * Recycle the hrtimer in ts, so we can share the
     * hrtimer_forward with the highres code.
     */
    hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
    /* Get the next period */
    next = tick_init_jiffy_update();

    hrtimer_set_expires(&ts->sched_timer, next);
    hrtimer_forward_now(&ts->sched_timer, tick_period);
    tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
    tick_nohz_activate(ts, NOHZ_MODE_LOWRES);
}

2.2 动态任务函数tick_nohz_handler

static void tick_nohz_handler(struct clock_event_device *dev)
{
    struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
    struct pt_regs *regs = get_irq_regs();
    ktime_t now = ktime_get();

    dev->next_event.tv64 = KTIME_MAX;

    tick_sched_do_timer(now);---------------------------------------动态tick更新time、调度
    tick_sched_handle(ts, regs);------------------------------------动态任务

    /* No need to reprogram if we are running tickless  */
    if (unlikely(ts->tick_stopped))
        return;

    hrtimer_forward(&ts->sched_timer, now, tick_period);
    tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);-----编程下一个时钟信号时间
}

3. 高精度模式下的动态任务


3.1 切换到高精度动态任务

linux时间子系统 - 动态任务_第2张图片

3.2 动态任务函数hrtimer_interrupt

linux时间子系统 - 动态任务_第3张图片

A : 更新hrtimer红黑树
B : 运行hrtimer中的到期的事件
C : 得到下一个事件时间
D : 编程下一个时钟信号时间

4. tick-sched


4.1 tick_sched_do_timer

static void tick_sched_do_timer(ktime_t now)
{
    int cpu = smp_processor_id();

#ifdef CONFIG_NO_HZ_COMMON
    /*
     * Check if the do_timer duty was dropped. We don't care about
     * concurrency: This happens only when the cpu in charge went
     * into a long sleep. If two cpus happen to assign themself to
     * this duty, then the jiffies update is still serialized by
     * jiffies_lock.
     */
    if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE)
        && !tick_nohz_full_cpu(cpu))
        tick_do_timer_cpu = cpu;
#endif

    /* Check, if the jiffies need an update */
    if (tick_do_timer_cpu == cpu)
        tick_do_update_jiffies64(now);
}

4.2 tick_sched_handle

static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
{
#ifdef CONFIG_NO_HZ_COMMON
    /*
     * When we are idle and the tick is stopped, we have to touch
     * the watchdog as we might not schedule for a really long
     * time. This happens on complete idle SMP systems while
     * waiting on the login prompt. We also increment the "start of
     * idle" jiffy stamp so the idle accounting adjustment we do
     * when we go busy again does not account too much ticks.
     */
    if (ts->tick_stopped) {
        touch_softlockup_watchdog_sched();
        if (is_idle_task(current))
            ts->idle_jiffies++;
    }
#endif
    update_process_times(user_mode(regs));
    profile_tick(CPU_PROFILING);
}

change log

date content linux
2017.1.2 tick-sched linux4.6.3

你可能感兴趣的:(Linux内核)