locking/mutex: clear MUTEX_FLAGS if wait_list is empty due to signal

When a interruptible mutex locker is interrupted by a signal
without acquiring this lock and removed from the wait queue.
if the mutex isn't contended enough to have a waiter
put into the wait queue again, the setting of the WAITER
bit will force mutex locker to go into the slowpath to
acquire the lock every time, so if the wait queue is empty,
the WAITER bit need to be clear.

Fixes: 040a0a371005 ("mutex: Add support for wound/wait style locks")
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Zqiang <qiang.zhang@windriver.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20210517034005.30828-1-qiang.zhang@windriver.com

authored by Zqiang and committed by Peter Zijlstra 3a010c49 89e70d5c

Changed files
+17 -11
kernel
+2 -2
kernel/locking/mutex-debug.c
··· 57 57 task->blocked_on = waiter; 58 58 } 59 59 60 - void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, 60 + void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, 61 61 struct task_struct *task) 62 62 { 63 63 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); ··· 65 65 DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter); 66 66 task->blocked_on = NULL; 67 67 68 - list_del_init(&waiter->list); 68 + INIT_LIST_HEAD(&waiter->list); 69 69 waiter->task = NULL; 70 70 } 71 71
+1 -1
kernel/locking/mutex-debug.h
··· 22 22 extern void debug_mutex_add_waiter(struct mutex *lock, 23 23 struct mutex_waiter *waiter, 24 24 struct task_struct *task); 25 - extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, 25 + extern void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, 26 26 struct task_struct *task); 27 27 extern void debug_mutex_unlock(struct mutex *lock); 28 28 extern void debug_mutex_init(struct mutex *lock, const char *name,
+13 -5
kernel/locking/mutex.c
··· 194 194 * Add @waiter to a given location in the lock wait_list and set the 195 195 * FLAG_WAITERS flag if it's the first waiter. 196 196 */ 197 - static void __sched 197 + static void 198 198 __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, 199 199 struct list_head *list) 200 200 { ··· 203 203 list_add_tail(&waiter->list, list); 204 204 if (__mutex_waiter_is_first(lock, waiter)) 205 205 __mutex_set_flag(lock, MUTEX_FLAG_WAITERS); 206 + } 207 + 208 + static void 209 + __mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter) 210 + { 211 + list_del(&waiter->list); 212 + if (likely(list_empty(&lock->wait_list))) 213 + __mutex_clear_flag(lock, MUTEX_FLAGS); 214 + 215 + debug_mutex_remove_waiter(lock, waiter, current); 206 216 } 207 217 208 218 /* ··· 1071 1061 __ww_mutex_check_waiters(lock, ww_ctx); 1072 1062 } 1073 1063 1074 - mutex_remove_waiter(lock, &waiter, current); 1075 - if (likely(list_empty(&lock->wait_list))) 1076 - __mutex_clear_flag(lock, MUTEX_FLAGS); 1064 + __mutex_remove_waiter(lock, &waiter); 1077 1065 1078 1066 debug_mutex_free_waiter(&waiter); 1079 1067 ··· 1088 1080 1089 1081 err: 1090 1082 __set_current_state(TASK_RUNNING); 1091 - mutex_remove_waiter(lock, &waiter, current); 1083 + __mutex_remove_waiter(lock, &waiter); 1092 1084 err_early_kill: 1093 1085 spin_unlock(&lock->wait_lock); 1094 1086 debug_mutex_free_waiter(&waiter);
+1 -3
kernel/locking/mutex.h
··· 10 10 * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs: 11 11 */ 12 12 13 - #define mutex_remove_waiter(lock, waiter, task) \ 14 - __list_del((waiter)->list.prev, (waiter)->list.next) 15 - 16 13 #define debug_mutex_wake_waiter(lock, waiter) do { } while (0) 17 14 #define debug_mutex_free_waiter(waiter) do { } while (0) 18 15 #define debug_mutex_add_waiter(lock, waiter, ti) do { } while (0) 16 + #define debug_mutex_remove_waiter(lock, waiter, ti) do { } while (0) 19 17 #define debug_mutex_unlock(lock) do { } while (0) 20 18 #define debug_mutex_init(lock, name, key) do { } while (0) 21 19