對內核高精度timer體系的一些分析

因爲在vim下輸入英文比較方便, 所以一般初稿都是用英文寫的.
下面的分析是基於最新的內核(2.6.33)的.

there is not included at current platform commented #
在kernel的time目錄裏,會根據不同的編譯選項來選擇不同的tick模式,一般爲以下模式(arm)
帶#爲沒有編譯進內核的.

obn-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)        += clockevents.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS)        += tick-common.o
#obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += tick-broadcast.o
obj-$(CONFIG_TICK_ONESHOT)            += tick-oneshot.o
obj-$(CONFIG_TICK_ONESHOT)            += tick-sched.o
#obj-$(CONFIG_TIMER_STATS)            += timer_stats.o

 

Currently, the kernel time-keeping is based on nsec.
event_handler is assigned at tick_setup_periodic during initialization, and the value is tick_handle_periodic(before softirq initialization), after softirq initialization, the evt->enent_handler will be assigned to hrtimer_interrupt if hrtimer is enable or no hz handler if hrtimer is disabled and no hz mode is enabled.
hrtimer will be called during hard irq context if it expires, the other hrtimer will be called during softirq context
現在的內核計時的最小單位爲納表,一般的計時都是表和納秒的組合.
如果hrtimer和no hz模式被始能,時鐘中斷的處理方式會有些不同.一開始(在軟中斷初始化之前)event_handler是指向tick_handle_periodic,在軟中斷初始化之後,evt->enent_handler將根據hrtimer與no hz是否始能,指向對應的函數.如果兩個都始能,就指向hrtimer_interrupt, 如果hrtimer不始能,就指向tick_nohz_handler.
在內核的timer系統中會經常看到mult,shift,min_delta_ns等名詞.下面具體說一下它們的意思,
先列一個內核的結構以及相應的註釋.
/**
 * struct clock_event_device - clock event device descriptor
 * @name:        ptr to clock event name
 * @features:        features
 * @max_delta_ns:    maximum delta value in ns
 * @min_delta_ns:    minimum delta value in ns
 * @mult:        nanosecond to cycles multiplier
 * @shift:        nanoseconds to cycles divisor (power of two)
 * @rating:        variable to rate clock event devices
 * @irq:        IRQ number (only for non CPU local devices)
 * @cpumask:        cpumask to indicate for which CPUs this device works
 * @set_next_event:    set next event function
 * @set_mode:        set mode function
 * @event_handler:    Assigned by the framework to be called by the low
 *            level handler of the event source
 * @broadcast:        function to broadcast events
 * @list:        list head for the management code
 * @mode:        operating mode assigned by the management code
 * @next_event:        local storage for the next event in oneshot mode
 */
struct clock_event_device {
    const char        *name;
    unsigned int        features;
    u64            max_delta_ns;
    u64            min_delta_ns;
    u32            mult;
    u32            shift;
    int            rating;
    int            irq;
    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_head    list;
    enum clock_event_mode    mode;
    ktime_t            next_event;
};
freq = mult/(2^shift): freq is how many ticks for ns, for our platform, it is 1/1000.
mult和shift是用來轉化timer的tick和納秒的.freq = mult/(2^shift)中,freq表示一個ns有多少個tick,如果tick是1M,那freq就是1/1000.

The hrtimer will be called at both hardirq condition (at evt->event_handler) and softirq context.The condition which adjust the timer is expired or not is calling ktime_get() to get current kernel time; it will reture tick count at timer register finally. But the software timer is different, it uses jiffies to adjust whether the timer is expired or not
hrtimer的回調函數會同時在硬件中斷上下文和軟中斷上下文中調用,判斷timer時候過期是用ktime_get()函數,該函數最終會去讀timer的tick來更新內核的時間.而軟件timer就不同了,它是根據jiffies來判斷timer是否過期的.

 

NOTICE: The hrtimer expires value should be larger than 2 ticks (currently is 2000ns), otherwise, the hrtimer which is setting at hrtimer's callback function will be called a little late, about more than 40-50 ticks
有一個要注意,hrtimer的過期值不能設的太小,如果少於3個tick,並且下一次hrtimer的設定就是在上一次hrtimer的回調函數裏,且過期時間也是少於3個tick的,這樣在執行過3次hrtimer以後就會觸發hrtimer_interrupt裏的一個錯誤條件(將已經過期的timer誤認爲沒有過期,且3次出現這樣的情況),這個錯誤條件一旦成立,它的會調函數可能要過40-50個tick(具體跟回調函數的執行時間有關)纔可能會執行.

 

在nohz和highres模式下, timer中斷的interval爲以highres timer和software timer expires中較小的一個.

 

發佈了50 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章