Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

workqueue: Update lock debugging code

These changes are in preparation of BH workqueue which will execute work
items from BH context.

- Update lock and RCU depth checks in process_one_work() so that it
remembers and checks against the starting depths and prints out the depth
changes.

- Factor out lockdep annotations in the flush paths into
touch_{wq|work}_lockdep_map(). The work->lockdep_map touching is moved
from __flush_work() to its callee - start_flush_work(). This brings it
closer to the wq counterpart and will allow testing the associated wq's
flags which will be needed to support BH workqueues. This is not expected
to cause any functional changes.

Signed-off-by: Tejun Heo <tj@kernel.org>
Tested-by: Allen Pais <allen.lkml@gmail.com>

+34 -17
+34 -17
kernel/workqueue.c
··· 2965 2965 struct pool_workqueue *pwq = get_work_pwq(work); 2966 2966 struct worker_pool *pool = worker->pool; 2967 2967 unsigned long work_data; 2968 + int lockdep_start_depth, rcu_start_depth; 2968 2969 #ifdef CONFIG_LOCKDEP 2969 2970 /* 2970 2971 * It is permissible to free the struct work_struct from ··· 3028 3027 pwq->stats[PWQ_STAT_STARTED]++; 3029 3028 raw_spin_unlock_irq(&pool->lock); 3030 3029 3030 + rcu_start_depth = rcu_preempt_depth(); 3031 + lockdep_start_depth = lockdep_depth(current); 3031 3032 lock_map_acquire(&pwq->wq->lockdep_map); 3032 3033 lock_map_acquire(&lockdep_map); 3033 3034 /* ··· 3065 3062 lock_map_release(&lockdep_map); 3066 3063 lock_map_release(&pwq->wq->lockdep_map); 3067 3064 3068 - if (unlikely(in_atomic() || lockdep_depth(current) > 0 || 3069 - rcu_preempt_depth() > 0)) { 3070 - pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d/%d\n" 3071 - " last function: %ps\n", 3072 - current->comm, preempt_count(), rcu_preempt_depth(), 3073 - task_pid_nr(current), worker->current_func); 3065 + if (unlikely((worker->task && in_atomic()) || 3066 + lockdep_depth(current) != lockdep_start_depth || 3067 + rcu_preempt_depth() != rcu_start_depth)) { 3068 + pr_err("BUG: workqueue leaked atomic, lock or RCU: %s[%d]\n" 3069 + " preempt=0x%08x lock=%d->%d RCU=%d->%d workfn=%ps\n", 3070 + current->comm, task_pid_nr(current), preempt_count(), 3071 + lockdep_start_depth, lockdep_depth(current), 3072 + rcu_start_depth, rcu_preempt_depth(), 3073 + worker->current_func); 3074 3074 debug_show_held_locks(current); 3075 3075 dump_stack(); 3076 3076 } ··· 3555 3549 return wait; 3556 3550 } 3557 3551 3552 + static void touch_wq_lockdep_map(struct workqueue_struct *wq) 3553 + { 3554 + lock_map_acquire(&wq->lockdep_map); 3555 + lock_map_release(&wq->lockdep_map); 3556 + } 3557 + 3558 + static void touch_work_lockdep_map(struct work_struct *work, 3559 + struct workqueue_struct *wq) 3560 + { 3561 + lock_map_acquire(&work->lockdep_map); 3562 + lock_map_release(&work->lockdep_map); 3563 + } 3564 + 3558 3565 /** 3559 3566 * __flush_workqueue - ensure that any scheduled work has run to completion. 3560 3567 * @wq: workqueue to flush ··· 3587 3568 if (WARN_ON(!wq_online)) 3588 3569 return; 3589 3570 3590 - lock_map_acquire(&wq->lockdep_map); 3591 - lock_map_release(&wq->lockdep_map); 3571 + touch_wq_lockdep_map(wq); 3592 3572 3593 3573 mutex_lock(&wq->mutex); 3594 3574 ··· 3786 3768 struct worker *worker = NULL; 3787 3769 struct worker_pool *pool; 3788 3770 struct pool_workqueue *pwq; 3771 + struct workqueue_struct *wq; 3789 3772 3790 3773 might_sleep(); 3791 3774 ··· 3810 3791 pwq = worker->current_pwq; 3811 3792 } 3812 3793 3813 - check_flush_dependency(pwq->wq, work); 3794 + wq = pwq->wq; 3795 + check_flush_dependency(wq, work); 3814 3796 3815 3797 insert_wq_barrier(pwq, barr, work, worker); 3816 3798 raw_spin_unlock_irq(&pool->lock); 3799 + 3800 + touch_work_lockdep_map(work, wq); 3817 3801 3818 3802 /* 3819 3803 * Force a lock recursion deadlock when using flush_work() inside a ··· 3827 3805 * workqueues the deadlock happens when the rescuer stalls, blocking 3828 3806 * forward progress. 3829 3807 */ 3830 - if (!from_cancel && 3831 - (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)) { 3832 - lock_map_acquire(&pwq->wq->lockdep_map); 3833 - lock_map_release(&pwq->wq->lockdep_map); 3834 - } 3808 + if (!from_cancel && (wq->saved_max_active == 1 || wq->rescuer)) 3809 + touch_wq_lockdep_map(wq); 3810 + 3835 3811 rcu_read_unlock(); 3836 3812 return true; 3837 3813 already_gone: ··· 3847 3827 3848 3828 if (WARN_ON(!work->func)) 3849 3829 return false; 3850 - 3851 - lock_map_acquire(&work->lockdep_map); 3852 - lock_map_release(&work->lockdep_map); 3853 3830 3854 3831 if (start_flush_work(work, &barr, from_cancel)) { 3855 3832 wait_for_completion(&barr.done);