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.

Merge branch 'fixes-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq

* 'fixes-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
workqueue: note the nested NOT_RUNNING test in worker_clr_flags() isn't a noop
workqueue: relax lockdep annotation on flush_work()

+20 -3
+3
include/linux/lockdep.h
··· 514 514 #ifdef CONFIG_DEBUG_LOCK_ALLOC 515 515 # ifdef CONFIG_PROVE_LOCKING 516 516 # define lock_map_acquire(l) lock_acquire(l, 0, 0, 0, 2, NULL, _THIS_IP_) 517 + # define lock_map_acquire_read(l) lock_acquire(l, 0, 0, 2, 2, NULL, _THIS_IP_) 517 518 # else 518 519 # define lock_map_acquire(l) lock_acquire(l, 0, 0, 0, 1, NULL, _THIS_IP_) 520 + # define lock_map_acquire_read(l) lock_acquire(l, 0, 0, 2, 1, NULL, _THIS_IP_) 519 521 # endif 520 522 # define lock_map_release(l) lock_release(l, 1, _THIS_IP_) 521 523 #else 522 524 # define lock_map_acquire(l) do { } while (0) 525 + # define lock_map_acquire_read(l) do { } while (0) 523 526 # define lock_map_release(l) do { } while (0) 524 527 #endif 525 528
+17 -3
kernel/workqueue.c
··· 768 768 769 769 worker->flags &= ~flags; 770 770 771 - /* if transitioning out of NOT_RUNNING, increment nr_running */ 771 + /* 772 + * If transitioning out of NOT_RUNNING, increment nr_running. Note 773 + * that the nested NOT_RUNNING is not a noop. NOT_RUNNING is mask 774 + * of multiple flags, not a single flag. 775 + */ 772 776 if ((flags & WORKER_NOT_RUNNING) && (oflags & WORKER_NOT_RUNNING)) 773 777 if (!(worker->flags & WORKER_NOT_RUNNING)) 774 778 atomic_inc(get_gcwq_nr_running(gcwq->cpu)); ··· 1844 1840 spin_unlock_irq(&gcwq->lock); 1845 1841 1846 1842 work_clear_pending(work); 1847 - lock_map_acquire(&cwq->wq->lockdep_map); 1843 + lock_map_acquire_read(&cwq->wq->lockdep_map); 1848 1844 lock_map_acquire(&lockdep_map); 1849 1845 trace_workqueue_execute_start(work); 1850 1846 f(work); ··· 2388 2384 insert_wq_barrier(cwq, barr, work, worker); 2389 2385 spin_unlock_irq(&gcwq->lock); 2390 2386 2391 - lock_map_acquire(&cwq->wq->lockdep_map); 2387 + /* 2388 + * If @max_active is 1 or rescuer is in use, flushing another work 2389 + * item on the same workqueue may lead to deadlock. Make sure the 2390 + * flusher is not running on the same workqueue by verifying write 2391 + * access. 2392 + */ 2393 + if (cwq->wq->saved_max_active == 1 || cwq->wq->flags & WQ_RESCUER) 2394 + lock_map_acquire(&cwq->wq->lockdep_map); 2395 + else 2396 + lock_map_acquire_read(&cwq->wq->lockdep_map); 2392 2397 lock_map_release(&cwq->wq->lockdep_map); 2398 + 2393 2399 return true; 2394 2400 already_gone: 2395 2401 spin_unlock_irq(&gcwq->lock);