Commit 0898678c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'locking-urgent-2021-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Thomas Gleixner:
 "Two locking fixes:

   - Invoke the lockdep tracepoints in the correct place so the ordering
     is correct again

   - Don't leave the mutex WAITER bit stale when the last waiter is
     dropping out early due to a signal as that forces all subsequent
     lock operations needlessly into the slowpath until it's cleaned up
     again"

* tag 'locking-urgent-2021-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  locking/mutex: clear MUTEX_FLAGS if wait_list is empty due to signal
  locking/lockdep: Correct calling tracepoints
parents f73d2a42 3a010c49
...@@ -5736,7 +5736,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip) ...@@ -5736,7 +5736,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip)
{ {
unsigned long flags; unsigned long flags;
trace_lock_acquired(lock, ip); trace_lock_contended(lock, ip);
if (unlikely(!lock_stat || !lockdep_enabled())) if (unlikely(!lock_stat || !lockdep_enabled()))
return; return;
...@@ -5754,7 +5754,7 @@ void lock_acquired(struct lockdep_map *lock, unsigned long ip) ...@@ -5754,7 +5754,7 @@ void lock_acquired(struct lockdep_map *lock, unsigned long ip)
{ {
unsigned long flags; unsigned long flags;
trace_lock_contended(lock, ip); trace_lock_acquired(lock, ip);
if (unlikely(!lock_stat || !lockdep_enabled())) if (unlikely(!lock_stat || !lockdep_enabled()))
return; return;
......
...@@ -57,7 +57,7 @@ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, ...@@ -57,7 +57,7 @@ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
task->blocked_on = waiter; task->blocked_on = waiter;
} }
void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
struct task_struct *task) struct task_struct *task)
{ {
DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
...@@ -65,7 +65,7 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, ...@@ -65,7 +65,7 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter); DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter);
task->blocked_on = NULL; task->blocked_on = NULL;
list_del_init(&waiter->list); INIT_LIST_HEAD(&waiter->list);
waiter->task = NULL; waiter->task = NULL;
} }
......
...@@ -22,7 +22,7 @@ extern void debug_mutex_free_waiter(struct mutex_waiter *waiter); ...@@ -22,7 +22,7 @@ extern void debug_mutex_free_waiter(struct mutex_waiter *waiter);
extern void debug_mutex_add_waiter(struct mutex *lock, extern void debug_mutex_add_waiter(struct mutex *lock,
struct mutex_waiter *waiter, struct mutex_waiter *waiter,
struct task_struct *task); struct task_struct *task);
extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, extern void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
struct task_struct *task); struct task_struct *task);
extern void debug_mutex_unlock(struct mutex *lock); extern void debug_mutex_unlock(struct mutex *lock);
extern void debug_mutex_init(struct mutex *lock, const char *name, extern void debug_mutex_init(struct mutex *lock, const char *name,
......
...@@ -194,7 +194,7 @@ static inline bool __mutex_waiter_is_first(struct mutex *lock, struct mutex_wait ...@@ -194,7 +194,7 @@ static inline bool __mutex_waiter_is_first(struct mutex *lock, struct mutex_wait
* Add @waiter to a given location in the lock wait_list and set the * Add @waiter to a given location in the lock wait_list and set the
* FLAG_WAITERS flag if it's the first waiter. * FLAG_WAITERS flag if it's the first waiter.
*/ */
static void __sched static void
__mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
struct list_head *list) struct list_head *list)
{ {
...@@ -205,6 +205,16 @@ __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, ...@@ -205,6 +205,16 @@ __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
__mutex_set_flag(lock, MUTEX_FLAG_WAITERS); __mutex_set_flag(lock, MUTEX_FLAG_WAITERS);
} }
static void
__mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter)
{
list_del(&waiter->list);
if (likely(list_empty(&lock->wait_list)))
__mutex_clear_flag(lock, MUTEX_FLAGS);
debug_mutex_remove_waiter(lock, waiter, current);
}
/* /*
* Give up ownership to a specific task, when @task = NULL, this is equivalent * Give up ownership to a specific task, when @task = NULL, this is equivalent
* to a regular unlock. Sets PICKUP on a handoff, clears HANDOFF, preserves * to a regular unlock. Sets PICKUP on a handoff, clears HANDOFF, preserves
...@@ -1061,9 +1071,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, ...@@ -1061,9 +1071,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
__ww_mutex_check_waiters(lock, ww_ctx); __ww_mutex_check_waiters(lock, ww_ctx);
} }
mutex_remove_waiter(lock, &waiter, current); __mutex_remove_waiter(lock, &waiter);
if (likely(list_empty(&lock->wait_list)))
__mutex_clear_flag(lock, MUTEX_FLAGS);
debug_mutex_free_waiter(&waiter); debug_mutex_free_waiter(&waiter);
...@@ -1080,7 +1088,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, ...@@ -1080,7 +1088,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
err: err:
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
mutex_remove_waiter(lock, &waiter, current); __mutex_remove_waiter(lock, &waiter);
err_early_kill: err_early_kill:
spin_unlock(&lock->wait_lock); spin_unlock(&lock->wait_lock);
debug_mutex_free_waiter(&waiter); debug_mutex_free_waiter(&waiter);
......
...@@ -10,12 +10,10 @@ ...@@ -10,12 +10,10 @@
* !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs: * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs:
*/ */
#define mutex_remove_waiter(lock, waiter, task) \
__list_del((waiter)->list.prev, (waiter)->list.next)
#define debug_mutex_wake_waiter(lock, waiter) do { } while (0) #define debug_mutex_wake_waiter(lock, waiter) do { } while (0)
#define debug_mutex_free_waiter(waiter) do { } while (0) #define debug_mutex_free_waiter(waiter) do { } while (0)
#define debug_mutex_add_waiter(lock, waiter, ti) do { } while (0) #define debug_mutex_add_waiter(lock, waiter, ti) do { } while (0)
#define debug_mutex_remove_waiter(lock, waiter, ti) do { } while (0)
#define debug_mutex_unlock(lock) do { } while (0) #define debug_mutex_unlock(lock) do { } while (0)
#define debug_mutex_init(lock, name, key) do { } while (0) #define debug_mutex_init(lock, name, key) do { } while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment