Using Timers
Timers are represented by struct timer_list, which is defined in <linux/timer.h>:
struct timer_list {
struct list_head entry; /* entry in linked list of timers */
unsigned long expires; /* expiration value, in jiffies */
spinlock_t lock; /* lock protecting this timer */
void (*function)(unsigned long); /* the timer handler function */
unsigned long data; /* lone argument to the handler */
struct tvec_t_base_s *base; /* internal timer field, do not touch */
};
The kernel provides a family of timer-related interfaces to make timer management easy.
Everything is declared in <linux/timer.h>. Most of the actual implementation is in
kernel/timer.c.
The first step in creating a timer is defining it:
struct timer_list my_timer;
Next, the timer's internal values must be initialized. This is done via a helper function
and must be done prior to calling any timer management functions on the timer:
init_timer(&my_timer);
Now you fill out the remaining values as required:
my_timer.expires = jiffies + delay; /* timer expires in delay ticks */
my_timer.data = 0; /* zero is passed to the timer handler */
my_timer.function = my_function; /* function to run when timer expires */
The my_timer.expires value specifies the timeout value in absolute ticks. When the current
jiffies count is equal to or greater than my_timer.expires, the handler function
my_timer.function is run with the lone argument of my_timer.data. As you can see from the
timer_list definition, the function must match this prototype:
void my_timer_function(unsigned long data);
The data parameter enables you to register multiple timers with the same handler, and
differentiate between them via the argument. If you do not need the argument, you can
simply pass zero (or any other value).
Finally, you activate the timer:
add_timer(&my_timer);
Sometimes you might need to modify the expiration of an already active timer. The kernel
implements a function, mod_timer(), which changes the expiration of a given timer:
mod_timer(&my_timer, jiffies + new_delay); /* new expiration */
The mod_timer() function can operate on timers that are initialized but not active, too. If
the timer is inactive, mod_timer() activates it. The function returns zero if the timer was
inactive and one if the timer was active. In either case, upon return from mod_timer(), the
timer is activated and set to the new expiration.(这段话关键啊!!!!)
If you need to deactivate a timer prior to its expiration, use the del_timer() function:
del_timer(&my_timer);
The function works on both active and inactive timers. If the timer is already inactive,
the function returns zero; otherwise, the function returns one. Note that you do not need
to call this for timers that have expired because they are automatically deactivated.
A potential race condition that must be guarded against exists when deleting timers. When
del_timer() returns, it guarantees only that the timer is no longer active (that is, that
it will not be executed in the future). On a multiprocessing machine, however, the timer
handler might already be executing on another processor. To deactivate the timer and wait
until a potentially executing handler for the timer exits, use del_timer_sync():
del_timer_sync(&my_timer);
Unlike del_timer(), del_timer_sync() cannot be used from interrupt context(关键!注意).
Timer Race Conditions
Because timers run asynchronously with respect to the currently executing code, several
potential race conditions exist. First, never do the following as a substitute for a mere
mod_timer(), because this is unsafe on multiprocessing machines:
del_timer(my_timer)
my_timer->expires = jiffies + new_delay;
add_timer(my_timer);
//不要用上面的方法来代替(在调用mod_timer之前,需要调用del_timer,使timer是inactive吗?)
mod_timer();
Second, in almost all cases, you should use del_timer_sync() over del_timer(). (但它不能用
子中断上下文)Otherwise, you cannot assume the timer is not currently running, and that is
why you made the call in the first place! Imagine if, after deleting the timer, the code
went on to free or otherwise manipulate resources used by the timer handler. Therefore, the
synchronous version is preferred.
Finally, you must make sure to protect any shared data used in the timer handler function.
The kernel runs the function asynchronously with respect to other code. Data with a timer
should be protected 。