All of lore.kernel.org
 help / color / mirror / Atom feed
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 03/13] rwsem: move rwsem_down_failed_common code into rwsem_down_{read,write}_failed
Date: Fri, 15 Mar 2013 03:54:19 -0700	[thread overview]
Message-ID: <1363344869-15732-4-git-send-email-walken@google.com> (raw)
In-Reply-To: <1363344869-15732-1-git-send-email-walken@google.com>

Remove the rwsem_down_failed_common function and replace it with two
identical copies of its code in rwsem_down_{read,write}_failed.

This is because we want to make different optimizations in
rwsem_down_{read,write}_failed; we are adding this pure-duplication
step as a separate commit in order to make it easier to check the
following steps.

Signed-off-by: Michel Lespinasse <walken@google.com>

---
 lib/rwsem.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 57 insertions(+), 15 deletions(-)

diff --git a/lib/rwsem.c b/lib/rwsem.c
index 40636454cf3c..fb658af1c12c 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -178,12 +178,12 @@ try_again_write:
 }
 
 /*
- * wait for a lock to be granted
+ * wait for the read lock to be granted
  */
-static struct rw_semaphore __sched *
-rwsem_down_failed_common(struct rw_semaphore *sem,
-			 enum rwsem_waiter_type type, signed long adjustment)
+struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
 {
+	enum rwsem_waiter_type type = RWSEM_WAITING_FOR_READ;
+	signed long adjustment = -RWSEM_ACTIVE_READ_BIAS;
 	struct rwsem_waiter waiter;
 	struct task_struct *tsk = current;
 	signed long count;
@@ -238,21 +238,63 @@ rwsem_down_failed_common(struct rw_semaphore *sem,
 }
 
 /*
- * wait for the read lock to be granted
- */
-struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
-{
-	return rwsem_down_failed_common(sem, RWSEM_WAITING_FOR_READ,
-					-RWSEM_ACTIVE_READ_BIAS);
-}
-
-/*
  * wait for the write lock to be granted
  */
 struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
 {
-	return rwsem_down_failed_common(sem, RWSEM_WAITING_FOR_WRITE,
-					-RWSEM_ACTIVE_WRITE_BIAS);
+	enum rwsem_waiter_type type = RWSEM_WAITING_FOR_WRITE;
+	signed long adjustment = -RWSEM_ACTIVE_WRITE_BIAS;
+	struct rwsem_waiter waiter;
+	struct task_struct *tsk = current;
+	signed long count;
+
+	/* set up my own style of waitqueue */
+	waiter.task = tsk;
+	waiter.type = type;
+	get_task_struct(tsk);
+
+	raw_spin_lock_irq(&sem->wait_lock);
+	if (list_empty(&sem->wait_list))
+		adjustment += RWSEM_WAITING_BIAS;
+	list_add_tail(&waiter.list, &sem->wait_list);
+
+	/* we're now waiting on the lock, but no longer actively locking */
+	count = rwsem_atomic_update(adjustment, sem);
+
+	/* If there are no active locks, wake the front queued process(es) up.
+	 *
+	 * Alternatively, if we're called from a failed down_write(), there
+	 * were already threads queued before us and there are no active
+	 * writers, the lock must be read owned; so we try to wake any read
+	 * locks that were queued ahead of us. */
+	if (count == RWSEM_WAITING_BIAS)
+		sem = __rwsem_do_wake(sem, RWSEM_WAKE_NO_ACTIVE);
+	else if (count > RWSEM_WAITING_BIAS &&
+		 adjustment == -RWSEM_ACTIVE_WRITE_BIAS)
+		sem = __rwsem_do_wake(sem, RWSEM_WAKE_READ_OWNED);
+
+	raw_spin_unlock_irq(&sem->wait_lock);
+
+	/* wait to be given the lock */
+	while (true) {
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (!waiter.task)
+			break;
+
+		raw_spin_lock_irq(&sem->wait_lock);
+		/* Try to get the writer sem, may steal from the head writer: */
+		if (type == RWSEM_WAITING_FOR_WRITE)
+			if (try_get_writer_sem(sem, &waiter)) {
+				raw_spin_unlock_irq(&sem->wait_lock);
+				return sem;
+			}
+		raw_spin_unlock_irq(&sem->wait_lock);
+		schedule();
+	}
+
+	tsk->state = TASK_RUNNING;
+
+	return sem;
 }
 
 /*
-- 
1.8.1.3

  parent reply	other threads:[~2013-03-15 10:57 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 ` Michel Lespinasse [this message]
2013-03-28 17:05   ` [PATCH v2 03/13] rwsem: move rwsem_down_failed_common code into rwsem_down_{read,write}_failed 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 ` [PATCH v2 10/13] rwsem: simplify __rwsem_do_wake Michel Lespinasse
2013-03-28 16:51   ` 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-4-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.