Posted by RichardMc

Double cast in setting of INITIAL_JIFFIES October 03, 2013 05:37PM |
Registered: 5 years ago Posts: 3 |

I’ve been trying to wrap my head around the double cast (unsigned long)(unsigned int) used in the definition of INITIAL_JIFFIES here…..

from Linux/include/linux/jiffies.h :

162 /*

163 * Have the 32 bit jiffies value wrap 5 minutes after boot

164 * so jiffies wrap bugs show up earlier.

165 */

166 #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))

Here’s my best explanation… can someone confirm this ?

My thoughts are that on the first (rightmost) cast, the negative signed int (-300*HZ) is converted to an unsigned int with sign extension to whatever size an unsigned int is on that implementation (typically 32 bits), then the second cast (to unsigned long) casts that up to the size of an unsigned long (32 or 64 bits depending on implementation) with zero extension (as we are going from unsigned to unsigned type).

In the case of 32 bit unsigned long, the second (leftmost) cast does nothing.

In the case of 64 bit unsigned long, the second cast would cause the upper 32 bits to be set to 0.

In any case, the jiffies variable (32 or 64 bit) is overlaid on the jiffies_64 (type u64) variable, aligned at the least significant bit, so if the upper 32 bits of jiffies_64 are not already set to zero (in the case of 32 bit unsigned long), they will be when jiffies_64 gets initialised due to implicit type conversion of unsigned 32 bit integer to unsigned 64 bit integer with zero extension:

from Linux/kernel/timer.c :

55 u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;

In other words, by whatever path, the upper 32 bits of the jiffies/jiffies_64 combo will start at zero, and the lower 32 bits are set so that they will clock over in 5 mins.

If a real time in jiffies since startup is needed, the initial value can always be subtracted from the current value (as a 64 bit subtraction using jiffies_64 and INITIAL_JIFFIES).

If we used a single typecast to get us from from signed int to unsigned long in the definition of INITIAL_JIFFIES, we would sign extend right up to the most significant bit, and in the case of a 64 bit unsigned long, set the upper 32 bits to 1.

We are only trying to establish proper wrapping behaviour for the lower 32 bits, as the full 64 bit version will not be expected to wrap around in any of our lifetimes as long as the upper 32 bits start out at 0.

Is this what's going on here ?

from Linux/include/linux/jiffies.h :

162 /*

163 * Have the 32 bit jiffies value wrap 5 minutes after boot

164 * so jiffies wrap bugs show up earlier.

165 */

166 #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))

Here’s my best explanation… can someone confirm this ?

My thoughts are that on the first (rightmost) cast, the negative signed int (-300*HZ) is converted to an unsigned int with sign extension to whatever size an unsigned int is on that implementation (typically 32 bits), then the second cast (to unsigned long) casts that up to the size of an unsigned long (32 or 64 bits depending on implementation) with zero extension (as we are going from unsigned to unsigned type).

In the case of 32 bit unsigned long, the second (leftmost) cast does nothing.

In the case of 64 bit unsigned long, the second cast would cause the upper 32 bits to be set to 0.

In any case, the jiffies variable (32 or 64 bit) is overlaid on the jiffies_64 (type u64) variable, aligned at the least significant bit, so if the upper 32 bits of jiffies_64 are not already set to zero (in the case of 32 bit unsigned long), they will be when jiffies_64 gets initialised due to implicit type conversion of unsigned 32 bit integer to unsigned 64 bit integer with zero extension:

from Linux/kernel/timer.c :

55 u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;

In other words, by whatever path, the upper 32 bits of the jiffies/jiffies_64 combo will start at zero, and the lower 32 bits are set so that they will clock over in 5 mins.

If a real time in jiffies since startup is needed, the initial value can always be subtracted from the current value (as a 64 bit subtraction using jiffies_64 and INITIAL_JIFFIES).

If we used a single typecast to get us from from signed int to unsigned long in the definition of INITIAL_JIFFIES, we would sign extend right up to the most significant bit, and in the case of a 64 bit unsigned long, set the upper 32 bits to 1.

We are only trying to establish proper wrapping behaviour for the lower 32 bits, as the full 64 bit version will not be expected to wrap around in any of our lifetimes as long as the upper 32 bits start out at 0.

Is this what's going on here ?