timer changes for v3.7
Linus,
Please pull the latest timers-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers-core-for-linus
HEAD: c5f66e99b7cb091e3d51ae8e8156892e8feb7fa3 timer: Implement TIMER_IRQSAFE
timer enhancements, generalizations and cleanups from Tejun Heo, in preparation for workqueue facility enhancements.
Thanks,
Ingo
------------------>
Tejun Heo (4):
timer: Generalize timer->base flags handling
timer: Relocate declarations of init_timer_on_stack_key()
timer: Clean up timer initializers
timer: Implement TIMER_IRQSAFE
include/linux/timer.h | 165 ++++++++++++++++++++------------------------------ kernel/timer.c | 108 +++++++++++++++------------------ 2 files changed, 114 insertions(+), 159 deletions(-)
include/linux/timer.h +65 -100
@@ -49,147 +49,112 @@ extern struct tvec_base boot_tvec_bases;#endif /* -* Note that all tvec_bases are 2 byte aligned and lower bit of -* base in timer_list is guaranteed to be zero. Use the LSB to -* indicate whether the timer is deferrable. +* Note that all tvec_bases are at least 4 byte aligned and lower two bits +* of base in timer_list is guaranteed to be zero. Use them for flags. * * A deferrable timer will work normally when the system is busy, but * will not cause a CPU to come out of idle just to service it; instead, * the timer will be serviced when the CPU eventually wakes up with a * subsequent non-deferrable timer. +* +* An irqsafe timer is executed with IRQ disabled and it's safe to wait for +* the completion of the running instance from IRQ handlers, for example, +* by calling del_timer_sync(). +* +* Note: The irq disabled callback execution is a special case for +* workqueue locking issues. It's not meant for executing random crap +* with interrupts disabled. Abuse is monitored! */ -#define TBASE_DEFERRABLE_FLAG (0x1) +#define TIMER_DEFERRABLE 0x1LU +#define TIMER_IRQSAFE 0x2LU -#define TIMER_INITIALIZER (_function, _expires, _data) { \ +#define TIMER_FLAG_MASK 0x3LU + +#define __TIMER_INITIALIZER (_function, _expires, _data, _flags) { \ .entry = { .prev = TIMER_ENTRY_STATIC }, \ .function = (_function), \ .expires = (_expires), \ .data = (_data), \ - .base = &boot_tvec_bases, \ + .base = (void *)((unsigned long)&boot_tvec_bases + (_flags)), \ .slack = -1, \ __TIMER_LOCKDEP_MAP_INITIALIZER( \ __FILE__ ":" __stringify(__LINE__)) \ } -#define TBASE_MAKE_DEFERRED (ptr) ((struct tvec_base *) \ - ((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG)) +#define TIMER_INITIALIZER (_function, _expires, _data) \ + __TIMER_INITIALIZER((_function), (_expires), (_data), 0) -#define TIMER_DEFERRED_INITIALIZER (_function, _expires, _data) {\ - .entry = { .prev = TIMER_ENTRY_STATIC }, \ - .function = (_function), \ - .expires = (_expires), \ - .data = (_data), \ - .base = TBASE_MAKE_DEFERRED(&boot_tvec_bases), \ - __TIMER_LOCKDEP_MAP_INITIALIZER( \ - __FILE__ ":" __stringify(__LINE__)) \ - } +#define TIMER_DEFERRED_INITIALIZER (_function, _expires, _data) \ + __TIMER_INITIALIZER((_function), (_expires), (_data), TIMER_DEFERRABLE)#define DEFINE_TIMER (_name, _function, _expires, _data) \ struct timer_list _name = \ TIMER_INITIALIZER(_function, _expires, _data) -void init_timer_key (struct timer_list *timer, -const char *name, -struct lock_class_key *key); -void init_timer_deferrable_key (struct timer_list *timer, -const char *name, -struct lock_class_key *key); +void init_timer_key (struct timer_list *timer,unsigned int flags, +const char *name,struct lock_class_key *key); + +#ifdef CONFIG_DEBUG_OBJECTS_TIMERS +extern void init_timer_on_stack_key (struct timer_list *timer, +unsigned int flags,const char *name, +struct lock_class_key *key); +extern void destroy_timer_on_stack (struct timer_list *timer); +#else +static inline void destroy_timer_on_stack (struct timer_list *timer) { } +static inline void init_timer_on_stack_key (struct timer_list *timer, +unsigned int flags,const char *name, +struct lock_class_key *key) +{ +init_timer_key (timer, flags, name, key); +} +#endif #ifdef CONFIG_LOCKDEP -#define init_timer (timer) \ +#define __init_timer (_timer, _flags) \ do { \ static struct lock_class_key __key; \ - init_timer_key((timer), #timer, &__key); \ + init_timer_key((_timer), (_flags), #_timer, &__key); \ } while (0) -#define init_timer_deferrable (timer) \ +#define __init_timer_on_stack (_timer, _flags) \ do { \ static struct lock_class_key __key; \ - init_timer_deferrable_key((timer), #timer, &__key); \ + init_timer_on_stack_key((_timer), (_flags), #_timer, &__key); \ } while (0) +#else +#define __init_timer (_timer, _flags) \ + init_timer_key((_timer), (_flags), NULL, NULL) +#define __init_timer_on_stack (_timer, _flags) \ + init_timer_on_stack_key((_timer), (_flags), NULL, NULL) +#endif +#define init_timer (timer) \ + __init_timer((timer), 0) +#define init_timer_deferrable (timer) \ + __init_timer((timer), TIMER_DEFERRABLE)#define init_timer_on_stack (timer) \ + __init_timer_on_stack((timer), 0) + +#define __setup_timer (_timer, _fn, _data, _flags) \ do { \ - static struct lock_class_key __key; \ - init_timer_on_stack_key((timer), #timer, &__key); \ + __init_timer((_timer), (_flags)); \ + (_timer)->function = (_fn); \ + (_timer)->data = (_data); \ } while (0) -#define setup_timer (timer, fn, data) \ +#define __setup_timer_on_stack (_timer, _fn, _data, _flags) \ do { \ - static struct lock_class_key __key; \ - setup_timer_key((timer), #timer, &__key, (fn), (data));\ + __init_timer_on_stack((_timer), (_flags)); \ + (_timer)->function = (_fn); \ + (_timer)->data = (_data); \ } while (0) +#define setup_timer (timer, fn, data) \ + __setup_timer((timer), (fn), (data), 0)#define setup_timer_on_stack (timer, fn, data) \ - do { \ - static struct lock_class_key __key; \ - setup_timer_on_stack_key((timer), #timer, &__key, \ - (fn), (data)); \ - } while (0) + __setup_timer_on_stack((timer), (fn), (data), 0)#define setup_deferrable_timer_on_stack (timer, fn, data) \ - do { \ - static struct lock_class_key __key; \ - setup_deferrable_timer_on_stack_key((timer), #timer, \ - &__key, (fn), \ - (data)); \ - } while (0) -#else -#define init_timer (timer)\ - init_timer_key((timer), NULL, NULL) -#define init_timer_deferrable (timer)\ - init_timer_deferrable_key((timer), NULL, NULL) -#define init_timer_on_stack (timer)\ - init_timer_on_stack_key((timer), NULL, NULL) -#define setup_timer (timer, fn, data)\ - setup_timer_key((timer), NULL, NULL, (fn), (data)) -#define setup_timer_on_stack (timer, fn, data)\ - setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) -#define setup_deferrable_timer_on_stack (timer, fn, data)\ - setup_deferrable_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) -#endif - -#ifdef CONFIG_DEBUG_OBJECTS_TIMERS -extern void init_timer_on_stack_key (struct timer_list *timer, -const char *name, -struct lock_class_key *key); -extern void destroy_timer_on_stack (struct timer_list *timer); -#else -static inline void destroy_timer_on_stack (struct timer_list *timer) { } -static inline void init_timer_on_stack_key (struct timer_list *timer, -const char *name, -struct lock_class_key *key) -{ -init_timer_key (timer, name, key); -} -#endif - -static inline void setup_timer_key (struct timer_list * timer, -const char *name, -struct lock_class_key *key, -void (*function)(unsigned long ), -unsigned long data) -{ - timer->function = function; - timer->data = data; -init_timer_key (timer, name, key); -} - -static inline void setup_timer_on_stack_key (struct timer_list *timer, -const char *name, -struct lock_class_key *key, -void (*function)(unsigned long ), -unsigned long data) -{ - timer->function = function; - timer->data = data; -init_timer_on_stack_key (timer, name, key); -} - -extern void setup_deferrable_timer_on_stack_key (struct timer_list *timer, -const char *name, -struct lock_class_key *key, -void (*function)(unsigned long ), -unsigned long data); + __setup_timer_on_stack((timer), (fn), (data), TIMER_DEFERRABLE)/** * timer_pending - is a timer pending?
kernel/timer.c +49 -59
210 lines not on this page · raw message