@@ -2450,9 +2450,11 @@ struct rcu_torture_one_read_state_updown {
2450
2450
struct hrtimer rtorsu_hrt ;
2451
2451
bool rtorsu_inuse ;
2452
2452
ktime_t rtorsu_kt ;
2453
+ int rtorsu_cpu ;
2453
2454
unsigned long rtorsu_j ;
2454
2455
unsigned long rtorsu_ndowns ;
2455
2456
unsigned long rtorsu_nups ;
2457
+ unsigned long rtorsu_nmigrates ;
2456
2458
struct torture_random_state rtorsu_trs ;
2457
2459
struct rcu_torture_one_read_state rtorsu_rtors ;
2458
2460
};
@@ -2463,12 +2465,15 @@ static int rcu_torture_updown(void *arg);
2463
2465
2464
2466
static enum hrtimer_restart rcu_torture_updown_hrt (struct hrtimer * hrtp )
2465
2467
{
2468
+ int cpu = raw_smp_processor_id ();
2466
2469
struct rcu_torture_one_read_state_updown * rtorsup ;
2467
2470
2468
2471
rtorsup = container_of (hrtp , struct rcu_torture_one_read_state_updown , rtorsu_hrt );
2469
2472
rcu_torture_one_read_end (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs , -1 );
2470
2473
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 ));
2472
2477
smp_store_release (& rtorsup -> rtorsu_inuse , false);
2473
2478
return HRTIMER_NORESTART ;
2474
2479
}
@@ -2516,7 +2521,7 @@ static void rcu_torture_updown_cleanup(void)
2516
2521
if (hrtimer_cancel (& rtorsup -> rtorsu_hrt ) || WARN_ON_ONCE (rtorsup -> rtorsu_inuse )) {
2517
2522
rcu_torture_one_read_end (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs , -1 );
2518
2523
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 ) ;
2520
2525
smp_store_release (& rtorsup -> rtorsu_inuse , false);
2521
2526
}
2522
2527
@@ -2534,13 +2539,14 @@ static void rcu_torture_updown_one(struct rcu_torture_one_read_state_updown *rto
2534
2539
2535
2540
init_rcu_torture_one_read_state (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs );
2536
2541
rawidx = cur_ops -> down_read ();
2537
- rtorsup -> rtorsu_ndowns ++ ;
2542
+ WRITE_ONCE ( rtorsup -> rtorsu_ndowns , rtorsup -> rtorsu_ndowns + 1 ) ;
2538
2543
idx = (rawidx << RCUTORTURE_RDR_SHIFT_1 ) & RCUTORTURE_RDR_MASK_1 ;
2539
2544
rtorsup -> rtorsu_rtors .readstate = idx | RCUTORTURE_RDR_UPDOWN ;
2540
2545
rtorsup -> rtorsu_rtors .rtrsp ++ ;
2546
+ rtorsup -> rtorsu_cpu = raw_smp_processor_id ();
2541
2547
if (!rcu_torture_one_read_start (& rtorsup -> rtorsu_rtors , & rtorsup -> rtorsu_trs , -1 )) {
2542
2548
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 ) ;
2544
2550
schedule_timeout_idle (HZ );
2545
2551
return ;
2546
2552
}
@@ -2649,6 +2655,10 @@ rcu_torture_stats_print(void)
2649
2655
long pipesummary [RCU_TORTURE_PIPE_LEN + 1 ] = { 0 };
2650
2656
long batchsummary [RCU_TORTURE_PIPE_LEN + 1 ] = { 0 };
2651
2657
long n_gpwraps = 0 ;
2658
+ unsigned long ndowns = 0 ;
2659
+ unsigned long nunexpired = 0 ;
2660
+ unsigned long nmigrates = 0 ;
2661
+ unsigned long nups = 0 ;
2652
2662
struct rcu_torture * rtcp ;
2653
2663
static unsigned long rtcv_snap = ULONG_MAX ;
2654
2664
static bool splatted ;
@@ -2662,10 +2672,18 @@ rcu_torture_stats_print(void)
2662
2672
if (cur_ops -> get_gpwrap_count )
2663
2673
n_gpwraps += cur_ops -> get_gpwrap_count (cpu );
2664
2674
}
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
+ }
2665
2683
for (i = RCU_TORTURE_PIPE_LEN ; i >= 0 ; i -- ) {
2666
2684
if (pipesummary [i ] != 0 )
2667
2685
break ;
2668
- }
2686
+ } // The value of variable "i" is used later, so don't clobber it!
2669
2687
2670
2688
pr_alert ("%s%s " , torture_type , TORTURE_FLAG );
2671
2689
rtcp = rcu_access_pointer (rcu_torture_current );
@@ -2686,6 +2704,8 @@ rcu_torture_stats_print(void)
2686
2704
n_rcu_torture_boost_failure ,
2687
2705
n_rcu_torture_boosts ,
2688
2706
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 );
2689
2709
torture_onoff_stats ();
2690
2710
pr_cont ("barrier: %ld/%ld:%ld " ,
2691
2711
data_race (n_barrier_successes ),
0 commit comments