Linux内核实现的timer在LDD3中讲解的非常清楚,这里就简单的笔记下部分代码注释吧。
【 Linux-2.6.11/kernel/timer.c 】
/* * per-CPU timer vector definitions: */ #define TVN_BITS 6 #define TVR_BITS 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) typedef struct tvec_s { struct list_head vec[TVN_SIZE]; } tvec_t; typedef struct tvec_root_s { struct list_head vec[TVR_SIZE]; } tvec_root_t; struct tvec_t_base_s { spinlock_t lock; unsigned long timer_jiffies; struct timer_list *running_timer; tvec_root_t tv1; tvec_t tv2; tvec_t tv3; tvec_t tv4; tvec_t tv5; } ____cacheline_aligned_in_smp; typedef struct tvec_t_base_s tvec_base_t; static inline void set_running_timer(tvec_base_t *base, struct timer_list *timer) { #ifdef CONFIG_SMP base->running_timer = timer; #endif } /* Fake initialization */ static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED }; /* 定时器无效后打印堆栈函数 */ static void check_timer_failed(struct timer_list *timer) { static int whine_count;/* 静态变量 */ if (whine_count < 16) { whine_count++; printk("Uninitialised timer!\n"); printk("This is just a warning. Your computer is OK\n"); printk("function=0x%p, data=0x%lx\n", timer->function, timer->data); dump_stack(); } /* * Now fix it up */ spin_lock_init(&timer->lock);/* 初始化定时器里面的自旋锁 */ timer->magic = TIMER_MAGIC; /* 赋值magic,便于校验 */ } /* 检查一个定时器是否有效 */ static inline void check_timer(struct timer_list *timer) {/* 如果定时器的magic不匹配,说明定时器变量出错了 */ if (timer->magic != TIMER_MAGIC) check_timer_failed(timer); } /* 添加定时器的内部实现函数 */ /* PS:个人感觉这个函数的最后可以增加 timer->base = new_base; */ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer) { unsigned long expires = timer->expires;/* 获取定时器到期时间(绝对值) */ unsigned long idx = expires - base->timer_jiffies;/*获取当前时间和定时器到期时间的相对值*/ struct list_head *vec; /* 根据相对值的大小,将定时器变量添加到对应的链表中,即vec */ if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = base->tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { 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 0xffffffff on 64-bit * architectures then we use the maximum timeout: */ if (idx > 0xffffffffUL) { idx = 0xffffffffUL; 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); } /* 修改定时器的到期时间 */ int __mod_timer(struct timer_list *timer, unsigned long expires) { tvec_base_t *old_base, *new_base; unsigned long flags; int ret = 0; BUG_ON(!timer->function); /* 首先看下定时器是否有效 */ check_timer(timer); /* 先锁定定时器,同时关闭中断 */ spin_lock_irqsave(&timer->lock, flags); new_base = &__get_cpu_var(tvec_bases);//获取当前CPU对应的定时器链表集 repeat: old_base = timer->base;//获取要修改的定时器之前存放的链表集 /* * Prevent deadlocks via ordering by old_base < new_base. */ if (old_base && (new_base != old_base)) { if (old_base < new_base) { spin_lock(&new_base->lock); spin_lock(&old_base->lock); } else { spin_lock(&old_base->lock); spin_lock(&new_base->lock); } /* * The timer base might have been cancelled while we were * trying to take the lock(s): */ if (timer->base != old_base) { spin_unlock(&new_base->lock); spin_unlock(&old_base->lock); goto repeat; } } else { spin_lock(&new_base->lock); if (timer->base != old_base) { spin_unlock(&new_base->lock); goto repeat; } } /* * Delete the previous timeout (if there was any), and install * the new one: */ /* 如果定时器之前有存放在链表中,就把它从老的链表中删掉 */ if (old_base) { list_del(&timer->entry); ret = 1; } /* 然后更新定时器变量,然后插入到链表中 */ timer->expires = expires; internal_add_timer(new_base, timer);//这里的第一个参数是新的链表集 timer->base = new_base; if (old_base && (new_base != old_base)) spin_unlock(&old_base->lock); spin_unlock(&new_base->lock); spin_unlock_irqrestore(&timer->lock, flags); return ret; } EXPORT_SYMBOL(__mod_timer); /*** * add_timer_on - start a timer on a particular CPU * @timer: the timer to be added * @cpu: the CPU to start it on * * This is not very scalable on SMP. Double adds are not possible. */ /* 将定时器加入到指定的CPU中 */ void add_timer_on(struct timer_list *timer, int cpu) { /*获取指定CPU对应的链表集*/ tvec_base_t *base = &per_cpu(tvec_bases, cpu); unsigned long flags; /* 定时器的回调函数不能为空,而且定时器不能已经被注册 */ BUG_ON(timer_pending(timer) || !timer->function); /* 校验定时器 */ check_timer(timer); /* 加锁,添加 */ spin_lock_irqsave(&base->lock, flags); internal_add_timer(base, timer); timer->base = base;/* 注意这里更新了base变量 */ spin_unlock_irqrestore(&base->lock, flags); } /*** * mod_timer - modify a timer's timeout * @timer: the timer to be modified * * mod_timer is a more efficient way to update the expire field of an * active timer (if the timer is inactive it will be activated) * * mod_timer(timer, expires) is equivalent to: * * del_timer(timer); timer->expires = expires; add_timer(timer); * * Note that if there are multiple unserialized concurrent users of the * same timer, then mod_timer() is the only safe way to modify the timeout, * since add_timer() cannot modify an already running timer. * * The function returns whether it has modified a pending timer or not. * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an * active timer returns 1.) */ /* 修改定时器的到期时间 */ int mod_timer(struct timer_list *timer, unsigned long expires) { BUG_ON(!timer->function); check_timer(timer); /* * 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->expires == expires && timer_pending(timer)) return 1; /* 调用内部函数 */ return __mod_timer(timer, expires); } EXPORT_SYMBOL(mod_timer); /*** * del_timer - deactive a timer. * @timer: the timer to be deactivated * * del_timer() deactivates a timer - this works on both active and inactive * timers. * * The function returns whether it has deactivated a pending timer or not. * (ie. del_timer() of an inactive timer returns 0, del_timer() of an * active timer returns 1.) */ /* 删掉一个定时器,这里并不等待定时器完成。同步版本是下面的函数 */ int del_timer(struct timer_list *timer) { unsigned long flags; tvec_base_t *base; check_timer(timer); /* 防止定时器对应的集合被变更,不停地加锁,检测 */ repeat: base = timer->base; if (!base) return 0; spin_lock_irqsave(&base->lock, flags); if (base != timer->base) { spin_unlock_irqrestore(&base->lock, flags); goto repeat; } /* 将定时器从集合中删除 */ list_del(&timer->entry); /* Need to make sure that anybody who sees a NULL base also sees the list ops */ smp_wmb();/* 防止编译器优化。 */ timer->base = NULL; spin_unlock_irqrestore(&base->lock, flags); return 1; } EXPORT_SYMBOL(del_timer); #ifdef CONFIG_SMP /*** * del_timer_sync - deactivate a timer and wait for the handler to finish. * @timer: the timer to be deactivated * * This function only differs from del_timer() on SMP: besides deactivating * the timer it also makes sure the handler has finished executing on other * CPUs. * * Synchronization rules: callers must prevent restarting of the timer, * otherwise this function is meaningless. It must not be called from * interrupt contexts. The caller must not hold locks which would prevent * completion of the timer's handler. Upon exit the timer is not queued and * the handler is not running on any CPU. * * The function returns whether it has deactivated a pending timer or not. * * del_timer_sync() is slow and complicated because it copes with timer * handlers which re-arm the timer (periodic timers). If the timer handler * is known to not do this (a single shot timer) then use * del_singleshot_timer_sync() instead. */ /* 删掉一个定时器,如果定时器在执行,就等待它结束在返回 */ int del_timer_sync(struct timer_list *timer) { tvec_base_t *base; int i, ret = 0; check_timer(timer); del_again: ret += del_timer(timer);//首先从链表集中尝试删除该定时器 for_each_online_cpu(i) { base = &per_cpu(tvec_bases, i);//在所有的CPU中查找该定时器对应的CPU if (base->running_timer == timer) { /* 如果能找到该CPU,而且该定时器也在执行,此时就放弃CPU,并且允许内核抢占。 */ while (base->running_timer == timer) { cpu_relax(); preempt_check_resched();//允许内核抢占,并发起调度 } break; } } smp_rmb(); if (timer_pending(timer))//如果定时器没有被删除,重试, goto del_again; return ret; } EXPORT_SYMBOL(del_timer_sync); /*** * del_singleshot_timer_sync - deactivate a non-recursive timer * @timer: the timer to be deactivated * * This function is an optimization of del_timer_sync for the case where the * caller can guarantee the timer does not reschedule itself in its timer * function. * * Synchronization rules: callers must prevent restarting of the timer, * otherwise this function is meaningless. It must not be called from * interrupt contexts. The caller must not hold locks which wold prevent * completion of the timer's handler. Upon exit the timer is not queued and * the handler is not running on any CPU. * * The function returns whether it has deactivated a pending timer or not. */ /* 删除一个非周期的定时器 */ int del_singleshot_timer_sync(struct timer_list *timer) { int ret = del_timer(timer); if (!ret) { ret = del_timer_sync(timer); BUG_ON(ret); } return ret; } EXPORT_SYMBOL(del_singleshot_timer_sync); #endif /* 工具函数,将链表集tv中的某一个index下的所有的定时器添加到base集中 */ static int cascade(tvec_base_t *base, tvec_t *tv, int index) { /* cascade all the timers from tv up one level */ struct list_head *head, *curr; head = tv->vec + index; curr = head->next; /* * We are removing _all_ timers from the list, so we don't have to * detach them individually, just clear the list afterwards. */ /* 循环便利tv+index中的定时器,将它们加入到base中 */ while (curr != head) { struct timer_list *tmp; tmp = list_entry(curr, struct timer_list, entry); BUG_ON(tmp->base != base); curr = curr->next; internal_add_timer(base, tmp); } /* 直接重新初始化原来的链表头就可以去掉原来的关联了。 */ INIT_LIST_HEAD(head); return index; } /*** * __run_timers - run all expired timers (if any) on this CPU. * @base: the timer vector to be processed. * * This function cascades all vectors and executes all expired timer * vectors. */ #define INDEX(N) (base->timer_jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK /* 遍历并执行某个链表集下的所有的定时器 */ static inline void __run_timers(tvec_base_t *base) { struct timer_list *timer; spin_lock_irq(&base->lock); while (time_after_eq(jiffies, base->timer_jiffies)) { struct list_head work_list = LIST_HEAD_INIT(work_list); struct list_head *head = &work_list; int index = base->timer_jiffies & TVR_MASK; /* * Cascade timers: */ if (!index && (!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_splice_init(base->tv1.vec + index, &work_list); repeat: if (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; timer = list_entry(head->next,struct timer_list,entry); fn = timer->function; data = timer->data; list_del(&timer->entry); set_running_timer(base, timer); smp_wmb(); timer->base = NULL; spin_unlock_irq(&base->lock); { u32 preempt_count = preempt_count(); fn(data); if (preempt_count != preempt_count()) { printk("huh, entered %p with %08x, exited with %08x?\n", fn, preempt_count, preempt_count()); BUG(); } } spin_lock_irq(&base->lock); goto repeat; } } set_running_timer(base, NULL); spin_unlock_irq(&base->lock); }
发表评论