Skip to contentSkip to conversation

rcutorture and documentation patches for 3.6

PATCH In review Paul E. McKenney 3 participants 18 messages Jun 15, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover rcutorture and documentation patches for 3.6

Hello!

This patch series updates documentation and rcutorture:

1. Update documentation to allow for the new call_srcu() and
srcu_barrier() functions.
2. Fix ordering of the torture_ops list.
3. Make rcutorture actually test the new srcu_barrier() function.
4. Fix synchronization of the kthreads testing the various
rcu_barrier() functions.
5. Fix an incorrect (and quite confusing) message in rcutorture.
6. Make rcutorture's fakewriters occasionally invoke the appropriate
rcu_barrier() function so that we test concurrent rcu_barrier() calls.

Thanx, Paul

 b/Documentation/RCU/checklist.txt  |   39 ++++++++++++++++++-------------------
 b/Documentation/RCU/rcubarrier.txt |    6 +++--
 b/Documentation/RCU/torture.txt    |    9 ++++++++
 b/Documentation/RCU/whatisRCU.txt  |    6 ++---
 b/kernel/rcutorture.c              |    4 +--
 kernel/rcutorture.c                |   32 ++++++++++++++++++++++++------
 6 files changed, 64 insertions(+), 32 deletions(-)
#1 lore raw

PATCH 1/6 rcu: Update documentation to cover call_srcu() and srcu_barrier().

From: "Paul E. McKenney" <[email protected]>

The advent of call_srcu() and srcu_barrier() obsoleted some of the documentation, so this commit brings that up to date.

---
 Documentation/RCU/checklist.txt  |   39 +++++++++++++++++++------------------
 Documentation/RCU/rcubarrier.txt |    6 +++-
 Documentation/RCU/torture.txt    |    9 ++++++++
 Documentation/RCU/whatisRCU.txt  |    6 ++--
 4 files changed, 36 insertions(+), 24 deletions(-)
Documentation/RCU/checklist.txt +20 -19
index 5c8d749..fc103d7 100644
@@ -162,9 +162,9 @@ over a rather long period of time, but improvements are always welcome!
 		when publicizing a pointer to a structure that can
 		be traversed by an RCU read-side critical section.
 
-5.	If call_rcu(), or a related primitive such as call_rcu_bh() or
-	call_rcu_sched(), is used, the callback function must be
-	written to be called from softirq context.  In particular,
+5.	If call_rcu(), or a related primitive such as call_rcu_bh(),
+	call_rcu_sched(), or call_srcu() is used, the callback function
+	must be written to be called from softirq context.  In particular,
 	it cannot block.
 
 6.	Since synchronize_rcu() can block, it cannot be called from
@@ -202,11 +202,12 @@ over a rather long period of time, but improvements are always welcome!
 	updater uses call_rcu_sched() or synchronize_sched(), then
 	the corresponding readers must disable preemption, possibly
 	by calling rcu_read_lock_sched() and rcu_read_unlock_sched().
-	If the updater uses synchronize_srcu(), the the corresponding
-	readers must use srcu_read_lock() and srcu_read_unlock(),
-	and with the same srcu_struct.	The rules for the expedited
-	primitives are the same as for their non-expedited counterparts.
-	Mixing things up will result in confusion and broken kernels.
+	If the updater uses synchronize_srcu() or call_srcu(),
+	the the corresponding readers must use srcu_read_lock() and
+	srcu_read_unlock(), and with the same srcu_struct.  The rules for
+	the expedited primitives are the same as for their non-expedited
+	counterparts.  Mixing things up will result in confusion and
+	broken kernels.
 
 	One exception to this rule: rcu_read_lock() and rcu_read_unlock()
 	may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
