标签:
#include <linux/init.h> #include <linux/module.h> #include <linux/time.h> static struct timer_list test_time; static int count=0; static void test_time_function(unsigned long data) { printk(KERN_EMERG "timer: test_time_function: count=%d, data=%lu\n", count,data); printk(KERN_EMERG "timer: jiffies = %lu\n", jiffies); count++; test_time.expires = jiffies + HZ; ----------------------------------E add_timer(&test_time); ----------------------------------F } static int time_test_open(void) { printk(KERN_EMERG "timer: time_test_open\n"); init_timer(&test_time); -------------------------------------A test_time.expires = jiffies + HZ; -------------------------------------B test_time.function = &test_time_function; -------------------------------------C test_time.data = 123; -------------------------------------D add_timer(&test_time); -------------------------------------H return 0; } static void time_test_close(void) { printk(KERN_EMERG "timer: time_test_close\n"); del_timer(&test_time); -------------------------------------G } module_init(time_test_open); module_exit(time_test_close); MODULE_LICENSE("GPL");
timer: time_test_open timer: test_time_function: count=0, data=123 timer: jiffies = 4294950523 timer: test_time_function: count=1, data=123 timer: jiffies = 4294950775 timer: test_time_function: count=2, data=123 timer: jiffies = 4294951026 timer: test_time_function: count=3, data=123 timer: jiffies = 4294951277 timer: test_time_function: count=4, data=123 timer: jiffies = 4294951528 timer: test_time_function: count=5, data=123 timer: jiffies = 4294951779 timer: test_time_function: count=6, data=123 timer: jiffies = 4294952030 timer: test_time_function: count=7, data=123 timer: jiffies = 4294952282 timer: test_time_function: count=8, data=123 timer: jiffies = 4294952534 timer: time_test_close
struct timer_list { /* * All fields that change during normal runtime grouped to the * same cacheline */ struct list_head entry; unsigned long expires; struct tvec_base *base; void (*function)(unsigned long); unsigned long data; int slack; };为了更好的分析,去掉其中的一些调试选项之后如上。
struct tvec_base { spinlock_t lock; struct timer_list *running_timer; unsigned long timer_jiffies; unsigned long next_timer; unsigned long active_timers; unsigned long all_timers; int cpu; struct tvec_root tv1; struct tvec tv2; struct tvec tv3; struct tvec tv4; struct tvec tv5; } ____cacheline_aligned;running_timer: 该字段指向当前cpu正在执行的定时器对应的timer_list结构。
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) #define TVN_SIZE (1 << TVN_BITS) #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) #define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1)) struct tvec { struct list_head vec[TVN_SIZE]; }; struct tvec_root { struct list_head vec[TVR_SIZE]; };在默认的情况下CONFIG_BASE_SMALL没有使能,也就是CONFIG_BASE_SMALL=0,这时候TVN_SIZE=64, TVR_SIZE=256。而如果CONFIG_BASE_SMALL使能的话,CONFIG_BASE_SMALL=1,则TVN_SIZE=64, TVR_SIZE=16。至于如何分组,会到后面详细说明。
struct tvec_base boot_tvec_bases; static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
static void do_init_timer(struct timer_list *timer, unsigned int flags, const char *name, struct lock_class_key *key) { struct tvec_base *base = raw_cpu_read(tvec_bases); timer->entry.next = NULL; timer->base = (void *)((unsigned long)base | flags); timer->slack = -1; lockdep_init_map(&timer->lockdep_map, name, key, 0); }初始化timer_list结构体中的各个成员。
数组 | idx范围 |
---|---|
tv1 | 0--2^8-1 |
tv2 | 2^8--2^14-1 |
tv3 | 2^14--2^20-1 |
tv4 | 2^20--2^26-1 |
tv5 | 2^26--2^32-1 |
static void __internal_add_timer(struct tvec_base *base, struct timer_list *timer) { unsigned long expires = timer->expires; unsigned long idx = expires - base->timer_jiffies; ----------------------A struct list_head *vec; if (idx < TVR_SIZE) { ---------------------B int i = expires & TVR_MASK; vec = base->tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { ---------------------C int i = (expires >> TVR_BITS) & TVN_MASK; vec = base->tv2.vec + i; } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; vec = base->tv3.vec + i; } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK; vec = base->tv4.vec + i; } else if ((signed long) idx < 0) { /* * Can happen if you add a timer with expires == jiffies, * or you set a timer to go off in the past */ vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK); } else { int i; /* If the timeout is larger than MAX_TVAL (on 64-bit * architectures or with CONFIG_BASE_SMALL=1) then we * use the maximum timeout. */ if (idx > MAX_TVAL) { idx = MAX_TVAL; expires = idx + base->timer_jiffies; } i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; vec = base->tv5.vec + i; } /* * Timers are FIFO: */ list_add_tail(&timer->entry, vec); }A: 确认超时的时间差,通过超期时间减去time_jiffies的值
void __init init_timers(void) { int err; /* ensure there are enough low bits for flags in timer->base pointer */ BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK); err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, (void *)(long)smp_processor_id()); BUG_ON(err != NOTIFY_OK); init_timer_stats(); register_cpu_notifier(&timers_nb); open_softirq(TIMER_SOFTIRQ, run_timer_softirq); }当每次时钟中断发生后,系统就会调用到run_local_timers, 在run_local_timers函数中就会调用TIMER_SOFTIRQ对于的中断处理函数。
void run_local_timers(void) { hrtimer_run_queues(); raise_softirq(TIMER_SOFTIRQ); }对于的中断处理函数为:
static void run_timer_softirq(struct softirq_action *h) { struct tvec_base *base = __this_cpu_read(tvec_bases); hrtimer_run_pending(); if (time_after_eq(jiffies, base->timer_jiffies)) __run_timers(base); }在每次中断处理函数中,系统会处理timer_jiffies到期的定时器,调用__run_timer
static inline void __run_timers(struct tvec_base *base) { struct timer_list *timer; spin_lock_irq(&base->lock); if (catchup_timer_jiffies(base)) { -----------------------------------A spin_unlock_irq(&base->lock); return; } while (time_after_eq(jiffies, base->timer_jiffies)) { ----------------B struct list_head work_list; struct list_head *head = &work_list; int index = base->timer_jiffies & TVR_MASK; ------------------C /* * Cascade timers: */ if (!index && -------------------D (!cascade(base, &base->tv2, INDEX(0))) && (!cascade(base, &base->tv3, INDEX(1))) && !cascade(base, &base->tv4, INDEX(2))) cascade(base, &base->tv5, INDEX(3)); ++base->timer_jiffies; list_replace_init(base->tv1.vec + index, head); ------------------E while (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; bool irqsafe; timer = list_first_entry(head, struct timer_list,entry); fn = timer->function; data = timer->data; -----------------------------F irqsafe = tbase_get_irqsafe(timer->base); timer_stats_account_timer(timer); base->running_timer = timer; detach_expired_timer(timer, base); ----------------------------------G if (irqsafe) { spin_unlock(&base->lock); call_timer_fn(timer, fn, data); ----------------------————H spin_lock(&base->lock); } else { spin_unlock_irq(&base->lock); call_timer_fn(timer, fn, data); spin_lock_irq(&base->lock); } } } base->running_timer = NULL; spin_unlock_irq(&base->lock); }A: 判断all_timer是否还有值,如果为0,说明没有要处理的定时器,直接返回退出。
#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)比如这时候系统中有10个定时器,超时时间分别是256 - 266, 这10个定时器都会存放到tv2中的index1的链表中。因为tv2有64组,每组有256项,刚好这10项是存放在第一项中。
static int cascade(struct tvec_base *base, struct tvec *tv, int index) { /* cascade all the timers from tv up one level */ struct timer_list *timer, *tmp; struct list_head tv_list; list_replace_init(tv->vec + index, &tv_list); ---------------------------A /* * We are removing _all_ timers from the list, so we * don't have to detach them individually. */ list_for_each_entry_safe(timer, tmp, &tv_list, entry) { BUG_ON(tbase_get_base(timer->base) != base); /* No accounting, while moving them */ __internal_add_timer(base, timer); --------------------------------B } return index; }A: 将tv2中的马上超时定时器放入到tv_list中
标签:
原文地址:http://blog.csdn.net/longwang155069/article/details/52290252