diff options
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index 9b77fc9a9ac8..cffffad01c31 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -491,14 +491,18 @@ static inline void debug_timer_free(struct timer_list *timer) | |||
491 | debug_object_free(timer, &timer_debug_descr); | 491 | debug_object_free(timer, &timer_debug_descr); |
492 | } | 492 | } |
493 | 493 | ||
494 | static void __init_timer(struct timer_list *timer); | 494 | static void __init_timer(struct timer_list *timer, |
495 | const char *name, | ||
496 | struct lock_class_key *key); | ||
495 | 497 | ||
496 | void init_timer_on_stack(struct timer_list *timer) | 498 | void init_timer_on_stack_key(struct timer_list *timer, |
499 | const char *name, | ||
500 | struct lock_class_key *key) | ||
497 | { | 501 | { |
498 | debug_object_init_on_stack(timer, &timer_debug_descr); | 502 | debug_object_init_on_stack(timer, &timer_debug_descr); |
499 | __init_timer(timer); | 503 | __init_timer(timer, name, key); |
500 | } | 504 | } |
501 | EXPORT_SYMBOL_GPL(init_timer_on_stack); | 505 | EXPORT_SYMBOL_GPL(init_timer_on_stack_key); |
502 | 506 | ||
503 | void destroy_timer_on_stack(struct timer_list *timer) | 507 | void destroy_timer_on_stack(struct timer_list *timer) |
504 | { | 508 | { |
@@ -512,7 +516,9 @@ static inline void debug_timer_activate(struct timer_list *timer) { } | |||
512 | static inline void debug_timer_deactivate(struct timer_list *timer) { } | 516 | static inline void debug_timer_deactivate(struct timer_list *timer) { } |
513 | #endif | 517 | #endif |
514 | 518 | ||
515 | static void __init_timer(struct timer_list *timer) | 519 | static void __init_timer(struct timer_list *timer, |
520 | const char *name, | ||
521 | struct lock_class_key *key) | ||
516 | { | 522 | { |
517 | timer->entry.next = NULL; | 523 | timer->entry.next = NULL; |
518 | timer->base = __raw_get_cpu_var(tvec_bases); | 524 | timer->base = __raw_get_cpu_var(tvec_bases); |
@@ -521,28 +527,36 @@ static void __init_timer(struct timer_list *timer) | |||
521 | timer->start_pid = -1; | 527 | timer->start_pid = -1; |
522 | memset(timer->start_comm, 0, TASK_COMM_LEN); | 528 | memset(timer->start_comm, 0, TASK_COMM_LEN); |
523 | #endif | 529 | #endif |
530 | lockdep_init_map(&timer->lockdep_map, name, key, 0); | ||
524 | } | 531 | } |
525 | 532 | ||
526 | /** | 533 | /** |
527 | * init_timer - initialize a timer. | 534 | * init_timer_key - initialize a timer |
528 | * @timer: the timer to be initialized | 535 | * @timer: the timer to be initialized |
536 | * @name: name of the timer | ||
537 | * @key: lockdep class key of the fake lock used for tracking timer | ||
538 | * sync lock dependencies | ||
529 | * | 539 | * |
530 | * init_timer() must be done to a timer prior calling *any* of the | 540 | * init_timer_key() must be done to a timer prior calling *any* of the |
531 | * other timer functions. | 541 | * other timer functions. |
532 | */ | 542 | */ |
533 | void init_timer(struct timer_list *timer) | 543 | void init_timer_key(struct timer_list *timer, |
544 | const char *name, | ||
545 | struct lock_class_key *key) | ||
534 | { | 546 | { |
535 | debug_timer_init(timer); | 547 | debug_timer_init(timer); |
536 | __init_timer(timer); | 548 | __init_timer(timer, name, key); |
537 | } | 549 | } |
538 | EXPORT_SYMBOL(init_timer); | 550 | EXPORT_SYMBOL(init_timer_key); |
539 | 551 | ||
540 | void init_timer_deferrable(struct timer_list *timer) | 552 | void init_timer_deferrable_key(struct timer_list *timer, |
553 | const char *name, | ||
554 | struct lock_class_key *key) | ||
541 | { | 555 | { |
542 | init_timer(timer); | 556 | init_timer_key(timer, name, key); |
543 | timer_set_deferrable(timer); | 557 | timer_set_deferrable(timer); |
544 | } | 558 | } |
545 | EXPORT_SYMBOL(init_timer_deferrable); | 559 | EXPORT_SYMBOL(init_timer_deferrable_key); |
546 | 560 | ||
547 | static inline void detach_timer(struct timer_list *timer, | 561 | static inline void detach_timer(struct timer_list *timer, |
548 | int clear_pending) | 562 | int clear_pending) |
@@ -826,6 +840,15 @@ EXPORT_SYMBOL(try_to_del_timer_sync); | |||
826 | */ | 840 | */ |
827 | int del_timer_sync(struct timer_list *timer) | 841 | int del_timer_sync(struct timer_list *timer) |
828 | { | 842 | { |
843 | #ifdef CONFIG_LOCKDEP | ||
844 | unsigned long flags; | ||
845 | |||
846 | local_irq_save(flags); | ||
847 | lock_map_acquire(&timer->lockdep_map); | ||
848 | lock_map_release(&timer->lockdep_map); | ||
849 | local_irq_restore(flags); | ||
850 | #endif | ||
851 | |||
829 | for (;;) { | 852 | for (;;) { |
830 | int ret = try_to_del_timer_sync(timer); | 853 | int ret = try_to_del_timer_sync(timer); |
831 | if (ret >= 0) | 854 | if (ret >= 0) |
@@ -897,10 +920,36 @@ static inline void __run_timers(struct tvec_base *base) | |||
897 | 920 | ||
898 | set_running_timer(base, timer); | 921 | set_running_timer(base, timer); |
899 | detach_timer(timer, 1); | 922 | detach_timer(timer, 1); |
923 | |||
900 | spin_unlock_irq(&base->lock); | 924 | spin_unlock_irq(&base->lock); |
901 | { | 925 | { |
902 | int preempt_count = preempt_count(); | 926 | int preempt_count = preempt_count(); |
927 | |||
928 | #ifdef CONFIG_LOCKDEP | ||
929 | /* | ||
930 | * It is permissible to free the timer from | ||
931 | * inside the function that is called from | ||
932 | * it, this we need to take into account for | ||
933 | * lockdep too. To avoid bogus "held lock | ||
934 | * freed" warnings as well as problems when | ||
935 | * looking into timer->lockdep_map, make a | ||
936 | * copy and use that here. | ||
937 | */ | ||
938 | struct lockdep_map lockdep_map = | ||
939 | timer->lockdep_map; | ||
940 | #endif | ||
941 | /* | ||
942 | * Couple the lock chain with the lock chain at | ||
943 | * del_timer_sync() by acquiring the lock_map | ||
944 | * around the fn() call here and in | ||
945 | * del_timer_sync(). | ||
946 | */ | ||
947 | lock_map_acquire(&lockdep_map); | ||
948 | |||
903 | fn(data); | 949 | fn(data); |
950 | |||
951 | lock_map_release(&lockdep_map); | ||
952 | |||
904 | if (preempt_count != preempt_count()) { | 953 | if (preempt_count != preempt_count()) { |
905 | printk(KERN_ERR "huh, entered %p " | 954 | printk(KERN_ERR "huh, entered %p " |
906 | "with preempt_count %08x, exited" | 955 | "with preempt_count %08x, exited" |