| ÂÛ̳ע²á| ¼ÓÈëÊÕ²Ø | ÉèΪÊ×Ò³| RSS
Google
Äúµ±Ç°µÄλÖãºÊ×Ò³ > LinuxƵµÀ > Linux¿ª·¢Çø > ÄÚºËÑо¿

¶¨Ê±Æ÷

ʱ¼ä£º2005-12-01 12:54:54  À´Ô´£º  ×÷Õߣº
£¶ø¶ÔÓÚÄÇЩ256¡Üinterval¡Ü0xffffffffµÄ¶¨Ê±Æ÷£¬ÓÉÓÚËûÃÇÀëµ½ÆÚ»¹ÓÐÒ»¶Îʱ¼ä£¬Òò´ËÄں˲¢²»¹ØÐÄËûÃÇ£¬¶øÊÇ
½«ËüÃÇÒÔÒ»ÖÖÀ©Õ¹µÄ¶¨Ê±Æ÷ÏòÁ¿ÓïÒ壨»ò³ÆÎª¡°ËÉÉ¢µÄ¶¨Ê±Æ÷ÏòÁ¿ÓïÒ塱£©½øÐÐ×éÖ¯¡£Ëùν¡°ËÉÉ¢µÄ¶¨Ê±Æ÷ÏòÁ¿ÓïÒ塱¾ÍÊÇÖ¸£º¸÷¶¨Ê±
Æ÷µÄexpiresÖµ¿ÉÒÔ»¥²»ÏàͬµÄÒ»¸ö¶¨Ê±Æ÷¶ÓÁС£
¾ßÌåµÄ×éÖ¯·½°¸¿ÉÒÔ·ÖΪÁ½´ó²¿·Ö£º
£¨1£©¶ÔÓÚÄÚºË×î¹ØÐĵġ¢intervalÖµÔÚ£Û0£¬255£ÝÖ®¼äµÄǰ256¸ö¶¨Ê±Æ÷ÏòÁ¿£¬ÄÚºËÊÇÕâÑù×éÖ¯ËüÃǵģºÕâ256¸ö¶¨Ê±Æ÷ÏòÁ¿±»×é
Ö¯ÔÚÒ»Æð×é³ÉÒ»¸ö¶¨Ê±Æ÷ÏòÁ¿Êý×飬²¢×÷ΪÊý¾Ý½á¹¹timer_vec_rootµÄÒ»²¿·Ö£¬¸ÃÊý¾Ý½á¹¹¶¨ÒåÔÚkernel/timer.cÎļþÖУ¬Èç
ÏÂÊö´úÂë¶ÎËùʾ£º
/*
* Event timer code
*/
#define TVN_BITS 6
#define TVR_BITS 8
#define TVN_SIZE (1 >8£©¾ßÓÐÏàֵͬµÄ¶¨Ê±Æ÷¶¼½«±»×é
Ö¯ÔÚͬһ¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿ÖС£Òò´Ë£¬Îª×éÖ¯ËùÓÐÂú×ãÌõ¼þ0x100¡Üinterval¡Ü0x3fffµÄ¶¨Ê±Æ÷£¬¾ÍÐèÒª26£½64¸öËÉÉ¢¶¨Ê±Æ÷Ïò
Á¿¡£Í¬ÑùµØ£¬Îª·½±ãÆð¼û£¬Õâ64¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿Ò²·ÅÔÚÒ»ÆðÐγÉÊý×飬²¢×÷ΪÊý¾Ý½á¹¹timer_vecµÄÒ»²¿·Ö¡£»ùÓÚÊý¾Ý½á¹¹
timer_vec£¬Linux¶¨ÒåÁËÈ«¾Ö±äÁ¿tv2£¬À´±íʾÕâ64ÌõËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿¡£ÈçÉÏÊö´úÂë¶ÎËùʾ¡£
¶ÔÓÚÄÇЩÂú×ãÌõ¼þ0x4000¡Üinterval¡Ü0xfffffµÄ¶¨Ê±Æ÷£¬Ö»Òª±í´ïʽ£¨interval>>8£«6£©µÄÖµÏàͬµÄ¶¨Ê±Æ÷¶¼½«±»·ÅÔÚͬһ¸ö
ËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿ÖС£Í¬Ñù£¬Òª×éÖ¯ËùÓÐÂú×ãÌõ¼þ0x4000¡Üinterval¡Ü0xfffffµÄ¶¨Ê±Æ÷£¬Ò²ÐèÒª26£½64¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿¡£ÀàËÆ
µØ£¬Õâ64¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿Ò²¿ÉÒÔÓÃÒ»¸ötimer_vec½á¹¹À´ÃèÊö£¬ÏàÓ¦µØLinux¶¨ÒåÁËtv3È«¾Ö±äÁ¿À´±íʾÕâ64¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿¡£
¶ÔÓÚÄÇЩÂú×ãÌõ¼þ0x100000¡Üinterval¡Ü0x3ffffffµÄ¶¨Ê±Æ÷£¬Ö»Òª±í´ïʽ£¨interval>>8£«6£«6£©µÄÖµÏàͬµÄ¶¨Ê±Æ÷¶¼½«±»·Å
ÔÚͬһ¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿ÖС£Í¬Ñù£¬Òª×éÖ¯ËùÓÐÂú×ãÌõ¼þ0x100000¡Üinterval¡Ü0x3ffffffµÄ¶¨Ê±Æ÷£¬Ò²ÐèÒª26£½64¸öËÉÉ¢¶¨Ê±Æ÷
ÏòÁ¿¡£ÀàËÆµØ£¬Õâ64¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿Ò²¿ÉÒÔÓÃÒ»¸ötimer_vec½á¹¹À´ÃèÊö£¬ÏàÓ¦µØLinux¶¨ÒåÁËtv4È«¾Ö±äÁ¿À´±íʾÕâ64¸öËÉÉ¢¶¨
ʱÆ÷ÏòÁ¿¡£
¶ÔÓÚÄÇЩÂú×ãÌõ¼þ0x4000000¡Üinterval¡Ü0xffffffffµÄ¶¨Ê±Æ÷£¬Ö»Òª±í´ïʽ£¨interval>>8£«6£«6£«6£©µÄÖµÏàͬµÄ¶¨Ê±Æ÷¶¼½«
±»·ÅÔÚͬһ¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿ÖС£Í¬Ñù£¬Òª×éÖ¯ËùÓÐÂú×ãÌõ¼þ0x4000000¡Üinterval¡Ü0xffffffffµÄ¶¨Ê±Æ÷£¬Ò²ÐèÒª26£½64¸öËÉÉ¢
¶¨Ê±Æ÷ÏòÁ¿¡£ÀàËÆµØ£¬Õâ64¸öËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿Ò²¿ÉÒÔÓÃÒ»¸ötimer_vec½á¹¹À´ÃèÊö£¬ÏàÓ¦µØLinux¶¨ÒåÁËtv5È«¾Ö±äÁ¿À´±íʾÕâ64¸ö
ËÉÉ¢¶¨Ê±Æ÷ÏòÁ¿¡£

