Jiffies

The jiffies variable holds the number of ticks elapsed since system bootup. Every time a tick occurs, jiffies is incremented by one. It's a 32-bit variable, meaning for a tick rate of 100 Hz, overflow will occur in approximately 497 days (and in 49 days, 17 hours for a 1000 Hz tick rate).

To overcome this issue, a 64-bit variable jiffies_64 is used instead, which allows for thousands of millions of years before the overflow occurs. The jiffies variable is equated to the 32 least significant bits of jiffies_64. The reason for having both jiffies and jiffies_64 variables is that in 32-bit machines, a 64-bit variable can not be accessed atomically; some synchronization is required in order to avoid any counter update while these two 32-bit halves are processed. The function get_jiffies_64() defined in the /kernel/time/jiffies.c source file returns the current value of jiffies:

u64 get_jiffies_64(void)
{
        unsigned long seq;
        u64 ret;

        do {
                seq = read_seqbegin(&jiffies_lock);
                ret = jiffies_64;
        } while (read_seqretry(&jiffies_lock, seq));
        return ret;
}

While working with jiffies, it's crucial to take into account the possibility of wraparound, because it leads to unpredictable results while comparing two time events. There are four macros that serve this purpose, defined in include/linux/jiffies.h:

#define time_after(a,b)           
       (typecheck(unsigned long, a) && 
        typecheck(unsigned long, b) && 
        ((long)((b) - (a)) < 0))
#define time_before(a,b)       time_after(b,a)

#define time_after_eq(a,b)     
       (typecheck(unsigned long, a) && 
        typecheck(unsigned long, b) && 
        ((long)((a) - (b)) >= 0))
#define time_before_eq(a,b)    time_after_eq(b,a)

All these macros return Boolean values; parameters a and b are time events to be compared. If a happens to be the time after b, time_after() returns true, otherwise false. Conversely, if a happens to be before b, time_before() returns true, else false. Both time_after_eq() and time_before_eq() return true if both a and b are equal. Jiffies can be converted to other time units such as milliseconds, microseconds, and nanoseconds using routines jiffies_to_msecs(), jiffies_to_usecs(), defined in kernel/time/time.c, and jiffies_to_nsecs(), in include/linux/jiffies.h:

unsigned int jiffies_to_msecs(const unsigned long j)
{
#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
        return (MSEC_PER_SEC / HZ) * j;
#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
        return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
#else
# if BITS_PER_LONG == 32
        return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32;
# else
        return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN;
# endif
#endif
}

unsigned int jiffies_to_usecs(const unsigned long j) { /* * Hz doesn't go much further MSEC_PER_SEC. * jiffies_to_usecs() and usecs_to_jiffies() depend on that. */ BUILD_BUG_ON(HZ > USEC_PER_SEC); #if !(USEC_PER_SEC % HZ) return (USEC_PER_SEC / HZ) * j; #else # if BITS_PER_LONG == 32 return (HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32; # else return (j * HZ_TO_USEC_NUM) / HZ_TO_USEC_DEN; # endif #endif }

static inline u64 jiffies_to_nsecs(const unsigned long j) { return (u64)jiffies_to_usecs(j) * NSEC_PER_USEC; }

Other conversion routines can be explored in the include/linux/jiffies.h file.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.6.75