From: Waiman Long <waiman.long@hp.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, "H. Peter Anvin" <hpa@zytor.com>,
Arnd Bergmann <arnd@arndb.de>,
linux-arch@vger.kernel.org, x86@kernel.org,
linux-kernel@vger.kernel.org,
Steven Rostedt <rostedt@goodmis.org>,
Andrew Morton <akpm@linux-foundation.org>,
Michel Lespinasse <walken@google.com>,
Andi Kleen <andi@firstfloor.org>, Rik van Riel <riel@redhat.com>,
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>,
George Spelvin <linux@horizon.com>,
Tim Chen <tim.c.chen@linux.intel.com>,
Daniel J Blueman <daniel@numascale.com>,
Alexander Fyodorov <halcy@yandex.ru>,
Aswin Chandramouleeswaran <aswin@hp.com>,
Scott J Norton <scott.norton@hp.com>,
Thavatchai Makphaibulchoke <thavatchai.makpahibulchoke@hp.com>
Subject: Re: [PATCH v4 1/3] qspinlock: Introducing a 4-byte queue spinlock implementation
Date: Tue, 18 Feb 2014 14:39:31 -0500 [thread overview]
Message-ID: <5303B6F3.9090001@hp.com> (raw)
In-Reply-To: <20140218073951.GZ27965@twins.programming.kicks-ass.net>
On 02/18/2014 02:39 AM, Peter Zijlstra wrote:
> On Mon, Feb 17, 2014 at 03:41:22PM -0500, Waiman Long wrote:
>> +void queue_spin_lock_slowpath(struct qspinlock *lock, int qsval)
>> +{
>> + unsigned int cpu_nr, qn_idx;
>> + struct qnode *node, *next;
>> + u32 prev_qcode, my_qcode;
>> +
>> +#ifdef queue_spin_trylock_quick
>> + /*
>> + * Try the quick spinning code path
>> + */
>> + if (queue_spin_trylock_quick(lock, qsval))
>> + return;
>> +#endif
> why oh why?
I could take this #ifdef away. I just need to add a default version that
always return 0.
>> + /*
>> + * Get the queue node
>> + */
>> + cpu_nr = smp_processor_id();
>> + node = get_qnode(&qn_idx);
>> +
>> + if (unlikely(!node)) {
>> + /*
>> + * This shouldn't happen, print a warning message
>> + *& busy spinning on the lock.
>> + */
>> + printk_sched(
>> + "qspinlock: queue node table exhausted at cpu %d!\n",
>> + cpu_nr);
>> + while (!queue_spin_trylock_unfair(lock))
>> + arch_mutex_cpu_relax();
>> + return;
>> + }
>> +
>> + /*
>> + * Set up the new cpu code to be exchanged
>> + */
>> + my_qcode = _SET_QCODE(cpu_nr, qn_idx);
>> +
>> + /*
>> + * Initialize the queue node
>> + */
>> + node->wait = true;
>> + node->next = NULL;
>> +
>> + /*
>> + * The lock may be available at this point, try again if no task was
>> + * waiting in the queue.
>> + */
>> + if (!(qsval>> _QCODE_OFFSET)&& queue_spin_trylock(lock)) {
>> + put_qnode();
>> + return;
>> + }
>> +
>> +#ifdef queue_code_xchg
>> + prev_qcode = queue_code_xchg(lock, my_qcode);
>> +#else
>> + /*
>> + * Exchange current copy of the queue node code
>> + */
>> + prev_qcode = atomic_xchg(&lock->qlcode, my_qcode);
>> + /*
>> + * It is possible that we may accidentally steal the lock. If this is
>> + * the case, we need to either release it if not the head of the queue
>> + * or get the lock and be done with it.
>> + */
>> + if (unlikely(!(prev_qcode& _QSPINLOCK_LOCKED))) {
>> + if (prev_qcode == 0) {
>> + /*
>> + * Got the lock since it is at the head of the queue
>> + * Now try to atomically clear the queue code.
>> + */
>> + if (atomic_cmpxchg(&lock->qlcode, my_qcode,
>> + _QSPINLOCK_LOCKED) == my_qcode)
>> + goto release_node;
>> + /*
>> + * The cmpxchg fails only if one or more tasks
>> + * are added to the queue. In this case, we need to
>> + * notify the next one to be the head of the queue.
>> + */
>> + goto notify_next;
>> + }
>> + /*
>> + * Accidentally steal the lock, release the lock and
>> + * let the queue head get it.
>> + */
>> + queue_spin_unlock(lock);
>> + } else
>> + prev_qcode&= ~_QSPINLOCK_LOCKED; /* Clear the lock bit */
>> + my_qcode&= ~_QSPINLOCK_LOCKED;
>> +#endif /* queue_code_xchg */
> WTF is this #ifdef for?
The #ifdef is harder to take away here. The point is that doing a 32-bit
exchange may accidentally steal the lock with the additional code to
handle that. Doing a 16-bit exchange, on the other hand, will never
steal the lock and so don't need the extra handling code. I could
construct a function with different return values to handle the
different cases if you think it will make the code easier to read.
>> + if (prev_qcode) {
>> + /*
>> + * Not at the queue head, get the address of the previous node
>> + * and set up the "next" fields of the that node.
>> + */
>> + struct qnode *prev = xlate_qcode(prev_qcode);
>> +
>> + ACCESS_ONCE(prev->next) = node;
>> + /*
>> + * Wait until the waiting flag is off
>> + */
>> + while (smp_load_acquire(&node->wait))
>> + arch_mutex_cpu_relax();
>> + }
>> +
>> + /*
>> + * At the head of the wait queue now
>> + */
>> + while (true) {
>> + u32 qcode;
>> + int retval;
>> +
>> + retval = queue_get_lock_qcode(lock,&qcode, my_qcode);
>> + if (retval> 0)
>> + ; /* Lock not available yet */
>> + else if (retval< 0)
>> + /* Lock taken, can release the node& return */
>> + goto release_node;
>> + else if (qcode != my_qcode) {
>> + /*
>> + * Just get the lock with other spinners waiting
>> + * in the queue.
>> + */
>> + if (queue_spin_trylock_unfair(lock))
>> + goto notify_next;
> Why is this an option at all?
>
>
Are you referring to the case (qcode != my_qcode)? This condition will
be true if more than one tasks have queued up.
-Longman
next prev parent reply other threads:[~2014-02-18 19:40 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-17 20:41 [PATCH v4 0/3] qspinlock: Introducing a 4-byte queue spinlock Waiman Long
2014-02-17 20:41 ` [PATCH v4 1/3] qspinlock: Introducing a 4-byte queue spinlock implementation Waiman Long
2014-02-17 22:45 ` [tip:x86/spinlocks] " tip-bot for Waiman Long
2014-02-18 7:30 ` [PATCH v4 1/3] " Peter Zijlstra
2014-02-18 19:29 ` Waiman Long
2014-02-18 7:33 ` Peter Zijlstra
2014-02-18 19:31 ` Waiman Long
2014-02-18 7:39 ` Peter Zijlstra
2014-02-18 19:39 ` Waiman Long [this message]
2014-02-18 21:34 ` Peter Zijlstra
2014-02-19 0:50 ` Waiman Long
2014-02-19 8:52 ` Peter Zijlstra
2014-02-19 19:26 ` Waiman Long
2014-02-18 21:37 ` Peter Zijlstra
2014-02-19 0:58 ` Waiman Long
2014-02-19 8:55 ` Peter Zijlstra
2014-02-19 19:30 ` Waiman Long
2014-02-17 20:41 ` [PATCH v4 2/3] qspinlock, x86: Enable x86-64 to use queue spinlock Waiman Long
2014-02-17 22:46 ` [tip:x86/spinlocks] " tip-bot for Waiman Long
2014-02-17 20:41 ` [PATCH v4 3/3] qspinlock, x86: Add x86 specific optimization for 2 contending tasks Waiman Long
2014-02-17 22:46 ` [tip:x86/spinlocks] " tip-bot for Waiman Long
2014-02-21 12:12 ` [PATCH v4 3/3] " Peter Zijlstra
2014-02-21 17:08 ` Waiman Long
2014-02-21 17:09 ` Waiman Long
2014-02-21 17:26 ` Peter Zijlstra
2014-02-22 1:36 ` Waiman Long
2014-02-21 17:28 ` Peter Zijlstra
2014-02-22 1:39 ` Waiman Long
2014-02-17 22:47 ` [PATCH v4 0/3] qspinlock: Introducing a 4-byte queue spinlock H. Peter Anvin
2014-02-18 7:31 ` Peter Zijlstra
2014-02-18 7:39 ` H. Peter Anvin
2014-02-18 19:30 ` Waiman Long
2014-02-18 21:28 ` Peter Zijlstra
2014-02-19 0:42 ` Waiman Long
2014-02-19 7:09 ` Raghavendra K T
2014-02-19 8:51 ` Peter Zijlstra
2014-02-19 19:24 ` Waiman Long
2014-02-19 19:48 ` Peter Zijlstra
2014-02-20 17:37 ` Waiman Long
2014-02-20 17:44 ` Linus Torvalds
2014-02-20 17:44 ` Linus Torvalds
2014-02-20 18:15 ` Peter Zijlstra
2014-02-19 20:17 ` Linus Torvalds
2014-02-19 20:17 ` Linus Torvalds
2014-02-20 17:54 ` Waiman Long
2014-02-20 17:54 ` Waiman Long
2014-02-20 18:42 ` Linus Torvalds
2014-02-20 18:42 ` Linus Torvalds
2014-02-20 19:21 ` Waiman Long
2014-02-20 19:21 ` Waiman Long
2014-02-20 19:32 ` Raghavendra K T
2014-02-20 19:32 ` Raghavendra K T
2014-02-21 17:02 ` Waiman Long
2014-02-21 17:02 ` Waiman Long
2014-02-21 17:05 ` Linus Torvalds
2014-02-21 17:05 ` Linus Torvalds
2014-02-19 21:29 ` H. Peter Anvin
2014-02-18 7:38 ` Peter Zijlstra
2014-02-22 16:56 ` Ingo Molnar
2014-02-25 3:37 ` Waiman Long
2014-02-25 3:37 ` Waiman Long
2014-02-18 19:27 ` 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=5303B6F3.9090001@hp.com \
--to=waiman.long@hp.com \
--cc=akpm@linux-foundation.org \
--cc=andi@firstfloor.org \
--cc=arnd@arndb.de \
--cc=aswin@hp.com \
--cc=daniel@numascale.com \
--cc=halcy@yandex.ru \
--cc=hpa@zytor.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@horizon.com \
--cc=mingo@redhat.com \
--cc=paulmck@linux.vnet.ibm.com \
--cc=peterz@infradead.org \
--cc=raghavendra.kt@linux.vnet.ibm.com \
--cc=riel@redhat.com \
--cc=rostedt@goodmis.org \
--cc=scott.norton@hp.com \
--cc=tglx@linutronix.de \
--cc=thavatchai.makpahibulchoke@hp.com \
--cc=tim.c.chen@linux.intel.com \
--cc=torvalds@linux-foundation.org \
--cc=walken@google.com \
--cc=x86@kernel.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.