@@ -1661,6 +1661,7 @@ static void rcu_torture_fwd_prog_cb(struct rcu_head *rhp)
1661
1661
struct rcu_fwd_cb {
1662
1662
struct rcu_head rh ;
1663
1663
struct rcu_fwd_cb * rfc_next ;
1664
+ struct rcu_fwd * rfc_rfp ;
1664
1665
int rfc_gps ;
1665
1666
};
1666
1667
@@ -1692,24 +1693,24 @@ struct rcu_fwd rcu_fwds = {
1692
1693
1693
1694
bool rcu_fwd_emergency_stop ;
1694
1695
1695
- static void rcu_torture_fwd_cb_hist (void )
1696
+ static void rcu_torture_fwd_cb_hist (struct rcu_fwd * rfp )
1696
1697
{
1697
1698
unsigned long gps ;
1698
1699
unsigned long gps_old ;
1699
1700
int i ;
1700
1701
int j ;
1701
1702
1702
- for (i = ARRAY_SIZE (rcu_fwds . n_launders_hist ) - 1 ; i > 0 ; i -- )
1703
- if (rcu_fwds . n_launders_hist [i ].n_launders > 0 )
1703
+ for (i = ARRAY_SIZE (rfp -> n_launders_hist ) - 1 ; i > 0 ; i -- )
1704
+ if (rfp -> n_launders_hist [i ].n_launders > 0 )
1704
1705
break ;
1705
1706
pr_alert ("%s: Callback-invocation histogram (duration %lu jiffies):" ,
1706
- __func__ , jiffies - rcu_fwds . rcu_fwd_startat );
1707
- gps_old = rcu_fwds . rcu_launder_gp_seq_start ;
1707
+ __func__ , jiffies - rfp -> rcu_fwd_startat );
1708
+ gps_old = rfp -> rcu_launder_gp_seq_start ;
1708
1709
for (j = 0 ; j <= i ; j ++ ) {
1709
- gps = rcu_fwds . n_launders_hist [j ].launder_gp_seq ;
1710
+ gps = rfp -> n_launders_hist [j ].launder_gp_seq ;
1710
1711
pr_cont (" %ds/%d: %ld:%ld" ,
1711
1712
j + 1 , FWD_CBS_HIST_DIV ,
1712
- rcu_fwds . n_launders_hist [j ].n_launders ,
1713
+ rfp -> n_launders_hist [j ].n_launders ,
1713
1714
rcutorture_seq_diff (gps , gps_old ));
1714
1715
gps_old = gps ;
1715
1716
}
@@ -1723,20 +1724,21 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
1723
1724
int i ;
1724
1725
struct rcu_fwd_cb * rfcp = container_of (rhp , struct rcu_fwd_cb , rh );
1725
1726
struct rcu_fwd_cb * * rfcpp ;
1727
+ struct rcu_fwd * rfp = rfcp -> rfc_rfp ;
1726
1728
1727
1729
rfcp -> rfc_next = NULL ;
1728
1730
rfcp -> rfc_gps ++ ;
1729
- spin_lock_irqsave (& rcu_fwds . rcu_fwd_lock , flags );
1730
- rfcpp = rcu_fwds . rcu_fwd_cb_tail ;
1731
- rcu_fwds . rcu_fwd_cb_tail = & rfcp -> rfc_next ;
1731
+ spin_lock_irqsave (& rfp -> rcu_fwd_lock , flags );
1732
+ rfcpp = rfp -> rcu_fwd_cb_tail ;
1733
+ rfp -> rcu_fwd_cb_tail = & rfcp -> rfc_next ;
1732
1734
WRITE_ONCE (* rfcpp , rfcp );
1733
- WRITE_ONCE (rcu_fwds . n_launders_cb , rcu_fwds . n_launders_cb + 1 );
1734
- i = ((jiffies - rcu_fwds . rcu_fwd_startat ) / (HZ / FWD_CBS_HIST_DIV ));
1735
- if (i >= ARRAY_SIZE (rcu_fwds . n_launders_hist ))
1736
- i = ARRAY_SIZE (rcu_fwds . n_launders_hist ) - 1 ;
1737
- rcu_fwds . n_launders_hist [i ].n_launders ++ ;
1738
- rcu_fwds . n_launders_hist [i ].launder_gp_seq = cur_ops -> get_gp_seq ();
1739
- spin_unlock_irqrestore (& rcu_fwds . rcu_fwd_lock , flags );
1735
+ WRITE_ONCE (rfp -> n_launders_cb , rfp -> n_launders_cb + 1 );
1736
+ i = ((jiffies - rfp -> rcu_fwd_startat ) / (HZ / FWD_CBS_HIST_DIV ));
1737
+ if (i >= ARRAY_SIZE (rfp -> n_launders_hist ))
1738
+ i = ARRAY_SIZE (rfp -> n_launders_hist ) - 1 ;
1739
+ rfp -> n_launders_hist [i ].n_launders ++ ;
1740
+ rfp -> n_launders_hist [i ].launder_gp_seq = cur_ops -> get_gp_seq ();
1741
+ spin_unlock_irqrestore (& rfp -> rcu_fwd_lock , flags );
1740
1742
}
1741
1743
1742
1744
// Give the scheduler a chance, even on nohz_full CPUs.
@@ -1786,7 +1788,8 @@ static unsigned long rcu_torture_fwd_prog_cbfree(void)
1786
1788
}
1787
1789
1788
1790
/* Carry out need_resched()/cond_resched() forward-progress testing. */
1789
- static void rcu_torture_fwd_prog_nr (int * tested , int * tested_tries )
1791
+ static void rcu_torture_fwd_prog_nr (struct rcu_fwd * rfp ,
1792
+ int * tested , int * tested_tries )
1790
1793
{
1791
1794
unsigned long cver ;
1792
1795
unsigned long dur ;
@@ -1816,8 +1819,8 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries)
1816
1819
sd = cur_ops -> stall_dur () + 1 ;
1817
1820
sd4 = (sd + fwd_progress_div - 1 ) / fwd_progress_div ;
1818
1821
dur = sd4 + torture_random (& trs ) % (sd - sd4 );
1819
- WRITE_ONCE (rcu_fwds . rcu_fwd_startat , jiffies );
1820
- stopat = rcu_fwds . rcu_fwd_startat + dur ;
1822
+ WRITE_ONCE (rfp -> rcu_fwd_startat , jiffies );
1823
+ stopat = rfp -> rcu_fwd_startat + dur ;
1821
1824
while (time_before (jiffies , stopat ) &&
1822
1825
!shutdown_time_arrived () &&
1823
1826
!READ_ONCE (rcu_fwd_emergency_stop ) && !torture_must_stop ()) {
@@ -1852,7 +1855,7 @@ static void rcu_torture_fwd_prog_nr(int *tested, int *tested_tries)
1852
1855
}
1853
1856
1854
1857
/* Carry out call_rcu() forward-progress testing. */
1855
- static void rcu_torture_fwd_prog_cr (void )
1858
+ static void rcu_torture_fwd_prog_cr (struct rcu_fwd * rfp )
1856
1859
{
1857
1860
unsigned long cver ;
1858
1861
unsigned long flags ;
@@ -1876,31 +1879,31 @@ static void rcu_torture_fwd_prog_cr(void)
1876
1879
/* Loop continuously posting RCU callbacks. */
1877
1880
WRITE_ONCE (rcu_fwd_cb_nodelay , true);
1878
1881
cur_ops -> sync (); /* Later readers see above write. */
1879
- WRITE_ONCE (rcu_fwds . rcu_fwd_startat , jiffies );
1880
- stopat = rcu_fwds . rcu_fwd_startat + MAX_FWD_CB_JIFFIES ;
1882
+ WRITE_ONCE (rfp -> rcu_fwd_startat , jiffies );
1883
+ stopat = rfp -> rcu_fwd_startat + MAX_FWD_CB_JIFFIES ;
1881
1884
n_launders = 0 ;
1882
- rcu_fwds . n_launders_cb = 0 ; // Hoist initialization for multi-kthread
1885
+ rfp -> n_launders_cb = 0 ; // Hoist initialization for multi-kthread
1883
1886
n_launders_sa = 0 ;
1884
1887
n_max_cbs = 0 ;
1885
1888
n_max_gps = 0 ;
1886
- for (i = 0 ; i < ARRAY_SIZE (rcu_fwds . n_launders_hist ); i ++ )
1887
- rcu_fwds . n_launders_hist [i ].n_launders = 0 ;
1889
+ for (i = 0 ; i < ARRAY_SIZE (rfp -> n_launders_hist ); i ++ )
1890
+ rfp -> n_launders_hist [i ].n_launders = 0 ;
1888
1891
cver = READ_ONCE (rcu_torture_current_version );
1889
1892
gps = cur_ops -> get_gp_seq ();
1890
- rcu_fwds . rcu_launder_gp_seq_start = gps ;
1893
+ rfp -> rcu_launder_gp_seq_start = gps ;
1891
1894
tick_dep_set_task (current , TICK_DEP_BIT_RCU );
1892
1895
while (time_before (jiffies , stopat ) &&
1893
1896
!shutdown_time_arrived () &&
1894
1897
!READ_ONCE (rcu_fwd_emergency_stop ) && !torture_must_stop ()) {
1895
- rfcp = READ_ONCE (rcu_fwds . rcu_fwd_cb_head );
1898
+ rfcp = READ_ONCE (rfp -> rcu_fwd_cb_head );
1896
1899
rfcpn = NULL ;
1897
1900
if (rfcp )
1898
1901
rfcpn = READ_ONCE (rfcp -> rfc_next );
1899
1902
if (rfcpn ) {
1900
1903
if (rfcp -> rfc_gps >= MIN_FWD_CB_LAUNDERS &&
1901
1904
++ n_max_gps >= MIN_FWD_CBS_LAUNDERED )
1902
1905
break ;
1903
- rcu_fwds . rcu_fwd_cb_head = rfcpn ;
1906
+ rfp -> rcu_fwd_cb_head = rfcpn ;
1904
1907
n_launders ++ ;
1905
1908
n_launders_sa ++ ;
1906
1909
} else {
@@ -1912,6 +1915,7 @@ static void rcu_torture_fwd_prog_cr(void)
1912
1915
n_max_cbs ++ ;
1913
1916
n_launders_sa = 0 ;
1914
1917
rfcp -> rfc_gps = 0 ;
1918
+ rfcp -> rfc_rfp = rfp ;
1915
1919
}
1916
1920
cur_ops -> call (& rfcp -> rh , rcu_torture_fwd_cb_cr );
1917
1921
rcu_torture_fwd_prog_cond_resched (n_launders + n_max_cbs );
@@ -1922,7 +1926,7 @@ static void rcu_torture_fwd_prog_cr(void)
1922
1926
}
1923
1927
}
1924
1928
stoppedat = jiffies ;
1925
- n_launders_cb_snap = READ_ONCE (rcu_fwds . n_launders_cb );
1929
+ n_launders_cb_snap = READ_ONCE (rfp -> n_launders_cb );
1926
1930
cver = READ_ONCE (rcu_torture_current_version ) - cver ;
1927
1931
gps = rcutorture_seq_diff (cur_ops -> get_gp_seq (), gps );
1928
1932
cur_ops -> cb_barrier (); /* Wait for callbacks to be invoked. */
@@ -1933,12 +1937,11 @@ static void rcu_torture_fwd_prog_cr(void)
1933
1937
WARN_ON (n_max_gps < MIN_FWD_CBS_LAUNDERED );
1934
1938
pr_alert ("%s Duration %lu barrier: %lu pending %ld n_launders: %ld n_launders_sa: %ld n_max_gps: %ld n_max_cbs: %ld cver %ld gps %ld\n" ,
1935
1939
__func__ ,
1936
- stoppedat - rcu_fwds .rcu_fwd_startat ,
1937
- jiffies - stoppedat ,
1940
+ stoppedat - rfp -> rcu_fwd_startat , jiffies - stoppedat ,
1938
1941
n_launders + n_max_cbs - n_launders_cb_snap ,
1939
1942
n_launders , n_launders_sa ,
1940
1943
n_max_gps , n_max_cbs , cver , gps );
1941
- rcu_torture_fwd_cb_hist ();
1944
+ rcu_torture_fwd_cb_hist (rfp );
1942
1945
}
1943
1946
schedule_timeout_uninterruptible (HZ ); /* Let CBs drain. */
1944
1947
tick_dep_clear_task (current , TICK_DEP_BIT_RCU );
@@ -1955,7 +1958,7 @@ static int rcutorture_oom_notify(struct notifier_block *self,
1955
1958
{
1956
1959
WARN (1 , "%s invoked upon OOM during forward-progress testing.\n" ,
1957
1960
__func__ );
1958
- rcu_torture_fwd_cb_hist ();
1961
+ rcu_torture_fwd_cb_hist (& rcu_fwds );
1959
1962
rcu_fwd_progress_check (1 + (jiffies - READ_ONCE (rcu_fwds .rcu_fwd_startat )) / 2 );
1960
1963
WRITE_ONCE (rcu_fwd_emergency_stop , true);
1961
1964
smp_mb (); /* Emergency stop before free and wait to avoid hangs. */
@@ -1980,6 +1983,7 @@ static struct notifier_block rcutorture_oom_nb = {
1980
1983
/* Carry out grace-period forward-progress testing. */
1981
1984
static int rcu_torture_fwd_prog (void * args )
1982
1985
{
1986
+ struct rcu_fwd * rfp = args ;
1983
1987
int tested = 0 ;
1984
1988
int tested_tries = 0 ;
1985
1989
@@ -1991,8 +1995,8 @@ static int rcu_torture_fwd_prog(void *args)
1991
1995
schedule_timeout_interruptible (fwd_progress_holdoff * HZ );
1992
1996
WRITE_ONCE (rcu_fwd_emergency_stop , false);
1993
1997
register_oom_notifier (& rcutorture_oom_nb );
1994
- rcu_torture_fwd_prog_nr (& tested , & tested_tries );
1995
- rcu_torture_fwd_prog_cr ();
1998
+ rcu_torture_fwd_prog_nr (rfp , & tested , & tested_tries );
1999
+ rcu_torture_fwd_prog_cr (rfp );
1996
2000
unregister_oom_notifier (& rcutorture_oom_nb );
1997
2001
1998
2002
/* Avoid slow periods, better to test when busy. */
@@ -2027,7 +2031,7 @@ static int __init rcu_torture_fwd_prog_init(void)
2027
2031
if (fwd_progress_div <= 0 )
2028
2032
fwd_progress_div = 4 ;
2029
2033
return torture_create_kthread (rcu_torture_fwd_prog ,
2030
- NULL , fwd_prog_task );
2034
+ & rcu_fwds , fwd_prog_task );
2031
2035
}
2032
2036
2033
2037
/* Callback function for RCU barrier testing. */
0 commit comments