标签:
#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_timerstatic 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