把握linux核心設計思想(六):核心時鐘中斷
阿新 • • 發佈:2019-01-23
(位於檔案kernel/time/tick-common.c)
下面來看分析一下該函式:
其中函式do_timer()(位於kernel/timer.c中)對jiffies_64做增加操作:
void __init tick_init(void)
{
clockevents_register_notifier(&tick_notifier);
}
tick_notifier定義如下:tick_periodic()函式主要有以下工作:static struct notifier_block tick_notifier = { .notifier_call = tick_notify, }; static int tick_notify(struct notifier_block *nb, unsigned long reason, void *dev) { switch (reason) { ...... case CLOCK_EVT_NOTIFY_RESUME: tick_resume(); break; default: break; } return NOTIFY_OK; } static void tick_resume(void) { struct tick_device *td = &__get_cpu_var(tick_cpu_device); unsigned long flags; int broadcast = tick_resume_broadcast(); spin_lock_irqsave(&tick_device_lock, flags); clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME); if (!broadcast) { if (td->mode == TICKDEV_MODE_PERIODIC) tick_setup_periodic(td->evtdev, 0); else tick_resume_oneshot(); } spin_unlock_irqrestore(&tick_device_lock, flags); } /* * Setup the device for a periodic tick */ void tick_setup_periodic(struct clock_event_device *dev, int broadcast) { tick_set_periodic_handler(dev, broadcast); ...... } /* * 根據broadcast設定週期性的處理函式(kernel/time/tick-broadcast.c),這裡就設定了始終中斷函式timer_interrupt中呼叫的時鐘處理例程 */ void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast) { if (!broadcast) dev->event_handler = tick_handle_periodic; else dev->event_handler = tick_handle_periodic_broadcast; } /* * ,以tick_handle_periodic為例,每一個始終節拍都呼叫該處理函式,而該處理過程中,主要處理工作處於tick_periodic()函式中。 */ void tick_handle_periodic(struct clock_event_device *dev) { int cpu = smp_processor_id(); ktime_t next; tick_periodic(cpu); if (dev->mode != CLOCK_EVT_MODE_ONESHOT) return; next = ktime_add(dev->next_event, tick_period); for (;;) { if (!clockevents_program_event(dev, next, ktime_get())) return; if (timekeeping_valid_for_hres()) tick_periodic(cpu); next = ktime_add(next, tick_period); } }
下面來看分析一下該函式:
/* * Periodic tick */ static void tick_periodic(int cpu) { if (tick_do_timer_cpu == cpu) { write_seqlock(&xtime_lock); /* 記錄下一個節拍事件 */ tick_next_period = ktime_add(tick_next_period, tick_period); do_timer(1); write_sequnlock(&xtime_lock); } update_process_times(user_mode(get_irq_regs()));//更新所耗費的各種節拍數 profile_tick(CPU_PROFILING); }
其中函式do_timer()(位於kernel/timer.c中)對jiffies_64做增加操作:
void do_timer(unsigned long ticks)
{
jiffies_64 += ticks;
update_wall_time(); //更新牆上時鐘
calc_global_load(); //更新系統平均負載統計值
}
update_process_times更新所耗費的各種節拍數。函式run_local_timers()會標記一個軟中斷去處理所有到期的定時器。void update_process_times(int user_tick) { struct task_struct *p = current; int cpu = smp_processor_id(); /* Note: this timer irq context must be accounted for as well. */ account_process_tick(p, user_tick); run_local_timers(); rcu_check_callbacks(cpu, user_tick); printk_tick(); scheduler_tick(); run_posix_cpu_timers(p); }
void run_local_timers(void)
{
hrtimer_run_queues();
raise_softirq(TIMER_SOFTIRQ);
softlockup_tick();
}
在時鐘中斷處理函式time_interrupt()函式呼叫體系結構無關的時鐘處理例程完成之後,返回到與體系結構的相關的中斷處理函式中。以上所有的工作每一次時鐘中斷都會執行,也就是說如果HZ=100,那麼時鐘中斷處理程式每一秒就會執行100次。