linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Waiman Long <longman@redhat.com>
To: Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Jonathan Corbet <corbet@lwn.net>
Cc: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Davidlohr Bueso <dave@stgolabs.net>,
	Mike Galbraith <umgwanakikbuti@gmail.com>,
	Scott J Norton <scott.norton@hpe.com>,
	Waiman Long <longman@redhat.com>
Subject: [PATCH-tip v5 13/21] TP-futex: Add timeout support
Date: Fri,  3 Feb 2017 13:03:46 -0500	[thread overview]
Message-ID: <1486145034-22210-14-git-send-email-longman@redhat.com> (raw)
In-Reply-To: <1486145034-22210-1-git-send-email-longman@redhat.com>

Unlike other futexes, TP futexes do not accept the specification of
a timeout value. To align with the other futexes, timeout support is
now added.  However, the timeout isn't as precise as the other futex
types due to the fact that timer expiration can't be detected when
the thread is waiting in the serialization mutex.

Signed-off-by: Waiman Long <longman@redhat.com>
---
 kernel/futex.c | 50 ++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 42 insertions(+), 8 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 22f7906..91b2e02 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -3558,9 +3558,10 @@ static inline int futex_set_waiters_bit(u32 __user *uaddr, u32 *puval)
 
 /**
  * futex_spin_on_owner - Optimistically spin on futex owner
- * @uaddr: futex address
- * @vpid:  PID of current task
- * @state: futex state object
+ * @uaddr:   futex address
+ * @vpid:    PID of current task
+ * @state:   futex state object
+ * @timeout: hrtimer_sleeper structure
  *
  * Spin on the futex word while the futex owner is active. Otherwise, set
  * the FUTEX_WAITERS bit and go to sleep.
@@ -3576,7 +3577,8 @@ static inline int futex_set_waiters_bit(u32 __user *uaddr, u32 *puval)
  * Return: TP status code if lock acquired, < 0 if an error happens.
  */
 static int futex_spin_on_owner(u32 __user *uaddr, const u32 vpid,
-			       struct futex_state *state)
+			       struct futex_state *state,
+			       struct hrtimer_sleeper *timeout)
 {
 #define OWNER_DEAD_MESSAGE					\
 	"futex: owner pid %d of TP futex 0x%lx was %s.\n"	\
@@ -3648,6 +3650,12 @@ static int futex_spin_on_owner(u32 __user *uaddr, const u32 vpid,
 			continue;
 		}
 
+
+		if (timeout && !timeout->task) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+
 		if (signal_pending(current)) {
 			ret = -EINTR;
 			break;
@@ -3755,10 +3763,18 @@ static int futex_spin_on_owner(u32 __user *uaddr, const u32 vpid,
  * This function is not inlined so that it can show up separately in perf
  * profile for performance analysis purpose.
  *
+ * The timeout functionality isn't as precise as other other futex types
+ * as timer expiration will not be detected while waiting in the
+ * serialization mutex. One possible solution is to modify the expiration
+ * function to send out a signal as well so as to break the thread out of
+ * the mutex code if we really want more precise timeout.
+ *
  * Return: TP status code if lock acquired, < 0 if an error happens.
  */
-static noinline int futex_lock(u32 __user *uaddr, unsigned int flags)
+static noinline int
+futex_lock(u32 __user *uaddr, unsigned int flags, ktime_t *time)
 {
+	struct hrtimer_sleeper timeout, *to;
 	struct futex_hash_bucket *hb;
 	union futex_key key = FUTEX_KEY_INIT;
 	struct futex_state *state;
@@ -3782,6 +3798,8 @@ static noinline int futex_lock(u32 __user *uaddr, unsigned int flags)
 	if (refill_futex_state_cache())
 		return -ENOMEM;
 
+	to = futex_setup_timer(time, &timeout, flags, current->timer_slack_ns);
+
 	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_WRITE);
 	if (unlikely(ret))
 		goto out;
@@ -3807,6 +3825,9 @@ static noinline int futex_lock(u32 __user *uaddr, unsigned int flags)
 		goto out_put_state_key;
 	}
 
+	if (to)
+		hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS);
+
 	/*
 	 * Acquiring the serialization mutex.
 	 *
@@ -3818,10 +3839,19 @@ static noinline int futex_lock(u32 __user *uaddr, unsigned int flags)
 		goto out_put_state_key;
 
 	/*
+	 * Check for timeout.
+	 */
+	if (to && !timeout.task) {
+		ret = -ETIMEDOUT;
+		mutex_unlock(&state->mutex);
+		goto out_put_state_key;
+	}
+
+	/*
 	 * As the mutex owner, we can now spin on the futex word as well as
 	 * the active-ness of the futex owner.
 	 */
-	ret = futex_spin_on_owner(uaddr, vpid, state);
+	ret = futex_spin_on_owner(uaddr, vpid, state, to);
 
 	mutex_unlock(&state->mutex);
 
@@ -3838,6 +3868,10 @@ static noinline int futex_lock(u32 __user *uaddr, unsigned int flags)
 	put_futex_key(&key);
 
 out:
+	if (to) {
+		hrtimer_cancel(&to->timer);
+		destroy_hrtimer_on_stack(&to->timer);
+	}
 	return ret;
 }
 
