All of lore.kernel.org
 help / color / mirror / Atom feed
From: Waiman Long <waiman.long@hpe.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>, <linux-kernel@vger.kernel.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Ding Tianhong <dingtianhong@huawei.com>,
	Jason Low <jason.low2@hpe.com>,
	Davidlohr Bueso <dave@stgolabs.net>,
	"Paul E. McKenney" <paulmck@us.ibm.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Will Deacon <Will.Deacon@arm.com>,
	Tim Chen <tim.c.chen@linux.intel.com>,
	Imre Deak <imre.deak@intel.com>
Subject: Re: [RFC PATCH-queue/locking/rfc 2/2] locking/mutex: Enable optimistic spinning of woken waiter
Date: Tue, 30 Aug 2016 18:58:03 -0400	[thread overview]
Message-ID: <57C60F7B.9040804@hpe.com> (raw)
In-Reply-To: <20160830150841.GB3318@worktop.controleur.wifipass.org>

On 08/30/2016 11:08 AM, Peter Zijlstra wrote:
> On Fri, Aug 26, 2016 at 07:35:09PM -0400, Waiman Long wrote:
>
>> @@ -624,13 +649,24 @@ __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();
>>
>> +		/*
>> +		 * Both __mutex_trylock() and __mutex_waiter_is_first()
>> +		 * can be done without the protection of wait_lock.
>> +		 */
> True, but it took me a little while to figure out why
> __mutex_waiter_is_first() is safe without the lock :-)

Yes, if you are the first waiter, the condition will not be changed even 
when new waiter is being added to the tail of the list.

>
>> +		acquired = __mutex_trylock(lock);
>>
>> +		if (!acquired&&  __mutex_waiter_is_first(lock,&waiter)) {
>>   			__mutex_set_flag(lock, MUTEX_FLAG_HANDOFF);
>> +			/*
>> +			 * Wait until the lock is handed off or the owner
>> +			 * sleeps.
>> +			 */
>> +			acquired = mutex_optimistic_spin(lock, ww_ctx,
>> +							 use_ww_ctx, true);
>> +		}
> That said; I think there's a few problems with this. Since we now poke
> at the loop termination conditions outside of the wait_lock, it becomes
> important where we do the task->state vs wakeup bits.
>
> Specifically, since we still have state==RUNNING here, its possible
> we'll fail to acquire the lock _and_ miss the wakeup from
> mutex_unlock(). Leaving us stuck forever more.
>
> Also, we should do the __mutex_trylock _after_ we set the handoff,
> otherwise its possible we get the lock handed (miss the wakeup as per
> the above) and fail to notice, again going back to sleep forever more.
>

Yes, you are right. I am less familiar with the intricacy of the 
sleep-wakeup interaction.

> @@ -638,7 +636,8 @@ __mutex_lock_common(struct mutex *lock,
>
>   	lock_contended(&lock->dep_map, ip);
>
> -	for (acquired = false; !acquired; ) {
> +	set_task_state(task, state);
> +	for (;;) {
>   		/*
>   		 * got a signal? (This code gets eliminated in the
>   		 * TASK_UNINTERRUPTIBLE case.)
> @@ -654,30 +653,23 @@ __mutex_lock_common(struct mutex *lock,
>   				goto err;
>   		}
>
> -		__set_task_state(task, state);
> -
> -		/* didn't get the lock, go to sleep: */
>   		spin_unlock_mutex(&lock->wait_lock, flags);
>   		schedule_preempt_disabled();
>
> -		/*
> -		 * Both __mutex_trylock() and __mutex_waiter_is_first()
> -		 * can be done without the protection of wait_lock.
> -		 */
> -		acquired = __mutex_trylock(lock, true);
> +		set_task_state(task, state);
>
> -		if (!acquired&&  __mutex_waiter_is_first(lock,&waiter)) {
> +		if (__mutex_waiter_is_first(lock,&waiter)) {
>   			__mutex_set_flag(lock, MUTEX_FLAG_HANDOFF);
> -			/*
> -			 * Wait until the lock is handed off or the owner
> -			 * sleeps.
> -			 */
> -			acquired = mutex_optimistic_spin(lock, ww_ctx,
> -							 use_ww_ctx, true);
> +			if (mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, true))
> +				break;
>   		}
>
> +		if (__mutex_trylock(lock, true))
> +			break;
> +

I think the set _task_state() can be moved to just before 
__mutex_trylock(). In this way, we can save a smp_mb() if we can get the 
lock in the optspin loop. Other than that, I am fine with the other changes.

Cheers,
Longman

  reply	other threads:[~2016-08-30 23:13 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-26 23:35 [RFC PATCH-queue/locking/rfc 1/2] locking/mutex: Simplify some ww_mutex code in __mutex_lock_common() Waiman Long
2016-08-26 23:35 ` [RFC PATCH-queue/locking/rfc 2/2] locking/mutex: Enable optimistic spinning of woken waiter Waiman Long
2016-08-30 15:08   ` Peter Zijlstra
2016-08-30 22:58     ` Waiman Long [this message]
2016-10-25 10:29   ` [tip:locking/core] " tip-bot for Waiman Long
2016-10-25 10:29 ` [tip:locking/core] locking/mutex: Simplify some ww_mutex code in __mutex_lock_common() tip-bot for Waiman Long

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57C60F7B.9040804@hpe.com \
    --to=waiman.long@hpe.com \
    --cc=Will.Deacon@arm.com \
    --cc=dave@stgolabs.net \
    --cc=dingtianhong@huawei.com \
    --cc=imre.deak@intel.com \
    --cc=jason.low2@hpe.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=paulmck@us.ibm.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=tim.c.chen@linux.intel.com \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.