migrate_disable() is called to disable migration in the kernel, and it is
used togather with rcu_read_lock() oftenly.
However, with PREEMPT_RCU disabled, it's unnecessary, as rcu_read_lock()
will disable preemption, which will also disable migration.
Introduce rcu_migrate_enable() and rcu_migrate_disable(), which will do
the migration enable and disable only when the rcu_read_lock() can't do
it.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
include/linux/rcupdate.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 120536f4c6eb..0d9dbd90d025 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -72,6 +72,16 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned
void __rcu_read_lock(void);
void __rcu_read_unlock(void);
+static inline void rcu_migrate_enable(void)
+{
+ migrate_enable();
+}
+
+static inline void rcu_migrate_disable(void)
+{
+ migrate_disable();
+}
+
/*
* Defined as a macro as it is a very low level header included from
* areas that don't even know about current. This gives the rcu_read_lock()
@@ -105,6 +115,14 @@ static inline int rcu_preempt_depth(void)
return 0;
}
+static inline void rcu_migrate_enable(void)
+{
+}
+
+static inline void rcu_migrate_disable(void)
+{
+}
+
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
#ifdef CONFIG_RCU_LAZY
--
2.50.1
On Fri, Aug 15, 2025 at 9:18 AM Menglong Dong <menglong8.dong@gmail.com> wrote: > > migrate_disable() is called to disable migration in the kernel, and it is > used togather with rcu_read_lock() oftenly. > > However, with PREEMPT_RCU disabled, it's unnecessary, as rcu_read_lock() > will disable preemption, which will also disable migration. > > Introduce rcu_migrate_enable() and rcu_migrate_disable(), which will do > the migration enable and disable only when the rcu_read_lock() can't do > it. > > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > --- > include/linux/rcupdate.h | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > index 120536f4c6eb..0d9dbd90d025 100644 > --- a/include/linux/rcupdate.h > +++ b/include/linux/rcupdate.h > @@ -72,6 +72,16 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned > void __rcu_read_lock(void); > void __rcu_read_unlock(void); > > +static inline void rcu_migrate_enable(void) > +{ > + migrate_enable(); > +} Interesting idea. I think it has to be combined with rcu_read_lock(), since this api makes sense only when used together. rcu_read_lock_dont_migrate() ? It will do rcu_read_lock() + migrate_disalbe() in PREEMPT_RCU and rcu_read_lock() + preempt_disable() otherwise? Also I'm not sure we can rely on rcu_read_lock() disabling preemption in all !PREEMPT_RCU cases. iirc it's more nuanced than that.
On Fri, Aug 15, 2025 at 9:02 PM Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote: > > On Fri, Aug 15, 2025 at 9:18 AM Menglong Dong <menglong8.dong@gmail.com> wrote: > > > > migrate_disable() is called to disable migration in the kernel, and it is > > used togather with rcu_read_lock() oftenly. > > > > However, with PREEMPT_RCU disabled, it's unnecessary, as rcu_read_lock() > > will disable preemption, which will also disable migration. > > > > Introduce rcu_migrate_enable() and rcu_migrate_disable(), which will do > > the migration enable and disable only when the rcu_read_lock() can't do > > it. > > > > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > > --- > > include/linux/rcupdate.h | 18 ++++++++++++++++++ > > 1 file changed, 18 insertions(+) > > > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > > index 120536f4c6eb..0d9dbd90d025 100644 > > --- a/include/linux/rcupdate.h > > +++ b/include/linux/rcupdate.h > > @@ -72,6 +72,16 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned > > void __rcu_read_lock(void); > > void __rcu_read_unlock(void); > > > > +static inline void rcu_migrate_enable(void) > > +{ > > + migrate_enable(); > > +} > > Interesting idea. > I think it has to be combined with rcu_read_lock(), since this api > makes sense only when used together. > > rcu_read_lock_dont_migrate() ? Yeah, it looks much better. So we can introduce: rcu_read_lock_dont_migrate() rcu_read_unlock_do_ migrate() > > It will do rcu_read_lock() + migrate_disalbe() in PREEMPT_RCU > and rcu_read_lock() + preempt_disable() otherwise? > > Also I'm not sure we can rely on rcu_read_lock() > disabling preemption in all !PREEMPT_RCU cases. > iirc it's more nuanced than that.
On Fri, Aug 15, 2025 at 04:02:14PM +0300, Alexei Starovoitov wrote: > On Fri, Aug 15, 2025 at 9:18 AM Menglong Dong <menglong8.dong@gmail.com> wrote: > > > > migrate_disable() is called to disable migration in the kernel, and it is > > used togather with rcu_read_lock() oftenly. > > > > However, with PREEMPT_RCU disabled, it's unnecessary, as rcu_read_lock() > > will disable preemption, which will also disable migration. > > > > Introduce rcu_migrate_enable() and rcu_migrate_disable(), which will do > > the migration enable and disable only when the rcu_read_lock() can't do > > it. > > > > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > > --- > > include/linux/rcupdate.h | 18 ++++++++++++++++++ > > 1 file changed, 18 insertions(+) > > > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > > index 120536f4c6eb..0d9dbd90d025 100644 > > --- a/include/linux/rcupdate.h > > +++ b/include/linux/rcupdate.h > > @@ -72,6 +72,16 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned > > void __rcu_read_lock(void); > > void __rcu_read_unlock(void); > > > > +static inline void rcu_migrate_enable(void) > > +{ > > + migrate_enable(); > > +} > > Interesting idea. > I think it has to be combined with rcu_read_lock(), since this api > makes sense only when used together. > > rcu_read_lock_dont_migrate() ? > > It will do rcu_read_lock() + migrate_disalbe() in PREEMPT_RCU > and rcu_read_lock() + preempt_disable() otherwise? That could easily be provided. Or just make one, and if it starts having enough use cases, it could be pulled into RCU proper. > Also I'm not sure we can rely on rcu_read_lock() > disabling preemption in all !PREEMPT_RCU cases. > iirc it's more nuanced than that. For once, something about RCU is non-nuanced. But don't worry, it won't happen again. ;-) In all !PREEMPT_RCU, preemption must be disabled across all RCU read-side critical sections in order for RCU to work correctly. Thanx, Paul
On Fri, Aug 15, 2025 at 11:31 PM Paul E. McKenney <paulmck@kernel.org> wrote: > > On Fri, Aug 15, 2025 at 04:02:14PM +0300, Alexei Starovoitov wrote: > > On Fri, Aug 15, 2025 at 9:18 AM Menglong Dong <menglong8.dong@gmail.com> wrote: > > > > > > migrate_disable() is called to disable migration in the kernel, and it is > > > used togather with rcu_read_lock() oftenly. > > > > > > However, with PREEMPT_RCU disabled, it's unnecessary, as rcu_read_lock() > > > will disable preemption, which will also disable migration. > > > > > > Introduce rcu_migrate_enable() and rcu_migrate_disable(), which will do > > > the migration enable and disable only when the rcu_read_lock() can't do > > > it. > > > > > > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > > > --- > > > include/linux/rcupdate.h | 18 ++++++++++++++++++ > > > 1 file changed, 18 insertions(+) > > > > > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > > > index 120536f4c6eb..0d9dbd90d025 100644 > > > --- a/include/linux/rcupdate.h > > > +++ b/include/linux/rcupdate.h > > > @@ -72,6 +72,16 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned > > > void __rcu_read_lock(void); > > > void __rcu_read_unlock(void); > > > > > > +static inline void rcu_migrate_enable(void) > > > +{ > > > + migrate_enable(); > > > +} > > > > Interesting idea. > > I think it has to be combined with rcu_read_lock(), since this api > > makes sense only when used together. > > > > rcu_read_lock_dont_migrate() ? > > > > It will do rcu_read_lock() + migrate_disalbe() in PREEMPT_RCU > > and rcu_read_lock() + preempt_disable() otherwise? > > That could easily be provided. Or just make one, and if it starts > having enough use cases, it could be pulled into RCU proper. Hi, do you mean that we should start with a single use case? In this series, I started it with the BPF subsystem. Most of the situations are similar, which will call rcu_read_lock+migrate_disable and run bpf prog. > > > Also I'm not sure we can rely on rcu_read_lock() > > disabling preemption in all !PREEMPT_RCU cases. > > iirc it's more nuanced than that. > > For once, something about RCU is non-nuanced. But don't worry, it won't > happen again. ;-) > > In all !PREEMPT_RCU, preemption must be disabled across all RCU read-side > critical sections in order for RCU to work correctly. Great! I worried about this part too. Thanks! Menglong Dong > > Thanx, Paul
On Sun, Aug 17, 2025 at 10:01:23AM +0800, Menglong Dong wrote: > On Fri, Aug 15, 2025 at 11:31 PM Paul E. McKenney <paulmck@kernel.org> wrote: > > > > On Fri, Aug 15, 2025 at 04:02:14PM +0300, Alexei Starovoitov wrote: > > > On Fri, Aug 15, 2025 at 9:18 AM Menglong Dong <menglong8.dong@gmail.com> wrote: > > > > > > > > migrate_disable() is called to disable migration in the kernel, and it is > > > > used togather with rcu_read_lock() oftenly. > > > > > > > > However, with PREEMPT_RCU disabled, it's unnecessary, as rcu_read_lock() > > > > will disable preemption, which will also disable migration. > > > > > > > > Introduce rcu_migrate_enable() and rcu_migrate_disable(), which will do > > > > the migration enable and disable only when the rcu_read_lock() can't do > > > > it. > > > > > > > > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > > > > --- > > > > include/linux/rcupdate.h | 18 ++++++++++++++++++ > > > > 1 file changed, 18 insertions(+) > > > > > > > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > > > > index 120536f4c6eb..0d9dbd90d025 100644 > > > > --- a/include/linux/rcupdate.h > > > > +++ b/include/linux/rcupdate.h > > > > @@ -72,6 +72,16 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned > > > > void __rcu_read_lock(void); > > > > void __rcu_read_unlock(void); > > > > > > > > +static inline void rcu_migrate_enable(void) > > > > +{ > > > > + migrate_enable(); > > > > +} > > > > > > Interesting idea. > > > I think it has to be combined with rcu_read_lock(), since this api > > > makes sense only when used together. > > > > > > rcu_read_lock_dont_migrate() ? > > > > > > It will do rcu_read_lock() + migrate_disalbe() in PREEMPT_RCU > > > and rcu_read_lock() + preempt_disable() otherwise? > > > > That could easily be provided. Or just make one, and if it starts > > having enough use cases, it could be pulled into RCU proper. > > Hi, do you mean that we should start with a single > use case? In this series, I started it with the BPF > subsystem. Most of the situations are similar, which will > call rcu_read_lock+migrate_disable and run bpf prog. Other than my wanting more compact code, what you did in your patch series is fine. Thanx, Paul > > > Also I'm not sure we can rely on rcu_read_lock() > > > disabling preemption in all !PREEMPT_RCU cases. > > > iirc it's more nuanced than that. > > > > For once, something about RCU is non-nuanced. But don't worry, it won't > > happen again. ;-) > > > > In all !PREEMPT_RCU, preemption must be disabled across all RCU read-side > > critical sections in order for RCU to work correctly. > > Great! I worried about this part too. > > Thanks! > Menglong Dong > > > > > Thanx, Paul
© 2016 - 2025 Red Hat, Inc.