All of lore.kernel.org
 help / color / mirror / Atom feed
From: Waiman Long <longman@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>, Will Deacon <will.deacon@arm.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Borislav Petkov <bp@alien8.de>, "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-kernel@vger.kernel.org, x86@kernel.org,
	Davidlohr Bueso <dave@stgolabs.net>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Tim Chen <tim.c.chen@linux.intel.com>,
	huang ying <huang.ying.caritas@gmail.com>,
	Waiman Long <longman@redhat.com>
Subject: [PATCH-tip v7 20/20] locking/rwsem: Disable preemption in down_read*() if owner in count
Date: Sun, 28 Apr 2019 17:25:57 -0400	[thread overview]
Message-ID: <20190428212557.13482-21-longman@redhat.com> (raw)
In-Reply-To: <20190428212557.13482-1-longman@redhat.com>

It is very unlikely that successive preemption at the middle of
down_read's inc-check-dec sequence will cause the reader count to
overflow, For absolute correctness, however, we still need to prevent
that possibility from happening. So preemption will be disabled during
the down_read*() call.

For PREEMPT=n kernels, there isn't much overhead in doing that.
For PREEMPT=y kernels, there will be some additional cost. RT kernels
have their own rwsem code, so it will not be a problem for them.

If MERGE_OWNER_INTO_COUNT isn't defined, we don't need to worry about
reader count overflow and so we don't need to disable preemption.

Signed-off-by: Waiman Long <longman@redhat.com>
---
 kernel/locking/rwsem.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index cd7fdb8b02ed..60783267b50d 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -375,6 +375,24 @@ static inline void rwsem_set_nonspinnable(struct rw_semaphore *sem)
 }
 
 #ifdef MERGE_OWNER_INTO_COUNT
+/*
+ * It is very unlikely that successive preemption at the middle of
+ * down_read's inc-check-dec sequence will cause the reader count to
+ * overflow, For absolute correctness, we still need to prevent
+ * that possibility from happening. So preemption will be disabled
+ * during the down_read*() call.
+ *
+ * For PREEMPT=n kernels, there isn't much overhead in doing that.
+ * For PREEMPT=y kernels, there will be some additional cost.
+ *
+ * If MERGE_OWNER_INTO_COUNT isn't defined, we don't need to worry
+ * about reader count overflow and so we don't need to disable
+ * preemption.
+ */
+#define rwsem_preempt_disable()			preempt_disable()
+#define rwsem_preempt_enable()			preempt_enable()
+#define rwsem_schedule_preempt_disabled()	schedule_preempt_disabled()
+
 /*
  * Get the owner value from count to have early access to the task structure.
  * Owner from sem->count should includes the RWSEM_NONSPINNABLE bits
@@ -431,6 +449,11 @@ static int __init rwsem_show_count_status(void)
 }
 late_initcall(rwsem_show_count_status);
 #else /* !MERGE_OWNER_INTO_COUNT */
+
+#define rwsem_preempt_disable()
+#define rwsem_preempt_enable()
+#define rwsem_schedule_preempt_disabled()	schedule()
+
 static inline struct task_struct *rwsem_get_owner(struct rw_semaphore *sem)
 {
 	return READ_ONCE(sem->owner);
@@ -1255,7 +1278,7 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, int state, long adjustment)
 			raw_spin_unlock_irq(&sem->wait_lock);
 			break;
 		}
-		schedule();
+		rwsem_schedule_preempt_disabled();
 		lockevent_inc(rwsem_sleep_reader);
 	}
 
@@ -1486,28 +1509,36 @@ static struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
  */
 inline void __down_read(struct rw_semaphore *sem)
 {
-	long tmp, adjustment = rwsem_read_trylock(sem, &tmp);
+	long tmp, adjustment;
 
+	rwsem_preempt_disable();
+	adjustment = rwsem_read_trylock(sem, &tmp);
 	if (unlikely(tmp & RWSEM_READ_FAILED_MASK)) {
 		rwsem_down_read_slowpath(sem, TASK_UNINTERRUPTIBLE, adjustment);
 		DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
 	} else {
 		rwsem_set_reader_owned(sem);
 	}
+	rwsem_preempt_enable();
 }
 
 static inline int __down_read_killable(struct rw_semaphore *sem)
 {
-	long tmp, adjustment = rwsem_read_trylock(sem, &tmp);
+	long tmp, adjustment;
 
+	rwsem_preempt_disable();
+	adjustment = rwsem_read_trylock(sem, &tmp);
 	if (unlikely(tmp & RWSEM_READ_FAILED_MASK)) {
 		if (IS_ERR(rwsem_down_read_slowpath(sem, TASK_KILLABLE,
-						    adjustment)))
+						    adjustment))) {
+			rwsem_preempt_enable();
 			return -EINTR;
+		}
 		DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
 	} else {
 		rwsem_set_reader_owned(sem);
 	}
