diff mbox series

[RFC,v3,04/15] rcu: Add a small-width RCU watching counter debug option

Message ID 20241119153502.41361-5-vschneid@redhat.com (mailing list archive)
State New
Headers show
Series context_tracking,x86: Defer some IPIs until a user->kernel transition | expand

Commit Message

Valentin Schneider Nov. 19, 2024, 3:34 p.m. UTC
A later commit will reduce the size of the RCU watching counter to free up
some bits for another purpose. Paul suggested adding a config option to
test the extreme case where the counter is reduced to its minimum usable
width for rcutorture to poke at, so do that.

Make it only configurable under RCU_EXPERT. While at it, add a comment to
explain the layout of context_tracking->state.

Link: http://lore.kernel.org/r/4c2cb573-168f-4806-b1d9-164e8276e66a@paulmck-laptop
Suggested-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Valentin Schneider <vschneid@redhat.com>
---
 include/linux/context_tracking_state.h | 44 ++++++++++++++++++++++----
 kernel/rcu/Kconfig.debug               | 14 ++++++++
 2 files changed, 51 insertions(+), 7 deletions(-)

Comments

Peter Zijlstra Nov. 20, 2024, 2:50 p.m. UTC | #1
On Tue, Nov 19, 2024 at 04:34:51PM +0100, Valentin Schneider wrote:
> A later commit will reduce the size of the RCU watching counter to free up
> some bits for another purpose. Paul suggested adding a config option to
> test the extreme case where the counter is reduced to its minimum usable
> width for rcutorture to poke at, so do that.
> 
> Make it only configurable under RCU_EXPERT. While at it, add a comment to
> explain the layout of context_tracking->state.

Note that this means it will get selected by allyesconfig and the like,
is that desired?

If no, depends on !COMPILE_TEST can help here.
Valentin Schneider Nov. 20, 2024, 4:15 p.m. UTC | #2
On 20/11/24 15:50, Peter Zijlstra wrote:
> On Tue, Nov 19, 2024 at 04:34:51PM +0100, Valentin Schneider wrote:
>> A later commit will reduce the size of the RCU watching counter to free up
>> some bits for another purpose. Paul suggested adding a config option to
>> test the extreme case where the counter is reduced to its minimum usable
>> width for rcutorture to poke at, so do that.
>> 
>> Make it only configurable under RCU_EXPERT. While at it, add a comment to
>> explain the layout of context_tracking->state.
>
> Note that this means it will get selected by allyesconfig and the like,
> is that desired?
>

I would say no

> If no, depends on !COMPILE_TEST can help here.

Noted, thank you!
Paul E. McKenney Nov. 22, 2024, 12:53 p.m. UTC | #3
On Tue, Nov 19, 2024 at 04:34:51PM +0100, Valentin Schneider wrote:
> A later commit will reduce the size of the RCU watching counter to free up
> some bits for another purpose. Paul suggested adding a config option to
> test the extreme case where the counter is reduced to its minimum usable
> width for rcutorture to poke at, so do that.
> 
> Make it only configurable under RCU_EXPERT. While at it, add a comment to
> explain the layout of context_tracking->state.
> 
> Link: http://lore.kernel.org/r/4c2cb573-168f-4806-b1d9-164e8276e66a@paulmck-laptop
> Suggested-by: Paul E. McKenney <paulmck@kernel.org>
> Signed-off-by: Valentin Schneider <vschneid@redhat.com>

Looks good, one help-text nit below.

Reviewed-by: Paul E. McKenney <paulmck@kernel.org>

