diff options
| author | Andrew Morton <akpm@osdl.org> | 2003-08-14 10:07:00 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-08-14 10:07:00 -0700 |
| commit | c49d806049638d278c3d0cdc8d30d770fca183ce (patch) | |
| tree | 87770f90fc0cdcf227bf4f98448f017292fdfd01 /include/linux/timer.h | |
| parent | 752274c9ef15215e1c9e7855450203326fdc3644 (diff) | |
[PATCH] timer race fixes
From: Ingo Molnar <mingo@elte.hu>
It unifies the functionality of add_timer() and mod_timer(), and makes any
combination of the timer API calls completely SMP-safe. del_timer() is still
not using the timer lock.
this patch fixes the only timer bug in 2.6 i'm aware of: the del_timer_sync()
+ add_timer() combination in kernel/itimer.c is buggy. This was correct code
in 2.4, because there it was safe to do an add_timer() from the timer handler
itself, parallel to a del_timer_sync().
If we want to make this safe in 2.6 too (which i think we want to) then we
have to make add_timer() almost equivalent to mod_timer(), locking-wise. And
once we are at this point i think it's much cleaner to actually make
add_timer() a variant of mod_timer(). (There's no locking cost for
add_timer(), only the cost of an extra branch. And we've removed another
commonly used function from the icache.)
Diffstat (limited to 'include/linux/timer.h')
| -rw-r--r-- | include/linux/timer.h | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/include/linux/timer.h b/include/linux/timer.h index d98c9a948aa7..e8f79ea49c74 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -60,11 +60,30 @@ static inline int timer_pending(const struct timer_list * timer) return timer->base != NULL; } -extern void add_timer(struct timer_list * timer); extern void add_timer_on(struct timer_list *timer, int cpu); extern int del_timer(struct timer_list * timer); +extern int __mod_timer(struct timer_list *timer, unsigned long expires); extern int mod_timer(struct timer_list *timer, unsigned long expires); - + +/*** + * add_timer - start a timer + * @timer: the timer to be added + * + * The kernel will do a ->function(->data) callback from the + * timer interrupt at the ->expired point in the future. The + * current time is 'jiffies'. + * + * The timer's ->expired, ->function (and if the handler uses it, ->data) + * fields must be set prior calling this function. + * + * Timers with an ->expired field in the past will be executed in the next + * timer tick. + */ +static inline void add_timer(struct timer_list * timer) +{ + __mod_timer(timer, timer->expires); +} + #ifdef CONFIG_SMP extern int del_timer_sync(struct timer_list * timer); #else |