@@ -333,14 +334,14 @@ over a rather long period of time, but improvements are always welcome!
 	victim CPU from ever going offline.)
 
 14.	SRCU (srcu_read_lock(), srcu_read_unlock(), srcu_dereference(),
-	synchronize_srcu(), and synchronize_srcu_expedited()) may only
-	be invoked from process context.  Unlike other forms of RCU, it
-	-is- permissible to block in an SRCU read-side critical section
-	(demarked by srcu_read_lock() and srcu_read_unlock()), hence the
-	"SRCU": "sleepable RCU".  Please note that if you don't need
-	to sleep in read-side critical sections, you should be using
-	RCU rather than SRCU, because RCU is almost always faster and
-	easier to use than is SRCU.
+	synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu())
+	may only be invoked from process context.  Unlike other forms of
+	RCU, it -is- permissible to block in an SRCU read-side critical
+	section (demarked by srcu_read_lock() and srcu_read_unlock()),
+	hence the "SRCU": "sleepable RCU".  Please note that if you
+	don't need to sleep in read-side critical sections, you should be
+	using RCU rather than SRCU, because RCU is almost always faster
+	and easier to use than is SRCU.
 
 	If you need to enter your read-side critical section in a
 	hardirq or exception handler, and then exit that same read-side
@@ -353,8 +354,8 @@ over a rather long period of time, but improvements are always welcome!
 	cleanup_srcu_struct().	These are passed a "struct srcu_struct"
 	that defines the scope of a given SRCU domain.	Once initialized,
 	the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
-	synchronize_srcu(), and synchronize_srcu_expedited().  A given
-	synchronize_srcu() waits only for SRCU read-side critical
+	synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu().
+	A given synchronize_srcu() waits only for SRCU read-side critical
 	sections governed by srcu_read_lock() and srcu_read_unlock()
 	calls that have been passed the same srcu_struct.  This property
 	is what makes sleeping read-side critical sections tolerable --
@@ -374,7 +375,7 @@ over a rather long period of time, but improvements are always welcome!
 	requiring SRCU's read-side deadlock immunity or low read-side
 	realtime latency.
 
-	Note that, rcu_assign_pointer() relates to SRCU just as they do
+	Note that, rcu_assign_pointer() relates to SRCU just as it does
 	to other forms of RCU.
 
 15.	The whole point of call_rcu(), synchronize_rcu(), and friends
Documentation/RCU/rcubarrier.txt +4 -2
index e439a0e..a511fe6 100644
@@ -261,8 +261,10 @@ Answers to Quick Quizzes
 
 Quick Quiz #1: Why is there no srcu_barrier()?
 
-Answer: Since there is no call_srcu(), there can be no outstanding SRCU
-	callbacks. Therefore, there is no need to wait for them.
+Answer: There really is an srcu_barrier() now that there is a call_srcu().
+	Before call_srcu(), there were no SRCU callbacks, and there was
+	therefore no need to wait for them, and therefore there was
+	no srcu_barrier().
 
 Quick Quiz #2: Is there any other situation where rcu_barrier() might
 	be required?
Documentation/RCU/torture.txt +9 -0
index 4ddf391..7dce8a1 100644
@@ -174,11 +174,20 @@ torture_type	The type of RCU to test, with string values as follows:
 			and synchronize_rcu_bh_expedited().
 
 		"srcu": srcu_read_lock(), srcu_read_unlock() and
+			call_srcu().
+
+		"srcu_sync": srcu_read_lock(), srcu_read_unlock() and
 			synchronize_srcu().
 
 		"srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
 			synchronize_srcu_expedited().
 
+		"srcu_raw": srcu_read_lock_raw(), srcu_read_unlock_raw(),
+			and call_srcu().
+
+		"srcu_raw_sync": srcu_read_lock_raw(), srcu_read_unlock_raw(),
+			and synchronize_srcu().
+
 		"sched": preempt_disable(), preempt_enable(), and
 			call_rcu_sched().
 
Documentation/RCU/whatisRCU.txt +3 -3
index 6bbe8dc..69ee188 100644
@@ -833,9 +833,9 @@ sched:	Critical sections	Grace period		Barrier
 
 SRCU:	Critical sections	Grace period		Barrier
 
-	srcu_read_lock		synchronize_srcu	N/A
-	srcu_read_unlock	synchronize_srcu_expedited
-	srcu_read_lock_raw
+	srcu_read_lock		synchronize_srcu	srcu_barrier
+	srcu_read_unlock	call_srcu
+	srcu_read_lock_raw	synchronize_srcu_expedited
 	srcu_read_unlock_raw
 	srcu_dereference
 
