aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-08-23 07:23:30 -0400
committerIngo Molnar <mingo@kernel.org>2017-08-25 05:06:33 -0400
commite6f3faa734a00c606b7b06c6b9f15e5627d3245b (patch)
tree4c3f0047d1fa1796442512e03147c40c026f25a8
parenta1d14934ea4b9db816a8dbfeab1c3e7204a0d871 (diff)
locking/lockdep: Fix workqueue crossrelease annotation
The new completion/crossrelease annotations interact unfavourable with the extant flush_work()/flush_workqueue() annotations. The problem is that when a single work class does: wait_for_completion(&C) and complete(&C) in different executions, we'll build dependencies like: lock_map_acquire(W) complete_acquire(C) and lock_map_acquire(W) complete_release(C) which results in the dependency chain: W->C->W, which lockdep thinks spells deadlock, even though there is no deadlock potential since works are ran concurrently. One possibility would be to change the work 'lock' to recursive-read, but that would mean hitting a lockdep limitation on recursive locks. Also, unconditinoally switching to recursive-read here would fail to detect the actual deadlock on single-threaded workqueues, which do have a problem with this. For now, forcefully disregard these locks for crossrelease. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Tejun Heo <tj@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: boqun.feng@gmail.com Cc: byungchul.park@lge.com Cc: david@fromorbit.com Cc: johannes@sipsolutions.net Cc: oleg@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--include/linux/irqflags.h4
-rw-r--r--include/linux/lockdep.h10
-rw-r--r--kernel/locking/lockdep.c56
-rw-r--r--kernel/workqueue.c23
4 files changed, 66 insertions, 27 deletions
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 5fdd93bb9300..9bc050bc81b2 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -26,7 +26,7 @@
26# define trace_hardirq_enter() \ 26# define trace_hardirq_enter() \
27do { \ 27do { \
28 current->hardirq_context++; \ 28 current->hardirq_context++; \
29 crossrelease_hist_start(XHLOCK_HARD); \ 29 crossrelease_hist_start(XHLOCK_HARD, 0);\
30} while (0) 30} while (0)
31# define trace_hardirq_exit() \ 31# define trace_hardirq_exit() \
32do { \ 32do { \
@@ -36,7 +36,7 @@ do { \
36# define lockdep_softirq_enter() \ 36# define lockdep_softirq_enter() \
37do { \ 37do { \
38 current->softirq_context++; \ 38 current->softirq_context++; \
39 crossrelease_hist_start(XHLOCK_SOFT); \ 39 crossrelease_hist_start(XHLOCK_SOFT, 0);\
40} while (0) 40} while (0)
41# define lockdep_softirq_exit() \ 41# define lockdep_softirq_exit() \
42do { \ 42do { \
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index fc827cab6d6e..78bb7133abed 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -18,6 +18,8 @@ extern int lock_stat;
18 18
19#define MAX_LOCKDEP_SUBCLASSES 8UL 19#define MAX_LOCKDEP_SUBCLASSES 8UL
20 20
21#include <linux/types.h>
22
21#ifdef CONFIG_LOCKDEP 23#ifdef CONFIG_LOCKDEP
22 24
23#include <linux/linkage.h> 25#include <linux/linkage.h>
@@ -578,11 +580,11 @@ extern void lock_commit_crosslock(struct lockdep_map *lock);
578#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \ 580#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
579 { .name = (_name), .key = (void *)(_key), .cross = 0, } 581 { .name = (_name), .key = (void *)(_key), .cross = 0, }
580 582
581extern void crossrelease_hist_start(enum xhlock_context_t c); 583extern void crossrelease_hist_start(enum xhlock_context_t c, bool force);
582extern void crossrelease_hist_end(enum xhlock_context_t c); 584extern void crossrelease_hist_end(enum xhlock_context_t c);
583extern void lockdep_init_task(struct task_struct *task); 585extern void lockdep_init_task(struct task_struct *task);
584extern void lockdep_free_task(struct task_struct *task); 586extern void lockdep_free_task(struct task_struct *task);
585#else 587#else /* !CROSSRELEASE */
586#define lockdep_init_map_crosslock(m, n, k, s) do {} while (0) 588#define lockdep_init_map_crosslock(m, n, k, s) do {} while (0)
587/* 589/*
588 * To initialize a lockdep_map statically use this macro. 590 * To initialize a lockdep_map statically use this macro.
@@ -591,11 +593,11 @@ extern void lockdep_free_task(struct task_struct *task);
591#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \ 593#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
592 { .name = (_name), .key = (void *)(_key), } 594 { .name = (_name), .key = (void *)(_key), }
593 595
594static inline void crossrelease_hist_start(enum xhlock_context_t c) {} 596static inline void crossrelease_hist_start(enum xhlock_context_t c, bool force) {}
595static inline void crossrelease_hist_end(enum xhlock_context_t c) {} 597static inline void crossrelease_hist_end(enum xhlock_context_t c) {}
596static inline void lockdep_init_task(struct task_struct *task) {} 598static inline void lockdep_init_task(struct task_struct *task) {}
597static inline void lockdep_free_task(struct task_struct *task) {} 599static inline void lockdep_free_task(struct task_struct *task) {}
598#endif 600#endif /* CROSSRELEASE */
599 601
600#ifdef CONFIG_LOCK_STAT 602#ifdef CONFIG_LOCK_STAT
601 603
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 66011c9f5df3..f73ca595b81e 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -4629,7 +4629,7 @@ asmlinkage __visible void lockdep_sys_exit(void)
4629 * the index to point to the last entry, which is already invalid. 4629 * the index to point to the last entry, which is already invalid.
4630 */ 4630 */
4631 crossrelease_hist_end(XHLOCK_PROC); 4631 crossrelease_hist_end(XHLOCK_PROC);
4632 crossrelease_hist_start(XHLOCK_PROC); 4632 crossrelease_hist_start(XHLOCK_PROC, false);
4633} 4633}
4634 4634
4635void lockdep_rcu_suspicious(const char *file, const int line, const char *s) 4635void lockdep_rcu_suspicious(const char *file, const int line, const char *s)
@@ -4725,25 +4725,25 @@ static inline void invalidate_xhlock(struct hist_lock *xhlock)
4725/* 4725/*
4726 * Lock history stacks; we have 3 nested lock history stacks: 4726 * Lock history stacks; we have 3 nested lock history stacks:
4727 * 4727 *
4728 * Hard IRQ 4728 * HARD(IRQ)
4729 * Soft IRQ 4729 * SOFT(IRQ)
4730 * History / Task 4730 * PROC(ess)
4731 * 4731 *
4732 * The thing is that once we complete a (Hard/Soft) IRQ the future task locks 4732 * The thing is that once we complete a HARD/SOFT IRQ the future task locks
4733 * should not depend on any of the locks observed while running the IRQ. 4733 * should not depend on any of the locks observed while running the IRQ. So
4734 * what we do is rewind the history buffer and erase all our knowledge of that
4735 * temporal event.
4734 * 4736 *
4735 * So what we do is rewind the history buffer and erase all our knowledge of 4737 * The PROCess one is special though; it is used to annotate independence
4736 * that temporal event. 4738 * inside a task.
4737 */ 4739 *
4738 4740 * Take for instance workqueues; each work is independent of the last. The
4739/* 4741 * completion of a future work does not depend on the completion of a past work
4740 * We need this to annotate lock history boundaries. Take for instance 4742 * (in general). Therefore we must not carry that (lock) dependency across
4741 * workqueues; each work is independent of the last. The completion of a future 4743 * works.
4742 * work does not depend on the completion of a past work (in general).
4743 * Therefore we must not carry that (lock) dependency across works.
4744 * 4744 *
4745 * This is true for many things; pretty much all kthreads fall into this 4745 * This is true for many things; pretty much all kthreads fall into this
4746 * pattern, where they have an 'idle' state and future completions do not 4746 * pattern, where they have an invariant state and future completions do not
4747 * depend on past completions. Its just that since they all have the 'same' 4747 * depend on past completions. Its just that since they all have the 'same'
4748 * form -- the kthread does the same over and over -- it doesn't typically 4748 * form -- the kthread does the same over and over -- it doesn't typically
4749 * matter. 4749 * matter.
@@ -4751,15 +4751,31 @@ static inline void invalidate_xhlock(struct hist_lock *xhlock)
4751 * The same is true for system-calls, once a system call is completed (we've 4751 * The same is true for system-calls, once a system call is completed (we've
4752 * returned to userspace) the next system call does not depend on the lock 4752 * returned to userspace) the next system call does not depend on the lock
4753 * history of the previous system call. 4753 * history of the previous system call.
4754 *
4755 * They key property for independence, this invariant state, is that it must be
4756 * a point where we hold no locks and have no history. Because if we were to
4757 * hold locks, the restore at _end() would not necessarily recover it's history
4758 * entry. Similarly, independence per-definition means it does not depend on
4759 * prior state.
4754 */ 4760 */
4755void crossrelease_hist_start(enum xhlock_context_t c) 4761void crossrelease_hist_start(enum xhlock_context_t c, bool force)
4756{ 4762{
4757 struct task_struct *cur = current; 4763 struct task_struct *cur = current;
4758 4764
4759 if (cur->xhlocks) { 4765 if (!cur->xhlocks)
4760 cur->xhlock_idx_hist[c] = cur->xhlock_idx; 4766 return;
4761 cur->hist_id_save[c] = cur->hist_id; 4767
4768 /*
4769 * We call this at an invariant point, no current state, no history.
4770 */
4771 if (c == XHLOCK_PROC) {
4772 /* verified the former, ensure the latter */
4773 WARN_ON_ONCE(!force && cur->lockdep_depth);
4774 invalidate_xhlock(&xhlock(cur->xhlock_idx));
4762 } 4775 }
4776
4777 cur->xhlock_idx_hist[c] = cur->xhlock_idx;
4778 cur->hist_id_save[c] = cur->hist_id;
4763} 4779}
4764 4780
4765void crossrelease_hist_end(enum xhlock_context_t c) 4781void crossrelease_hist_end(enum xhlock_context_t c)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 8ad214dc15a9..c0331891dec1 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2093,7 +2093,28 @@ __acquires(&pool->lock)
2093 2093
2094 lock_map_acquire(&pwq->wq->lockdep_map); 2094 lock_map_acquire(&pwq->wq->lockdep_map);
2095 lock_map_acquire(&lockdep_map); 2095 lock_map_acquire(&lockdep_map);
2096 crossrelease_hist_start(XHLOCK_PROC); 2096 /*
2097 * Strictly speaking we should do start(PROC) without holding any
2098 * locks, that is, before these two lock_map_acquire()'s.
2099 *
2100 * However, that would result in:
2101 *
2102 * A(W1)
2103 * WFC(C)
2104 * A(W1)
2105 * C(C)
2106 *
2107 * Which would create W1->C->W1 dependencies, even though there is no
2108 * actual deadlock possible. There are two solutions, using a
2109 * read-recursive acquire on the work(queue) 'locks', but this will then
2110 * hit the lockdep limitation on recursive locks, or simly discard
2111 * these locks.
2112 *
2113 * AFAICT there is no possible deadlock scenario between the
2114 * flush_work() and complete() primitives (except for single-threaded
2115 * workqueues), so hiding them isn't a problem.
2116 */
2117 crossrelease_hist_start(XHLOCK_PROC, true);
2097 trace_workqueue_execute_start(work); 2118 trace_workqueue_execute_start(work);
2098 worker->current_func(work); 2119 worker->current_func(work);
2099 /* 2120 /*