@@ -1432,28 +1432,34 @@ static void rcutorture_one_extend(int *readstate, int newstate,
1432
1432
/* First, put new protection in place to avoid critical-section gap. */
1433
1433
if (statesnew & RCUTORTURE_RDR_BH )
1434
1434
local_bh_disable ();
1435
+ if (statesnew & RCUTORTURE_RDR_RBH )
1436
+ rcu_read_lock_bh ();
1435
1437
if (statesnew & RCUTORTURE_RDR_IRQ )
1436
1438
local_irq_disable ();
1437
1439
if (statesnew & RCUTORTURE_RDR_PREEMPT )
1438
1440
preempt_disable ();
1439
- if (statesnew & RCUTORTURE_RDR_RBH )
1440
- rcu_read_lock_bh ();
1441
1441
if (statesnew & RCUTORTURE_RDR_SCHED )
1442
1442
rcu_read_lock_sched ();
1443
1443
if (statesnew & RCUTORTURE_RDR_RCU )
1444
1444
idxnew = cur_ops -> readlock () << RCUTORTURE_RDR_SHIFT ;
1445
1445
1446
- /* Next, remove old protection, irq first due to bh conflict. */
1446
+ /*
1447
+ * Next, remove old protection, in decreasing order of strength
1448
+ * to avoid unlock paths that aren't safe in the stronger
1449
+ * context. Namely: BH can not be enabled with disabled interrupts.
1450
+ * Additionally PREEMPT_RT requires that BH is enabled in preemptible
1451
+ * context.
1452
+ */
1447
1453
if (statesold & RCUTORTURE_RDR_IRQ )
1448
1454
local_irq_enable ();
1449
- if (statesold & RCUTORTURE_RDR_BH )
1450
- local_bh_enable ();
1451
1455
if (statesold & RCUTORTURE_RDR_PREEMPT )
1452
1456
preempt_enable ();
1453
- if (statesold & RCUTORTURE_RDR_RBH )
1454
- rcu_read_unlock_bh ();
1455
1457
if (statesold & RCUTORTURE_RDR_SCHED )
1456
1458
rcu_read_unlock_sched ();
1459
+ if (statesold & RCUTORTURE_RDR_BH )
1460
+ local_bh_enable ();
1461
+ if (statesold & RCUTORTURE_RDR_RBH )
1462
+ rcu_read_unlock_bh ();
1457
1463
if (statesold & RCUTORTURE_RDR_RCU ) {
1458
1464
bool lockit = !statesnew && !(torture_random (trsp ) & 0xffff );
1459
1465
@@ -1496,18 +1502,36 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp)
1496
1502
int mask = rcutorture_extend_mask_max ();
1497
1503
unsigned long randmask1 = torture_random (trsp ) >> 8 ;
1498
1504
unsigned long randmask2 = randmask1 >> 3 ;
1505
+ unsigned long preempts = RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED ;
1506
+ unsigned long preempts_irq = preempts | RCUTORTURE_RDR_IRQ ;
1507
+ unsigned long bhs = RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH ;
1499
1508
1500
1509
WARN_ON_ONCE (mask >> RCUTORTURE_RDR_SHIFT );
1501
1510
/* Mostly only one bit (need preemption!), sometimes lots of bits. */
1502
1511
if (!(randmask1 & 0x7 ))
1503
1512
mask = mask & randmask2 ;
1504
1513
else
1505
1514
mask = mask & (1 << (randmask2 % RCUTORTURE_RDR_NBITS ));
1506
- /* Can't enable bh w/irq disabled. */
1507
- if ((mask & RCUTORTURE_RDR_IRQ ) &&
1508
- ((!(mask & RCUTORTURE_RDR_BH ) && (oldmask & RCUTORTURE_RDR_BH )) ||
1509
- (!(mask & RCUTORTURE_RDR_RBH ) && (oldmask & RCUTORTURE_RDR_RBH ))))
1510
- mask |= RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH ;
1515
+
1516
+ /*
1517
+ * Can't enable bh w/irq disabled.
1518
+ */
1519
+ if (mask & RCUTORTURE_RDR_IRQ )
1520
+ mask |= oldmask & bhs ;
1521
+
1522
+ /*
1523
+ * Ideally these sequences would be detected in debug builds
1524
+ * (regardless of RT), but until then don't stop testing
1525
+ * them on non-RT.
1526
+ */
1527
+ if (IS_ENABLED (CONFIG_PREEMPT_RT )) {
1528
+ /* Can't modify BH in atomic context */
1529
+ if (oldmask & preempts_irq )
1530
+ mask &= ~bhs ;
1531
+ if ((oldmask | mask ) & preempts_irq )
1532
+ mask |= oldmask & bhs ;
1533
+ }
1534
+
1511
1535
return mask ?: RCUTORTURE_RDR_RCU ;
1512
1536
}
1513
1537
@@ -2741,7 +2765,7 @@ static int rcu_torture_read_exit(void *unused)
2741
2765
static int rcu_torture_read_exit_init (void )
2742
2766
{
2743
2767
if (read_exit_burst <= 0 )
2744
- return - EINVAL ;
2768
+ return 0 ;
2745
2769
init_waitqueue_head (& read_exit_wq );
2746
2770
read_exit_child_stop = false;
2747
2771
read_exit_child_stopped = false;
@@ -2819,7 +2843,7 @@ rcu_torture_cleanup(void)
2819
2843
rcutorture_seq_diff (gp_seq , start_gp_seq ));
2820
2844
torture_stop_kthread (rcu_torture_stats , stats_task );
2821
2845
torture_stop_kthread (rcu_torture_fqs , fqs_task );
2822
- if (rcu_torture_can_boost ())
2846
+ if (rcu_torture_can_boost () && rcutor_hp >= 0 )
2823
2847
cpuhp_remove_state (rcutor_hp );
2824
2848
2825
2849
/*
@@ -3037,7 +3061,7 @@ rcu_torture_init(void)
3037
3061
rcu_torture_write_types ();
3038
3062
firsterr = torture_create_kthread (rcu_torture_writer , NULL ,
3039
3063
writer_task );
3040
- if (firsterr )
3064
+ if (torture_init_error ( firsterr ) )
3041
3065
goto unwind ;
3042
3066
if (nfakewriters > 0 ) {
3043
3067
fakewriter_tasks = kcalloc (nfakewriters ,
@@ -3052,7 +3076,7 @@ rcu_torture_init(void)
3052
3076
for (i = 0 ; i < nfakewriters ; i ++ ) {
3053
3077
firsterr = torture_create_kthread (rcu_torture_fakewriter ,
3054
3078
NULL , fakewriter_tasks [i ]);
3055
- if (firsterr )
3079
+ if (torture_init_error ( firsterr ) )
3056
3080
goto unwind ;
3057
3081
}
3058
3082
reader_tasks = kcalloc (nrealreaders , sizeof (reader_tasks [0 ]),
@@ -3068,7 +3092,7 @@ rcu_torture_init(void)
3068
3092
rcu_torture_reader_mbchk [i ].rtc_chkrdr = -1 ;
3069
3093
firsterr = torture_create_kthread (rcu_torture_reader , (void * )i ,
3070
3094
reader_tasks [i ]);
3071
- if (firsterr )
3095
+ if (torture_init_error ( firsterr ) )
3072
3096
goto unwind ;
3073
3097
}
3074
3098
nrealnocbers = nocbs_nthreads ;
@@ -3088,18 +3112,18 @@ rcu_torture_init(void)
3088
3112
}
3089
3113
for (i = 0 ; i < nrealnocbers ; i ++ ) {
3090
3114
firsterr = torture_create_kthread (rcu_nocb_toggle , NULL , nocb_tasks [i ]);
3091
- if (firsterr )
3115
+ if (torture_init_error ( firsterr ) )
3092
3116
goto unwind ;
3093
3117
}
3094
3118
if (stat_interval > 0 ) {
3095
3119
firsterr = torture_create_kthread (rcu_torture_stats , NULL ,
3096
3120
stats_task );
3097
- if (firsterr )
3121
+ if (torture_init_error ( firsterr ) )
3098
3122
goto unwind ;
3099
3123
}
3100
3124
if (test_no_idle_hz && shuffle_interval > 0 ) {
3101
3125
firsterr = torture_shuffle_init (shuffle_interval * HZ );
3102
- if (firsterr )
3126
+ if (torture_init_error ( firsterr ) )
3103
3127
goto unwind ;
3104
3128
}
3105
3129
if (stutter < 0 )
@@ -3109,7 +3133,7 @@ rcu_torture_init(void)
3109
3133
3110
3134
t = cur_ops -> stall_dur ? cur_ops -> stall_dur () : stutter * HZ ;
3111
3135
firsterr = torture_stutter_init (stutter * HZ , t );
3112
- if (firsterr )
3136
+ if (torture_init_error ( firsterr ) )
3113
3137
goto unwind ;
3114
3138
}
3115
3139
if (fqs_duration < 0 )
@@ -3118,7 +3142,7 @@ rcu_torture_init(void)
3118
3142
/* Create the fqs thread */
3119
3143
firsterr = torture_create_kthread (rcu_torture_fqs , NULL ,
3120
3144
fqs_task );
3121
- if (firsterr )
3145
+ if (torture_init_error ( firsterr ) )
3122
3146
goto unwind ;
3123
3147
}
3124
3148
if (test_boost_interval < 1 )
@@ -3132,9 +3156,9 @@ rcu_torture_init(void)
3132
3156
firsterr = cpuhp_setup_state (CPUHP_AP_ONLINE_DYN , "RCU_TORTURE" ,
3133
3157
rcutorture_booster_init ,
3134
3158
rcutorture_booster_cleanup );
3135
- if (firsterr < 0 )
3136
- goto unwind ;
3137
3159
rcutor_hp = firsterr ;
3160
+ if (torture_init_error (firsterr ))
3161
+ goto unwind ;
3138
3162
3139
3163
// Testing RCU priority boosting requires rcutorture do
3140
3164
// some serious abuse. Counter this by running ksoftirqd
@@ -3153,23 +3177,23 @@ rcu_torture_init(void)
3153
3177
}
3154
3178
shutdown_jiffies = jiffies + shutdown_secs * HZ ;
3155
3179
firsterr = torture_shutdown_init (shutdown_secs , rcu_torture_cleanup );
3156
- if (firsterr )
3180
+ if (torture_init_error ( firsterr ) )
3157
3181
goto unwind ;
3158
3182
firsterr = torture_onoff_init (onoff_holdoff * HZ , onoff_interval ,
3159
3183
rcutorture_sync );
3160
- if (firsterr )
3184
+ if (torture_init_error ( firsterr ) )
3161
3185
goto unwind ;
3162
3186
firsterr = rcu_torture_stall_init ();
3163
- if (firsterr )
3187
+ if (torture_init_error ( firsterr ) )
3164
3188
goto unwind ;
3165
3189
firsterr = rcu_torture_fwd_prog_init ();
3166
- if (firsterr )
3190
+ if (torture_init_error ( firsterr ) )
3167
3191
goto unwind ;
3168
3192
firsterr = rcu_torture_barrier_init ();
3169
- if (firsterr )
3193
+ if (torture_init_error ( firsterr ) )
3170
3194
goto unwind ;
3171
3195
firsterr = rcu_torture_read_exit_init ();
3172
- if (firsterr )
3196
+ if (torture_init_error ( firsterr ) )
3173
3197
goto unwind ;
3174
3198
if (object_debug )
3175
3199
rcu_test_debug_objects ();
0 commit comments