@@ -3991,7 +4025,7 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1);
 #ifdef CONFIG_SMP
 	case FUTEX_LOCK:
-		return futex_lock(uaddr, flags);
+		return futex_lock(uaddr, flags, timeout);
 	case FUTEX_UNLOCK:
 		return futex_unlock(uaddr, flags);
 #endif
@@ -4010,7 +4044,7 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 	int cmd = op & FUTEX_CMD_MASK;
 
 	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
-		      cmd == FUTEX_WAIT_BITSET ||
+		      cmd == FUTEX_WAIT_BITSET || cmd == FUTEX_LOCK ||
 		      cmd == FUTEX_WAIT_REQUEUE_PI)) {
 		if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG))))
 			return -EFAULT;
-- 
1.8.3.1

  parent reply	other threads:[~2017-02-03 18:06 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-03 18:03 [PATCH-tip v5 00/21] futex: Introducing throughput-optimized (TP) futexes Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 01/21] perf bench: New microbenchmark for userspace mutex performance Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 02/21] perf bench: New microbenchmark for userspace rwlock performance Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 03/21] futex: Consolidate duplicated timer setup code Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 04/21] futex: Rename futex_pi_state to futex_state Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 05/21] futex: Add helpers to get & cmpxchg futex value without lock Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 06/21] futex: Consolidate pure pi_state_list add & delete codes to helpers Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 07/21] futex: Add a new futex type field into futex_state Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 08/21] futex: Allow direct attachment of futex_state objects to hash bucket Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 09/21] futex: Introduce throughput-optimized (TP) futexes Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 10/21] TP-futex: Enable robust handling Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 11/21] TP-futex: Implement lock handoff to prevent lock starvation Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 12/21] TP-futex: Return status code on FUTEX_LOCK calls Waiman Long
2017-02-03 18:03 ` Waiman Long [this message]
2017-02-03 18:03 ` [PATCH-tip v5 14/21] TP-futex, doc: Add TP futexes documentation Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 15/21] TP-futex: Support userspace reader/writer locks Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 16/21] TP-futex: Enable kernel reader lock stealing Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 17/21] TP-futex: Group readers together in wait queue Waiman Long
2017-02-03 18:23   ` valdis.kletnieks
2017-02-03 18:42     ` Waiman Long
2017-02-03 19:26       ` valdis.kletnieks
2017-02-03 18:03 ` [PATCH-tip v5 18/21] TP-futex, doc: Update TP futexes document on shared locking Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 19/21] perf bench: Extend mutex/rwlock futex suite to test TP futexes Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 20/21] sched, TP-futex: Make wake_up_q() return wakeup count Waiman Long
2017-02-03 18:03 ` [PATCH-tip v5 21/21] futex: Dump internal futex state via debugfs 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=1486145034-22210-14-git-send-email-longman@redhat.com \
    --to=longman@redhat.com \
    --cc=acme@kernel.org \
    --cc=corbet@lwn.net \
    --cc=dave@stgolabs.net \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=scott.norton@hpe.com \
    --cc=tglx@linutronix.de \
    --cc=umgwanakikbuti@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).