轉自:http://blog.csdn.net/walkingman321/article/details/6151172
本文介紹Linux2.6.29中,配置高精度模式的hrtimer與未配置高精度模式時行為的區別。本文暫不考慮高精度模式對Linux系統時鐘中斷的影響。
在沒有配置高精度模式時,hrtimer的逾時在系統時鐘中斷的輪循中檢查,所以此時hrtimer的定時精度(jiffy)還是以輪循的間隔為單位,精度與傳統的時間輪定時器一樣。
在配置高精度模式後,hrtimer的逾時由struct clock_event_device的逾時中斷完成。clock_event_device一般來說描述的都是一個硬體定時器,其定時精度由硬體定時器決定,比如我的板子上的此定時器參數為:Timer at Vir:0xE0100200 = Phy:0xE0100200,
using Irq:27, at Freq:250000000,可見其精度之高:250MHz,這也是高精度時鐘這個名稱的由來。
struct clock_event_device {const char*name;unsigned intfeatures;u64max_delta_ns;u64min_delta_ns;u32mult;u32shift;intrating;intirq;const struct cpumask*cpumask;int(*set_next_event)(unsigned long evt, struct clock_event_device *);void(*set_mode)(enum clock_event_mode mode, struct clock_event_device *);void(*event_handler)(struct clock_event_device *);void(*broadcast)(const struct cpumask *mask);struct list_headlist;enum clock_event_modemode;ktime_tnext_event;unsigned longretries;};
下面簡要介紹一下在配置了高精度模式之後hrtimer的實現細節。
1. 添加hrtimer
在配置高精度模式後,添加hrtimer也是由函數hrtimer_start完成,這與沒有配置高精度模式時一樣。但是,高精度模式時,如果添加的hrtimer在紅/黑樹狀結構的最左邊一個節點,即要添加的hrtimer是將會第一個到期的hrtimer時,那麼這時會調用子函數hrtimer_enqueue_reprogram重新設定clock_event_device的逾時中斷。
hrtimer_enqueue_reprogram
hrtimer_reprogram
tick_program_event
tick_dev_program_event
clockevents_program_event
struct clock_event_device * pDev->set_next_event
比如我的平台的clock_event_device的定義如下:
static struct clock_event_device timer0_clockevent = {.name= "my_timer_evt",.features= CLOCK_EVT_FEAT_PERIODIC,.set_mode= my_set_mode,.set_next_event= my_set_next_event,.rating= 300,.cpumask= cpu_all_mask,};
其中timer_set_next_event主要是設定硬體裝置的相關registers.
2. 刪除hrtimer
刪除hrtimer時的改動與添加hrtimer一樣,需要考慮刪除的定時器正好是紅/黑樹狀結構中最左邊節點的情況。因為此時clock_event_device的逾時中斷設定的逾時值正好是要刪除的定時器的逾時值。
3. hrtimer的到期
3.1 未配置高精度模式時
hrtimer的到期由函數hrtimer_run_queues檢查。hrtimer_run_queues是在run_local_timers中被調用,而run_local_timers又是在系統時鐘(jiffy)中斷中被調用。從這裡可以看出,與傳統的使用時間輪演算法的定時器一樣,hrtimer在未配置高精度模式時採用了在每一個系統時鐘中斷中輪循的方式來判斷hrtimer是否到期,因此,這裡的定時精度為時鐘中斷輪循的時間間隔。
但是,在函數hrtimer_run_queues的開始處,會執行一項檢查:
if (hrtimer_hres_active())
return;
所以在配置高精度模式後,這裡的hrtimer_run_queues函數相當於空函數,會直接返回。
3.2 配置了高精度模式之後
hrtimer的到期由clock_event(是一個硬體裝置)裝置的中斷處理來調用,處理函數為hrtimer_interrupt。注意這裡不再採用傳統的輪循方式判斷定時器是否到期,而是通過設定clock_event_device的延時中斷,在第一個到期的定時器逾時的時間點觸發一個中斷來執行逾時操作。所以,這裡的定時精度由clock_event_device的計時精度決定。
4. 非強制中斷
未配置高精度模式時,如果hrtimer設定了非強制中斷標記位,觸發其逾時處理的非強制中斷為TIMER_SOFTIRQ。配置高精度模式後,系統為hrtimer分配了一個專用的非強制中斷,非強制中斷編號為HRTIMER_SOFTIRQ。
本文介紹Linux2.6.29中,配置高精度模式的hrtimer與未配置高精度模式時行為的區別。本文暫不考慮高精度模式對Linux系統時鐘中斷的影響。
在沒有配置高精度模式時,hrtimer的逾時在系統時鐘中斷的輪循中檢查,所以此時hrtimer的定時精度(jiffy)還是以輪循的間隔為單位,精度與傳統的時間輪定時器一樣。
在配置高精度模式後,hrtimer的逾時由struct clock_event_device的逾時中斷完成。clock_event_device一般來說描述的都是一個硬體定時器,其定時精度由硬體定時器決定,比如我的板子上的此定時器參數為:Timer at Vir:0xE0100200 = Phy:0xE0100200,
using Irq:27, at Freq:250000000,可見其精度之高:250MHz,這也是高精度時鐘這個名稱的由來。
struct clock_event_device {const char*name;unsigned intfeatures;u64max_delta_ns;u64min_delta_ns;u32mult;u32shift;intrating;intirq;const struct cpumask*cpumask;int(*set_next_event)(unsigned long evt, struct clock_event_device *);void(*set_mode)(enum clock_event_mode mode, struct clock_event_device *);void(*event_handler)(struct clock_event_device *);void(*broadcast)(const struct cpumask *mask);struct list_headlist;enum clock_event_modemode;ktime_tnext_event;unsigned longretries;};
下面簡要介紹一下在配置了高精度模式之後hrtimer的實現細節。
1. 添加hrtimer
在配置高精度模式後,添加hrtimer也是由函數hrtimer_start完成,這與沒有配置高精度模式時一樣。但是,高精度模式時,如果添加的hrtimer在紅/黑樹狀結構的最左邊一個節點,即要添加的hrtimer是將會第一個到期的hrtimer時,那麼這時會調用子函數hrtimer_enqueue_reprogram重新設定clock_event_device的逾時中斷。
hrtimer_enqueue_reprogram
hrtimer_reprogram
tick_program_event
tick_dev_program_event
clockevents_program_event
struct clock_event_device * pDev->set_next_event
比如我的平台的clock_event_device的定義如下:
static struct clock_event_device timer0_clockevent = {.name= "my_timer_evt",.features= CLOCK_EVT_FEAT_PERIODIC,.set_mode= my_set_mode,.set_next_event= my_set_next_event,.rating= 300,.cpumask= cpu_all_mask,};
其中timer_set_next_event主要是設定硬體裝置的相關registers.
2. 刪除hrtimer
刪除hrtimer時的改動與添加hrtimer一樣,需要考慮刪除的定時器正好是紅/黑樹狀結構中最左邊節點的情況。因為此時clock_event_device的逾時中斷設定的逾時值正好是要刪除的定時器的逾時值。
3. hrtimer的到期
3.1 未配置高精度模式時
hrtimer的到期由函數hrtimer_run_queues檢查。hrtimer_run_queues是在run_local_timers中被調用,而run_local_timers又是在系統時鐘(jiffy)中斷中被調用。從這裡可以看出,與傳統的使用時間輪演算法的定時器一樣,hrtimer在未配置高精度模式時採用了在每一個系統時鐘中斷中輪循的方式來判斷hrtimer是否到期,因此,這裡的定時精度為時鐘中斷輪循的時間間隔。
但是,在函數hrtimer_run_queues的開始處,會執行一項檢查:
if (hrtimer_hres_active())
return;
所以在配置高精度模式後,這裡的hrtimer_run_queues函數相當於空函數,會直接返回。
3.2 配置了高精度模式之後
hrtimer的到期由clock_event(是一個硬體裝置)裝置的中斷處理來調用,處理函數為hrtimer_interrupt。注意這裡不再採用傳統的輪循方式判斷定時器是否到期,而是通過設定clock_event_device的延時中斷,在第一個到期的定時器逾時的時間點觸發一個中斷來執行逾時操作。所以,這裡的定時精度由clock_event_device的計時精度決定。
4. 非強制中斷
未配置高精度模式時,如果hrtimer設定了非強制中斷標記位,觸發其逾時處理的非強制中斷為TIMER_SOFTIRQ。配置高精度模式後,系統為hrtimer分配了一個專用的非強制中斷,非強制中斷編號為HRTIMER_SOFTIRQ。