+	rwsem_preempt_enable();
 	return 0;
 }
 
-- 
2.18.1


  parent reply	other threads:[~2019-04-28 21:27 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-28 21:25 [PATCH-tip v7 00/20] locking/rwsem: Rwsem rearchitecture part 2 Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 01/20] locking/rwsem: Prevent decrement of reader count before increment Waiman Long
2019-05-03 12:06   ` Peter Zijlstra
2019-05-03 13:32     ` Waiman Long
2019-05-07  7:07   ` [tip:locking/urgent] " tip-bot for Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 02/20] locking/rwsem: Make owner available even if !CONFIG_RWSEM_SPIN_ON_OWNER Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 03/20] locking/rwsem: Remove rwsem_wake() wakeup optimization Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 04/20] locking/rwsem: Implement a new locking scheme Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 05/20] locking/rwsem: Merge rwsem.h and rwsem-xadd.c into rwsem.c Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 06/20] locking/rwsem: Code cleanup after files merging Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 07/20] locking/rwsem: Make rwsem_spin_on_owner() return owner state Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 08/20] locking/rwsem: Implement lock handoff to prevent lock starvation Waiman Long
2019-05-03 13:10   ` Peter Zijlstra
2019-05-03 13:57     ` Waiman Long
2019-05-03 14:37     ` David Laight
2019-04-28 21:25 ` [PATCH-tip v7 09/20] locking/rwsem: Always release wait_lock before waking up tasks Waiman Long
2019-05-03 13:37   ` Peter Zijlstra
2019-05-03 13:56     ` Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 10/20] locking/rwsem: More optimal RT task handling of null owner Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 11/20] locking/rwsem: Wake up almost all readers in wait queue Waiman Long
2019-05-03 16:51   ` Peter Zijlstra
2019-05-03 17:15     ` Waiman Long
2019-05-06 11:49       ` Peter Zijlstra
2019-04-28 21:25 ` [PATCH-tip v7 12/20] locking/rwsem: Clarify usage of owner's nonspinaable bit Waiman Long
2019-05-03 15:21   ` Peter Zijlstra
2019-05-03 15:26     ` Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 13/20] locking/rwsem: Enable readers spinning on writer Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 14/20] locking/rwsem: Enable time-based spinning on reader-owned rwsem Waiman Long
2019-05-06 15:47   ` Peter Zijlstra
2019-04-28 21:25 ` [PATCH-tip v7 15/20] locking/rwsem: Adaptive disabling of reader optimistic spinning Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 16/20] locking/rwsem: Add more rwsem owner access helpers Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 17/20] locking/rwsem: Guard against making count negative Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 18/20] locking/rwsem: Merge owner into count on x86-64 Waiman Long
2019-04-28 21:25 ` [PATCH-tip v7 19/20] locking/rwsem: Remove redundant computation of writer lock word Waiman Long
2019-04-28 21:25 ` Waiman Long [this message]
2019-04-28 22:46 ` [PATCH-tip v7 00/20] locking/rwsem: Rwsem rearchitecture part 2 Linus Torvalds
2019-04-28 23:12   ` Waiman Long
2019-04-28 23:19     ` Waiman Long
2019-04-29  0:10     ` Linus Torvalds
2019-04-29  0:27       ` Waiman Long
2019-04-29  2:41         ` Linus Torvalds

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=20190428212557.13482-21-longman@redhat.com \
    --to=longman@redhat.com \
    --cc=bp@alien8.de \
    --cc=dave@stgolabs.net \
    --cc=hpa@zytor.com \
    --cc=huang.ying.caritas@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=tim.c.chen@linux.intel.com \
    --cc=torvalds@linux-foundation.org \
    --cc=will.deacon@arm.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.