Updating Section Deferred Processing
cover Updating Section Deferred Processing
Hi Paul,
Most of the following patches switch from ACCESS_ONCE to READ_ONCE/WRITE_ONCE in Section Deferred Processing. Please take a look.
Thanks,
--Jason
Junchang Wang (5):
hazptr: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
route_rcu: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
route_rcu: Remove redundant assignment statement to rep->re_freed
seqlocktorture: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
rcu_rcpls: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
CodeSamples/defer/hazptr.h | 8 ++++---- CodeSamples/defer/hazptrtorture.h | 6 +++--- CodeSamples/defer/rcu_rcpls.c | 6 +++--- CodeSamples/defer/rcu_rcpls.h | 2 +- CodeSamples/defer/rcutorture.h | 2 +- CodeSamples/defer/route_rcu.c | 5 ++--- CodeSamples/defer/seqlocktorture.c | 8 ++++---- appendix/toyrcu/toyrcu.tex | 14 +++++++------- defer/rcuusage.tex | 4 ++-- 9 files changed, 27 insertions(+), 28 deletions(-)
Signature · 1 line
2.7.4
PATCH 1/5 hazptr: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
--- CodeSamples/defer/hazptr.h | 8 ++++---- CodeSamples/defer/hazptrtorture.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-)
CodeSamples/defer/hazptr.h +4 -4
@@ -65,17 +65,17 @@ static inline void *hp_record(void **p, hazard_pointer *hp)hazptr_head_t *tmp;do { - tmp =ACCESS_ONCE (*p); -ACCESS_ONCE (hp->p) = tmp; + tmp =READ_ONCE (*p); +WRITE_ONCE (hp->p, tmp);smp_mb (); - }while (tmp !=ACCESS_ONCE (*p)); + }while (tmp !=READ_ONCE (*p));return tmp; }static inline void hp_clear (hazard_pointer *hp) {smp_mb (); -ACCESS_ONCE (hp->p) =NULL ; +WRITE_ONCE (hp->p,NULL ); }#define hazptr_clean_pointer (p) ((typeof(p))((unsigned long)(p) & ~0x1UL))
CodeSamples/defer/hazptrtorture.h +3 -3
@@ -286,17 +286,17 @@ void *hazptr_update_stress_test(void *arg)if (i >=HAZPTR_STRESS_PIPE_LEN ) i =0 ; p = &hazptr_stress_array[i]; -if (ACCESS_ONCE (p->inuse)) { +if (READ_ONCE (p->inuse)) { hazptr_stress_idx = i;continue ; } p->pipe_count =0 ; -ACCESS_ONCE (p->inuse) =1 ; +WRITE_ONCE (p->inuse,1 ); p->mbtest =0 ;smp_mb (); p->mbtest =1 ;smp_mb (); -ACCESS_ONCE (hazptr_stress_current) = p; +WRITE_ONCE (hazptr_stress_current, p); hazptr_stress_idx = i;for (i =0 ; i <HAZPTR_STRESS_PIPE_LEN ; i++)if (!hazptr_stress_array[i].inuse) {
Signature · 1 line
2.7.4
PATCH 2/5 route_rcu: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
In reply to Junchang Wang--- CodeSamples/defer/route_rcu.c | 6 +++--- defer/rcuusage.tex | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-)
CodeSamples/defer/route_rcu.c +3 -3
@@ -44,7 +44,7 @@ DEFINE_SPINLOCK(routelock);static void re_free (struct route_entry *rep) { -ACCESS_ONCE (rep->re_freed) =1 ; +WRITE_ONCE (rep->re_freed,1 );free (rep); }
@@ -60,7 +60,7 @@ unsigned long route_lookup(unsigned long addr)cds_list_for_each_entry_rcu (rep, &route_list, re_next) {if (rep->addr == addr) { ret = rep->iface; -if (ACCESS_ONCE (rep->re_freed)) +if (READ_ONCE (rep->re_freed))abort ();rcu_read_unlock ();return ret;
@@ -93,7 +93,7 @@ static void route_cb(struct rcu_head *rhp) { struct route_entry *rep = container_of(rhp, struct route_entry, rh); -ACCESS_ONCE (rep->re_freed) =1 ; +WRITE_ONCE (rep->re_freed,1 );re_free (rep); }
defer/rcuusage.tex +2 -2
@@ -64,7 +64,7 @@ Section~\ref{sec:defer:RCU Usage Summary} provides a summary. 18 re_next) { 19 if (rep->addr == addr) { 20 ret = rep->iface; -21 if (ACCESS_ONCE(rep->re_freed)) +21 if (READ_ONCE(rep->re_freed)) 22 abort(); 23 rcu_read_unlock(); 24 return ret;
@@ -106,7 +106,7 @@ Section~\ref{sec:defer:RCU Usage Summary} provides a summary. 20 struct route_entry *rep; 21 22 rep = container_of(rhp, struct route_entry, rh); -23 ACCESS_ONCE(rep->re_freed) = 1; +23 WRITE_ONCE(rep->re_freed, 1); 24 free(rep); 25 } 26
Signature · 1 line
2.7.4
PATCH 3/5 route_rcu: Remove redundant assignment statement to rep->re_freed
In reply to Junchang Wang--- CodeSamples/defer/route_rcu.c | 1 - 1 file changed, 1 deletion(-)
CodeSamples/defer/route_rcu.c +0 -1
@@ -93,7 +93,6 @@ static void route_cb(struct rcu_head *rhp) { struct route_entry *rep = container_of(rhp, struct route_entry, rh); -WRITE_ONCE (rep->re_freed,1 );re_free (rep); }
Signature · 1 line
2.7.4
PATCH 4/5 seqlocktorture: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
In reply to Junchang Wang--- CodeSamples/defer/seqlocktorture.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
CodeSamples/defer/seqlocktorture.c +4 -4
@@ -78,9 +78,9 @@ void *seqlock_read_test(void *arg)run_on (me);atomic_inc (&nthreadsrunning); -while (ACCESS_ONCE (goflag) ==GOFLAG_INIT ) +while (READ_ONCE (goflag) ==GOFLAG_INIT )poll (NULL ,0 ,1 ); -while (ACCESS_ONCE (goflag) ==GOFLAG_RUN ) { +while (READ_ONCE (goflag) ==GOFLAG_RUN ) {for (i =COUNT_READ_RUN ; i >0 ; i--) { n_retries_local_cur =-1 ; do {
@@ -115,9 +115,9 @@ void *seqlock_write_test(void *arg)run_on (me);atomic_inc (&nthreadsrunning); -while (ACCESS_ONCE (goflag) ==GOFLAG_INIT ) +while (READ_ONCE (goflag) ==GOFLAG_INIT )poll (NULL ,0 ,1 ); -while (ACCESS_ONCE (goflag) ==GOFLAG_RUN ) { +while (READ_ONCE (goflag) ==GOFLAG_RUN ) {for (i =COUNT_UPDATE_RUN ; i >0 ; i--) {write_seqlock (&test_seqlock);for (j =0 ; j < n_elems; j++)
Signature · 1 line
2.7.4
PATCH 5/5 rcu_rcpls: Switch from ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
In reply to Junchang Wang--- CodeSamples/defer/rcu_rcpls.c | 6 +++--- CodeSamples/defer/rcu_rcpls.h | 2 +- CodeSamples/defer/rcutorture.h | 2 +- appendix/toyrcu/toyrcu.tex | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-)
CodeSamples/defer/rcu_rcpls.c +3 -3
@@ -28,7 +28,7 @@ static void flip_counter_and_wait(int ctr)int i;int t; -ACCESS_ONCE (rcu_idx) = ctr +1 ; +WRITE_ONCE (rcu_idx, ctr +1 ); i = ctr &0x1 ;smp_mb ();for_each_thread (t) {
@@ -46,10 +46,10 @@ void synchronize_rcu(void)int oldctr;smp_mb (); - oldctr =ACCESS_ONCE (rcu_idx); + oldctr =READ_ONCE (rcu_idx);smp_mb ();spin_lock (&rcu_gp_lock); - ctr =ACCESS_ONCE (rcu_idx); + ctr =READ_ONCE (rcu_idx);if (ctr - oldctr >=3 ) {/*
CodeSamples/defer/rcu_rcpls.h +1 -1
@@ -47,7 +47,7 @@ static void rcu_read_lock(void) n =__get_thread_var (rcu_nesting);if (n ==0 ) { - i =ACCESS_ONCE (rcu_idx) &0x1 ; + i =READ_ONCE (rcu_idx) &0x1 ;__get_thread_var (rcu_read_idx) = i;__get_thread_var (rcu_refcnt)[i]++; }
CodeSamples/defer/rcutorture.h +1 -1
@@ -271,7 +271,7 @@ void *rcu_read_stress_test(void *arg) n_mberror++;rcu_read_lock_nest ();for (i =0 ; i <100 ; i++) -ACCESS_ONCE (garbage)++; +WRITE_ONCE (garbage,READ_ONCE (garbage) +1 );rcu_read_unlock_nest (); pc = p->pipe_count;rcu_read_unlock ();
appendix/toyrcu/toyrcu.tex +7 -7
@@ -1003,7 +1003,7 @@ concurrent RCU updates. 5 6 n = __get_thread_var(rcu_nesting); 7 if (n == 0) { - 8 i = ACCESS_ONCE(rcu_idx) & 0x1; + 8 i = READ_ONCE(rcu_idx) & 0x1; 9 __get_thread_var(rcu_read_idx) = i; 10 __get_thread_var(rcu_refcnt)[i]++; 11 }
@@ -1044,7 +1044,7 @@ so that line~8 of Figure~\ref{fig:app:toyrcu:RCU Read-Side Using Per-Thread Reference-Count Pair and Shared Update} must mask off the low-order bit. We also switched from using \co{atomic_read()} and \co{atomic_set()} -to using \co{ACCESS_ONCE()}. +to using \co{READ_ONCE()}. The data is also quite similar, as shown in Figure~\ref{fig:app:toyrcu:RCU Read-Side Using Per-Thread Reference-Count Pair and Shared Update Data}, with \co{rcu_idx} now being a \co{long} instead of an
@@ -1058,7 +1058,7 @@ with \co{rcu_idx} now being a \co{long} instead of an 3 int i; 4 int t; 5 - 6 ACCESS_ONCE(rcu_idx) = ctr + 1; + 6 WRITE_ONCE(rcu_idx, ctr + 1); 7 i = ctr & 0x1; 8 smp_mb(); 9 for_each_thread(t) {
@@ -1075,10 +1075,10 @@ with \co{rcu_idx} now being a \co{long} instead of an 20 int oldctr; 21 22 smp_mb(); - 23 oldctr = ACCESS_ONCE(rcu_idx); + 23 oldctr = READ_ONCE(rcu_idx); 24 smp_mb(); 25 spin_lock(&rcu_gp_lock); - 26 ctr = ACCESS_ONCE(rcu_idx); + 26 ctr = READ_ONCE(rcu_idx); 27 if (ctr - oldctr >= 3) { 28 spin_unlock(&rcu_gp_lock); 29 smp_mb();
@@ -1106,7 +1106,7 @@ These are similar to those in Figure~\ref{fig:app:toyrcu:RCU Update Using Per-Thread Reference-Count Pair}. The differences in \co{flip_counter_and_wait()} include: \begin{enumerate} -\item Line~6 uses \co{ACCESS_ONCE()} instead of \co{atomic_set()}, +\item Line~6 uses \co{WRITE_ONCE()} instead of \co{atomic_set()}, and increments rather than complementing. \item A new line~7 masks the counter down to its bottom bit. \end{enumerate}
@@ -1116,7 +1116,7 @@ The changes to \co{synchronize_rcu()} are more pervasive: \item There is a new \co{oldctr} local variable that captures the pre-lock-acquisition value of \co{rcu_idx} on line~23. -\item Line~26 uses \co{ACCESS_ONCE()} instead of \co{atomic_read()}. +\item Line~26 uses \co{READ_ONCE()} instead of \co{atomic_read()}. \item Lines~27-30 check to see if at least three counter flips were performed by other threads while the lock was being acquired, and, if so, releases the lock, does a memory barrier, and returns.
Signature · 1 line
2.7.4
Quoted 4 lines · Junchang Wang
Hi Paul,
Most of the following patches switch from
ACCESS_ONCEto READ_ONCE/WRITE_ONCE in Section Deferred Processing. Please take a look.
Applied and pushed, thank you!
And good catch on the redundant assignment! ;-)
Thanx, Paul
Quoted 24 lines
Thanks,
--JasonJunchang Wang (5):
hazptr: Switch fromACCESS_ONCE()to READ_ONCE()/WRITE_ONCE()
route_rcu: Switch fromACCESS_ONCE()to READ_ONCE()/WRITE_ONCE()
route_rcu: Remove redundant assignment statement torep->re_freed
seqlocktorture: Switch fromACCESS_ONCE()to READ_ONCE()/WRITE_ONCE()
rcu_rcpls: Switch fromACCESS_ONCE()to READ_ONCE()/WRITE_ONCE()CodeSamples/defer/hazptr.h | 8 ++++---- CodeSamples/defer/hazptrtorture.h | 6 +++--- CodeSamples/defer/rcu_rcpls.c | 6 +++--- CodeSamples/defer/rcu_rcpls.h | 2 +- CodeSamples/defer/rcutorture.h | 2 +- CodeSamples/defer/route_rcu.c | 5 ++--- CodeSamples/defer/seqlocktorture.c | 8 ++++---- appendix/toyrcu/toyrcu.tex | 14 +++++++------- defer/rcuusage.tex | 4 ++-- 9 files changed, 27 insertions(+), 28 deletions(-)Signature · 1 line
2.7.4