Re: [PATCH RFC tip/core/rcu 1/5] srcu: Make Tiny SRCU use multi-bit grace-period counter
On Thu, Nov 19, 2020 at 01:44:49PM +0530, Neeraj Upadhyay wrote: > Hi Paul, > > On 11/17/2020 6:10 AM, paul...@kernel.org wrote: > > From: "Paul E. McKenney" > > > > There is a need for a polling interface for SRCU grace periods. This > > polling needs to distinguish between an SRCU instance being idle on the > > one hand or in the middle of a grace period on the other. This commit > > therefore converts the Tiny SRCU srcu_struct structure's srcu_idx from > > a defacto boolean to a free-running counter, using the bottom bit to > > indicate that a grace period is in progress. The second-from-bottom > > bit is thus used as the index returned by srcu_read_lock(). > > > > Link: https://lore.kernel.org/rcu/20201112201547.gf3365...@moria.home.lan/ > > Reported-by: Kent Overstreet > > Signed-off-by: Paul E. McKenney > > --- > > include/linux/srcutiny.h | 4 ++-- > > kernel/rcu/srcutiny.c| 5 +++-- > > 2 files changed, 5 insertions(+), 4 deletions(-) > > > > diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h > > index 5a5a194..fed4a2d 100644 > > --- a/include/linux/srcutiny.h > > +++ b/include/linux/srcutiny.h > > @@ -15,7 +15,7 @@ > > struct srcu_struct { > > short srcu_lock_nesting[2]; /* srcu_read_lock() nesting depth. */ > > - short srcu_idx; /* Current reader array element. */ > > + unsigned short srcu_idx;/* Current reader array element in bit > > 0x2. */ > > u8 srcu_gp_running; /* GP workqueue running? */ > > u8 srcu_gp_waiting; /* GP waiting for readers? */ > > struct swait_queue_head srcu_wq; > > @@ -59,7 +59,7 @@ static inline int __srcu_read_lock(struct srcu_struct > > *ssp) > > { > > int idx; > > - idx = READ_ONCE(ssp->srcu_idx); > > + idx = (READ_ONCE(ssp->srcu_idx) & 0x2) / 2; > > Should we use bit 0x2 of (READ_ONCE(ssp->srcu_idx) + 1) , if GP > (srcu_drive_gp()) is in progress? Or am I missing something here? > > idx = ((READ_ONCE(ssp->srcu_idx) +1) & 0x2) / 2; You miss nothing! I am running about 200 hours of concurrent rcutorture of the SRCU-t and SRCU-u scenarios, but I must admit that this race could be hard to hit. But it could of course result in too-short grace periods. I will fold this into the original with attribution. > Also, any reason for using divison instead of shift; something to > do with 16-bit srcu_idx which I am missing here? I just figure that the compiler is better at selecting instructions than I am. Either would work. Thanx, Paul > Thanks > Neeraj > > > WRITE_ONCE(ssp->srcu_lock_nesting[idx], ssp->srcu_lock_nesting[idx] + > > 1); > > return idx; > > } > > diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c > > index 6208c1d..5598cf6 100644 > > --- a/kernel/rcu/srcutiny.c > > +++ b/kernel/rcu/srcutiny.c > > @@ -124,11 +124,12 @@ void srcu_drive_gp(struct work_struct *wp) > > ssp->srcu_cb_head = NULL; > > ssp->srcu_cb_tail = >srcu_cb_head; > > local_irq_enable(); > > - idx = ssp->srcu_idx; > > - WRITE_ONCE(ssp->srcu_idx, !ssp->srcu_idx); > > + idx = (ssp->srcu_idx & 0x2) / 2; > > + WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); > > WRITE_ONCE(ssp->srcu_gp_waiting, true); /* srcu_read_unlock() wakes! */ > > swait_event_exclusive(ssp->srcu_wq, > > !READ_ONCE(ssp->srcu_lock_nesting[idx])); > > WRITE_ONCE(ssp->srcu_gp_waiting, false); /* srcu_read_unlock() cheap. */ > > + WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); > > /* Invoke the callbacks we removed above. */ > > while (lh) { > > > > -- > QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of > the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCH RFC tip/core/rcu 1/5] srcu: Make Tiny SRCU use multi-bit grace-period counter
Hi Paul, On 11/17/2020 6:10 AM, paul...@kernel.org wrote: From: "Paul E. McKenney" There is a need for a polling interface for SRCU grace periods. This polling needs to distinguish between an SRCU instance being idle on the one hand or in the middle of a grace period on the other. This commit therefore converts the Tiny SRCU srcu_struct structure's srcu_idx from a defacto boolean to a free-running counter, using the bottom bit to indicate that a grace period is in progress. The second-from-bottom bit is thus used as the index returned by srcu_read_lock(). Link: https://lore.kernel.org/rcu/20201112201547.gf3365...@moria.home.lan/ Reported-by: Kent Overstreet Signed-off-by: Paul E. McKenney --- include/linux/srcutiny.h | 4 ++-- kernel/rcu/srcutiny.c| 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h index 5a5a194..fed4a2d 100644 --- a/include/linux/srcutiny.h +++ b/include/linux/srcutiny.h @@ -15,7 +15,7 @@ struct srcu_struct { short srcu_lock_nesting[2]; /* srcu_read_lock() nesting depth. */ - short srcu_idx; /* Current reader array element. */ + unsigned short srcu_idx;/* Current reader array element in bit 0x2. */ u8 srcu_gp_running; /* GP workqueue running? */ u8 srcu_gp_waiting; /* GP waiting for readers? */ struct swait_queue_head srcu_wq; @@ -59,7 +59,7 @@ static inline int __srcu_read_lock(struct srcu_struct *ssp) { int idx; - idx = READ_ONCE(ssp->srcu_idx); + idx = (READ_ONCE(ssp->srcu_idx) & 0x2) / 2; Should we use bit 0x2 of (READ_ONCE(ssp->srcu_idx) + 1) , if GP (srcu_drive_gp()) is in progress? Or am I missing something here? idx = ((READ_ONCE(ssp->srcu_idx) +1) & 0x2) / 2; Also, any reason for using divison instead of shift; something to do with 16-bit srcu_idx which I am missing here? Thanks Neeraj WRITE_ONCE(ssp->srcu_lock_nesting[idx], ssp->srcu_lock_nesting[idx] + 1); return idx; } diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c index 6208c1d..5598cf6 100644 --- a/kernel/rcu/srcutiny.c +++ b/kernel/rcu/srcutiny.c @@ -124,11 +124,12 @@ void srcu_drive_gp(struct work_struct *wp) ssp->srcu_cb_head = NULL; ssp->srcu_cb_tail = >srcu_cb_head; local_irq_enable(); - idx = ssp->srcu_idx; - WRITE_ONCE(ssp->srcu_idx, !ssp->srcu_idx); + idx = (ssp->srcu_idx & 0x2) / 2; + WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); WRITE_ONCE(ssp->srcu_gp_waiting, true); /* srcu_read_unlock() wakes! */ swait_event_exclusive(ssp->srcu_wq, !READ_ONCE(ssp->srcu_lock_nesting[idx])); WRITE_ONCE(ssp->srcu_gp_waiting, false); /* srcu_read_unlock() cheap. */ + WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); /* Invoke the callbacks we removed above. */ while (lh) { -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
[PATCH RFC tip/core/rcu 1/5] srcu: Make Tiny SRCU use multi-bit grace-period counter
From: "Paul E. McKenney" There is a need for a polling interface for SRCU grace periods. This polling needs to distinguish between an SRCU instance being idle on the one hand or in the middle of a grace period on the other. This commit therefore converts the Tiny SRCU srcu_struct structure's srcu_idx from a defacto boolean to a free-running counter, using the bottom bit to indicate that a grace period is in progress. The second-from-bottom bit is thus used as the index returned by srcu_read_lock(). Link: https://lore.kernel.org/rcu/20201112201547.gf3365...@moria.home.lan/ Reported-by: Kent Overstreet Signed-off-by: Paul E. McKenney --- include/linux/srcutiny.h | 4 ++-- kernel/rcu/srcutiny.c| 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h index 5a5a194..fed4a2d 100644 --- a/include/linux/srcutiny.h +++ b/include/linux/srcutiny.h @@ -15,7 +15,7 @@ struct srcu_struct { short srcu_lock_nesting[2]; /* srcu_read_lock() nesting depth. */ - short srcu_idx; /* Current reader array element. */ + unsigned short srcu_idx;/* Current reader array element in bit 0x2. */ u8 srcu_gp_running; /* GP workqueue running? */ u8 srcu_gp_waiting; /* GP waiting for readers? */ struct swait_queue_head srcu_wq; @@ -59,7 +59,7 @@ static inline int __srcu_read_lock(struct srcu_struct *ssp) { int idx; - idx = READ_ONCE(ssp->srcu_idx); + idx = (READ_ONCE(ssp->srcu_idx) & 0x2) / 2; WRITE_ONCE(ssp->srcu_lock_nesting[idx], ssp->srcu_lock_nesting[idx] + 1); return idx; } diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c index 6208c1d..5598cf6 100644 --- a/kernel/rcu/srcutiny.c +++ b/kernel/rcu/srcutiny.c @@ -124,11 +124,12 @@ void srcu_drive_gp(struct work_struct *wp) ssp->srcu_cb_head = NULL; ssp->srcu_cb_tail = >srcu_cb_head; local_irq_enable(); - idx = ssp->srcu_idx; - WRITE_ONCE(ssp->srcu_idx, !ssp->srcu_idx); + idx = (ssp->srcu_idx & 0x2) / 2; + WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); WRITE_ONCE(ssp->srcu_gp_waiting, true); /* srcu_read_unlock() wakes! */ swait_event_exclusive(ssp->srcu_wq, !READ_ONCE(ssp->srcu_lock_nesting[idx])); WRITE_ONCE(ssp->srcu_gp_waiting, false); /* srcu_read_unlock() cheap. */ + WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); /* Invoke the callbacks we removed above. */ while (lh) { -- 2.9.5