Commit 6e204488 authored by Paul E. McKenney's avatar Paul E. McKenney Committed by Boqun Feng
Browse files

rcutorture: Add RCU Tasks Trace and SRCU deadlock scenarios



Add a test number 3 that creates deadlock cycles involving one RCU
Tasks Trace step and L-1 SRCU steps.  Please note that lockdep will not
detect these deadlocks until synchronize_rcu_tasks_trace() is marked
with lockdep's new "sync" annotation, which will probably not happen
until some time after these markings prove their worth on SRCU.

Please note that these tests are available only in kernels built with
CONFIG_TASKS_TRACE_RCU=y.

Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBoqun Feng <boqun.feng@gmail.com>
parent d94f12e8
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -3604,12 +3604,46 @@ static void rcu_torture_init_srcu_lockdep(void)
		return;
	}

#ifdef CONFIG_TASKS_TRACE_RCU
	if (testtype == 3) {
		pr_info("%s: test_srcu_lockdep = %05d: SRCU and Tasks Trace RCU %d-way %sdeadlock.\n",
			__func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
		if (deadlock && cyclelen == 1)
			pr_info("%s: Expect hang.\n", __func__);
		for (i = 0; i < cyclelen; i++) {
			char *fl = i == 0 ? "rcu_read_lock_trace" : "srcu_read_lock";
			char *fs = i == cyclelen - 1 ? "synchronize_rcu_tasks_trace"
						     : "synchronize_srcu";
			char *fu = i == 0 ? "rcu_read_unlock_trace" : "srcu_read_unlock";

			j = srcu_lockdep_next(__func__, fl, fs, fu, i, cyclelen, deadlock);
			if (i == 0)
				rcu_read_lock_trace();
			else
				idx = srcu_read_lock(srcus[i]);
			if (j >= 0) {
				if (i == cyclelen - 1)
					synchronize_rcu_tasks_trace();
				else
					synchronize_srcu(srcus[j]);
			}
			if (i == 0)
				rcu_read_unlock_trace();
			else
				srcu_read_unlock(srcus[i], idx);
		}
		return;
	}
#endif // #ifdef CONFIG_TASKS_TRACE_RCU

err_out:
	pr_info("%s: test_srcu_lockdep = %05d does nothing.\n", __func__, test_srcu_lockdep);
	pr_info("%s: test_srcu_lockdep = DNNL.\n", __func__);
	pr_info("%s: D: Deadlock if nonzero.\n", __func__);
	pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem.\n", __func__);
	pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem, 3=SRCU/Tasks Trace RCU.\n", __func__);
	pr_info("%s: L: Cycle length.\n", __func__);
	if (!IS_ENABLED(CONFIG_TASKS_TRACE_RCU))
		pr_info("%s: NN=3 disallowed because kernel is built with CONFIG_TASKS_TRACE_RCU=n\n", __func__);
}

static int __init