Linux Time Management
linux's time keeping architecture is the set of kernel data structure and functions related to the flow of time.
- In a uniprocessor system, all time-keeping activities are triggered by interrupt raised by the global timer. (either PIT or HPET)
- In a multiprocessor system, all general activities are triggered by interrupt raised by global timer, while specific CPU activities are triggered by the interrupt raised by the local APIC timer.
The time keeping architecture does the few things in kernel:
- Update the time elapsed since system startup.
- Update the time and date.
- Determines, for every CPU, how long the current processes has been running, and preempts it if it has exceeded the time allocated to it.
- Update resource usage statistics
- Check whether the interval of time associate with each software timer has elapsed.
Tick Rate - HZ
The frequency of the system timer (the tick rate) is programmed on system boot based on a static preprocessor define, HZ.
A common values for HZ are 250 and 1000, corresponding to periods of 4ms and 1 ms.
then, what happened when HZ is higher ?
- increase accuracy
- system call such poll or select that execute with improved precision.
- process preemption occurs more accurately
Jiffies
jiffies is incremented when every global system timer interrupt.
a jiffies
variable usually declared in <linux/jiffies.h>
extern unsigned long volatile jiffies;
unsigned long is 32bits in size of 32bits CPU and 64bits in size of 64bits CPU.
for 32bits CPU
- jiffies overflows in about 497 days when 100Hz
- jiffies overflows in about 49.7 days when 1000Hz
But for 64bits CPU, the jiffies is endless and never overflow.
Prevent overflow from 32bit CPU
A second variable is also defined in <linux/jiffies.h>
extern u64 jiffies_64;
In <kernel source>/arch/<arch>/kernel/vmlinux.lds.S, depends on different CPU arch,
for example:
arm64
[1]:
jiffies = jiffies_64
jiffies is initailzed to 0xfffb6c20 in linux kernel.
How to get jiffies in kernel ?
unsigned long long get_jiffies64(void) {
unsigned long seq;
unsigned long long ret;
do {
seq = read_seqbegin(&xtime_lock);
ret = jiffies_64;
} while (read_seqretry(&xtime_lock, seq));
return ret;
}
xtime
The xtime
stores the current time and date; it is a structure of type timespec having two fields:
- tv_sec
- stores the number of seconds that have elapsed since midnight of Jan 1.
- tv_nsec
- stores the number of nanoseconds that have elapsed within the last second
The xtime_lock seqlock avoids the race confitions that could occur due to concurrent accesses to the xtime variable.