linux時間子系統 - 動態任務

1. 動態任務的切換


系統初期是在periodic模式,在週期性函數調用update_process_times過程中,會進行動態任務的切換,具體是在函數hrtimer_run_queues中進行

這裏寫圖片描述

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 切換到高精度動態任務

這裏寫圖片描述

3.2 動態任務函數hrtimer_interrupt

這裏寫圖片描述

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
發佈了96 篇原創文章 · 獲贊 33 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章