Timers in Linux



Introduction

This article talks about Timers provided by Linux Operating System. Timers are critical to both application level programs as well as device drivers and other lower level system programs. The Linux OS provides various mechanisms to provide timers. Here I discuss some of these mechanisms. The Kernel version referred in this article is 2.4.20. This article will help a developer analyze timer capabilities of Linux, however no implementation code has been included here.


RTC and System Clock

One of the major areas in timing which often confuse many people is difference between RTC (Real Time Clock) and System Clock. The RTC keeps track of time when the system is powered down by using a small battery on the motherboard (usually the CMOS battery in Desktop systems). On bootup, the RTC is read by the kernel to initialize a variable xtime (xtime is declared in 2.4 linux kernel in /include/linux/sched.h) The kernel uses this xtime to initialize then wall time (time_of_the_day). So User space applications which read the time of day get their value in fact from xtime variable. Usually, the kernel reads the RTC only on bootup, so changing the RTC is not reflected in user space method which call time_of_the_day().


Timer Interrupt

The Kernel usually keeps track of time intervals (usually for servicing various timers called by applications) using timer interrupt which is generated by system's timer hardware at predefined periods, which is set by a variable HZ. This variable is defined in Depending upon the value of HZ (which can be set during kernel building time), the basic minimum timer value (basic clock interrupt frequency) supported by the system can change (default is 10 millisecond).


jiffies

jiffies is an internal system variable maintained by kernel storing the number of clock ticks since power-on (start) of the system. It is defined in <linux/schedule.h>. However despite being defined as volatile and long, it could overflow due to a continuous uptime (around 1.5 years).


Architecture Specific Methods

Most of the platforms supports some architecture specific timer mechanisms which help developers to have very short timer intervals. One such option is a timer counter register which increments its value after every clock cycle. It maybe 32 bit or 64 bit depending upon the platform. The most renowed counter register is TSC (timestamp counter) which is now available on all major platforms and can be read rom both user space as well as kernel space. The following macros are used to read this register (#include <asm/msr.h>)

rtdsc(low,high); //Catches the 64 bit value into two 32 bit variables
rtdscl(low); //Catches the lower 32 bit value

Most of the other platforms (I am not sure if all of them offer) an Arch independent function as a replacement of rtdsc (#include <linux/timex.h>). cycles_t get_cycles(void); // catches only the lower 32 bit of the counter


Current Time

The value of jiffies can always give the module, the correct value of current time. jiffies are an excellent method to measure relativley long timer intervals; however one has to retreat to Arch specific methods to get relativley short timers. Usually system programs like device drivers or kernel modules usually requires system time and not wall time (the format of time what a user program like cron and at gives). Thus, there are many functions provided for knowing the current time.
One such method is gettimeofday(). It fills a timeval structure with current time in seconds and microsecond value. Another similar function is do_gettimeofday(). Its prototype is defined as (#include <linux/time.h>)

void do_gettimeofday(struct timeval *tv);

This function gives a near microsecond resolution value. Another option of getting current time in a fast and efficient way is kernel function get_fast_time ().

void get_fast_time (struct timeval *tv);

Further the most easy way to read the current time is using the value of variable xtime although its precision level is low. However access to all all its fields cannot be done in atomically unless interrrupts are disabled and this is strongly discouraged in case of Real Time Systems.



Kernel Timers

Timer is a mechanism of ensuring time critical functionality in any module. For cases where a task needs to check a buffer or any device needs to be polled after a particular period of time be it periodic or discrete, there has to be a mechanism to intimate the task at the end of the particular interval so that task is free to do its normal course of the work without bothering or waiting for the intimation to come. Timer process is used to satisfy such needs in any application.

The Kernel timers are organized in a doubly Link List with both forward and backward pointer in operation. The timer is characterized by its value after which it should expire; its tag for identification (name, process to which it belongs and other data) and the function called (handler) which is invoked when the timer expires. The data structure of a timer looks like this (#<linux/timer.h>)

struct timer_list
{
	struct timer_list *next; //pointer to next timer in list
	struct timer_list *prev; //pointer to previous timer in list
	unsigned long expires; // timeout values in jiffies
	unsigned long data; // argument to handler 
	void (*function) (unsigned long); // handler function
	volatile int running;	//flag denoting state of node
};

The timer handler will be called when timer->expires>=jiffies. Once the timer_list structure is initialized, add_timer() inserts it into a sorted list which is polled periodically. Here are all Kernel Timer APIs given :

void init_timer (struct timer_list* timer);

This function initializes a newly allocated timer.

void add_timer (struct timer_list* timer);

This function inserts the newly allocated timer into the gloabal list of active timers.

void mod_timer (struct timer_list* timer, unsigned long expires);

This function is used to modify the value of an active timer.

int del_timer (struct timer_list* timer);

This function is to delete the specified timer from the list of active timers.



I am Nikhil Bhargava, curently working on 3G mobile communication protocol stacks at C-DOT, India for past year and a half year in capacity of Research Engineer. My research intrests include Real Time Operating Sytems and Mobile Networks. All comments, bug fixes, and suggestions will be highly appreciated.

Hosted by www.Geocities.ws

1