@@ -359,7 +359,8 @@ struct rcu_torture_ops {
359
359
void (* read_delay )(struct torture_random_state * rrsp ,
360
360
struct rt_read_seg * rtrsp );
361
361
void (* readunlock )(int idx );
362
- int (* readlock_held )(void );
362
+ int (* readlock_held )(void ); // lockdep.
363
+ int (* readlock_nesting )(void ); // actual nesting, if available, -1 if not.
363
364
unsigned long (* get_gp_seq )(void );
364
365
unsigned long (* gp_diff )(unsigned long new , unsigned long old );
365
366
void (* deferred_free )(struct rcu_torture * p );
@@ -466,6 +467,15 @@ static void rcu_torture_read_unlock(int idx)
466
467
rcu_read_unlock ();
467
468
}
468
469
470
+ static int rcu_torture_readlock_nesting (void )
471
+ {
472
+ if (IS_ENABLED (CONFIG_PREEMPT_RCU ))
473
+ return rcu_preempt_depth ();
474
+ if (IS_ENABLED (CONFIG_PREEMPT_COUNT ))
475
+ return (preempt_count () & PREEMPT_MASK );
476
+ return -1 ;
477
+ }
478
+
469
479
/*
470
480
* Update callback in the pipe. This should be invoked after a grace period.
471
481
*/
@@ -555,6 +565,7 @@ static struct rcu_torture_ops rcu_ops = {
555
565
.read_delay = rcu_read_delay ,
556
566
.readunlock = rcu_torture_read_unlock ,
557
567
.readlock_held = torture_readlock_not_held ,
568
+ .readlock_nesting = rcu_torture_readlock_nesting ,
558
569
.get_gp_seq = rcu_get_gp_seq ,
559
570
.gp_diff = rcu_seq_diff ,
560
571
.deferred_free = rcu_torture_deferred_free ,
@@ -1847,6 +1858,44 @@ static void rcu_torture_reader_do_mbchk(long myid, struct rcu_torture *rtp,
1847
1858
smp_store_release (& rtrcp_assigner -> rtc_chkrdr , -1 ); // Assigner can again assign.
1848
1859
}
1849
1860
1861
+ // Verify the specified RCUTORTURE_RDR* state.
1862
+ #define ROEC_ARGS "%s %s: Current %#x To add %#x To remove %#x\n", __func__, s, curstate, new, old
1863
+ static void rcutorture_one_extend_check (char * s , int curstate , int new , int old , bool insoftirq )
1864
+ {
1865
+ if (!IS_ENABLED (CONFIG_RCU_TORTURE_TEST_CHK_RDR_STATE ))
1866
+ return ;
1867
+
1868
+ WARN_ONCE (!(curstate & RCUTORTURE_RDR_IRQ ) && irqs_disabled (), ROEC_ARGS );
1869
+ WARN_ONCE ((curstate & RCUTORTURE_RDR_IRQ ) && !irqs_disabled (), ROEC_ARGS );
1870
+
1871
+ // If CONFIG_PREEMPT_COUNT=n, further checks are unreliable.
1872
+ if (!IS_ENABLED (CONFIG_PREEMPT_COUNT ))
1873
+ return ;
1874
+
1875
+ WARN_ONCE ((curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH )) &&
1876
+ !(preempt_count () & SOFTIRQ_MASK ), ROEC_ARGS );
1877
+ WARN_ONCE ((curstate & (RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED )) &&
1878
+ !(preempt_count () & PREEMPT_MASK ), ROEC_ARGS );
1879
+ WARN_ONCE (cur_ops -> readlock_nesting &&
1880
+ (curstate & (RCUTORTURE_RDR_RCU_1 | RCUTORTURE_RDR_RCU_2 )) &&
1881
+ cur_ops -> readlock_nesting () == 0 , ROEC_ARGS );
1882
+
1883
+ // Timer handlers have all sorts of stuff disabled, so ignore
1884
+ // unintended disabling.
1885
+ if (insoftirq )
1886
+ return ;
1887
+
1888
+ WARN_ONCE (cur_ops -> extendables &&
1889
+ !(curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH )) &&
1890
+ (preempt_count () & SOFTIRQ_MASK ), ROEC_ARGS );
1891
+ WARN_ONCE (cur_ops -> extendables &&
1892
+ !(curstate & (RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED )) &&
1893
+ (preempt_count () & PREEMPT_MASK ), ROEC_ARGS );
1894
+ WARN_ONCE (cur_ops -> readlock_nesting &&
1895
+ !(curstate & (RCUTORTURE_RDR_RCU_1 | RCUTORTURE_RDR_RCU_2 )) &&
1896
+ cur_ops -> readlock_nesting () > 0 , ROEC_ARGS );
1897
+ }
1898
+
1850
1899
/*
1851
1900
* Do one extension of an RCU read-side critical section using the
1852
1901
* current reader state in readstate (set to zero for initial entry
@@ -1856,7 +1905,7 @@ static void rcu_torture_reader_do_mbchk(long myid, struct rcu_torture *rtp,
1856
1905
* beginning or end of the critical section and if there was actually a
1857
1906
* change, do a ->read_delay().
1858
1907
*/
1859
- static void rcutorture_one_extend (int * readstate , int newstate ,
1908
+ static void rcutorture_one_extend (int * readstate , int newstate , bool insoftirq ,
1860
1909
struct torture_random_state * trsp ,
1861
1910
struct rt_read_seg * rtrsp )
1862
1911
{
@@ -1870,6 +1919,7 @@ static void rcutorture_one_extend(int *readstate, int newstate,
1870
1919
1871
1920
WARN_ON_ONCE (idxold2 < 0 );
1872
1921
WARN_ON_ONCE (idxold2 & ~RCUTORTURE_RDR_ALLBITS );
1922
+ rcutorture_one_extend_check ("before change" , idxold1 , statesnew , statesold , insoftirq );
1873
1923
rtrsp -> rt_readstate = newstate ;
1874
1924
if (IS_ENABLED (CONFIG_RCU_TORTURE_TEST_LOG_CPU ))
1875
1925
rtrsp -> rt_cpu = raw_smp_processor_id ();
@@ -1890,6 +1940,10 @@ static void rcutorture_one_extend(int *readstate, int newstate,
1890
1940
if (statesnew & RCUTORTURE_RDR_RCU_2 )
1891
1941
idxnew2 = (cur_ops -> readlock () << RCUTORTURE_RDR_SHIFT_2 ) & RCUTORTURE_RDR_MASK_2 ;
1892
1942
1943
+ // Complain unless both the old and the new protection is in place.
1944
+ rcutorture_one_extend_check ("during change" ,
1945
+ idxold1 | statesnew , statesnew , statesold , insoftirq );
1946
+
1893
1947
/*
1894
1948
* Next, remove old protection, in decreasing order of strength
1895
1949
* to avoid unlock paths that aren't safe in the stronger
@@ -1940,6 +1994,7 @@ static void rcutorture_one_extend(int *readstate, int newstate,
1940
1994
WARN_ON_ONCE (* readstate < 0 );
1941
1995
if (WARN_ON_ONCE (* readstate & ~RCUTORTURE_RDR_ALLBITS ))
1942
1996
pr_info ("Unexpected readstate value of %#x\n" , * readstate );
1997
+ rcutorture_one_extend_check ("after change" , * readstate , statesnew , statesold , insoftirq );
1943
1998
}
1944
1999
1945
2000
/* Return the biggest extendables mask given current RCU and boot parameters. */
@@ -2006,7 +2061,7 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp)
2006
2061
* critical section.
2007
2062
*/
2008
2063
static struct rt_read_seg *
2009
- rcutorture_loop_extend (int * readstate , struct torture_random_state * trsp ,
2064
+ rcutorture_loop_extend (int * readstate , bool insoftirq , struct torture_random_state * trsp ,
2010
2065
struct rt_read_seg * rtrsp )
2011
2066
{
2012
2067
int i ;
@@ -2021,7 +2076,7 @@ rcutorture_loop_extend(int *readstate, struct torture_random_state *trsp,
2021
2076
i = ((i | (i >> 3 )) & RCUTORTURE_RDR_MAX_LOOPS ) + 1 ;
2022
2077
for (j = 0 ; j < i ; j ++ ) {
2023
2078
mask = rcutorture_extend_mask (* readstate , trsp );
2024
- rcutorture_one_extend (readstate , mask , trsp , & rtrsp [j ]);
2079
+ rcutorture_one_extend (readstate , mask , insoftirq , trsp , & rtrsp [j ]);
2025
2080
}
2026
2081
return & rtrsp [j ];
2027
2082
}
@@ -2051,7 +2106,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
2051
2106
2052
2107
WARN_ON_ONCE (!rcu_is_watching ());
2053
2108
newstate = rcutorture_extend_mask (readstate , trsp );
2054
- rcutorture_one_extend (& readstate , newstate , trsp , rtrsp ++ );
2109
+ rcutorture_one_extend (& readstate , newstate , myid < 0 , trsp , rtrsp ++ );
2055
2110
if (checkpolling ) {
2056
2111
if (cur_ops -> get_gp_state && cur_ops -> poll_gp_state )
2057
2112
cookie = cur_ops -> get_gp_state ();
@@ -2064,13 +2119,13 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
2064
2119
!cur_ops -> readlock_held || cur_ops -> readlock_held ());
2065
2120
if (p == NULL ) {
2066
2121
/* Wait for rcu_torture_writer to get underway */
2067
- rcutorture_one_extend (& readstate , 0 , trsp , rtrsp );
2122
+ rcutorture_one_extend (& readstate , 0 , myid < 0 , trsp , rtrsp );
2068
2123
return false;
2069
2124
}
2070
2125
if (p -> rtort_mbtest == 0 )
2071
2126
atomic_inc (& n_rcu_torture_mberror );
2072
2127
rcu_torture_reader_do_mbchk (myid , p , trsp );
2073
- rtrsp = rcutorture_loop_extend (& readstate , trsp , rtrsp );
2128
+ rtrsp = rcutorture_loop_extend (& readstate , myid < 0 , trsp , rtrsp );
2074
2129
preempt_disable ();
2075
2130
pipe_count = READ_ONCE (p -> rtort_pipe_count );
2076
2131
if (pipe_count > RCU_TORTURE_PIPE_LEN ) {
@@ -2112,7 +2167,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
2112
2167
preempted = cur_ops -> reader_blocked ();
2113
2168
if (IS_ENABLED (CONFIG_RCU_TORTURE_TEST_LOG_CPU ))
2114
2169
rt_last_cpu = raw_smp_processor_id ();
2115
- rcutorture_one_extend (& readstate , 0 , trsp , rtrsp );
2170
+ rcutorture_one_extend (& readstate , 0 , myid < 0 , trsp , rtrsp );
2116
2171
WARN_ON_ONCE (readstate );
2117
2172
// This next splat is expected behavior if leakpointer, especially
2118
2173
// for CONFIG_RCU_STRICT_GRACE_PERIOD=y kernels.
0 commit comments