Signature · 1 line
1.7.8
#2 lore raw

PATCH 2/6 rcu: Rationalize ordering of torture_ops list

From: "Paul E. McKenney" <[email protected]>

Move the raw SRCU interfaces out of the middle of the normal SRCU interfaces.

---
 kernel/rcutorture.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/rcutorture.c +2 -2
index e66b34a..9850479 100644
@@ -1908,8 +1908,8 @@ rcu_torture_init(void)
 	static struct rcu_torture_ops *torture_ops[] =
 		{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
 		  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
-		  &srcu_ops, &srcu_sync_ops, &srcu_raw_ops,
-		  &srcu_raw_sync_ops, &srcu_expedited_ops,
+		  &srcu_ops, &srcu_sync_ops, &srcu_expedited_ops,
+		  &srcu_raw_ops, &srcu_raw_sync_ops,
 		  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
 
 	mutex_lock(&fullstop_mutex);
Signature · 1 line
1.7.8
maintainer Reviewed-by on v1 2/6
#3 lore raw

Re: [PATCH tip/core/rcu 2/6] rcu: Rationalize ordering of torture_ops list

Quoted 6 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

Move the raw SRCU interfaces out of the middle of the normal SRCU interfaces.

Quoted 22 lines
---
 kernel/rcutorture.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/rcutorture.c +2 -2
index e66b34a..9850479 100644
@@ -1908,8 +1908,8 @@ rcu_torture_init(void)
 	static struct rcu_torture_ops *torture_ops[] =
 		{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
 		  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
-		  &srcu_ops, &srcu_sync_ops, &srcu_raw_ops,
-		  &srcu_raw_sync_ops, &srcu_expedited_ops,
+		  &srcu_ops, &srcu_sync_ops, &srcu_expedited_ops,
+		  &srcu_raw_ops, &srcu_raw_sync_ops,
 		  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
 
 	mutex_lock(&fullstop_mutex);
Signature · 1 line
1.7.8
#4 lore raw

PATCH 3/6 rcu: Test srcu_barrier() from rcutorture test suite

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

SRCU now has a call_srcu() and an srcu_barrier(), but rcutorture does not test srcu_barrier(). This commit adds the machinery to allow rcutorture's existing rcu_barrier() tests to apply to SRCU.

---
 kernel/rcutorture.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
kernel/rcutorture.c +13 -2
index 9850479..7b6935e 100644
@@ -635,6 +635,17 @@ static void srcu_torture_synchronize(void)
 	synchronize_srcu(&srcu_ctl);
 }
 
+static void srcu_torture_call(struct rcu_head *head,
+			      void (*func)(struct rcu_head *head))
+{
+	call_srcu(&srcu_ctl, head, func);
+}
+
+static void srcu_torture_barrier(void)
+{
+	srcu_barrier(&srcu_ctl);
+}
+
 static int srcu_torture_stats(char *page)
 {
 	int cnt = 0;
@@ -661,8 +672,8 @@ static struct rcu_torture_ops srcu_ops = {
 	.completed	= srcu_torture_completed,
 	.deferred_free	= srcu_torture_deferred_free,
 	.sync		= srcu_torture_synchronize,
-	.call		= NULL,
-	.cb_barrier	= NULL,
+	.call		= srcu_torture_call,
+	.cb_barrier	= srcu_torture_barrier,
 	.stats		= srcu_torture_stats,
 	.name		= "srcu"
 };
Signature · 1 line
1.7.8
maintainer Reviewed-by on v1 3/6
#5 lore raw

Re: [PATCH tip/core/rcu 3/6] rcu: Test srcu_barrier() from rcutorture test suite

Quoted 7 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

SRCU now has a call_srcu() and an srcu_barrier(), but rcutorture does not test srcu_barrier(). This commit adds the machinery to allow rcutorture's existing rcu_barrier() tests to apply to SRCU.

This commit message suggests that the commit only adds support for testing srcu_barrier, but it adds both call_srcu and srcu_barrier. You might want to wordsmith it a bit:

SRCU now has a call_srcu() and an srcu_barrier(), but rcutorture does not test them. This commit adds the machinery to allow rcutorture's existing tests for call_rcu() and rcu_barrier() to apply to the SRCU equivalents.

With that change:

Quoted 40 lines
---
 kernel/rcutorture.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
kernel/rcutorture.c +13 -2
index 9850479..7b6935e 100644
@@ -635,6 +635,17 @@ static void srcu_torture_synchronize(void)
 	synchronize_srcu(&srcu_ctl);
 }
 
+static void srcu_torture_call(struct rcu_head *head,
+			      void (*func)(struct rcu_head *head))
+{
+	call_srcu(&srcu_ctl, head, func);
+}
+
+static void srcu_torture_barrier(void)
+{
+	srcu_barrier(&srcu_ctl);
+}
+
 static int srcu_torture_stats(char *page)
 {
 	int cnt = 0;
@@ -661,8 +672,8 @@ static struct rcu_torture_ops srcu_ops = {
 	.completed	= srcu_torture_completed,
 	.deferred_free	= srcu_torture_deferred_free,
 	.sync		= srcu_torture_synchronize,
-	.call		= NULL,
-	.cb_barrier	= NULL,
+	.call		= srcu_torture_call,
+	.cb_barrier	= srcu_torture_barrier,
 	.stats		= srcu_torture_stats,
 	.name		= "srcu"
 };
Signature · 1 line
1.7.8
#6 lore raw

PATCH 4/6 rcu: Fix bug in rcu_barrier() torture test

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The child threads in the rcu_torture_barrier_cbs() are improperly synchronized, which can cause the rcu_barrier() tests to hang. The failure mode is as follows:

1. CPU 0 running in rcu_torture_barrier() sets barrier_cbs_count
to n_barrier_cbs.

2. CPU 1 running in rcu_torture_barrier_cbs() wakes up, posts
its RCU callback, and atomically decrements barrier_cbs_count. Because barrier_cbs_count is not zero, it does not do the wake_up().

3. CPU 2 running in rcu_torture_barrier_cbs() wakes up, but
finds that barrier_cbs_count is not equal to n_barrier_cbs, and so returns to sleep.

4. The value of barrier_cbs_count therefore never reaches zero,
which causes the test to hang.

This commit therefore uses a phase variable to coordinate the test, preventing this scenario from occurring.

---
 kernel/rcutorture.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
kernel/rcutorture.c +7 -2
index 7b6935e..08d8537 100644
@@ -206,6 +206,7 @@ static unsigned long boost_starttime;	/* jiffies of next boost test start. */
 DEFINE_MUTEX(boost_mutex);		/* protect setting boost_starttime */
 					/*  and boost task create/destroy. */
 static atomic_t barrier_cbs_count;	/* Barrier callbacks registered. */
+static bool barrier_phase;		/* Test phase. */
 static atomic_t barrier_cbs_invoked;	/* Barrier callbacks invoked. */
 static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
 static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
@@ -1642,6 +1643,7 @@ void rcu_torture_barrier_cbf(struct rcu_head *rcu)
 static int rcu_torture_barrier_cbs(void *arg)
 {
 	long myid = (long)arg;
+	bool lastphase = 0;
 	struct rcu_head rcu;
 
 	init_rcu_head_on_stack(&rcu);
@@ -1649,9 +1651,11 @@ static int rcu_torture_barrier_cbs(void *arg)
 	set_user_nice(current, 19);
 	do {
 		wait_event(barrier_cbs_wq[myid],
-			   atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
+			   barrier_phase != lastphase ||
 			   kthread_should_stop() ||
 			   fullstop != FULLSTOP_DONTSTOP);
+		lastphase = barrier_phase;
+		smp_mb();
 		if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
 			break;
 		cur_ops->call(&rcu, rcu_torture_barrier_cbf);
@@ -1676,7 +1680,8 @@ static int rcu_torture_barrier(void *arg)
 	do {
 		atomic_set(&barrier_cbs_invoked, 0);
 		atomic_set(&barrier_cbs_count, n_barrier_cbs);
-		/* wake_up() path contains the required barriers. */
+		smp_mb();
+		barrier_phase = !barrier_phase;
 		for (i = 0; i < n_barrier_cbs; i++)
 			wake_up(&barrier_cbs_wq[i]);
 		wait_event(barrier_wq,
Signature · 1 line
1.7.8
#7 lore raw

Re: [PATCH tip/core/rcu 4/6] rcu: Fix bug in rcu_barrier() torture test

* Paul E. McKenney ([email protected]) wrote:
[...]

Quoted 9 lines
kernel/rcutorture.c +1 -0
@@ -1642,6 +1643,7 @@ void rcu_torture_barrier_cbf(struct rcu_head *rcu)
 static int rcu_torture_barrier_cbs(void *arg)
 {
 	long myid = (long)arg;
+	bool lastphase = 0;
 	struct rcu_head rcu;
 
 	init_rcu_head_on_stack(&rcu);

kernel/rcutorture.c static int rcu_torture_barrier_cbs(void *arg) · line 1658

Quoted 9 lines
kernel/rcutorture.c +3 -1
@@ -1649,9 +1651,11 @@ static int rcu_torture_barrier_cbs(void *arg)
 	set_user_nice(current, 19);
 	do {
 		wait_event(barrier_cbs_wq[myid],
-			   atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
+			   barrier_phase != lastphase ||
 			   kthread_should_stop() ||
 			   fullstop != FULLSTOP_DONTSTOP);
+		lastphase = barrier_phase;
+		smp_mb();

Hi Paul,

Documenting this barrier, and the barrier below, along with the variable accesses they order, would appear to be a good idea, especially since the bug this is correcting was caused by the lack of appropriate smp_mb().

Thanks,

Mathieu

Quoted 16 lines
kernel/rcutorture.c +2 -1
 		if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
 			break;
 		cur_ops->call(&rcu, rcu_torture_barrier_cbf);
@@ -1676,7 +1680,8 @@ static int rcu_torture_barrier(void *arg)
 	do {
 		atomic_set(&barrier_cbs_invoked, 0);
 		atomic_set(&barrier_cbs_count, n_barrier_cbs);
-		/* wake_up() path contains the required barriers. */
+		smp_mb();
+		barrier_phase = !barrier_phase;
 		for (i = 0; i < n_barrier_cbs; i++)
 			wake_up(&barrier_cbs_wq[i]);
 		wait_event(barrier_wq,
Signature · 1 line
1.7.8
Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#8 lore raw

Re: [PATCH tip/core/rcu 4/6] rcu: Fix bug in rcu_barrier() torture test

Quoted 23 lines · Mathieu Desnoyers

* Paul E. McKenney ([email protected]) wrote:
[...]

Quoted 9 lines
kernel/rcutorture.c +1 -0
@@ -1642,6 +1643,7 @@ void rcu_torture_barrier_cbf(struct rcu_head *rcu)
 static int rcu_torture_barrier_cbs(void *arg)
 {
 	long myid = (long)arg;
+	bool lastphase = 0;
 	struct rcu_head rcu;
 
 	init_rcu_head_on_stack(&rcu);

kernel/rcutorture.c static int rcu_torture_barrier_cbs(void *arg) · line 1658

Quoted 9 lines
kernel/rcutorture.c +3 -1
@@ -1649,9 +1651,11 @@ static int rcu_torture_barrier_cbs(void *arg)
 	set_user_nice(current, 19);
 	do {
 		wait_event(barrier_cbs_wq[myid],
-			   atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
+			   barrier_phase != lastphase ||
 			   kthread_should_stop() ||
 			   fullstop != FULLSTOP_DONTSTOP);
+		lastphase = barrier_phase;
+		smp_mb();

Hi Paul,

Quoted 4 lines

Documenting this barrier, and the barrier below, along with the variable accesses they order, would appear to be a good idea, especially since the bug this is correcting was caused by the lack of appropriate smp_mb().

Fair point, even in rcutorture. Or maybe especially in rcutorture...

Will fix!

Thanx, Paul

Quoted 27 lines

Thanks,

Mathieu

Quoted 16 lines
kernel/rcutorture.c +2 -1
 		if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
 			break;
 		cur_ops->call(&rcu, rcu_torture_barrier_cbf);
@@ -1676,7 +1680,8 @@ static int rcu_torture_barrier(void *arg)
 	do {
 		atomic_set(&barrier_cbs_invoked, 0);
 		atomic_set(&barrier_cbs_count, n_barrier_cbs);
-		/* wake_up() path contains the required barriers. */
+		smp_mb();
+		barrier_phase = !barrier_phase;
 		for (i = 0; i < n_barrier_cbs; i++)
 			wake_up(&barrier_cbs_wq[i]);
 		wait_event(barrier_wq,
Signature · 1 line
1.7.8
Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#9 lore raw

PATCH 5/6 rcu: Fix diagnostic-printk typo in rcutorture

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The rcu_torture_barrier() function has a copy-and-paste typo in the string passed to rcutorture_shutdown_absorb(), which this commit fixes.

---
 kernel/rcutorture.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/rcutorture.c +1 -1
index 08d8537..54a3745 100644
@@ -1700,7 +1700,7 @@ static int rcu_torture_barrier(void *arg)
 		schedule_timeout_interruptible(HZ / 10);
 	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 	VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
-	rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+	rcutorture_shutdown_absorb("rcu_torture_barrier");
 	while (!kthread_should_stop())
 		schedule_timeout_interruptible(1);
 	return 0;
Signature · 1 line
1.7.8
maintainer Reviewed-by on v1 5/6
#10 lore raw

Re: [PATCH tip/core/rcu 5/6] rcu: Fix diagnostic-printk typo in rcutorture

Quoted 7 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The rcu_torture_barrier() function has a copy-and-paste typo in the string passed to rcutorture_shutdown_absorb(), which this commit fixes.

Quoted 20 lines
---
 kernel/rcutorture.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/rcutorture.c +1 -1
index 08d8537..54a3745 100644
@@ -1700,7 +1700,7 @@ static int rcu_torture_barrier(void *arg)
 		schedule_timeout_interruptible(HZ / 10);
 	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 	VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
-	rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+	rcutorture_shutdown_absorb("rcu_torture_barrier");
 	while (!kthread_should_stop())
 		schedule_timeout_interruptible(1);
 	return 0;
Signature · 1 line
1.7.8
#11 lore raw

PATCH 6/6 rcu: Make rcutorture fakewriters invoke rcu_barrier()

In reply to Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The current rcutorture rcu_barrier() testing never intentionally runs more than one instance of rcu_barrier() at a given time. This fails to test the the shiny new concurrency features of rcu_barrier(). This commit therefore modifies the rcutorture fakewriter kthread to randomly invoke rcu_barrier() rather than the usual synchronize_rcu().

---
 kernel/rcutorture.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
kernel/rcutorture.c +5 -1
index 54a3745..dfb4e20 100644
@@ -1025,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
 		udelay(rcu_random(&rand) & 0x3ff);
-		cur_ops->sync();
+		if (cur_ops->cb_barrier != NULL &&
+		    rcu_random(&rand) % (NR_CPUS * 8) == 0)
+			cur_ops->cb_barrier();
+		else
+			cur_ops->sync();
 		rcu_stutter_wait("rcu_torture_fakewriter");
 	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 
Signature · 1 line
1.7.8
maintainer
#12 lore raw

Re: [PATCH tip/core/rcu 6/6] rcu: Make rcutorture fakewriters invoke rcu_barrier()

Quoted 19 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The current rcutorture rcu_barrier() testing never intentionally runs more than one instance of rcu_barrier() at a given time. This fails to test the the shiny new concurrency features of rcu_barrier(). This commit therefore modifies the rcutorture fakewriter kthread to randomly invoke rcu_barrier() rather than the usual synchronize_rcu().

---
 kernel/rcutorture.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
kernel/rcutorture.c +0 -0
index 54a3745..dfb4e20 100644

kernel/rcutorture.c rcu_torture_fakewriter(void *arg) · line 1029

Quoted 6 lines
kernel/rcutorture.c +2 -1
@@ -1025,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
 		udelay(rcu_random(&rand) & 0x3ff);
-		cur_ops->sync();
+		if (cur_ops->cb_barrier != NULL &&
+		    rcu_random(&rand) % (NR_CPUS * 8) == 0)

NR_CPUS seems like an odd choice here. I assume you want to control for having many rcu_torture_fakewriter threads, and aim for the same average rate of barrier calls across the whole set of threads regardless of the number of threads. However, NR_CPUS does not accurately reflect either the number of fakewriter threads (which a user can set arbitrarily) or the number of CPUs currently on the system (since NR_CPUS represents the compile-time limit). I'd suggest changing this to use the actual number of fakewriter threads, which rcutorture knows at start time.

- Josh Triplett

#13 lore raw

Re: [PATCH tip/core/rcu 6/6] rcu: Make rcutorture fakewriters invoke rcu_barrier()

Quoted 27 lines · Josh Triplett
Quoted 19 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The current rcutorture rcu_barrier() testing never intentionally runs more than one instance of rcu_barrier() at a given time. This fails to test the the shiny new concurrency features of rcu_barrier(). This commit therefore modifies the rcutorture fakewriter kthread to randomly invoke rcu_barrier() rather than the usual synchronize_rcu().

---
 kernel/rcutorture.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
kernel/rcutorture.c +0 -0
index 54a3745..dfb4e20 100644

kernel/rcutorture.c rcu_torture_fakewriter(void *arg) · line 1029

Quoted 6 lines
kernel/rcutorture.c +2 -1
@@ -1025,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
 		udelay(rcu_random(&rand) & 0x3ff);
-		cur_ops->sync();
+		if (cur_ops->cb_barrier != NULL &&
+		    rcu_random(&rand) % (NR_CPUS * 8) == 0)
Quoted 8 lines

NR_CPUS seems like an odd choice here. I assume you want to control for having many rcu_torture_fakewriter threads, and aim for the same average rate of barrier calls across the whole set of threads regardless of the number of threads. However, NR_CPUS does not accurately reflect either the number of fakewriter threads (which a user can set arbitrarily) or the number of CPUs currently on the system (since NR_CPUS represents the compile-time limit). I'd suggest changing this to use the actual number of fakewriter threads, which rcutorture knows at start time.

Indeed, this should use the number of online CPUs. Which should be easy to compute, will fix.

Also will fix the commit message as suggested, and apply your reviewed-bys as specified.

Thanx, Paul

maintainer
#14 lore raw

Re: [PATCH tip/core/rcu 6/6] rcu: Make rcutorture fakewriters invoke rcu_barrier()

Quoted 37 lines · Paul E. McKenney
Quoted 27 lines · Josh Triplett
Quoted 19 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The current rcutorture rcu_barrier() testing never intentionally runs more than one instance of rcu_barrier() at a given time. This fails to test the the shiny new concurrency features of rcu_barrier(). This commit therefore modifies the rcutorture fakewriter kthread to randomly invoke rcu_barrier() rather than the usual synchronize_rcu().

---
 kernel/rcutorture.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
kernel/rcutorture.c +0 -0
index 54a3745..dfb4e20 100644

kernel/rcutorture.c rcu_torture_fakewriter(void *arg) · line 1029

Quoted 6 lines
kernel/rcutorture.c +2 -1
@@ -1025,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
 		udelay(rcu_random(&rand) & 0x3ff);
-		cur_ops->sync();
+		if (cur_ops->cb_barrier != NULL &&
+		    rcu_random(&rand) % (NR_CPUS * 8) == 0)
Quoted 8 lines

NR_CPUS seems like an odd choice here. I assume you want to control for having many rcu_torture_fakewriter threads, and aim for the same average rate of barrier calls across the whole set of threads regardless of the number of threads. However, NR_CPUS does not accurately reflect either the number of fakewriter threads (which a user can set arbitrarily) or the number of CPUs currently on the system (since NR_CPUS represents the compile-time limit). I'd suggest changing this to use the actual number of fakewriter threads, which rcutorture knows at start time.

Quoted 2 lines

Indeed, this should use the number of online CPUs. Which should be easy to compute, will fix.

I'd suggest using nfakewriters instead.

- Josh Triplett

#15 lore raw

Re: [PATCH tip/core/rcu 6/6] rcu: Make rcutorture fakewriters invoke rcu_barrier()

Quoted 38 lines · Josh Triplett
Quoted 37 lines · Paul E. McKenney
Quoted 35 lines · Josh Triplett
Quoted 19 lines · Paul E. McKenney

From: "Paul E. McKenney" <[email protected]>

The current rcutorture rcu_barrier() testing never intentionally runs more than one instance of rcu_barrier() at a given time. This fails to test the the shiny new concurrency features of rcu_barrier(). This commit therefore modifies the rcutorture fakewriter kthread to randomly invoke rcu_barrier() rather than the usual synchronize_rcu().

---
 kernel/rcutorture.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
kernel/rcutorture.c +0 -0
index 54a3745..dfb4e20 100644

kernel/rcutorture.c rcu_torture_fakewriter(void *arg) · line 1029

Quoted 6 lines
kernel/rcutorture.c +2 -1
@@ -1025,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
 	do {
 		schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
 		udelay(rcu_random(&rand) & 0x3ff);
-		cur_ops->sync();
+		if (cur_ops->cb_barrier != NULL &&
+		    rcu_random(&rand) % (NR_CPUS * 8) == 0)

NR_CPUS seems like an odd choice here. I assume you want to control for having many rcu_torture_fakewriter threads, and aim for the same average rate of barrier calls across the whole set of threads regardless of the number of threads. However, NR_CPUS does not accurately reflect either the number of fakewriter threads (which a user can set arbitrarily) or the number of CPUs currently on the system (since NR_CPUS represents the compile-time limit). I'd suggest changing this to use the actual number of fakewriter threads, which rcutorture knows at start time.

Quoted 4 lines
Quoted 2 lines

Indeed, this should use the number of online CPUs. Which should be easy to compute, will fix.

I'd suggest using nfakewriters instead.

Right... Fixed, thank you!!!

Thanx, Paul

maintainer
#16 lore raw

Re: [PATCH tip/core/rcu 1/6] rcu: Update documentation to cover call_srcu() and srcu_barrier().

In reply to Paul E. McKenney

Documentation/RCU/rcubarrier.txt Answers to Quick Quizzes · line 267

Quoted 12 lines · Paul E. McKenney
Documentation/RCU/rcubarrier.txt +4 -2
@@ -261,8 +261,10 @@ Answers to Quick Quizzes
 
 Quick Quiz #1: Why is there no srcu_barrier()?
 
-Answer: Since there is no call_srcu(), there can be no outstanding SRCU
-	callbacks. Therefore, there is no need to wait for them.
+Answer: There really is an srcu_barrier() now that there is a call_srcu().
+	Before call_srcu(), there were no SRCU callbacks, and there was
+	therefore no need to wait for them, and therefore there was
+	no srcu_barrier().

I don't think it makes sense to leave this question in its current form and just change the answer. It seems like a trick question now. :)

I'd suggest just dropping the question and renumbering the remaining questions.

- Josh Triplett

#17 lore raw

Re: [PATCH tip/core/rcu 1/6] rcu: Update documentation to cover call_srcu() and srcu_barrier().

Quoted 17 lines · Josh Triplett

Documentation/RCU/rcubarrier.txt Answers to Quick Quizzes · line 267

Quoted 12 lines · Paul E. McKenney
Documentation/RCU/rcubarrier.txt +4 -2
@@ -261,8 +261,10 @@ Answers to Quick Quizzes
 
 Quick Quiz #1: Why is there no srcu_barrier()?
 
-Answer: Since there is no call_srcu(), there can be no outstanding SRCU
-	callbacks. Therefore, there is no need to wait for them.
+Answer: There really is an srcu_barrier() now that there is a call_srcu().
+	Before call_srcu(), there were no SRCU callbacks, and there was
+	therefore no need to wait for them, and therefore there was
+	no srcu_barrier().

I don't think it makes sense to leave this question in its current form and just change the answer. It seems like a trick question now. :)

Quoted 2 lines

I'd suggest just dropping the question and renumbering the remaining questions.

But I -like- trick questions!!! ;-)

I will nevertheless update as suggested.

Thanx, Paul