7.2. Knowing the Current Time
Kernel code can always retrieve a
representation of the current time by looking at the value of
jiffies. Usually, the fact that the value
represents only the time since the last boot is not relevant to the
driver, because its life is limited to the system uptime. As shown,
drivers can use the current value of jiffies to
calculate time intervals across events (for example, to tell
double-clicks from single-clicks in input device drivers or calculate
timeouts). In short, looking at jiffies is almost
always sufficient when you need to measure time intervals. If you
need very precise measurements for short time lapses,
processor-specific registers come to the rescue (although they bring
in serious portability issues).
It's quite unlikely that a driver will ever need to
know the wall-clock time, expressed in months, days, and hours; the
information is usually needed only by user programs such as
cron and syslogd. Dealing
with real-world time is usually best left to user space, where the C
library offers better support; besides, such code is often too
policy-related to belong in the kernel. There is
a kernel function that turns a wall-clock time into a
jiffies value, however:
#include <linux/time.h>
unsigned long mktime (unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec);
To repeat: dealing directly with wall-clock time in a driver is often
a sign that policy is being implemented and should therefore be
questioned.
While you won't
have to deal with human-readable representations of the time,
sometimes you need to deal with absolute timestamp even in kernel
space. To this aim, <linux/time.h> exports
the do_gettimeofday function. When called, it
fills a struct timeval
pointer—the same one used in the
gettimeofday system call—with the familiar
seconds and microseconds values. The prototype for
do_gettimeofday is:
#include <linux/time.h>
void do_gettimeofday(struct timeval *tv);
The
source states that do_gettimeofday has
"near microsecond resolution,"
because it asks the timing hardware what fraction of the current
jiffy has already elapsed. The precision varies from one architecture
to another, however, since it depends on the actual hardware
mechanisms in use. For example, some m68knommu
processors, Sun3 systems, and other m68k systems
cannot offer more than jiffy resolution. Pentium systems, on the
other hand, offer very fast and precise subtick measures by reading
the timestamp counter described earlier in this chapter.
The current time is also available (though with jiffy granularity)
from the xtime variable, a struct
timespec value. Direct use of this variable is discouraged
because it is difficult to atomically access both the fields.
Therefore, the kernel offers the utility function
current_kernel_time:
#include <linux/time.h>
struct timespec current_kernel_time(void);
Code for retrieving the current time in
the various ways it is available within the jit
("just in time") module in the
source files provided on O'Reilly's
FTP site. jit creates a file called
/proc/currentime, which returns the following
items in ASCII when read:
The current jiffies and
jiffies_64 values as hex numbers The current time as returned by do_gettimeofday The timespec returned by
current_kernel_time
We chose to use a dynamic /proc file to keep the
boilerplate code to a minimum—it's not worth
creating a whole device just to return a little textual information.
The file returns text lines continuously as long as the module is
loaded; each read system call collects and
returns one set of data, organized in two lines for better
readability. Whenever you read multiple data sets in less than a
timer tick, you'll see the difference between
do_gettimeofday, which queries the hardware, and
the other values that are updated only when the timer ticks.
phon% head -8 /proc/currentime
0x00bdbc1f 0x0000000100bdbc1f 1062370899.630126
1062370899.629161488
0x00bdbc1f 0x0000000100bdbc1f 1062370899.630150
1062370899.629161488
0x00bdbc20 0x0000000100bdbc20 1062370899.630208
1062370899.630161336
0x00bdbc20 0x0000000100bdbc20 1062370899.630233
1062370899.630161336
In the screenshot above, there are two interesting things to note.
First, the current_kernel_time value, though
expressed in nanoseconds, has only clock-tick granularity;
do_gettimeofday consistently reports a later
time but not later than the next timer tick. Second, the 64-bit
jiffies counter has the least-significant bit of the upper 32-bit
word set. This happens because the default value for
INITIAL_JIFFIES, used at boot time to initialize
the counter, forces a low-word overflow a few minutes after boot time
to help detect problems related to that very overflow. This initial
bias in the counter has no effect, because jiffies
is unrelated to wall-clock time. In
/proc/uptime, where the kernel extracts the
uptime from the counter, the initial bias is
removed before conversion.
|