|
@@ -372,11 +372,14 @@ ww_mutex_set_context_slowpath(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
|
|
|
|
|
|
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
|
|
|
/*
|
|
|
- * Look out! "owner" is an entirely speculative pointer
|
|
|
- * access and not reliable.
|
|
|
+ * Look out! "owner" is an entirely speculative pointer access and not
|
|
|
+ * reliable.
|
|
|
+ *
|
|
|
+ * "noinline" so that this function shows up on perf profiles.
|
|
|
*/
|
|
|
static noinline
|
|
|
-bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
|
|
|
+bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner,
|
|
|
+ struct ww_acquire_ctx *ww_ctx)
|
|
|
{
|
|
|
bool ret = true;
|
|
|
|
|
@@ -399,6 +402,28 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ if (ww_ctx && ww_ctx->acquired > 0) {
|
|
|
+ struct ww_mutex *ww;
|
|
|
+
|
|
|
+ ww = container_of(lock, struct ww_mutex, base);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If ww->ctx is set the contents are undefined, only
|
|
|
+ * by acquiring wait_lock there is a guarantee that
|
|
|
+ * they are not invalid when reading.
|
|
|
+ *
|
|
|
+ * As such, when deadlock detection needs to be
|
|
|
+ * performed the optimistic spinning cannot be done.
|
|
|
+ *
|
|
|
+ * Check this in every inner iteration because we may
|
|
|
+ * be racing against another thread's ww_mutex_lock.
|
|
|
+ */
|
|
|
+ if (READ_ONCE(ww->ctx)) {
|
|
|
+ ret = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
cpu_relax();
|
|
|
}
|
|
|
rcu_read_unlock();
|
|
@@ -484,22 +509,6 @@ mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx,
|
|
|
for (;;) {
|
|
|
struct task_struct *owner;
|
|
|
|
|
|
- if (use_ww_ctx && ww_ctx && ww_ctx->acquired > 0) {
|
|
|
- struct ww_mutex *ww;
|
|
|
-
|
|
|
- ww = container_of(lock, struct ww_mutex, base);
|
|
|
- /*
|
|
|
- * If ww->ctx is set the contents are undefined, only
|
|
|
- * by acquiring wait_lock there is a guarantee that
|
|
|
- * they are not invalid when reading.
|
|
|
- *
|
|
|
- * As such, when deadlock detection needs to be
|
|
|
- * performed the optimistic spinning cannot be done.
|
|
|
- */
|
|
|
- if (READ_ONCE(ww->ctx))
|
|
|
- goto fail_unlock;
|
|
|
- }
|
|
|
-
|
|
|
/* Try to acquire the mutex... */
|
|
|
owner = __mutex_trylock_or_owner(lock);
|
|
|
if (!owner)
|
|
@@ -509,7 +518,7 @@ mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx,
|
|
|
* There's an owner, wait for it to either
|
|
|
* release the lock or go to sleep.
|
|
|
*/
|
|
|
- if (!mutex_spin_on_owner(lock, owner))
|
|
|
+ if (!mutex_spin_on_owner(lock, owner, ww_ctx))
|
|
|
goto fail_unlock;
|
|
|
|
|
|
/*
|