From: Michel Lespinasse <walken@google.com>
To: Alex Shi <alex.shi@intel.com>, Ingo Molnar <mingo@kernel.org>,
David Howells <dhowells@redhat.com>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
Thomas Gleixner <tglx@linutronix.de>,
Yuanhan Liu <yuanhan.liu@linux.intel.com>,
Rik van Riel <riel@redhat.com>,
Peter Hurley <peter@hurleysoftware.com>,
Dave Chinner <david@fromorbit.com>
Cc: Andrew Morton <akpm@linux-foundation.org>, linux-kernel@vger.kernel.org
Subject: [PATCH v2 10/13] rwsem: simplify __rwsem_do_wake
Date: Fri, 15 Mar 2013 03:54:26 -0700 [thread overview]
Message-ID: <1363344869-15732-11-git-send-email-walken@google.com> (raw)
In-Reply-To: <1363344869-15732-1-git-send-email-walken@google.com>
This is mostly for cleanup value:
- We don't need several gotos to handle the case where the first
waiter is a writer. Two simple tests will do (and generate very
similar code).
- In the remainder of the function, we know the first waiter is a reader,
so we don't have to double check that. We can use do..while loops
to iterate over the readers to wake (generates slightly better code).
Signed-off-by: Michel Lespinasse <walken@google.com>
---
lib/rwsem-spinlock.c | 25 ++++++++-----------------
lib/rwsem.c | 26 ++++++++++++--------------
2 files changed, 20 insertions(+), 31 deletions(-)
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
index 5f117f37ac0a..20207a6e8ac3 100644
--- a/lib/rwsem-spinlock.c
+++ b/lib/rwsem-spinlock.c
@@ -70,26 +70,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
- if (!wakewrite) {
- if (waiter->type == RWSEM_WAITING_FOR_WRITE)
- goto out;
- goto dont_wake_writers;
- }
-
- /*
- * as we support write lock stealing, we can't set sem->activity
- * to -1 here to indicate we get the lock. Instead, we wake it up
- * to let it go get it again.
- */
if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
- wake_up_process(waiter->task);
+ if (wakewrite)
+ /* Wake up a writer. Note that we do not grant it the
+ * lock - it will have to acquire it when it runs. */
+ wake_up_process(waiter->task);
goto out;
}
- /* grant an infinite number of read locks to the front of the queue */
- dont_wake_writers:
+ /* grant read locks to all queued readers. */
woken = 0;
- while (waiter->type == RWSEM_WAITING_FOR_READ) {
+ do {
struct list_head *next = waiter->list.next;
list_del(&waiter->list);
@@ -99,10 +90,10 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
wake_up_process(tsk);
put_task_struct(tsk);
woken++;
- if (list_empty(&sem->wait_list))
+ if (next == &sem->wait_list)
break;
waiter = list_entry(next, struct rwsem_waiter, list);
- }
+ } while (waiter->type != RWSEM_WAITING_FOR_WRITE);
sem->activity += woken;
diff --git a/lib/rwsem.c b/lib/rwsem.c
index 0d50e46d5b0c..9a675fa9d78e 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -68,20 +68,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wake_type)
signed long woken, loop, adjustment;
waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
- if (waiter->type != RWSEM_WAITING_FOR_WRITE)
- goto readers_only;
-
- if (wake_type == RWSEM_WAKE_READ_OWNED)
- /* Another active reader was observed, so wakeup is not
- * likely to succeed. Save the atomic op.
- */
+ if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
+ if (wake_type != RWSEM_WAKE_READ_OWNED)
+ /* Wake writer at the front of the queue, but do not
+ * grant it the lock yet as we want other writers
+ * to be able to steal it. Readers, on the other hand,
+ * will block as they will notice the queued writer.
+ */
+ wake_up_process(waiter->task);
goto out;
+ }
- /* Wake up the writing waiter and let the task grab the sem: */
- wake_up_process(waiter->task);
- goto out;
-
- readers_only:
/* If we come here from up_xxxx(), another thread might have reached
* rwsem_down_failed_common() before we acquired the spinlock and
* woken up a waiter, making it now active. We prefer to check for
@@ -125,7 +122,8 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wake_type)
rwsem_atomic_add(adjustment, sem);
next = sem->wait_list.next;
- for (loop = woken; loop > 0; loop--) {
+ loop = woken;
+ do {
waiter = list_entry(next, struct rwsem_waiter, list);
next = waiter->list.next;
tsk = waiter->task;
@@ -133,7 +131,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wake_type)
waiter->task = NULL;
wake_up_process(tsk);
put_task_struct(tsk);
- }
+ } while (--loop);
sem->wait_list.next = next;
next->prev = &sem->wait_list;
--
1.8.1.3
next prev parent reply other threads:[~2013-03-15 10:56 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-15 10:54 [PATCH v2 00/13] rwsem fast-path write lock stealing Michel Lespinasse
2013-03-15 10:54 ` [PATCH v2 01/13] rwsem: make the waiter type an enumeration rather than a bitmask Michel Lespinasse
2013-03-28 18:59 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 02/13] rwsem: shorter spinlocked section in rwsem_down_failed_common() Michel Lespinasse
2013-03-28 16:21 ` Peter Hurley
2013-03-28 19:03 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 03/13] rwsem: move rwsem_down_failed_common code into rwsem_down_{read,write}_failed Michel Lespinasse
2013-03-28 17:05 ` Peter Hurley
2013-04-27 21:21 ` Davidlohr Bueso
2013-03-28 19:08 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 04/13] rwsem: simplify rwsem_down_read_failed Michel Lespinasse
2013-03-28 19:22 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 05/13] rwsem: simplify rwsem_down_write_failed Michel Lespinasse
2013-03-28 20:33 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 06/13] rwsem: more agressive lock stealing in rwsem_down_write_failed Michel Lespinasse
2013-03-28 20:54 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 07/13] rwsem: use cmpxchg for trying to steal write lock Michel Lespinasse
2013-03-28 16:44 ` Peter Hurley
2013-03-28 20:59 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 08/13] rwsem: avoid taking wait_lock in rwsem_down_write_failed Michel Lespinasse
2013-03-28 21:01 ` Rik van Riel
2013-03-15 10:54 ` [PATCH v2 09/13] rwsem: skip initial trylock " Michel Lespinasse
2013-03-28 21:16 ` Rik van Riel
2013-03-15 10:54 ` Michel Lespinasse [this message]
2013-03-28 16:51 ` [PATCH v2 10/13] rwsem: simplify __rwsem_do_wake Peter Hurley
2013-03-15 10:54 ` [PATCH v2 11/13] rwsem: implement support for write lock stealing on the fastpath Michel Lespinasse
2013-03-28 16:17 ` Peter Hurley
2013-03-15 10:54 ` [PATCH v2 12/13] rwsem: do not block readers at head of queue if other readers are active Michel Lespinasse
2013-03-28 17:25 ` Peter Hurley
2013-03-15 10:54 ` [PATCH v2 13/13] x86 rwsem: avoid taking slow path when stealing write lock Michel Lespinasse
2013-03-28 19:19 ` [PATCH v2 00/13] rwsem fast-path write lock stealing Peter Hurley
[not found] ` <1367097352.1782.14.camel@buesod1.americas.hpqcorp.net>
2013-04-27 23:47 ` Michel Lespinasse
2013-05-07 9:18 ` Michel Lespinasse
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=1363344869-15732-11-git-send-email-walken@google.com \
--to=walken@google.com \
--cc=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=alex.shi@intel.com \
--cc=david@fromorbit.com \
--cc=dhowells@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peter@hurleysoftware.com \
--cc=riel@redhat.com \
--cc=tglx@linutronix.de \
--cc=yuanhan.liu@linux.intel.com \
/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.