diff mbox series

[2/2] rcu-tasks: Make synchronize_rcu_tasks_generic() no-ops on early booting

Message ID 20220712082606.3662616-3-qiang1.zhang@intel.com (mailing list archive)
State New, archived
Headers show
Series Optimize synchronize_rcu_tasks_generic() on early booting | expand

Commit Message

Zqiang July 12, 2022, 8:26 a.m. UTC
When the rcu_scheduler_active variable is RCU_SCHEDULER_INACTIVE and not
yet converted to RCU_SCHEDULER_INIT, there is only idle task, any legal
call synchronize_rcu_tasks_generic() is a quiescent state. this commit
make synchronize_rcu_tasks_generic() no-ops when the rcu_scheduler_active
variable is RCU_SCHEDULER_INACTIVE.

Signed-off-by: Zqiang <qiang1.zhang@intel.com>
---
 kernel/rcu/tasks.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Paul E. McKenney July 12, 2022, 5:37 p.m. UTC | #1
On Tue, Jul 12, 2022 at 04:26:06PM +0800, Zqiang wrote:
> When the rcu_scheduler_active variable is RCU_SCHEDULER_INACTIVE and not
> yet converted to RCU_SCHEDULER_INIT, there is only idle task, any legal
> call synchronize_rcu_tasks_generic() is a quiescent state. this commit
> make synchronize_rcu_tasks_generic() no-ops when the rcu_scheduler_active
> variable is RCU_SCHEDULER_INACTIVE.
> 
> Signed-off-by: Zqiang <qiang1.zhang@intel.com>
> ---

It looks like this would be a good way to provide early boot access
to synchronize_rcu_tasks(), synchronize_rcu_tasks_rude(), and
synchronize_rcu_tasks_trace().

But do we really need early boot access to these functions?  As in has
the below WARN_ON() actually triggered?

And if it has triggered, and in a context that means that these functions
really are needed during early boot, how should the testing strategy
change to test these at the relevant portions of the boot sequence?

From what I know, hitting these during early boot would indicate that
something was removing a trace during early boot, and I know of no way
to make that happen.  Hence my skepticism.  ;-)

But *if* this was really needed, this looks to be a reasonable way to
implement it.

							Thanx, Paul

>  kernel/rcu/tasks.h | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
> index 469bf2a3b505..0237e765c28e 100644
> --- a/kernel/rcu/tasks.h
> +++ b/kernel/rcu/tasks.h
> @@ -560,8 +560,9 @@ static int __noreturn rcu_tasks_kthread(void *arg)
>  static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
>  {
>  	/* Complain if the scheduler has not started.  */
> -	WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
> -			 "synchronize_rcu_tasks called too soon");
> +	if (WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
> +			 "synchronize_rcu_tasks called too soon"))
> +		return;
>  
>  	// If the grace-period kthread is running, use it.
>  	if (READ_ONCE(rtp->kthread_ptr)) {
> -- 
> 2.25.1
>
Zqiang July 14, 2022, 1:53 a.m. UTC | #2
On Tue, Jul 12, 2022 at 04:26:06PM +0800, Zqiang wrote:
> When the rcu_scheduler_active variable is RCU_SCHEDULER_INACTIVE and not
> yet converted to RCU_SCHEDULER_INIT, there is only idle task, any legal
> call synchronize_rcu_tasks_generic() is a quiescent state. this commit
> make synchronize_rcu_tasks_generic() no-ops when the rcu_scheduler_active
> variable is RCU_SCHEDULER_INACTIVE.
> 
> Signed-off-by: Zqiang <qiang1.zhang@intel.com>
> ---

>It looks like this would be a good way to provide early boot access
>to synchronize_rcu_tasks(), synchronize_rcu_tasks_rude(), and
>synchronize_rcu_tasks_trace().
>
>But do we really need early boot access to these functions?  As in has
>the below WARN_ON() actually triggered?

when the rcu_scheduler_active variable is RCU_SCHEDULER_INACTIVE,
invoke synchronize_rcu_tasks_generic(), in addition to triggering a warning, 
also need to make it return directly, if not, the rcu_tasks_one_gp() will be
called directly, but due to the rtp structure's -> pregp_func is not initialized,
A null pointer bug will appear.

But like said, I don't see the need to call synchronize_rcu_tasks_generic() on 
early booting.  maybe this change is  not necessary.

Thanks
Zqiang

>
>And if it has triggered, and in a context that means that these functions
>really are needed during early boot, how should the testing strategy
>change to test these at the relevant portions of the boot sequence?
>
>From what I know, hitting these during early boot would indicate that
>something was removing a trace during early boot, and I know of no way
>to make that happen.  Hence my skepticism.  ;-)
>
>But *if* this was really needed, this looks to be a reasonable way to
>implement it.
>
>							Thanx, Paul

