diff options
| author | Ingo Molnar <mingo@elte.hu> | 2002-10-02 23:33:06 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-10-02 23:33:06 -0700 |
| commit | afc141063a5b0f4e5a45e7e68060918daa69a859 (patch) | |
| tree | b93b5a9f5a15d8973090087c6abf1a1d129ac770 /include/linux | |
| parent | 794aa320b79d2cb8643ecb6058f0f3fadd51955d (diff) | |
[PATCH] timer-2.5.40-F7
This does a number of timer subsystem enhancements:
- simplified timer initialization, now it's the cheapest possible thing:
static inline void init_timer(struct timer_list * timer)
{
timer->base = NULL;
}
since the timer functions already did a !timer->base check this did not
have any effect on their fastpath.
- the rule from now on is that timer->base is set upon activation of the
timer, and cleared upon deactivation. This also made it possible to:
- reorganize all the timer handling code to not assume anything about
timer->entry.next and timer->entry.prev - this also removed lots of
unnecessery cleaning of these fields. Removed lots of unnecessary list
operations from the fastpath.
- simplified del_timer_sync(): it now uses del_timer() plus some simple
synchronization code. Note that this also fixes a bug: if mod_timer (or
add_timer) moves a currently executing timer to another CPU's timer
vector, then del_timer_sync() does not synchronize with the handler
properly.
- bugfix: moved run_local_timers() from scheduler_tick() into
update_process_times() .. scheduler_tick() might be called from the fork
code which will not quite have the intended effect ...
- removed the APIC-timer-IRQ shifting done on SMP, Dipankar Sarma's
testing shows no negative effects.
- cleaned up include/linux/timer.h:
- removed the timer_t typedef, and fixes up kernel/workqueue.c to use
the 'struct timer_list' name instead.
- removed unnecessery includes
- renamed the 'list' field to 'entry' (it's an entry not a list head)
- exchanged the 'function' and 'data' fields. This, besides being
more logical, also unearthed the last few remaining places that
initialized timers by assuming some given field ordering, the patch
also fixes these places. (fs/xfs/pagebuf/page_buf.c,
net/core/profile.c and net/ipv4/inetpeer.c)
- removed the defunct sync_timers(), timer_enter() and timer_exit()
prototypes.
- added docbook-style comments.
- other kernel/timer.c changes:
- base->running_timer does not have to be volatile ...
- added consistent comments to all the important functions.
- made the sync-waiting in del_timer_sync preempt- and lowpower-
friendly.
i've compiled, booted & tested the patched kernel on x86 UP and SMP. I
have tried moderately high networking load as well, to make sure the timer
changes are correct - they appear to be.
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/timer.h | 89 | ||||
| -rw-r--r-- | include/linux/workqueue.h | 2 |
2 files changed, 40 insertions, 51 deletions
diff --git a/include/linux/timer.h b/include/linux/timer.h index f890f4f3d668..cfedb5e8bb07 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -2,70 +2,59 @@ #define _LINUX_TIMER_H #include <linux/config.h> -#include <linux/smp.h> -#include <linux/stddef.h> #include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/cache.h> struct tvec_t_base_s; -/* - * Timers may be dynamically created and destroyed, and should be initialized - * by a call to init_timer() upon creation. - * - * The "data" field enables use of a common timeout function for several - * timeouts. You can use this field to distinguish between the different - * invocations. - */ -typedef struct timer_list { - struct list_head list; +struct timer_list { + struct list_head entry; unsigned long expires; - unsigned long data; + void (*function)(unsigned long); + unsigned long data; + struct tvec_t_base_s *base; -} timer_t; +}; -extern void add_timer(timer_t * timer); -extern int del_timer(timer_t * timer); - -#ifdef CONFIG_SMP -extern int del_timer_sync(timer_t * timer); -extern void sync_timers(void); -#define timer_enter(base, t) do { base->running_timer = t; mb(); } while (0) -#define timer_exit(base) do { base->running_timer = NULL; } while (0) -#define timer_is_running(base,t) (base->running_timer == t) -#define timer_synchronize(base,t) while (timer_is_running(base,t)) barrier() -#else -#define del_timer_sync(t) del_timer(t) -#define sync_timers() do { } while (0) -#define timer_enter(base,t) do { } while (0) -#define timer_exit(base) do { } while (0) -#endif - -/* - * mod_timer is a more efficient way to update the expire field of an - * active timer (if the timer is inactive it will be activated) - * mod_timer(a,b) is equivalent to del_timer(a); a->expires = b; add_timer(a). - * If the timer is known to be not pending (ie, in the handler), mod_timer - * is less efficient than a->expires = b; add_timer(a). +/*** + * init_timer - initialize a timer. + * @timer: the timer to be initialized + * + * init_timer() must be done to a timer prior calling *any* of the + * other timer functions. */ -int mod_timer(timer_t *timer, unsigned long expires); - -extern void it_real_fn(unsigned long); - -extern void init_timers(void); -extern void run_local_timers(void); - -static inline void init_timer(timer_t * timer) +static inline void init_timer(struct timer_list * timer) { - timer->list.next = timer->list.prev = NULL; timer->base = NULL; } -static inline int timer_pending(const timer_t * timer) +/*** + * timer_pending - is a timer pending? + * @timer: the timer in question + * + * timer_pending will tell whether a given timer is currently pending, + * or not. Callers must ensure serialization wrt. other operations done + * to this timer, eg. interrupt contexts, or other CPUs on SMP. + * + * return value: 1 if the timer is pending, 0 if not. + */ +static inline int timer_pending(const struct timer_list * timer) { - return timer->list.next != NULL; + return timer->base != NULL; } +extern void add_timer(struct timer_list * timer); +extern int del_timer(struct timer_list * timer); +extern int mod_timer(struct timer_list *timer, unsigned long expires); + +#if CONFIG_SMP + extern int del_timer_sync(struct timer_list * timer); +#else +# define del_timer_sync(t) del_timer(t) +#endif + +extern void init_timers(void); +extern void run_local_timers(void); +extern void it_real_fn(unsigned long); + #endif diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 7828c7bef55f..3e466894179f 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -15,7 +15,7 @@ struct work_struct { void (*func)(void *); void *data; void *wq_data; - timer_t timer; + struct timer_list timer; }; #define __WORK_INITIALIZER(n, f, d) { \ |