×îºó£¬ÎªÁËÒýÓ÷½±ã£¬Linux¶¨ÒåÁËÒ»¸öÖ¸ÕëÊý×étvecs£Û£Ý£¬À´·Ö±ðÖ¸Ïòtv1¡¢tv2¡¢¡­¡¢tv5½á¹¹±äÁ¿¡£ÈçÉÏÊö´úÂëËùʾ¡£
Õû¸öÄں˶¨Ê±Æ÷»úÖÆµÄ×ÜÌå½á¹¹ÈçÏÂͼ7£­8Ëùʾ£º

7£®6£®3 Äں˶¯Ì¬¶¨Ê±Æ÷»úÖÆµÄʵÏÖ
ÔÚÄں˶¯Ì¬¶¨Ê±Æ÷»úÖÆµÄʵÏÖÖУ¬ÓÐÈý¸ö²Ù×÷ʱ·Ç³£ÖØÒªµÄ£º£¨1£©½«Ò»¸ö¶¨Ê±Æ÷²åÈëµ½ËüÓ¦¸ÃËù´¦µÄ¶¨Ê±Æ÷ÏòÁ¿ÖС££¨2£©¶¨Ê±Æ÷µÄ
Ç¨ÒÆ£¬Ò²¼´½«Ò»¸ö¶¨Ê±Æ÷´ÓËüÔ­À´Ëù´¦µÄ¶¨Ê±Æ÷ÏòÁ¿Ç¨ÒƵ½ÁíÒ»¸ö¶¨Ê±Æ÷ÏòÁ¿ÖС££¨3£©É¨Ãè²¢Ö´Ðе±Ç°ÒѾ­µ½ÆÚµÄ¶¨Ê±Æ÷¡£