> ---
>  include/linux/context_tracking_state.h | 44 ++++++++++++++++++++++----
>  kernel/rcu/Kconfig.debug               | 14 ++++++++
>  2 files changed, 51 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/context_tracking_state.h b/include/linux/context_tracking_state.h
> index 7b8433d5a8efe..0b81248aa03e2 100644
> --- a/include/linux/context_tracking_state.h
> +++ b/include/linux/context_tracking_state.h
> @@ -18,12 +18,6 @@ enum ctx_state {
>  	CT_STATE_MAX		= 4,
>  };
>  
> -/* Odd value for watching, else even. */
> -#define CT_RCU_WATCHING CT_STATE_MAX
> -
> -#define CT_STATE_MASK (CT_STATE_MAX - 1)
> -#define CT_RCU_WATCHING_MASK (~CT_STATE_MASK)
> -
>  struct context_tracking {
>  #ifdef CONFIG_CONTEXT_TRACKING_USER
>  	/*
> @@ -44,9 +38,45 @@ struct context_tracking {
>  #endif
>  };
>  
> +/*
> + * We cram two different things within the same atomic variable:
> + *
> + *                     CT_RCU_WATCHING_START  CT_STATE_START
> + *                                |                |
> + *                                v                v
> + *     MSB [ RCU watching counter ][ context_state ] LSB
> + *         ^                       ^
> + *         |                       |
> + * CT_RCU_WATCHING_END        CT_STATE_END
> + *
> + * Bits are used from the LSB upwards, so unused bits (if any) will always be in
> + * upper bits of the variable.
> + */
>  #ifdef CONFIG_CONTEXT_TRACKING
> +#define CT_SIZE (sizeof(((struct context_tracking *)0)->state) * BITS_PER_BYTE)
> +
> +#define CT_STATE_WIDTH bits_per(CT_STATE_MAX - 1)
> +#define CT_STATE_START 0
> +#define CT_STATE_END   (CT_STATE_START + CT_STATE_WIDTH - 1)
> +
> +#define CT_RCU_WATCHING_MAX_WIDTH (CT_SIZE - CT_STATE_WIDTH)
> +#define CT_RCU_WATCHING_WIDTH     (IS_ENABLED(CONFIG_RCU_DYNTICKS_TORTURE) ? 2 : CT_RCU_WATCHING_MAX_WIDTH)
> +#define CT_RCU_WATCHING_START     (CT_STATE_END + 1)
> +#define CT_RCU_WATCHING_END       (CT_RCU_WATCHING_START + CT_RCU_WATCHING_WIDTH - 1)
> +#define CT_RCU_WATCHING           BIT(CT_RCU_WATCHING_START)
> +
> +#define CT_STATE_MASK        GENMASK(CT_STATE_END,        CT_STATE_START)
> +#define CT_RCU_WATCHING_MASK GENMASK(CT_RCU_WATCHING_END, CT_RCU_WATCHING_START)
> +
> +#define CT_UNUSED_WIDTH (CT_RCU_WATCHING_MAX_WIDTH - CT_RCU_WATCHING_WIDTH)
> +
> +static_assert(CT_STATE_WIDTH        +
> +	      CT_RCU_WATCHING_WIDTH +
> +	      CT_UNUSED_WIDTH       ==
> +	      CT_SIZE);
> +
>  DECLARE_PER_CPU(struct context_tracking, context_tracking);
> -#endif
> +#endif	/* CONFIG_CONTEXT_TRACKING */
>  
>  #ifdef CONFIG_CONTEXT_TRACKING_USER
>  static __always_inline int __ct_state(void)
> diff --git a/kernel/rcu/Kconfig.debug b/kernel/rcu/Kconfig.debug
> index 9b0b52e1836fa..8dc505d841f8d 100644
> --- a/kernel/rcu/Kconfig.debug
> +++ b/kernel/rcu/Kconfig.debug
> @@ -168,4 +168,18 @@ config RCU_STRICT_GRACE_PERIOD
>  	  when looking for certain types of RCU usage bugs, for example,
>  	  too-short RCU read-side critical sections.
>  
> +
> +config RCU_DYNTICKS_TORTURE
> +	bool "Minimize RCU dynticks counter size"
> +	depends on RCU_EXPERT
> +	default n
> +	help
> +	  This option controls the width of the dynticks counter.
> +
> +	  Lower values will make overflows more frequent, which will increase
> +	  the likelihood of extending grace-periods. This option sets the width
> +	  to its minimum usable value.

The second sentence ("Lower values ...") sounds at first reading like
this Kconfig option directly controls the width.  The third sentence sets
things straight, but the reader might well be irretrievably confused by
that point.  How about something like this instead?

	help
	  This option sets the width of the dynticks counter to its
	  minimum usable value.  This minimum width greatly increases
	  the probability of flushing out bugs involving counter wrap,
	  but it also increases the probability of extending grace period
	  durations.  This Kconfig option should therefore be avoided in
	  production due to the consequent increased probability of OOMs.

	  This has no value for production and is only for testing.

>  endmenu # "RCU Debugging"
> -- 
> 2.43.0
>
Valentin Schneider Nov. 22, 2024, 1:56 p.m. UTC | #4
On 22/11/24 04:53, Paul E. McKenney wrote:
> On Tue, Nov 19, 2024 at 04:34:51PM +0100, Valentin Schneider wrote:
>> +config RCU_DYNTICKS_TORTURE
>> +	bool "Minimize RCU dynticks counter size"
>> +	depends on RCU_EXPERT
>> +	default n
>> +	help
>> +	  This option controls the width of the dynticks counter.
>> +
>> +	  Lower values will make overflows more frequent, which will increase
>> +	  the likelihood of extending grace-periods. This option sets the width
>> +	  to its minimum usable value.
>
> The second sentence ("Lower values ...") sounds at first reading like
> this Kconfig option directly controls the width.  The third sentence sets
> things straight, but the reader might well be irretrievably confused by
> that point.  How about something like this instead?
>
>       help
>         This option sets the width of the dynticks counter to its
>         minimum usable value.  This minimum width greatly increases
>         the probability of flushing out bugs involving counter wrap,
>         but it also increases the probability of extending grace period
>         durations.  This Kconfig option should therefore be avoided in
>         production due to the consequent increased probability of OOMs.
>
>         This has no value for production and is only for testing.
>

Much better, I'll take that, thank you!

>>  endmenu # "RCU Debugging"
>> --
>> 2.43.0
>>
diff mbox series

Patch

diff --git a/include/linux/context_tracking_state.h b/include/linux/context_tracking_state.h
index 7b8433d5a8efe..0b81248aa03e2 100644
--- a/include/linux/context_tracking_state.h
+++ b/include/linux/context_tracking_state.h
@@ -18,12 +18,6 @@  enum ctx_state {
 	CT_STATE_MAX		= 4,
 };
 
-/* Odd value for watching, else even. */
-#define CT_RCU_WATCHING CT_STATE_MAX
-
-#define CT_STATE_MASK (CT_STATE_MAX - 1)
-#define CT_RCU_WATCHING_MASK (~CT_STATE_MASK)
-
 struct context_tracking {
 #ifdef CONFIG_CONTEXT_TRACKING_USER
 	/*
@@ -44,9 +38,45 @@  struct context_tracking {
 #endif
 };
 
+/*
+ * We cram two different things within the same atomic variable:
+ *
+ *                     CT_RCU_WATCHING_START  CT_STATE_START
+ *                                |                |
+ *                                v                v
+ *     MSB [ RCU watching counter ][ context_state ] LSB
+ *         ^                       ^
+ *         |                       |
+ * CT_RCU_WATCHING_END        CT_STATE_END
+ *
+ * Bits are used from the LSB upwards, so unused bits (if any) will always be in
+ * upper bits of the variable.
+ */
 #ifdef CONFIG_CONTEXT_TRACKING
+#define CT_SIZE (sizeof(((struct context_tracking *)0)->state) * BITS_PER_BYTE)
+
+#define CT_STATE_WIDTH bits_per(CT_STATE_MAX - 1)
+#define CT_STATE_START 0
+#define CT_STATE_END   (CT_STATE_START + CT_STATE_WIDTH - 1)
+
+#define CT_RCU_WATCHING_MAX_WIDTH (CT_SIZE - CT_STATE_WIDTH)
+#define CT_RCU_WATCHING_WIDTH     (IS_ENABLED(CONFIG_RCU_DYNTICKS_TORTURE) ? 2 : CT_RCU_WATCHING_MAX_WIDTH)
+#define CT_RCU_WATCHING_START     (CT_STATE_END + 1)
+#define CT_RCU_WATCHING_END       (CT_RCU_WATCHING_START + CT_RCU_WATCHING_WIDTH - 1)
+#define CT_RCU_WATCHING           BIT(CT_RCU_WATCHING_START)
+
+#define CT_STATE_MASK        GENMASK(CT_STATE_END,        CT_STATE_START)
+#define CT_RCU_WATCHING_MASK GENMASK(CT_RCU_WATCHING_END, CT_RCU_WATCHING_START)
+
+#define CT_UNUSED_WIDTH (CT_RCU_WATCHING_MAX_WIDTH - CT_RCU_WATCHING_WIDTH)
+
+static_assert(CT_STATE_WIDTH        +
+	      CT_RCU_WATCHING_WIDTH +
+	      CT_UNUSED_WIDTH       ==
+	      CT_SIZE);
+
 DECLARE_PER_CPU(struct context_tracking, context_tracking);
-#endif
+#endif	/* CONFIG_CONTEXT_TRACKING */
 
 #ifdef CONFIG_CONTEXT_TRACKING_USER
 static __always_inline int __ct_state(void)
diff --git a/kernel/rcu/Kconfig.debug b/kernel/rcu/Kconfig.debug
index 9b0b52e1836fa..8dc505d841f8d 100644
--- a/kernel/rcu/Kconfig.debug
+++ b/kernel/rcu/Kconfig.debug
@@ -168,4 +168,18 @@  config RCU_STRICT_GRACE_PERIOD
 	  when looking for certain types of RCU usage bugs, for example,
 	  too-short RCU read-side critical sections.
 
+
+config RCU_DYNTICKS_TORTURE
+	bool "Minimize RCU dynticks counter size"
+	depends on RCU_EXPERT
+	default n
+	help
+	  This option controls the width of the dynticks counter.
+
+	  Lower values will make overflows more frequent, which will increase
+	  the likelihood of extending grace-periods. This option sets the width
+	  to its minimum usable value.
+
+	  This has no value for production and is only for testing.
+
 endmenu # "RCU Debugging"