低级定时器timer时间轮极端情况

1 关于tvx[0]

假设timer_jiffies = 256;
expires = 256*64;
__internal_add_timer的时候
idx = 256*63 < 256*64;显然是落在tv2中;
i = (256*64 >>8) & 0x3f = 0;落在了tv2[0]中。
这个时间点,tv2[1]也会转到tv1中。
那它什么时候转走呢?
当tv1->index == 0; 即timer_jiffies & TVR_MASK
同时 tv2 -> index == 0;即(timer_jiffies >> TVR_BITS) &TVN_MASK
也就是timer_jiffies == 256*64的时候;
此时发生的事情有:
tv1为空了,所以需要从tv2[ tv2 -> index ] 中转入,刚好是从tv2[0]转入的,而且加入的这个expires = 256*64;会立即执行;
tv2[0]转走后,tv2也空了,需要从tv3[ tv3 -> index]中转入,这个时刻,刚好是从tv3[1]转入的。
此时tvx[0]记录的时间是该轮中最大的值。
由于256是个临界点,取个不特殊的值;
假设timer_jiffies = 321;
expires = 256*64+100;
idx = 256+64-221 < 256+64;落在tv2中;
i = (256+64+100)>>8 & 0x3f = 0;同样落在tv2[0]中。
在这个时刻,tv1应该转到了tv1[65]。
那它什么时候转走;
还是
当tv1->index == 0; 即timer_jiffies & TVR_MASK
同时 tv2 -> index == 0;即(timer_jiffies >> TVR_BITS) &TVN_MASK
也就是timer_jiffies == 256*64的时候;
只不过此时经过的时间是256*64-321;而不是256*63。
这个时刻
tv1为空了,所以需要从tv2[ tv2 -> index ] 中转入,刚好是tv2[0]中转入的,但是这个expires = 256*64+100;不会立即执行,要等100个tick后执行;
tv2[0]转走后,tv2也空了,需要从tv3[ tv3 -> index]中转入,这个时刻,刚好是从tv3[1]转入的。
极端假设,如果timer_jiffies = 0就运行了__run_timers();此时需要从tv2[0]转入tv1,也需要从tv3[0]、tv4[0]、tv5[0]中转入,
通过__internal_add_timer()中的判断tvx[0]中的一个timer也没有转走,因为它是时间轮中最大的。此后++timer_jiffies;会正常执行tv1[0]中的到期timer。

2 关于tvx[1]

仍然是假设
假设timer_jiffies = 0;
expires = 256;
add的时候会落在tv2[1]中,expires 为[256, 256*2-1]的时刻都会落在tv2[1]。
那它什么时候转出?
经过256个tick,tv1为空了,刚好需要重tv2[1]中转出,转到tv1。
如果此时还添加了一个expires = 256*64的timer;显然会添加到tv3[1]里,expires 为[256*64, 256*64*2-1]的时刻都会落在tv3[1]。
经过256*64个tick,tv1空了,tv2也空了,tv3[1]会转出,转入到tv2和tv1中;此时tv3[1]加入的256*64会直接转入tv1中,这个expires = 256;会立即执行。
原来时间轮是tv2转到tv1,tv3转到tv2和tv1,以此类推。
不取特殊值,假设timer_jiffies = 100; expires = 256*64+200;仍然会落在tv3[1]中。
经过256*64-100个tick,tv1空了,tv2也空了,tv3[1]会转出,转入到tv2和tv1中;此时tv3[1]加入的256*64+200,会直接转入tv1中,只是不会立即执行;要等到200个tick才执行到。




你可能感兴趣的:(linux驱动)