Messages in this thread Patch in this message | | | Date | Mon, 3 Oct 2022 21:44:52 +0000 | Subject | [RFC PATCH 02/11] locking/mutex: Rework task_struct::blocked_on | From | "Connor O'Brien" <> |
| |
From: Peter Zijlstra <peterz@infradead.org>
Track the blocked-on relation for mutexes, this allows following this relation at schedule time.
task | blocked-on v mutex | owner v task
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> [minor changes while rebasing] Signed-off-by: Juri Lelli <juri.lelli@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Connor O'Brien <connoro@google.com> Link: https://lkml.kernel.org/r/20181009092434.26221-4-juri.lelli@redhat.com --- include/linux/sched.h | 6 ++---- kernel/fork.c | 4 ++-- kernel/locking/mutex-debug.c | 9 +++++---- kernel/locking/mutex.c | 6 ++++++ 4 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h index e7b2f8a5c711..bd995e66d7d6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1130,10 +1130,8 @@ struct task_struct { struct rt_mutex_waiter *pi_blocked_on; #endif -#ifdef CONFIG_DEBUG_MUTEXES - /* Mutex deadlock detection: */ - struct mutex_waiter *blocked_on; -#endif + struct task_struct *blocked_proxy; /* task that is boosting us */ + struct mutex *blocked_on; /* lock we're blocked on */ #ifdef CONFIG_DEBUG_ATOMIC_SLEEP int non_block_count; diff --git a/kernel/fork.c b/kernel/fork.c index 2b6bd511c6ed..81e809c343fd 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2208,9 +2208,9 @@ static __latent_entropy struct task_struct *copy_process( lockdep_init_task(p); #endif -#ifdef CONFIG_DEBUG_MUTEXES + p->blocked_proxy = NULL; /* nobody is boosting us yet */ p->blocked_on = NULL; /* not blocked yet */ -#endif + #ifdef CONFIG_BCACHE p->sequential_io = 0; p->sequential_io_avg = 0; diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c index bc8abb8549d2..7228909c3e62 100644 --- a/kernel/locking/mutex-debug.c +++ b/kernel/locking/mutex-debug.c @@ -52,17 +52,18 @@ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, { lockdep_assert_held(&lock->wait_lock); - /* Mark the current thread as blocked on the lock: */ - task->blocked_on = waiter; + /* Current thread can't be already blocked (since it's executing!) */ + DEBUG_LOCKS_WARN_ON(task->blocked_on); } void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, struct task_struct *task) { + struct mutex *blocked_on = READ_ONCE(task->blocked_on); + DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); DEBUG_LOCKS_WARN_ON(waiter->task != task); - DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter); - task->blocked_on = NULL; + DEBUG_LOCKS_WARN_ON(blocked_on && blocked_on != lock); INIT_LIST_HEAD(&waiter->list); waiter->task = NULL; diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index 1582756914df..f05cd2d216c7 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -645,6 +645,7 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas goto err_early_kill; } + current->blocked_on = lock; set_current_state(state); trace_contention_begin(lock, LCB_F_MUTEX); for (;;) { @@ -682,6 +683,10 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas first = __mutex_waiter_is_first(lock, &waiter); + /* + * Gets reset by ttwu_runnable(). + */ + current->blocked_on = lock; set_current_state(state); /* * Here we order against unlock; we must either see it change @@ -715,6 +720,7 @@ __mutex_lock_common(struct mutex *lock, unsigned int state, unsigned int subclas } __mutex_remove_waiter(lock, &waiter); + current->blocked_on = NULL; debug_mutex_free_waiter(&waiter); -- 2.38.0.rc1.362.ged0d419d3c-goog
| |