world leader in high performance signal processing
Trace: » timers

Kernel Timers

The kernel timer API is designed to execute a function at some point in the future. Fortunately, they are quite simple to use.

The timer structure is defined in the include file linux/timer.h. Here we highlight the important parts.

file: include/linux/timer.h

scm failed with exit code 1:
file does not exist in git

The resolution of a timer is restricted to the kernel timer tick frequency. The default frequency is 250 HZ, but this can be changed in your kernel settings.

Higher resolution timers are available as a kernel patch. These add a element to the structure called sub_expires to give greater resolution but they also need a dedicated high resolution timer.

The basic timer is simply designed to execute some time in the future.

Timer Setup

Once your kernel code includes the linux/timer.h file, a timer can be defined as follows (from drivers/char/vt.c):

#include <linux/timer.h>
 
static struct timer_list console_timer;

It is most important to initialize the timer structure or BAD THINGS™ will happen.

    // somewhere in the set up code
    init_timer(&console_timer);

Next set up a function to be called when the timer expires:

   console_timer.function = blank_screen_t;

Schedule a Timer

There are two functions that can be used to schedule the timer.

  • add_timer() - here you need to set up the expires time
  • mod_timer() - the expired time is an argument
	/* trigger the timer to expire some time in the future */
	mod_timer(&console_timer, jiffies + blankinterval);

All About Jiffies

A Jiffie is a kernel global variable that tells you how many system timer ticks have expired since the system was booted.

Its definition is hiding in the linker script arch/blackfin/kernel/vmlinux.lds.S.

	OUTPUT_FORMAT("elf32-bfin")
	ENTRY(_start)
	jiffies = jiffies_64;
	MEMORY
	....

You will find jiffies_64 in the file include/linux/jiffies.h.

Things are done like this to allow jiffies to be defined at link time as either a 64 bit or a 32 bit number. For this architecture they are a 64 bit number.

Since the element in the timer_list structure is an unsigned long you can imagine that there is some clever work going on behind the scenes to make this function.

Stopping Timers

So timers are quite easy to get started. How about stopping them. Well this may give us a problem. Especially when we are using more than one CPU.

CPU 0 may decide to delete a timer at exactly the same time as CPU 1 decides to execute the timer function.

For this reason special care is taken when deleting timers on SMP systems.

For most cases the following code will delete a timer.

del_timer will return a 1 if it detects a timer in progress.

	del_timer(&console_timer);

Repeating Timers

Sometimes a timer function reschedules the timer to repeat the function some time in the future.

These timers can be difficult to stop. The preferred way is to provide a condition for the mod timer function.

In the example below a variable still_going has to be true for the timer to keep rescheduling.

struct completion timer_done;
int still_going;
 
	/* add this somewhere else before using the completion thing */
	init_completion(&timer_done);
 
void timer_function(...)
{
	unsigned long next_time = 24;  
	if (still_going)
		mod_timer(&console_timer, jiffies + next_time);
	else
		complete(&timer_done);
}

In the above example one way to close down the timer could be:

	still_going = 0;
	mod_timer(&console_timer, jiffies + 1);
	wait_for_completion(&timer_done);

Example Module

You can find an example kernel module in our uClinux-dist. After you load it, you should see messages like this in your kernel log buffer:

root:/> insmod timer_test.ko
root:/> dmesg
...
timer_test: timer module init
timer_test: arming timer 1 to fire 5 seconds from now
timer_test: arming timer 2 to fire 10 seconds from now
timer_test: timer_test_func: here i am with my data '1234'!
timer_test: timer_test_func: here i am with my data '9876'!

file: user/blkfin-test/timer_test/timer_test.c

scm failed with exit code 1:
file does not exist in git