???????У?timer_list????嶨????????(????????忴timer_list????)?????????tv1??tv2??tv3??tv4??tv5????????????????????????
#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)
struct tvec {
struct list_head vec[TVN_SIZE];
};
struct tvec_root {
struct list_head vec[TVR_SIZE];
};
????????????忴????tv1??????256?????飬????????list_head????????tv2??tv3??tv4??tv5????????64?????飬????????list_head??List_head??linux???????й???????????????????????????е??????????????list_head????á??????tv1-tv5????????+????????????hash?????????????????+??????????????????Щhash??ζ?????????????????????????????????
?????????????????У?
????for(j = 0; j < TVN_SIZE; j++) {
????INIT_LIST_HEAD(base->tv5.vec+ j);
????INIT_LIST_HEAD(base->tv4.vec+ j);
????INIT_LIST_HEAD(base->tv3.vec+ j);
????INIT_LIST_HEAD(base->tv2.vec+ j);
????}
????for(j = 0; j < TVR_SIZE; j++)
????INIT_LIST_HEAD(base->tv1.vec+ j);
????tv1-tv5??5???????е??????????list_head???г??????
????base->timer_jiffies= jiffies;
????base->next_timer= base->timer_jiffies;
??????base?е?timer_jiffies??next_timer????????jiffies??
???????????????init_timers?????????????????????
????open_softirq(TIMER_SOFTIRQ??run_timer_softirq);
????????????????????ж?????????ж????????linux?????ж????
???????????????嶨???????????????????
????????????????
#define init_timer(timer)                      
do {                               
static struct lock_class_key __key;        
init_timer_key((timer)?? #timer?? &__key);       
} while (0)
void init_timer_key(struct timer_list *timer??
const char *name??
struct lock_class_key *key)
{
debug_init(timer);
__init_timer(timer?? name?? key);
}
static void __init_timer(struct timer_list *timer??
const char *name??
struct lock_class_key *key)
{
timer->entry.next = NULL;
timer->base = __raw_get_cpu_var(tvec_bases);
#ifdef CONFIG_TIMER_STATS
timer->start_site = NULL;
timer->start_pid = -1;
memset(timer->start_comm?? 0?? TASK_COMM_LEN);
#endif
lockdep_init_map(&timer->lockdep_map?? name?? key?? 0);
}
?????????????壺
????<span style="font-family:'Liberation Serif'?? serif;">#define TIMER_INITIALIZER(_function?? _expires?? _data) {       
????.entry = { .prev = TIMER_ENTRY_STATIC }??   
????.function = (_function)??           
????.expires = (_expires)??             
????.data = (_data)??               
????.base = &boot_tvec_bases??          
????__TIMER_LOCKDEP_MAP_INITIALIZER(       
????__FILE__ ":" __stringify(__LINE__))
????}
????</span>
???????????????
????void add_timer(struct timer_list *timer)
????{
????BUG_ON(timer_pending(timer));
????mod_timer(timer?? timer->expires);
????}
????Timer_list???????壺
struct timer_list {
struct list_head entry;
unsigned long expires;
void (*function)(unsigned long);
unsigned long data;
struct tvec_base *base;
#ifdef CONFIG_TIMER_STATS
void *start_site;
char start_comm[16];
int start_pid;
#endif
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
int mod_timer(struct timer_list *timer?? unsigned long expires)
{
/*
* This is a common optimization triggered by the
* networking code - if the timer is re-modified
* to be the same thing then just return:
*/
if (timer_pending(timer) && timer->expires == expires)
return 1;
return __mod_timer(timer?? expires?? false?? TIMER_NOT_PINNED);
}
????1?? if(timer_pending(timer) && timer->expires == expires)
????return1;
?????????timer??????????????timer_base?е????????(tv1—tv5)?У?????????????????????