>  kernel/rcu/tasks.h | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
> index 469bf2a3b505..0237e765c28e 100644
> --- a/kernel/rcu/tasks.h
> +++ b/kernel/rcu/tasks.h
> @@ -560,8 +560,9 @@ static int __noreturn rcu_tasks_kthread(void *arg)
>  static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
>  {
>  	/* Complain if the scheduler has not started.  */
> -	WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
> -			 "synchronize_rcu_tasks called too soon");
> +	if (WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
> +			 "synchronize_rcu_tasks called too soon"))
> +		return;
>  
>  	// If the grace-period kthread is running, use it.
>  	if (READ_ONCE(rtp->kthread_ptr)) {
> -- 
> 2.25.1
>
Paul E. McKenney July 14, 2022, 3:37 a.m. UTC | #3
On Thu, Jul 14, 2022 at 01:53:20AM +0000, Zhang, Qiang1 wrote:
> 
> On Tue, Jul 12, 2022 at 04:26:06PM +0800, Zqiang wrote:
> > When the rcu_scheduler_active variable is RCU_SCHEDULER_INACTIVE and not
> > yet converted to RCU_SCHEDULER_INIT, there is only idle task, any legal
> > call synchronize_rcu_tasks_generic() is a quiescent state. this commit
> > make synchronize_rcu_tasks_generic() no-ops when the rcu_scheduler_active
> > variable is RCU_SCHEDULER_INACTIVE.
> > 
> > Signed-off-by: Zqiang <qiang1.zhang@intel.com>
> > ---
> 
> >It looks like this would be a good way to provide early boot access
> >to synchronize_rcu_tasks(), synchronize_rcu_tasks_rude(), and
> >synchronize_rcu_tasks_trace().
> >
> >But do we really need early boot access to these functions?  As in has
> >the below WARN_ON() actually triggered?
> 
> when the rcu_scheduler_active variable is RCU_SCHEDULER_INACTIVE,
> invoke synchronize_rcu_tasks_generic(), in addition to triggering a warning, 
> also need to make it return directly, if not, the rcu_tasks_one_gp() will be
> called directly, but due to the rtp structure's -> pregp_func is not initialized,
> A null pointer bug will appear.
> 
> But like said, I don't see the need to call synchronize_rcu_tasks_generic() on 
> early booting.  maybe this change is  not necessary.

Not yet, anyway.  And adding this would require more testing.

However, if the current warning does trigger, and the caller has a
legitimate reason for invoking this function so early, please remember
this patch.  ;-)

							Thanx, Paul

> Thanks
> Zqiang
> 
> >
> >And if it has triggered, and in a context that means that these functions
> >really are needed during early boot, how should the testing strategy
> >change to test these at the relevant portions of the boot sequence?
> >
> >>From what I know, hitting these during early boot would indicate that
> >something was removing a trace during early boot, and I know of no way
> >to make that happen.  Hence my skepticism.  ;-)
> >
> >But *if* this was really needed, this looks to be a reasonable way to
> >implement it.
> >
> >							Thanx, Paul
> 
> >  kernel/rcu/tasks.h | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
> > index 469bf2a3b505..0237e765c28e 100644
> > --- a/kernel/rcu/tasks.h
> > +++ b/kernel/rcu/tasks.h
> > @@ -560,8 +560,9 @@ static int __noreturn rcu_tasks_kthread(void *arg)
> >  static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
> >  {
> >  	/* Complain if the scheduler has not started.  */
> > -	WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
> > -			 "synchronize_rcu_tasks called too soon");
> > +	if (WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
> > +			 "synchronize_rcu_tasks called too soon"))
> > +		return;
> >  
> >  	// If the grace-period kthread is running, use it.
> >  	if (READ_ONCE(rtp->kthread_ptr)) {
> > -- 
> > 2.25.1
> >
diff mbox series

Patch

diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
index 469bf2a3b505..0237e765c28e 100644
--- a/kernel/rcu/tasks.h
+++ b/kernel/rcu/tasks.h
@@ -560,8 +560,9 @@  static int __noreturn rcu_tasks_kthread(void *arg)
 static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
 {
 	/* Complain if the scheduler has not started.  */
-	WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
-			 "synchronize_rcu_tasks called too soon");
+	if (WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
+			 "synchronize_rcu_tasks called too soon"))
+		return;
 
 	// If the grace-period kthread is running, use it.
 	if (READ_ONCE(rtp->kthread_ptr)) {