开发者

Jiffies Counter Over Flow case + Linux

Jiffies counter returns an unsigned integer of size four bytes. when the counter reaches maximum value then it restarts from 0 again. I'll subtract the latest value with the old value to get the duration. So how sh开发者_StackOverflow中文版ould i consider for a case such that when the old value is of maximum value and new value is more than zero so that I'll get wrong duration?


You don't have to do anything, you'll have the correct duration (as long as you make all your calculations using four bytes unsigned integers). That's the magic of integer values implemented as fixed-width binary arithmetic.

Here is an example with 8 bits unsigned integers. You can actually see that even when there's overflow, the difference is still valid.

236 - 221 = 11101100 - 11011101 = 11101100 + 00100011 = 00001111 = 15
251 - 236 = 11111011 - 11101100 = 11111011 + 00010100 = 00001111 = 15
 10 - 251 = 00001010 - 11111011 = 00001010 + 00000101 = 00001111 = 15
 25 -  10 = 00011001 - 00001010 = 00011001 + 11110110 = 00001111 = 15
   ...

Your single problem comes when the duration is not small compared to the maximum value of the counter, i.e. when it can be larger than the half of the maximum value.


This advice is only correct if your two events a and b, a actually happened before b, and the distance between them is less than 2^(32-1). If you calculate (b-a) then you get the right answer. If you subtract the smaller unsigned value from the larger unsigned (thinking that defines their time ordering), then you can get the negative of the answer you wanted.

So, you need to account for a new circular comparison operation as well (see Linux time_after, time_before and use them, etc).

Both signed and unsigned comparisons would be wrong, because counters that wrap around are not exactly the same thing as signed or unsigned numbers. Consider 8-bit case:

a=250, b=20   #8-bit sequence number a was created before b
a=120, b=130  #8-bit sequence number a was created before b

The main difference between signed and unsigned values with the same number of bits are the implementations of the comparison operators. Signed versus unsigned is significant when assigning to a value with more bits because of the decision to sign extend negative values with 1s or 0s.

Consider a new definition of less than designed for numbers that wrap around:

LT_CIRCULAR_32(250,5)     == True   //like signed?   
LT_CIRCULAR_32(0,11)      == True
LT_CIRCULAR_32(127,138)   == True   //like unsigned?

This comparison works so long as the actual distance between the first and second value is always less than 2^(32-1).

Imagine a circle with 256 positions on it, and counters a and b advancing clockwise. If a can reach b with less than 2^(8-1) increments then "a < b". It is a comparison that takes wrapping into account, and it's neither signed nor unsigned:

#define LT_CIRCULAR_LONG(a,b)  ((((long)(b)-(long)(a)) < 0)==0)

That is why time_after looks the way that it does. The casts of b and a separately ensure the sign extends are consistent. Making a value signed and checking for less than zero is a trick to test the high bit.

I am watching a fellow developer deal with this issue with jiffies right now (ie: -300 jiffies), and have seen it with TCP sequence numbers and a few other similar counters. So, being 2s compliment doesn't handle all of it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