Commit 5860f5ce authored by Kumar Kartikeya Dwivedi's avatar Kumar Kartikeya Dwivedi Committed by Alexei Starovoitov
Browse files

rqspinlock: Perform AA checks immediately



Currently, while we enter the check_timeout call immediately due to the
way the ts.spin is initialized, we still invoke the AA and ABBA checks
in the second invocation, and only initialize the timestamp in the first
one. Since each iteration is at least done with a 1ms delay, this can
add delays in detection of AA deadlocks, up to a ms.

Rework check_timeout() to avoid this. First, call check_deadlock_AA()
while initializing the timestamps for the wait period. This also means
that we only do it once per waiting period, instead of every invocation.
Finally, drop check_deadlock() and call check_deadlock_ABBA() directly.

To save on unnecessary ktime_get_mono_fast_ns() in case of AA deadlock,
sample the time only if it returns 0.

Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20251128232802.1031906-3-memxor@gmail.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent beb7021a
Loading
Loading
Loading
Loading
+7 −18
Original line number Diff line number Diff line
@@ -196,32 +196,21 @@ static noinline int check_deadlock_ABBA(rqspinlock_t *lock, u32 mask)
	return 0;
}

static noinline int check_deadlock(rqspinlock_t *lock, u32 mask)
{
	int ret;

	ret = check_deadlock_AA(lock);
	if (ret)
		return ret;
	ret = check_deadlock_ABBA(lock, mask);
	if (ret)
		return ret;

	return 0;
}

static noinline int check_timeout(rqspinlock_t *lock, u32 mask,
				  struct rqspinlock_timeout *ts)
{
	u64 time = ktime_get_mono_fast_ns();
	u64 prev = ts->cur;
	u64 time;

	if (!ts->timeout_end) {
		ts->cur = time;
		ts->timeout_end = time + ts->duration;
		if (check_deadlock_AA(lock))
			return -EDEADLK;
		ts->cur = ktime_get_mono_fast_ns();
		ts->timeout_end = ts->cur + ts->duration;
		return 0;
	}

	time = ktime_get_mono_fast_ns();
	if (time > ts->timeout_end)
		return -ETIMEDOUT;

@@ -231,7 +220,7 @@ static noinline int check_timeout(rqspinlock_t *lock, u32 mask,
	 */
	if (prev + NSEC_PER_MSEC < time) {
		ts->cur = time;
		return check_deadlock(lock, mask);
		return check_deadlock_ABBA(lock, mask);
	}

	return 0;