On 2016/1/22 21:59, Waiman Long wrote: > On 01/22/2016 06:06 AM, Peter Zijlstra wrote: >> On Fri, Jan 22, 2016 at 11:56:52AM +0100, Peter Zijlstra wrote: >>> On Fri, Jan 22, 2016 at 11:53:12AM +0100, Peter Zijlstra wrote: >>> >>>> There might be other details, but this is the one that stood out. >>> I think this also does the wrong thing for use_ww_ctx. >> Something like so? > > I think that should work. My only minor concern is that putting the waiter > spinner at the end of the OSQ will take it longer to get the lock, but that > shouldn't be a big issue. > >> --- >> kernel/locking/mutex.c | 15 +++++++++++++++ >> 1 file changed, 15 insertions(+) >> >> diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c >> index 0551c219c40e..070a0ac34aa7 100644 >> --- a/kernel/locking/mutex.c >> +++ b/kernel/locking/mutex.c >> @@ -512,6 +512,7 @@ __mutex_lock_common(struct mutex *lock, long state, >> unsigned int subclass, >> struct task_struct *task = current; >> struct mutex_waiter waiter; >> unsigned long flags; >> + bool acquired; >> int ret; >> >> preempt_disable(); >> @@ -543,6 +544,7 @@ __mutex_lock_common(struct mutex *lock, long state, >> unsigned int subclass, >> lock_contended(&lock->dep_map, ip); >> >> for (;;) { >> + acquired = false; >> /* >> * Lets try to take the lock again - this is needed even if >> * we get here for the first time (shortly after failing to >> @@ -577,7 +579,16 @@ __mutex_lock_common(struct mutex *lock, long state, >> unsigned int subclass, >> /* didn't get the lock, go to sleep: */ >> spin_unlock_mutex(&lock->wait_lock, flags); >> schedule_preempt_disabled(); >> + >> + if (mutex_is_locked(lock)) >> + acquired = mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx); >> + >> spin_lock_mutex(&lock->wait_lock, flags); >> + >> + if (acquired) { >> + atomic_set(&lock->count, -1); >> + break; >> + } >> } >> __set_task_state(task, TASK_RUNNING); >> >> @@ -587,6 +598,9 @@ __mutex_lock_common(struct mutex *lock, long state, >> unsigned int subclass, >> atomic_set(&lock->count, 0); >> debug_mutex_free_waiter(&waiter); >> >> + if (acquired) >> + goto unlock; >> + >> skip_wait: >> /* got the lock - cleanup and rejoice! */ >> lock_acquired(&lock->dep_map, ip); >> @@ -597,6 +611,7 @@ __mutex_lock_common(struct mutex *lock, long state, >> unsigned int subclass, >> ww_mutex_set_context_slowpath(ww, ww_ctx); >> } >> >> +unlock: >> spin_unlock_mutex(&lock->wait_lock, flags); >> preempt_enable(); >> return 0; > > Cheers, > Longman >
looks good to me, I will try this solution and report the result, thanks everyone. Ding > . >