51

How do I manually convert jiffies to milliseconds and vice versa in Linux? I know kernel 2.6 has a function for this, but I'm working on 2.4 (homework) and though I looked at the code it uses lots of macro constants which I have no idea if they're defined in 2.4.

Tim Post
  • 33,371
  • 15
  • 110
  • 174
EpsilonVector
  • 3,973
  • 7
  • 38
  • 62

4 Answers4

55

As a previous answer said, the rate at which jiffies increments is fixed.

The standard way of specifying time for a function that accepts jiffies is using the constant HZ.

That's the abbreviation for Hertz, or the number of ticks per second. On a system with a timer tick set to 1ms, HZ=1000. Some distributions or architectures may use another number (100 used to be common).

The standard way of specifying a jiffies count for a function is using HZ, like this:

schedule_timeout(HZ / 10);  /* Timeout after 1/10 second */

In most simple cases, this works fine.

2*HZ     /* 2 seconds in jiffies */
HZ       /* 1 second in jiffies */
foo * HZ /* foo seconds in jiffies */
HZ/10    /* 100 milliseconds in jiffies */
HZ/100   /* 10 milliseconds in jiffies */
bar*HZ/1000 /* bar milliseconds in jiffies */

Those last two have a bit of a problem, however, as on a system with a 10 ms timer tick, HZ/100 is 1, and the precision starts to suffer. You may get a delay anywhere between 0.0001 and 1.999 timer ticks (0-2 ms, essentially). If you tried to use HZ/200 on a 10ms tick system, the integer division gives you 0 jiffies!

So the rule of thumb is, be very careful using HZ for tiny values (those approaching 1 jiffie).

To convert the other way, you would use:

jiffies / HZ          /* jiffies to seconds */
jiffies * 1000 / HZ   /* jiffies to milliseconds */

You shouldn't expect anything better than millisecond precision.

Eric Seppanen
  • 5,923
  • 30
  • 24
  • Is it possible to obtain the HZ value using CLI? E.g. after reading utime from /proc/[pid]/stat on 2.6 kernel, can I easily convert it to seconds without need to compile it from C code? – Alois Mahdal May 26 '14 at 19:17
  • 1
    If you're interacting with HZ from userspace, use USER_HZ instead. 'man 7 time' says to use sysconf(_SC_CLK_TCK) to fetch this value. – Eric Seppanen Sep 11 '14 at 17:55
  • 1
    I don't see an obvious way of doing this from a shell script, but it's generally a constant unless you've been doing unnatural things to your kernel. On x86 USER_HZ is 100. – Eric Seppanen Sep 11 '14 at 18:01
16

Jiffies are hard-coded in Linux 2.4. Check the definition of HZ, which is defined in the architecture-specific param.h. It's often 100 Hz, which is one tick every (1 sec/100 ticks * 1000 ms/sec) 10 ms.

This holds true for i386, and HZ is defined in include/asm-i386/param.h.

There are functions in include/linux/time.h called timespec_to_jiffies and jiffies_to_timespec where you can convert back and forth between a struct timespec and jiffies:

    #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)

    static __inline__ unsigned long
    timespec_to_jiffies(struct timespec *value)
    {
            unsigned long sec = value->tv_sec;
            long nsec = value->tv_nsec;

            if (sec >= (MAX_JIFFY_OFFSET / HZ))
                    return MAX_JIFFY_OFFSET;
            nsec += 1000000000L / HZ - 1;
            nsec /= 1000000000L / HZ;
            return HZ * sec + nsec;
    }

    static __inline__ void
    jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
    {
            value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
            value->tv_sec = jiffies / HZ;
    }

Note: I checked this info in version 2.4.22.

Keshava GN
  • 4,195
  • 2
  • 36
  • 47
indiv
  • 17,306
  • 6
  • 61
  • 82
7

I found this sample code on kernelnewbies. Make sure you link with -lrt

#include <unistd.h>
#include <time.h>
#include <stdio.h>

int main()
{
    struct timespec res;
    double resolution;

    printf("UserHZ   %ld\n", sysconf(_SC_CLK_TCK));

    clock_getres(CLOCK_REALTIME, &res);
    resolution = res.tv_sec + (((double)res.tv_nsec)/1.0e9);

    printf("SystemHZ %ld\n", (unsigned long)(1/resolution + 0.5));
    return 0;
 }
phuclv
  • 37,963
  • 15
  • 156
  • 475
Anthony Giorgio
  • 1,844
  • 1
  • 15
  • 17
3

To obtain the USER_HZ value (see the comments under the accepted answer) using CLI:

getconf CLK_TCK
P. Cahyna
  • 31
  • 3