@@ -2450,9 +2450,11 @@ struct rcu_torture_one_read_state_updown {
24502450 struct hrtimer rtorsu_hrt ;
24512451 bool rtorsu_inuse ;
24522452 ktime_t rtorsu_kt ;
2453+ int rtorsu_cpu ;
24532454 unsigned long rtorsu_j ;
24542455 unsigned long rtorsu_ndowns ;
24552456 unsigned long rtorsu_nups ;
2457+ unsigned long rtorsu_nmigrates ;
24562458 struct torture_random_state rtorsu_trs ;
24572459 struct rcu_torture_one_read_state rtorsu_rtors ;
24582460};
@@ -2463,12 +2465,15 @@ static int rcu_torture_updown(void *arg);
24632465
24642466static enum hrtimer_restart rcu_torture_updown_hrt (struct hrtimer * hrtp )
24652467{
2468+ int cpu = raw_smp_processor_id ();
24662469 struct rcu_torture_one_read_state_updown * rtorsup ;
24672470
24682471 rtorsup = container_of (hrtp , struct rcu_torture_one_read_state_updown , rtorsu_hrt );
24692472 rcu_torture_one_read_end (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs , -1 );
24702473 WARN_ONCE (rtorsup -> rtorsu_nups >= rtorsup -> rtorsu_ndowns , "%s: Up without matching down #%zu.\n" , __func__ , rtorsup - updownreaders );
2471- rtorsup -> rtorsu_nups ++ ;
2474+ WRITE_ONCE (rtorsup -> rtorsu_nups , rtorsup -> rtorsu_nups + 1 );
2475+ WRITE_ONCE (rtorsup -> rtorsu_nmigrates ,
2476+ rtorsup -> rtorsu_nmigrates + (cpu != rtorsup -> rtorsu_cpu ));
24722477 smp_store_release (& rtorsup -> rtorsu_inuse , false);
24732478 return HRTIMER_NORESTART ;
24742479}
@@ -2516,7 +2521,7 @@ static void rcu_torture_updown_cleanup(void)
25162521 if (hrtimer_cancel (& rtorsup -> rtorsu_hrt ) || WARN_ON_ONCE (rtorsup -> rtorsu_inuse )) {
25172522 rcu_torture_one_read_end (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs , -1 );
25182523 WARN_ONCE (rtorsup -> rtorsu_nups >= rtorsup -> rtorsu_ndowns , "%s: Up without matching down #%zu.\n" , __func__ , rtorsup - updownreaders );
2519- rtorsup -> rtorsu_nups ++ ;
2524+ WRITE_ONCE ( rtorsup -> rtorsu_nups , rtorsup -> rtorsu_nups + 1 ) ;
25202525 smp_store_release (& rtorsup -> rtorsu_inuse , false);
25212526 }
25222527
@@ -2534,13 +2539,14 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
25342539
25352540 init_rcu_torture_one_read_state (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs );
25362541 rawidx = cur_ops -> down_read ();
2537- rtorsup -> rtorsu_ndowns ++ ;
2542+ WRITE_ONCE ( rtorsup -> rtorsu_ndowns , rtorsup -> rtorsu_ndowns + 1 ) ;
25382543 idx = (rawidx << RCUTORTURE_RDR_SHIFT_1 ) & RCUTORTURE_RDR_MASK_1 ;
25392544 rtorsup -> rtorsu_rtors .readstate = idx | RCUTORTURE_RDR_UPDOWN ;
25402545 rtorsup -> rtorsu_rtors .rtrsp ++ ;
2546+ rtorsup -> rtorsu_cpu = raw_smp_processor_id ();
25412547 if (!rcu_torture_one_read_start (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs , -1 )) {
25422548 WARN_ONCE (rtorsup -> rtorsu_nups >= rtorsup -> rtorsu_ndowns , "%s: Up without matching down #%zu.\n" , __func__ , rtorsup - updownreaders );
2543- rtorsup -> rtorsu_nups ++ ;
2549+ WRITE_ONCE ( rtorsup -> rtorsu_nups , rtorsup -> rtorsu_nups + 1 ) ;
25442550 schedule_timeout_idle (HZ );
25452551 return ;
25462552 }
@@ -2649,6 +2655,10 @@ rcu_torture_stats_print(void)
26492655 long pipesummary [RCU_TORTURE_PIPE_LEN + 1 ] = { 0 };
26502656 long batchsummary [RCU_TORTURE_PIPE_LEN + 1 ] = { 0 };
26512657 long n_gpwraps = 0 ;
2658+ unsigned long ndowns = 0 ;
2659+ unsigned long nunexpired = 0 ;
2660+ unsigned long nmigrates = 0 ;
2661+ unsigned long nups = 0 ;
26522662 struct rcu_torture * rtcp ;
26532663 static unsigned long rtcv_snap = ULONG_MAX ;
26542664 static bool splatted ;
@@ -2662,10 +2672,18 @@ rcu_torture_stats_print(void)
26622672 if (cur_ops -> get_gpwrap_count )
26632673 n_gpwraps += cur_ops -> get_gpwrap_count (cpu );
26642674 }
2675+ if (updownreaders ) {
2676+ for (i = 0 ; i < n_up_down ; i ++ ) {
2677+ ndowns += READ_ONCE (updownreaders [i ].rtorsu_ndowns );
2678+ nups += READ_ONCE (updownreaders [i ].rtorsu_nups );
2679+ nunexpired += READ_ONCE (updownreaders [i ].rtorsu_inuse );
2680+ nmigrates += READ_ONCE (updownreaders [i ].rtorsu_nmigrates );
2681+ }
2682+ }
26652683 for (i = RCU_TORTURE_PIPE_LEN ; i >= 0 ; i -- ) {
26662684 if (pipesummary [i ] != 0 )
26672685 break ;
2668- }
2686+ } // The value of variable "i" is used later, so don't clobber it!
26692687
26702688 pr_alert ("%s%s " , torture_type , TORTURE_FLAG );
26712689 rtcp = rcu_access_pointer (rcu_torture_current );
@@ -2686,6 +2704,8 @@ rcu_torture_stats_print(void)
26862704 n_rcu_torture_boost_failure ,
26872705 n_rcu_torture_boosts ,
26882706 atomic_long_read (& n_rcu_torture_timers ));
2707+ if (updownreaders )
2708+ pr_cont ("ndowns: %lu nups: %lu nhrt: %lu nmigrates: %lu " , ndowns , nups , nunexpired , nmigrates );
26892709 torture_onoff_stats ();
26902710 pr_cont ("barrier: %ld/%ld:%ld " ,
26912711 data_race (n_barrier_successes ),
0 commit comments