关于jiffies的回绕,time_after()linux宏是否100%可靠?
收藏

根据我在linux/include/linux/jiffies.h中找到的代码:

41 #define time_after(a,b)         \
42         (typecheck(unsigned long, a) && \
43          typecheck(unsigned long, b) && \
44          ((long)(b) - (long)(a) < 0))

在我看来,这并不是一种全面的监控。所以,如果jiffies(a)被包装起来,并回到相当接近超时(b)的位置,那么当它实际上是“true”时,结果将是“false”。
在这个例子中,我们使用一些相当小的数字。比方说,time_after(110,150)其中110是jiffies,150是超时。结果显然是错误的-不管jiffies是否被包裹:150-110总是大于0。
所以,我只是想确认我没有错过什么,事实就是这样。


最佳答案:

为了清楚起见,在您的示例中,因为110不在150之后,time_after(110,150)应该(并且确实)返回false。从评论中:

time_after(a,b) returns true if the time a is after time b.

另外,请注意,代码确实处理了对0的包装。为了使下面的内容更容易理解,我将使用无符号和有符号的单字节值,即8位2的补码。但争论是普遍的。
假设B是253,五个滴答声之后,jiffies已经绕到了2。因此,我们希望time_after(2,253)返回true。它确实(使用int8_t表示有符号的8位值):
(int8_t) 253 - (int8_t) 2 == -3 - 2 == -5 < 0

你也可以尝试其他的价值观。这一个更棘手,因为time_after(128, 127),这也应该是正确的:
(int8_t) 127 - (int8_t) 128 == 127 - (-128) == 255 == -1 (for 8-bit 2's complement) < 0

实际上,表达式的类型(int8_t) 127 - (int8_t) 128是一个int,值实际上是255。但是使用long,表达式类型将是long,而等效的示例将是,对于time_after( 2147483648, 2147483647)
(long) 2147483647 - (long) 2147483648 == 2147483647 - (-2147483648) == 4294967295 == -1 < 0

最后,在包装之后,“after”jiffies值a将开始赶上before值btime_after(a,b)将报告为false。对于n位2的补码,当a比b晚2^(n-1)个滴答时发生这种情况。对于n=8,当a比b晚128个滴答时发生这种情况。对于n=32,这是2147483648个滴答,或者(使用1毫秒滴答)大约25天。
对于具有数学倾向的情况,我认为一般来说,如果(a-b)的最小余数(模2^n)大于0且小于2^(n-1),则time_after(a,b)返回真值。

    公众号
    关注公众号订阅更多技术干货!