7£®6£®3£®1 ¶¯Ì¬¶¨Ê±Æ÷»úÖÆµÄ³õʼ»¯
º¯Êýinit_timervecs()ʵÏÖ¶Ô¶¯Ì¬¶¨Ê±Æ÷»úÖÆµÄ³õʼ»¯¡£¸Ãº¯Êý½ö±»sched_init()³õʼ»¯Àý³ÌËùµ÷Ó᣶¯Ì¬¶¨Ê±Æ÷»úÖÆ³õʼ»¯
¹ý³ÌµÄÖ÷ÒªÈÎÎñ¾ÍÊǽ«tv1¡¢tv2¡¢¡­¡¢tv5Õâ5¸ö½á¹¹±äÁ¿ÖеĶ¨Ê±Æ÷ÏòÁ¿Ö¸ÕëÊý×évec£Û£Ý³õʼ»¯ÎªNULL¡£ÈçÏÂËùʾ£¨kernel/
timer.c£©£º
void init_timervecs (void)
{
int i;

for (i = 0; i expires;
unsigned long idx = expires - timer_jiffies;
struct list_head * vec;

if (idx > TVR_BITS) & TVN_MASK;
vec = tv2.vec + i;
} else if (idx > (TVR_BITS + TVN_BITS)) & TVN_MASK;
vec = tv3.vec + i;
} else if (idx > (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
vec = tv4.vec + i;
} else if ((signed long) idx > (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
vec = tv5.vec + i;
} else {
/* Can only get here on architectures with 64-bit jiffies */
INIT_LIST_HEAD(&timer->list);
return;
}
/*
* Timers are FIFO!
*/
list_add(&timer->list, vec->prev);
}
¶Ô¸Ãº¯ÊýµÄ×¢ÊÍÈçÏ£º
£¨1£©Ê×ÏÈ£¬¼ÆË㶨ʱÆ÷µÄexpiresÖµÓëtimer_jiffiesµÄ²åÖµ£¨×¢Ò⣡ÕâÀïÓ¦¸ÃʹÓö¯Ì¬¶¨Ê±Æ÷×Ô¼ºµÄʱ¼ä»ù×¼£©£¬Õâ¸ö²îÖµ¾Í±í
ʾÕâ¸ö¶¨Ê±Æ÷Ïà¶ÔÓÚÉÏÒ»´ÎÔËÐж¨Ê±Æ÷»úÖÆµÄÄǸöʱ¿Ì»¹ÐèÒª¶à³¤Ê±¼ä¼ä¸ô²Åµ½ÆÚ¡£¾Ö²¿±äÁ¿idx±£´æÕâ¸ö²îÖµ¡£
£¨2£©¸ù¾ÝidxµÄֵȷ¶¨Õâ¸ö¶¨Ê±Æ÷Ó¦±»²åÈëµ½ÄÄÒ»¸ö¶¨Ê±Æ÷ÏòÁ¿ÖС£Æä¾ßÌåµÄÈ·¶¨·½·¨ÎÒÃÇÔÚ7.6.2½ÚÒѾ­Ëµ¹ýÁË£¬ÕâÀï²»ÔÙÏêÊö¡£
×îºó£¬¶¨Ê±Æ÷ÏòÁ¿µÄÍ·²¿Ö¸Õëvec±íʾÕâ¸ö¶¨Ê±Æ÷Ó¦¸ÃËù´¦µÄ¶¨Ê±Æ÷ÏòÁ¿Á´±íÍ·²¿¡£
£¨3£©×îºó£¬µ÷ÓÃlist_add()º¯Êý½«¶¨Ê±Æ÷²åÈëµ½vecÖ¸ÕëËùÖ¸ÏòµÄ¶¨Ê±Æ÷¶ÓÁеÄβ²¿¡£

7£®6£®3£®5 ÐÞ¸ÄÒ»¸ö¶¨Ê±Æ÷µÄexpiresÖµ
µ±Ò»¸ö¶¨Ê±Æ÷ÒѾ­±»²åÈëµ½Äں˶¯Ì¬¶¨Ê±Æ÷Á´±íÖкó£¬ÎÒÃÇ»¹¿ÉÒÔÐ޸ĸö¨Ê±Æ÷µÄexpiresÖµ¡£º¯Êýmod_timer()ʵÏÖÕâÒ»µã¡£Èç
ÏÂËùʾ£¨kernel/timer.c£©£º
int mod_timer(struct timer_list *timer, unsigned long expires)
{
int ret;
unsigned long flags;

spin_lock_irqsave(&timerlist_lock, flags);
timer->expires = expires;
ret = detach_timer(timer);
internal_add_timer(timer);
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
}
¸Ãº¯ÊýÊ×Ïȸù¾Ý²ÎÊýexpiresÖµ¸üж¨Ê±Æ÷µÄexpires³ÉÔ±¡£È»ºóµ÷ÓÃdetach_timer()º¯Êý½«¸Ã¶¨Ê±Æ÷´ÓËüÔ­À´ËùÊôµÄÁ´±íÖÐɾ
³ý¡£×îºóµ÷ÓÃinternal_add_timer()º¯Êý½«¸Ã¶¨Ê±Æ÷¸ù¾ÝËüеÄexpiresÖµÖØÐ²åÈëµ½ÏàÓ¦µÄÁ´±íÖС£

º¯Êýdetach_timer()Ê×Ïȵ÷ÓÃtimer_pending()À´ÅжÏÖ¸¶¨µÄ¶¨Ê±Æ÷ÊÇ·ñÒѾ­´¦ÓÚij¸öÁ´±íÖУ¬Èç¹û¶¨Ê±Æ÷Ô­À´¾Í²»´¦ÓÚÈκÎÁ´
±íÖУ¬Ôòdetach_timer()º¯ÊýʲôҲ²»×ö£¬Ö±½Ó·µ»Ø0Öµ£¬±íʾʧ°Ü¡£·ñÔò£¬¾Íµ÷ÓÃlist_del()º¯Êý½«¶¨Ê±Æ÷´ÓËüÔ­À´Ëù´¦µÄÁ´
±íÖÐÕª³ý¡£ÈçÏÂËùʾ£¨kernel/timer.c£©£º
static inline int detach_timer (struct timer_list *timer)
{
if (!timer_pending(timer))
return 0;
list_del(&timer->list);
return 1;
}

7£®6£®3£®6 ɾ³ýÒ»¸ö¶¨Ê±Æ÷
º¯Êýdel_timer()ÓÃÀ´½«Ò»¸ö¶¨Ê±Æ÷´ÓÏàÓ¦µÄÄں˶¨Ê±Æ÷¶ÓÁÐÖÐɾ³ý¡£¸Ãº¯Êýʵ¼ÊÉÏÊǶÔdetach_timer()º¯ÊýµÄ¸ß²ã·â×°¡£ÈçÏÂ
Ëùʾ£¨kernel/timer.c£©£º
int del_timer(struct timer_list * timer)
{
int ret;
unsigned long flags;

spin_lock_irqsave(&timerlist_lock, flags);
ret = detach_timer(timer);
timer->list.next = timer->list.prev = NULL;
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
}

7£®6£®3£®7 ¶¨Ê±Æ÷Ç¨ÒÆ²Ù×÷
ÓÉÓÚÒ»¸ö¶¨Ê±Æ÷µÄintervalÖµ»áËæ×Åʱ¼äµÄ²»¶ÏÁ÷ÊÅ£¨¼´jiffiesÖµµÄ²»¶ÏÔö´ó£©¶ø²»¶Ï±äС£¬Òò´ËÄÇЩԭ±¾µ½ÆÚ½ôÆÈ³Ì¶È½ÏµÍµÄ
¶¨Ê±Æ÷»áËæ×ÅjiffiesÖµµÄ²»¶ÏÔö´ó¶ø³ÉΪ¼È½«ÂíÉϵ½ÆÚµÄ¶¨Ê±Æ÷¡£±ÈÈ綨ʱÆ÷ÏòÁ¿tv2.vec[0]ÖеĶ¨Ê±Æ÷ÔÚ¾­¹ý256¸öʱÖӵδð
ºó»á³ÉΪδÀ´256¸öʱÖӵδðÄڻᵽÆÚµÄ¶¨Ê±Æ÷¡£Òò´Ë£¬¶¨Ê±Æ÷ÔÚÄں˶¯Ì¬¶¨Ê±Æ÷Á´±íÖеÄλÖÃÒ²Ó¦ÏàÓ¦µØËæ×Ÿı䡣¸Ä±äµÄ¹æÔò
ÊÇ£ºµ±tv1.indexÖØÐ±äΪ0ʱ£¨Òâζ×Åtv1ÖеÄ256¸ö¶¨Ê±Æ÷ÏòÁ¿¶¼Òѱ»ÄÚºËɨÃèÒ»±éÁË£¬´Ó¶øÊ¹tv1ÖеÄ256¸ö¶¨Ê±Æ÷ÏòÁ¿±äΪ
¿Õ£©£¬ÔòÓÃtv2.vec£Ûindex£Ý¶¨Ê±Æ÷ÏòÁ¿ÖеĶ¨Ê±Æ÷È¥Ìî³ätv1£¬Í¬Ê±Ê¹tv2.index¼Ó1£¨ËüÒÔ64Ϊ죩¡£µ±tv2.indexÖØÐ±äΪ
0£¨Òâζ×Åtv2ÖеÄ64¸ö¶¨Ê±Æ÷ÏòÁ¿¶¼ÒѾ­±»È«²¿Ìî³äµ½tv1ÖÐÈ¥ÁË£¬´Ó¶øÊ¹µÃtv2±äΪ¿Õ£©£¬ÔòÓÃtv3.vec£Ûindex£Ý¶¨Ê±Æ÷ÏòÁ¿ÖÐ
µÄ¶¨Ê±Æ÷È¥Ìî³ätv2¡£Èç´ËÒ»Ö±ÀàÍÆÏÂÈ¥£¬Ö±µ½tv5¡£
º¯Êýcascade_timers()Íê³ÉÕâÖÖ¶¨Ê±Æ÷Ç¨ÒÆ²Ù×÷£¬¸Ãº¯ÊýÖ»ÓÐÒ»¸ötimer_vec½á¹¹ÀàÐÍÖ¸ÕëµÄ²ÎÊýtv¡£Õâ¸öº¯Êý½«°Ñ¶¨Ê±Æ÷ÏòÁ¿
tv->vec£Ûtv->index£ÝÖеÄËùÓж¨Ê±Æ÷ÖØÐÂÌî³äµ½ÉÏÒ»²ã¶¨Ê±Æ÷ÏòÁ¿ÖÐÈ¥¡£ÈçÏÂËùʾ£¨kernel/timer.c£©£º
static inline void cascade_timers(struct timer_vec *tv)
{
/* cascade all the timers from tv up one level */
struct list_head *head, *curr, *next;

head = tv->vec + tv->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.
*/
while (curr != head) {
struct timer_list *tmp;

tmp = list_entry(curr, struct timer_list, list);
next = curr->next;
list_del(curr); // not needed
internal_add_timer(tmp);
curr = next;
}
INIT_LIST_HEAD(head);
tv->index = (tv->index + 1) & TVN_MASK;
}
¶Ô¸Ãº¯ÊýµÄ×¢ÊÍÈçÏ£º
£¨1£©Ê×ÏÈ£¬ÓÃÖ¸ÕëheadÖ¸Ïò¶¨Ê±Æ÷Í·²¿ÏòÁ¿Í·²¿µÄlist_head½á¹¹¡£Ö¸ÕëcurrÖ¸Ïò¶¨Ê±Æ÷ÏòÁ¿ÖеĵÚÒ»¸ö¶¨Ê±Æ÷¡£
£¨2£©È»ºó£¬ÓÃÒ»¸öwhile{}Ñ­»·À´±éÀú¶¨Ê±Æ÷ÏòÁ¿tv->vec£Ûtv->index£Ý¡£ÓÉÓÚ¶¨Ê±Æ÷ÏòÁ¿ÊÇÒ»¸öË«ÏòÑ­»·¶ÓÁУ¬Òò´ËÑ­»·µÄÖÕ
Ö¹Ìõ¼þÊÇcurr=head¡£¶ÔÓÚÿһ¸ö±»É¨ÃèµÄ¶¨Ê±Æ÷£¬Ñ­»·Ìå¶¼Ïȵ÷ÓÃlist_del()º¯Êý½«µ±Ç°¶¨Ê±Æ÷´ÓÁ´±íÖÐÕª³ý£¬È»ºóµ÷ÓÃ
internal_add_timer()º¯ÊýÖØÐÂÈ·¶¨¸Ã¶¨Ê±Æ÷Ó¦¸Ã±»·Åµ½Äĸö¶¨Ê±Æ÷ÏòÁ¿ÖÐÈ¥¡£
£¨3£©µ±´Ówhile{}Ñ­»·Í˳öºó£¬¶¨Ê±Æ÷ÏòÁ¿tv->vec£Ûtv->index£ÝÖÐËùÓеĶ¨Ê±Æ÷¶¼Òѱ»Ç¨ÒƵ½ÆäËüµØ·½£¨µ½ËüÃǸôôµÄµØ·½£º
£­£©£¬Òò´ËËü±¾Éí¾Í³ÉΪһ¸ö¿Õ¶ÓÁС£ÕâÀïÎÒÃÇÏÔʾµØµ÷ÓÃINIT_LIST_HEAD()ºêÀ´½«¶¨Ê±Æ÷ÏòÁ¿µÄ±íÍ·½á¹¹³õʼ»¯Îª¿Õ¡£
£¨4£©×îºó£¬½«tv->indexÖµ¼Ó1£¬µ±È»ËüÊÇÒÔ64Ϊģ¡£

7£®6£®4£®8 ɨÃè²¢Ö´Ðе±Ç°ÒѾ­µ½ÆÚµÄ¶¨Ê±Æ÷
º¯Êýrun_timer_list()Íê³ÉÕâ¸ö¹¦ÄÜ¡£ÈçǰËùÊö£¬¸Ãº¯ÊýÊDZ»timer_bh()º¯ÊýËùµ÷Óõģ¬Òò´ËÄں˶¨Ê±Æ÷ÊÇÔÚʱÖÓÖжϵÄ
Bottom HalfÖб»Ö´Ðеġ£¼ÇסÕâÒ»µã·Ç³£ÖØÒª¡£È«¾Ö±äÁ¿timer_jiffies±íʾÁËÄÚºËÉÏÒ»´ÎÖ´ÐÐrun_timer_list()º¯ÊýµÄʱ
¼ä£¬Òò´ËjiffiesÓëtimer_jiffiesµÄ²îÖµ¾Í±íʾÁË×Ô´ÓÉÏÒ»´Î´¦Àí¶¨Ê±Æ÷ÒÔÀ´£¬ÆÚ¼äÒ»¹²·¢ÉúÁ˶àÉÙ´ÎʱÖÓÖжϣ¬ÏÔÈ»
run_timer_list()º¯Êý±ØÐëΪÆÚ¼äËù·¢ÉúµÄÿһ´ÎʱÖÓÖжϲ¹É϶¨Ê±Æ÷·þÎñ¡£¸Ãº¯ÊýµÄÔ´ÂëÈçÏ£¨kernel/timer.c£©£º
static inline void run_timer_list(void)
{
spin_lock_irq(&timerlist_lock);
while ((long)(jiffies - timer_jiffies) >= 0) {
struct list_head *head, *curr;
if (!tv1.index) {
int n = 1;
do {
cascade_timers(tvecs[n]);
} while (tvecs[n]->index == 1 && ++n next;
if (curr != head) {
struct timer_list *timer;
void (*fn)(unsigned long);
unsigned long data;

timer = list_entry(curr, struct timer_list, list);
fn = timer->function;
data= timer->data;

detach_timer(timer);
timer->list.next = timer->list.prev = NULL;
timer_enter(timer);
spin_unlock_irq(&timerlist_lock);
fn(data);
spin_lock_irq(&timerlist_lock);
timer_exit();
goto repeat;
}
++timer_jiffies;
tv1.index = (tv1.index + 1) & TVR_MASK;
}
spin_unlock_irq(&timerlist_lock);
}
º¯Êýrun_timer_list()µÄÖ´Ðйý³ÌÖ÷Òª¾ÍÊÇÓÃÒ»¸ö´ówhile{}Ñ­»·À´ÎªÊ±ÖÓÖжÏÖ´Ðж¨Ê±Æ÷·þÎñ£¬Ã¿Ò»´ÎÑ­»··þÎñÒ»´ÎʱÖÓÖÐ
¶Ï¡£Òò´ËÒ»¹²ÒªÖ´ÐУ¨jiffies£­timer_jiffies£«1£©´ÎÑ­»·¡£Ñ­»·ÌåËùÖ´ÐеķþÎñ²½ÖèÈçÏ£º
£¨1£©Ê×ÏÈ£¬ÅжÏtv1.indexÊÇ·ñΪ0£¬Èç¹ûΪ0ÔòÐèÒª´Ótv2Öв¹³ä¶¨Ê±Æ÷µ½tv1ÖÐÀ´¡£µ«tv2Ò²¿ÉÄÜΪ¿Õ¶øÐèÒª´Ótv3Öв¹³ä¶¨Ê±
Æ÷£¬Òò´ËÓÃÒ»¸ödo{}whileÑ­»·À´µ÷ÓÃcascade_timer()º¯ÊýÀ´ÒÀ´ÎÊÓÐèÒª´Ótv2Öв¹³ätv1£¬´Ótv3Öв¹³ätv2¡¢¡­¡¢´Ótv5Öв¹
³ätv4¡£ÏÔÈ»Èç¹ûtvi.index=0£¨2¡Üi¡Ü5£©£¬Ôò¶ÔÓÚtviÖ´ÐÐcascade_timers()º¯Êýºó£¬tvi.index¿Ï¶¨Îª1¡
 5/7   |‹ ‹‹ 3 4 5 6 7 ›› ›|

À´¶¥Ò»ÏÂ
½ü»ØÊ×Ò³
·µ»ØÊ×Ò³
·¢±íÆÀÂÛ ¹²ÓÐÌõÆÀÂÛ
Óû§Ãû: ÃÜÂë:
ÑéÖ¤Âë: ÄäÃû·¢±í
Ïà¹ØÎÄÕÂ
    ÎÞÏà¹ØÐÅÏ¢
À¸Ä¿¸üÐÂ
À¸Ä¿ÈÈÃÅ