Commit b3fd4ea9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull RCU updates from Ingo Molnar:
 "Main changes:

   - Torture-test changes, including refactoring of rcutorture and
     introduction of a vestigial locktorture.

   - Real-time latency fixes.

   - Documentation updates.

   - Miscellaneous fixes"

* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (77 commits)
  rcu: Provide grace-period piggybacking API
  rcu: Ensure kernel/rcu/rcu.h can be sourced/used stand-alone
  rcu: Fix sparse warning for rcu_expedited from kernel/ksysfs.c
  notifier: Substitute rcu_access_pointer() for rcu_dereference_raw()
  Documentation/memory-barriers.txt: Clarify release/acquire ordering
  rcutorture: Save kvm.sh output to log
  rcutorture: Add a lock_busted to test the test
  rcutorture: Place kvm-test-1-run.sh output into res directory
  rcutorture: Rename TREE_RCU-Kconfig.txt
  locktorture: Add kvm-recheck.sh plug-in for locktorture
  rcutorture: Gracefully handle NULL cleanup hooks
  locktorture: Add vestigial locktorture configuration
  rcutorture: Introduce "rcu" directory level underneath configs
  rcutorture: Rename kvm-test-1-rcu.sh
  rcutorture: Remove RCU dependencies from ver_functions.sh API
  rcutorture: Create CFcommon file for common Kconfig parameters
  rcutorture: Create config files for scripted test-the-test testing
  rcutorture: Add an rcu_busted to test the test
  locktorture: Add a lock-torture kernel module
  rcutorture: Abstract kvm-recheck.sh
  ...
parents 462bf234 7de700e6
...@@ -31,6 +31,14 @@ has lapsed, so this approach may be used in non-GPL software, if desired. ...@@ -31,6 +31,14 @@ has lapsed, so this approach may be used in non-GPL software, if desired.
(In contrast, implementation of RCU is permitted only in software licensed (In contrast, implementation of RCU is permitted only in software licensed
under either GPL or LGPL. Sorry!!!) under either GPL or LGPL. Sorry!!!)
In 1987, Rashid et al. described lazy TLB-flush [RichardRashid87a].
At first glance, this has nothing to do with RCU, but nevertheless
this paper helped inspire the update-side batching used in the later
RCU implementation in DYNIX/ptx. In 1988, Barbara Liskov published
a description of Argus that noted that use of out-of-date values can
be tolerated in some situations. Thus, this paper provides some early
theoretical justification for use of stale data.
In 1990, Pugh [Pugh90] noted that explicitly tracking which threads In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
were reading a given data structure permitted deferred free to operate were reading a given data structure permitted deferred free to operate
in the presence of non-terminating threads. However, this explicit in the presence of non-terminating threads. However, this explicit
...@@ -41,11 +49,11 @@ providing a fine-grained locking design, however, it would be interesting ...@@ -41,11 +49,11 @@ providing a fine-grained locking design, however, it would be interesting
to see how much of the performance advantage reported in 1990 remains to see how much of the performance advantage reported in 1990 remains
today. today.
At about this same time, Adams [Adams91] described ``chaotic relaxation'', At about this same time, Andrews [Andrews91textbook] described ``chaotic
where the normal barriers between successive iterations of convergent relaxation'', where the normal barriers between successive iterations
numerical algorithms are relaxed, so that iteration $n$ might use of convergent numerical algorithms are relaxed, so that iteration $n$
data from iteration $n-1$ or even $n-2$. This introduces error, might use data from iteration $n-1$ or even $n-2$. This introduces
which typically slows convergence and thus increases the number of error, which typically slows convergence and thus increases the number of
iterations required. However, this increase is sometimes more than made iterations required. However, this increase is sometimes more than made
up for by a reduction in the number of expensive barrier operations, up for by a reduction in the number of expensive barrier operations,
which are otherwise required to synchronize the threads at the end which are otherwise required to synchronize the threads at the end
...@@ -55,7 +63,8 @@ is thus inapplicable to most data structures in operating-system kernels. ...@@ -55,7 +63,8 @@ is thus inapplicable to most data structures in operating-system kernels.
In 1992, Henry (now Alexia) Massalin completed a dissertation advising In 1992, Henry (now Alexia) Massalin completed a dissertation advising
parallel programmers to defer processing when feasible to simplify parallel programmers to defer processing when feasible to simplify
synchronization. RCU makes extremely heavy use of this advice. synchronization [HMassalinPhD]. RCU makes extremely heavy use of
this advice.
In 1993, Jacobson [Jacobson93] verbally described what is perhaps the In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
simplest deferred-free technique: simply waiting a fixed amount of time simplest deferred-free technique: simply waiting a fixed amount of time
...@@ -90,27 +99,29 @@ mechanism, which is quite similar to RCU [Gamsa99]. These operating ...@@ -90,27 +99,29 @@ mechanism, which is quite similar to RCU [Gamsa99]. These operating
systems made pervasive use of RCU in place of "existence locks", which systems made pervasive use of RCU in place of "existence locks", which
greatly simplifies locking hierarchies and helps avoid deadlocks. greatly simplifies locking hierarchies and helps avoid deadlocks.
2001 saw the first RCU presentation involving Linux [McKenney01a] The year 2000 saw an email exchange that would likely have
at OLS. The resulting abundance of RCU patches was presented the led to yet another independent invention of something like RCU
following year [McKenney02a], and use of RCU in dcache was first [RustyRussell2000a,RustyRussell2000b]. Instead, 2001 saw the first
described that same year [Linder02a]. RCU presentation involving Linux [McKenney01a] at OLS. The resulting
abundance of RCU patches was presented the following year [McKenney02a],
and use of RCU in dcache was first described that same year [Linder02a].
Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer" Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
techniques that defer the destruction of data structures to simplify techniques that defer the destruction of data structures to simplify
non-blocking synchronization (wait-free synchronization, lock-free non-blocking synchronization (wait-free synchronization, lock-free
synchronization, and obstruction-free synchronization are all examples of synchronization, and obstruction-free synchronization are all examples of
non-blocking synchronization). In particular, this technique eliminates non-blocking synchronization). The corresponding journal article appeared
locking, reduces contention, reduces memory latency for readers, and in 2004 [MagedMichael04a]. This technique eliminates locking, reduces
parallelizes pipeline stalls and memory latency for writers. However, contention, reduces memory latency for readers, and parallelizes pipeline
these techniques still impose significant read-side overhead in the stalls and memory latency for writers. However, these techniques still
form of memory barriers. Researchers at Sun worked along similar lines impose significant read-side overhead in the form of memory barriers.
in the same timeframe [HerlihyLM02]. These techniques can be thought Researchers at Sun worked along similar lines in the same timeframe
of as inside-out reference counts, where the count is represented by the [HerlihyLM02]. These techniques can be thought of as inside-out reference
number of hazard pointers referencing a given data structure rather than counts, where the count is represented by the number of hazard pointers
the more conventional counter field within the data structure itself. referencing a given data structure rather than the more conventional
The key advantage of inside-out reference counts is that they can be counter field within the data structure itself. The key advantage
stored in immortal variables, thus allowing races between access and of inside-out reference counts is that they can be stored in immortal
deletion to be avoided. variables, thus allowing races between access and deletion to be avoided.
By the same token, RCU can be thought of as a "bulk reference count", By the same token, RCU can be thought of as a "bulk reference count",
where some form of reference counter covers all reference by a given CPU where some form of reference counter covers all reference by a given CPU
...@@ -123,8 +134,10 @@ can be thought of in other terms as well. ...@@ -123,8 +134,10 @@ can be thought of in other terms as well.
In 2003, the K42 group described how RCU could be used to create In 2003, the K42 group described how RCU could be used to create
hot-pluggable implementations of operating-system functions [Appavoo03a]. hot-pluggable implementations of operating-system functions [Appavoo03a].
Later that year saw a paper describing an RCU implementation of System Later that year saw a paper describing an RCU implementation
V IPC [Arcangeli03], and an introduction to RCU in Linux Journal of System V IPC [Arcangeli03] (following up on a suggestion by
Hugh Dickins [Dickins02a] and an implementation by Mingming Cao
[MingmingCao2002IPCRCU]), and an introduction to RCU in Linux Journal
[McKenney03a]. [McKenney03a].
2004 has seen a Linux-Journal article on use of RCU in dcache 2004 has seen a Linux-Journal article on use of RCU in dcache
...@@ -383,6 +396,21 @@ for Programming Languages and Operating Systems}" ...@@ -383,6 +396,21 @@ for Programming Languages and Operating Systems}"
} }
} }
@phdthesis{HMassalinPhD
,author="H. Massalin"
,title="Synthesis: An Efficient Implementation of Fundamental Operating
System Services"
,school="Columbia University"
,address="New York, NY"
,year="1992"
,annotation={
Mondo optimizing compiler.
Wait-free stuff.
Good advice: defer work to avoid synchronization. See page 90
(PDF page 106), Section 5.4, fourth bullet point.
}
}
@unpublished{Jacobson93 @unpublished{Jacobson93
,author="Van Jacobson" ,author="Van Jacobson"
,title="Avoid Read-Side Locking Via Delayed Free" ,title="Avoid Read-Side Locking Via Delayed Free"
...@@ -671,6 +699,20 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni" ...@@ -671,6 +699,20 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
[Viewed October 18, 2004]" [Viewed October 18, 2004]"
} }
@conference{Michael02b
,author="Maged M. Michael"
,title="High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
,Year="2002"
,Month="August"
,booktitle="{Proceedings of the 14\textsuperscript{th} Annual ACM
Symposium on Parallel
Algorithms and Architecture}"
,pages="73-82"
,annotation={
Like the title says...
}
}
@Conference{Linder02a @Conference{Linder02a
,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni" ,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
,Title="Scalability of the Directory Entry Cache" ,Title="Scalability of the Directory Entry Cache"
...@@ -727,6 +769,24 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell" ...@@ -727,6 +769,24 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
} }
} }
@conference{Michael02a
,author="Maged M. Michael"
,title="Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic
Reads and Writes"
,Year="2002"
,Month="August"
,booktitle="{Proceedings of the 21\textsuperscript{st} Annual ACM
Symposium on Principles of Distributed Computing}"
,pages="21-30"
,annotation={
Each thread keeps an array of pointers to items that it is
currently referencing. Sort of an inside-out garbage collection
mechanism, but one that requires the accessing code to explicitly
state its needs. Also requires read-side memory barriers on
most architectures.
}
}
@unpublished{Dickins02a @unpublished{Dickins02a
,author="Hugh Dickins" ,author="Hugh Dickins"
,title="Use RCU for System-V IPC" ,title="Use RCU for System-V IPC"
...@@ -735,6 +795,17 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell" ...@@ -735,6 +795,17 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
,note="private communication" ,note="private communication"
} }
@InProceedings{HerlihyLM02
,author={Maurice Herlihy and Victor Luchangco and Mark Moir}
,title="The Repeat Offender Problem: A Mechanism for Supporting Dynamic-Sized,
Lock-Free Data Structures"
,booktitle={Proceedings of 16\textsuperscript{th} International
Symposium on Distributed Computing}
,year=2002
,month="October"
,pages="339-353"
}
@unpublished{Sarma02b @unpublished{Sarma02b
,Author="Dipankar Sarma" ,Author="Dipankar Sarma"
,Title="Some dcache\_rcu benchmark numbers" ,Title="Some dcache\_rcu benchmark numbers"
...@@ -749,6 +820,19 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell" ...@@ -749,6 +820,19 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
} }
} }
@unpublished{MingmingCao2002IPCRCU
,Author="Mingming Cao"
,Title="[PATCH]updated ipc lock patch"
,month="October"
,year="2002"
,note="Available:
\url{https://lkml.org/lkml/2002/10/24/262}
[Viewed February 15, 2014]"
,annotation={
Mingming Cao's patch to introduce RCU to SysV IPC.
}
}
@unpublished{LinusTorvalds2003a @unpublished{LinusTorvalds2003a
,Author="Linus Torvalds" ,Author="Linus Torvalds"
,Title="Re: {[PATCH]} small fixes in brlock.h" ,Title="Re: {[PATCH]} small fixes in brlock.h"
...@@ -982,6 +1066,23 @@ Realtime Applications" ...@@ -982,6 +1066,23 @@ Realtime Applications"
} }
} }
@article{MagedMichael04a
,author="Maged M. Michael"
,title="Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects"
,Year="2004"
,Month="June"
,journal="IEEE Transactions on Parallel and Distributed Systems"
,volume="15"
,number="6"
,pages="491-504"
,url="Available:
\url{http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf}
[Viewed March 1, 2005]"
,annotation={
New canonical hazard-pointer citation.
}
}
@phdthesis{PaulEdwardMcKenneyPhD @phdthesis{PaulEdwardMcKenneyPhD
,author="Paul E. McKenney" ,author="Paul E. McKenney"
,title="Exploiting Deferred Destruction: ,title="Exploiting Deferred Destruction:
......
...@@ -256,10 +256,10 @@ over a rather long period of time, but improvements are always welcome! ...@@ -256,10 +256,10 @@ over a rather long period of time, but improvements are always welcome!
variations on this theme. variations on this theme.
b. Limiting update rate. For example, if updates occur only b. Limiting update rate. For example, if updates occur only
once per hour, then no explicit rate limiting is required, once per hour, then no explicit rate limiting is
unless your system is already badly broken. The dcache required, unless your system is already badly broken.
subsystem takes this approach -- updates are guarded Older versions of the dcache subsystem take this approach,
by a global lock, limiting their rate. guarding updates with a global lock, limiting their rate.
c. Trusted update -- if updates can only be done manually by c. Trusted update -- if updates can only be done manually by
superuser or some other trusted user, then it might not superuser or some other trusted user, then it might not
...@@ -268,7 +268,8 @@ over a rather long period of time, but improvements are always welcome! ...@@ -268,7 +268,8 @@ over a rather long period of time, but improvements are always welcome!
the machine. the machine.
d. Use call_rcu_bh() rather than call_rcu(), in order to take d. Use call_rcu_bh() rather than call_rcu(), in order to take
advantage of call_rcu_bh()'s faster grace periods. advantage of call_rcu_bh()'s faster grace periods. (This
is only a partial solution, though.)
e. Periodically invoke synchronize_rcu(), permitting a limited e. Periodically invoke synchronize_rcu(), permitting a limited
number of updates per grace period. number of updates per grace period.
...@@ -276,6 +277,13 @@ over a rather long period of time, but improvements are always welcome! ...@@ -276,6 +277,13 @@ over a rather long period of time, but improvements are always welcome!
The same cautions apply to call_rcu_bh(), call_rcu_sched(), The same cautions apply to call_rcu_bh(), call_rcu_sched(),
call_srcu(), and kfree_rcu(). call_srcu(), and kfree_rcu().
Note that although these primitives do take action to avoid memory
exhaustion when any given CPU has too many callbacks, a determined
user could still exhaust memory. This is especially the case
if a system with a large number of CPUs has been configured to
offload all of its RCU callbacks onto a single CPU, or if the
system has relatively little free memory.
9. All RCU list-traversal primitives, which include 9. All RCU list-traversal primitives, which include
rcu_dereference(), list_for_each_entry_rcu(), and rcu_dereference(), list_for_each_entry_rcu(), and
list_for_each_safe_rcu(), must be either within an RCU read-side list_for_each_safe_rcu(), must be either within an RCU read-side
......
...@@ -162,7 +162,18 @@ Purpose: Execute workqueue requests ...@@ -162,7 +162,18 @@ Purpose: Execute workqueue requests
To reduce its OS jitter, do any of the following: To reduce its OS jitter, do any of the following:
1. Run your workload at a real-time priority, which will allow 1. Run your workload at a real-time priority, which will allow
preempting the kworker daemons. preempting the kworker daemons.
2. Do any of the following needed to avoid jitter that your 2. A given workqueue can be made visible in the sysfs filesystem
by passing the WQ_SYSFS to that workqueue's alloc_workqueue().
Such a workqueue can be confined to a given subset of the
CPUs using the /sys/devices/virtual/workqueue/*/cpumask sysfs
files. The set of WQ_SYSFS workqueues can be displayed using
"ls sys/devices/virtual/workqueue". That said, the workqueues
maintainer would like to caution people against indiscriminately
sprinkling WQ_SYSFS across all the workqueues. The reason for
caution is that it is easy to add WQ_SYSFS, but because sysfs is
part of the formal user/kernel API, it can be nearly impossible
to remove it, even if its addition was a mistake.
3. Do any of the following needed to avoid jitter that your
application cannot tolerate: application cannot tolerate:
a. Build your kernel with CONFIG_SLUB=y rather than a. Build your kernel with CONFIG_SLUB=y rather than
CONFIG_SLAB=y, thus avoiding the slab allocator's periodic CONFIG_SLAB=y, thus avoiding the slab allocator's periodic
......
This diff is collapsed.
...@@ -497,7 +497,7 @@ int __alloc_fd(struct files_struct *files, ...@@ -497,7 +497,7 @@ int __alloc_fd(struct files_struct *files,
error = fd; error = fd;
#if 1 #if 1
/* Sanity check */ /* Sanity check */
if (rcu_dereference_raw(fdt->fd[fd]) != NULL) { if (rcu_access_pointer(fdt->fd[fd]) != NULL) {
printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
rcu_assign_pointer(fdt->fd[fd], NULL); rcu_assign_pointer(fdt->fd[fd], NULL);
} }
......
...@@ -247,9 +247,10 @@ static inline void list_splice_init_rcu(struct list_head *list, ...@@ -247,9 +247,10 @@ static inline void list_splice_init_rcu(struct list_head *list,
* primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
*/ */
#define list_entry_rcu(ptr, type, member) \ #define list_entry_rcu(ptr, type, member) \
({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \ ({ \
typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \
container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
}) })
/** /**
* Where are list_empty_rcu() and list_first_entry_rcu()? * Where are list_empty_rcu() and list_first_entry_rcu()?
...@@ -285,11 +286,11 @@ static inline void list_splice_init_rcu(struct list_head *list, ...@@ -285,11 +286,11 @@ static inline void list_splice_init_rcu(struct list_head *list,
* primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
*/ */
#define list_first_or_null_rcu(ptr, type, member) \ #define list_first_or_null_rcu(ptr, type, member) \
({struct list_head *__ptr = (ptr); \ ({ \
struct list_head *__ptr = (ptr); \
struct list_head *__next = ACCESS_ONCE(__ptr->next); \ struct list_head *__next = ACCESS_ONCE(__ptr->next); \
likely(__ptr != __next) ? \ likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \
list_entry_rcu(__next, type, member) : NULL; \ })
})
/** /**
* list_for_each_entry_rcu - iterate over rcu list of given type * list_for_each_entry_rcu - iterate over rcu list of given type
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2001 * Copyright IBM Corporation, 2001
* *
...@@ -44,7 +44,9 @@ ...@@ -44,7 +44,9 @@
#include <linux/debugobjects.h> #include <linux/debugobjects.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <asm/barrier.h>
extern int rcu_expedited; /* for sysctl */
#ifdef CONFIG_RCU_TORTURE_TEST #ifdef CONFIG_RCU_TORTURE_TEST
extern int rcutorture_runnable; /* for sysctl */ extern int rcutorture_runnable; /* for sysctl */
#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
...@@ -479,11 +481,9 @@ static inline void rcu_preempt_sleep_check(void) ...@@ -479,11 +481,9 @@ static inline void rcu_preempt_sleep_check(void)
do { \ do { \
rcu_preempt_sleep_check(); \ rcu_preempt_sleep_check(); \
rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \ rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \
"Illegal context switch in RCU-bh" \ "Illegal context switch in RCU-bh read-side critical section"); \
" read-side critical section"); \
rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \ rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \
"Illegal context switch in RCU-sched"\ "Illegal context switch in RCU-sched read-side critical section"); \
" read-side critical section"); \
} while (0) } while (0)
#else /* #ifdef CONFIG_PROVE_RCU */ #else /* #ifdef CONFIG_PROVE_RCU */
...@@ -510,43 +510,40 @@ static inline void rcu_preempt_sleep_check(void) ...@@ -510,43 +510,40 @@ static inline void rcu_preempt_sleep_check(void)
#endif /* #else #ifdef __CHECKER__ */ #endif /* #else #ifdef __CHECKER__ */
#define __rcu_access_pointer(p, space) \ #define __rcu_access_pointer(p, space) \
({ \ ({ \
typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
rcu_dereference_sparse(p, space); \ rcu_dereference_sparse(p, space); \
((typeof(*p) __force __kernel *)(_________p1)); \ ((typeof(*p) __force __kernel *)(_________p1)); \
}) })
#define __rcu_dereference_check(p, c, space) \ #define __rcu_dereference_check(p, c, space) \
({ \ ({ \
typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \ rcu_lockdep_assert(c, "suspicious rcu_dereference_check() usage"); \
" usage"); \
rcu_dereference_sparse(p, space); \ rcu_dereference_sparse(p, space); \
smp_read_barrier_depends(); \ smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
((typeof(*p) __force __kernel *)(_________p1)); \ ((typeof(*p) __force __kernel *)(_________p1)); \
}) })
#define __rcu_dereference_protected(p, c, space) \ #define __rcu_dereference_protected(p, c, space) \
({ \ ({ \
rcu_lockdep_assert(c, "suspicious rcu_dereference_protected()" \ rcu_lockdep_assert(c, "suspicious rcu_dereference_protected() usage"); \
" usage"); \
rcu_dereference_sparse(p, space); \ rcu_dereference_sparse(p, space); \
((typeof(*p) __force __kernel *)(p)); \ ((typeof(*p) __force __kernel *)(p)); \
}) })
#define __rcu_access_index(p, space) \ #define __rcu_access_index(p, space) \
({ \ ({ \
typeof(p) _________p1 = ACCESS_ONCE(p); \ typeof(p) _________p1 = ACCESS_ONCE(p); \
rcu_dereference_sparse(p, space); \ rcu_dereference_sparse(p, space); \
(_________p1); \ (_________p1); \
}) })
#define __rcu_dereference_index_check(p, c) \ #define __rcu_dereference_index_check(p, c) \
({ \ ({ \
typeof(p) _________p1 = ACCESS_ONCE(p); \ typeof(p) _________p1 = ACCESS_ONCE(p); \
rcu_lockdep_assert(c, \ rcu_lockdep_assert(c, \
"suspicious rcu_dereference_index_check()" \ "suspicious rcu_dereference_index_check() usage"); \
" usage"); \ smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
smp_read_barrier_depends(); \
(_________p1); \ (_________p1); \
}) })
/** /**
* RCU_INITIALIZER() - statically initialize an RCU-protected global variable * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
...@@ -585,12 +582,7 @@ static inline void rcu_preempt_sleep_check(void) ...@@ -585,12 +582,7 @@ static inline void rcu_preempt_sleep_check(void)
* please be careful when making changes to rcu_assign_pointer() and the * please be careful when making changes to rcu_assign_pointer() and the
* other macros that it invokes. * other macros that it invokes.
*/ */
#define rcu_assign_pointer(p, v) \ #define rcu_assign_pointer(p, v) smp_store_release(&p, RCU_INITIALIZER(v))
do { \
smp_wmb(); \
ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
} while (0)
/** /**
* rcu_access_pointer() - fetch RCU pointer with no dereferencing * rcu_access_pointer() - fetch RCU pointer with no dereferencing
...@@ -1015,11 +1007,21 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -1015,11 +1007,21 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define kfree_rcu(ptr, rcu_head) \ #define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
#ifdef CONFIG_RCU_NOCB_CPU #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL)
static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
{
*delta_jiffies = ULONG_MAX;
return 0;
}
#endif /* #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL) */
#if defined(CONFIG_RCU_NOCB_CPU_ALL)
static inline bool rcu_is_nocb_cpu(int cpu) { return true; }
#elif defined(CONFIG_RCU_NOCB_CPU)
bool rcu_is_nocb_cpu(int cpu); bool rcu_is_nocb_cpu(int cpu);
#else #else
static inline bool rcu_is_nocb_cpu(int cpu) { return false; } static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ #endif
/* Only for use by adaptive-ticks code. */ /* Only for use by adaptive-ticks code. */
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
...@@ -27,6 +27,16 @@ ...@@ -27,6 +27,16 @@
#include <linux/cache.h> #include <linux/cache.h>
static inline unsigned long get_state_synchronize_rcu(void)
{
return 0;
}
static inline void cond_synchronize_rcu(unsigned long oldstate)
{
might_sleep();
}
static inline void rcu_barrier_bh(void) static inline void rcu_barrier_bh(void)
{ {
wait_rcu_gp(call_rcu_bh); wait_rcu_gp(call_rcu_bh);
...@@ -68,12 +78,6 @@ static inline void kfree_call_rcu(struct rcu_head *head, ...@@ -68,12 +78,6 @@ static inline void kfree_call_rcu(struct rcu_head *head,
call_rcu(head, func); call_rcu(head, func);
} }
static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
{
*delta_jiffies = ULONG_MAX;
return 0;
}
static inline void rcu_note_context_switch(int cpu) static inline void rcu_note_context_switch(int cpu)
{ {
rcu_sched_qs(cpu); rcu_sched_qs(cpu);
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
...@@ -31,7 +31,9 @@ ...@@ -31,7 +31,9 @@
#define __LINUX_RCUTREE_H #define __LINUX_RCUTREE_H
void rcu_note_context_switch(int cpu); void rcu_note_context_switch(int cpu);
#ifndef CONFIG_RCU_NOCB_CPU_ALL
int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
void rcu_cpu_stall_reset(void); void rcu_cpu_stall_reset(void);
/* /*
...@@ -74,6 +76,8 @@ static inline void synchronize_rcu_bh_expedited(void) ...@@ -74,6 +76,8 @@ static inline void synchronize_rcu_bh_expedited(void)
void rcu_barrier(void); void rcu_barrier(void);
void rcu_barrier_bh(void); void rcu_barrier_bh(void);
void rcu_barrier_sched(void); void rcu_barrier_sched(void);
unsigned long get_state_synchronize_rcu(void);
void cond_synchronize_rcu(unsigned long oldstate);
extern unsigned long rcutorture_testseq; extern unsigned long rcutorture_testseq;
extern unsigned long rcutorture_vernum; extern unsigned long rcutorture_vernum;
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright (C) IBM Corporation, 2006 * Copyright (C) IBM Corporation, 2006
* Copyright (C) Fujitsu, 2012 * Copyright (C) Fujitsu, 2012
......
/*
* Common functions for in-kernel torture tests.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2014
*
* Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
*/
#ifndef __LINUX_TORTURE_H
#define __LINUX_TORTURE_H
#include <linux/types.h>
#include <linux/cache.h>
#include <linux/spinlock.h>
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <linux/seqlock.h>
#include <linux/lockdep.h>
#include <linux/completion.h>
#include <linux/debugobjects.h>
#include <linux/bug.h>
#include <linux/compiler.h>
/* Definitions for a non-string torture-test module parameter. */
#define torture_param(type, name, init, msg) \
static type name = init; \
module_param(name, type, 0444); \
MODULE_PARM_DESC(name, msg);
#define TORTURE_FLAG "-torture:"
#define TOROUT_STRING(s) \
pr_alert("%s" TORTURE_FLAG s "\n", torture_type)
#define VERBOSE_TOROUT_STRING(s) \
do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0)
#define VERBOSE_TOROUT_ERRSTRING(s) \
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
/* Definitions for a non-string torture-test module parameter. */
#define torture_parm(type, name, init, msg) \
static type name = init; \
module_param(name, type, 0444); \
MODULE_PARM_DESC(name, msg);
/* Definitions for online/offline exerciser. */
int torture_onoff_init(long ooholdoff, long oointerval);
char *torture_onoff_stats(char *page);
bool torture_onoff_failures(void);
/* Low-rider random number generator. */
struct torture_random_state {
unsigned long trs_state;
long trs_count;
};
#define DEFINE_TORTURE_RANDOM(name) struct torture_random_state name = { 0, 0 }
unsigned long torture_random(struct torture_random_state *trsp);
/* Task shuffler, which causes CPUs to occasionally go idle. */
void torture_shuffle_task_register(struct task_struct *tp);
int torture_shuffle_init(long shuffint);
/* Test auto-shutdown handling. */
void torture_shutdown_absorb(const char *title);
int torture_shutdown_init(int ssecs, void (*cleanup)(void));
/* Task stuttering, which forces load/no-load transitions. */
void stutter_wait(const char *title);
int torture_stutter_init(int s);
/* Initialization and cleanup. */
void torture_init_begin(char *ttype, bool v, int *runnable);
void torture_init_end(void);
bool torture_cleanup(void);
bool torture_must_stop(void);
bool torture_must_stop_irq(void);
void torture_kthread_stopping(char *title);
int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
char *f, struct task_struct **tp);
void _torture_stop_kthread(char *m, struct task_struct **tp);
#define torture_create_kthread(n, arg, tp) \
_torture_create_kthread(n, (arg), #n, "Creating " #n " task", \
"Failed to create " #n, &(tp))
#define torture_stop_kthread(n, tp) \
_torture_stop_kthread("Stopping " #n " task", &(tp))
#endif /* __LINUX_TORTURE_H */
...@@ -93,6 +93,7 @@ obj-$(CONFIG_PADATA) += padata.o ...@@ -93,6 +93,7 @@ obj-$(CONFIG_PADATA) += padata.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
obj-$(CONFIG_TORTURE_TEST) += torture.o
$(obj)/configs.o: $(obj)/config_data.h $(obj)/configs.o: $(obj)/config_data.h
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/rcupdate.h> /* rcu_expedited */
#define KERNEL_ATTR_RO(_name) \ #define KERNEL_ATTR_RO(_name) \
static struct kobj_attribute _name##_attr = __ATTR_RO(_name) static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
......
...@@ -23,3 +23,4 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o ...@@ -23,3 +23,4 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
obj-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o obj-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o
obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
This diff is collapsed.
...@@ -309,7 +309,7 @@ int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, ...@@ -309,7 +309,7 @@ int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
* racy then it does not matter what the result of the test * racy then it does not matter what the result of the test
* is, we re-check the list after having taken the lock anyway: * is, we re-check the list after having taken the lock anyway:
*/ */
if (rcu_dereference_raw(nh->head)) { if (rcu_access_pointer(nh->head)) {
down_read(&nh->rwsem); down_read(&nh->rwsem);
ret = notifier_call_chain(&nh->head, val, v, nr_to_call, ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
nr_calls); nr_calls);
......
obj-y += update.o srcu.o obj-y += update.o srcu.o
obj-$(CONFIG_RCU_TORTURE_TEST) += torture.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
obj-$(CONFIG_TREE_RCU) += tree.o obj-$(CONFIG_TREE_RCU) += tree.o
obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o
obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2011 * Copyright IBM Corporation, 2011
* *
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#ifndef __LINUX_RCU_H #ifndef __LINUX_RCU_H
#define __LINUX_RCU_H #define __LINUX_RCU_H
#include <trace/events/rcu.h>
#ifdef CONFIG_RCU_TRACE #ifdef CONFIG_RCU_TRACE
#define RCU_TRACE(stmt) stmt #define RCU_TRACE(stmt) stmt
#else /* #ifdef CONFIG_RCU_TRACE */ #else /* #ifdef CONFIG_RCU_TRACE */
...@@ -116,8 +117,6 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) ...@@ -116,8 +117,6 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
} }
} }
extern int rcu_expedited;
#ifdef CONFIG_RCU_STALL_COMMON #ifdef CONFIG_RCU_STALL_COMMON
extern int rcu_cpu_stall_suppress; extern int rcu_cpu_stall_suppress;
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright (C) IBM Corporation, 2006 * Copyright (C) IBM Corporation, 2006
* Copyright (C) Fujitsu, 2012 * Copyright (C) Fujitsu, 2012
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/srcu.h> #include <linux/srcu.h>
#include <trace/events/rcu.h>
#include "rcu.h" #include "rcu.h"
/* /*
...@@ -398,7 +396,7 @@ void call_srcu(struct srcu_struct *sp, struct rcu_head *head, ...@@ -398,7 +396,7 @@ void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
rcu_batch_queue(&sp->batch_queue, head); rcu_batch_queue(&sp->batch_queue, head);
if (!sp->running) { if (!sp->running) {
sp->running = true; sp->running = true;
schedule_delayed_work(&sp->work, 0); queue_delayed_work(system_power_efficient_wq, &sp->work, 0);
} }
spin_unlock_irqrestore(&sp->queue_lock, flags); spin_unlock_irqrestore(&sp->queue_lock, flags);
} }
...@@ -674,7 +672,8 @@ static void srcu_reschedule(struct srcu_struct *sp) ...@@ -674,7 +672,8 @@ static void srcu_reschedule(struct srcu_struct *sp)
} }
if (pending) if (pending)
schedule_delayed_work(&sp->work, SRCU_INTERVAL); queue_delayed_work(system_power_efficient_wq,
&sp->work, SRCU_INTERVAL);
} }
/* /*
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
...@@ -37,10 +37,6 @@ ...@@ -37,10 +37,6 @@
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/ftrace_event.h> #include <linux/ftrace_event.h>
#ifdef CONFIG_RCU_TRACE
#include <trace/events/rcu.h>
#endif /* #else #ifdef CONFIG_RCU_TRACE */
#include "rcu.h" #include "rcu.h"
/* Forward declarations for tiny_plugin.h. */ /* Forward declarations for tiny_plugin.h. */
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright (c) 2010 Linaro * Copyright (c) 2010 Linaro
* *
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
...@@ -58,8 +58,6 @@ ...@@ -58,8 +58,6 @@
#include <linux/suspend.h> #include <linux/suspend.h>
#include "tree.h" #include "tree.h"
#include <trace/events/rcu.h>
#include "rcu.h" #include "rcu.h"
MODULE_ALIAS("rcutree"); MODULE_ALIAS("rcutree");
...@@ -837,7 +835,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp, ...@@ -837,7 +835,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
* to the next. Only do this for the primary flavor of RCU. * to the next. Only do this for the primary flavor of RCU.
*/ */
if (rdp->rsp == rcu_state && if (rdp->rsp == rcu_state &&
ULONG_CMP_GE(ACCESS_ONCE(jiffies), rdp->rsp->jiffies_resched)) { ULONG_CMP_GE(jiffies, rdp->rsp->jiffies_resched)) {
rdp->rsp->jiffies_resched += 5; rdp->rsp->jiffies_resched += 5;
resched_cpu(rdp->cpu); resched_cpu(rdp->cpu);
} }
...@@ -847,7 +845,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp, ...@@ -847,7 +845,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
static void record_gp_stall_check_time(struct rcu_state *rsp) static void record_gp_stall_check_time(struct rcu_state *rsp)
{ {
unsigned long j = ACCESS_ONCE(jiffies); unsigned long j = jiffies;
unsigned long j1; unsigned long j1;
rsp->gp_start = j; rsp->gp_start = j;
...@@ -1005,7 +1003,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) ...@@ -1005,7 +1003,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp)) if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp))
return; return;
j = ACCESS_ONCE(jiffies); j = jiffies;
/* /*
* Lots of memory barriers to reject false positives. * Lots of memory barriers to reject false positives.
...@@ -1423,13 +1421,14 @@ static int rcu_gp_init(struct rcu_state *rsp) ...@@ -1423,13 +1421,14 @@ static int rcu_gp_init(struct rcu_state *rsp)
/* Advance to a new grace period and initialize state. */ /* Advance to a new grace period and initialize state. */
record_gp_stall_check_time(rsp); record_gp_stall_check_time(rsp);
smp_wmb(); /* Record GP times before starting GP. */ /* Record GP times before starting GP, hence smp_store_release(). */
rsp->gpnum++; smp_store_release(&rsp->gpnum, rsp->gpnum + 1);
trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start")); trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
raw_spin_unlock_irq(&rnp->lock); raw_spin_unlock_irq(&rnp->lock);
/* Exclude any concurrent CPU-hotplug operations. */ /* Exclude any concurrent CPU-hotplug operations. */
mutex_lock(&rsp->onoff_mutex); mutex_lock(&rsp->onoff_mutex);
smp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */
/* /*
* Set the quiescent-state-needed bits in all the rcu_node * Set the quiescent-state-needed bits in all the rcu_node
...@@ -1557,10 +1556,11 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) ...@@ -1557,10 +1556,11 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
} }
rnp = rcu_get_root(rsp); rnp = rcu_get_root(rsp);
raw_spin_lock_irq(&rnp->lock); raw_spin_lock_irq(&rnp->lock);
smp_mb__after_unlock_lock(); smp_mb__after_unlock_lock(); /* Order GP before ->completed update. */
rcu_nocb_gp_set(rnp, nocb); rcu_nocb_gp_set(rnp, nocb);
rsp->completed = rsp->gpnum; /* Declare grace period done. */ /* Declare grace period done. */
ACCESS_ONCE(rsp->completed) = rsp->gpnum;
trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end")); trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end"));
rsp->fqs_state = RCU_GP_IDLE; rsp->fqs_state = RCU_GP_IDLE;
rdp = this_cpu_ptr(rsp->rda); rdp = this_cpu_ptr(rsp->rda);
...@@ -2304,7 +2304,7 @@ static void force_quiescent_state(struct rcu_state *rsp) ...@@ -2304,7 +2304,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
if (rnp_old != NULL) if (rnp_old != NULL)
raw_spin_unlock(&rnp_old->fqslock); raw_spin_unlock(&rnp_old->fqslock);
if (ret) { if (ret) {
rsp->n_force_qs_lh++; ACCESS_ONCE(rsp->n_force_qs_lh)++;
return; return;
} }
rnp_old = rnp; rnp_old = rnp;
...@@ -2316,7 +2316,7 @@ static void force_quiescent_state(struct rcu_state *rsp) ...@@ -2316,7 +2316,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
smp_mb__after_unlock_lock(); smp_mb__after_unlock_lock();
raw_spin_unlock(&rnp_old->fqslock); raw_spin_unlock(&rnp_old->fqslock);
if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
rsp->n_force_qs_lh++; ACCESS_ONCE(rsp->n_force_qs_lh)++;
raw_spin_unlock_irqrestore(&rnp_old->lock, flags); raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
return; /* Someone beat us to it. */ return; /* Someone beat us to it. */
} }
...@@ -2639,6 +2639,58 @@ void synchronize_rcu_bh(void) ...@@ -2639,6 +2639,58 @@ void synchronize_rcu_bh(void)
} }
EXPORT_SYMBOL_GPL(synchronize_rcu_bh); EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
/**
* get_state_synchronize_rcu - Snapshot current RCU state
*
* Returns a cookie that is used by a later call to cond_synchronize_rcu()
* to determine whether or not a full grace period has elapsed in the
* meantime.
*/
unsigned long get_state_synchronize_rcu(void)
{
/*
* Any prior manipulation of RCU-protected data must happen
* before the load from ->gpnum.
*/
smp_mb(); /* ^^^ */
/*
* Make sure this load happens before the purportedly
* time-consuming work between get_state_synchronize_rcu()
* and cond_synchronize_rcu().
*/
return smp_load_acquire(&rcu_state->gpnum);
}
EXPORT_SYMBOL_GPL(get_state_synchronize_rcu);
/**
* cond_synchronize_rcu - Conditionally wait for an RCU grace period
*
* @oldstate: return value from earlier call to get_state_synchronize_rcu()
*
* If a full RCU grace period has elapsed since the earlier call to
* get_state_synchronize_rcu(), just return. Otherwise, invoke
* synchronize_rcu() to wait for a full grace period.
*
* Yes, this function does not take counter wrap into account. But
* counter wrap is harmless. If the counter wraps, we have waited for
* more than 2 billion grace periods (and way more on a 64-bit system!),
* so waiting for one additional grace period should be just fine.
*/
void cond_synchronize_rcu(unsigned long oldstate)
{
unsigned long newstate;
/*
* Ensure that this load happens before any RCU-destructive
* actions the caller might carry out after we return.
*/
newstate = smp_load_acquire(&rcu_state->completed);
if (ULONG_CMP_GE(oldstate, newstate))
synchronize_rcu();
}
EXPORT_SYMBOL_GPL(cond_synchronize_rcu);
static int synchronize_sched_expedited_cpu_stop(void *data) static int synchronize_sched_expedited_cpu_stop(void *data)
{ {
/* /*
...@@ -2880,7 +2932,7 @@ static int rcu_pending(int cpu) ...@@ -2880,7 +2932,7 @@ static int rcu_pending(int cpu)
* non-NULL, store an indication of whether all callbacks are lazy. * non-NULL, store an indication of whether all callbacks are lazy.
* (If there are no callbacks, all of them are deemed to be lazy.) * (If there are no callbacks, all of them are deemed to be lazy.)
*/ */
static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy) static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
{ {
bool al = true; bool al = true;
bool hc = false; bool hc = false;
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright Red Hat, 2009 * Copyright Red Hat, 2009
* Copyright IBM Corporation, 2009 * Copyright IBM Corporation, 2009
...@@ -1586,11 +1586,13 @@ static void rcu_prepare_kthreads(int cpu) ...@@ -1586,11 +1586,13 @@ static void rcu_prepare_kthreads(int cpu)
* Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs * Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs
* any flavor of RCU. * any flavor of RCU.
*/ */
#ifndef CONFIG_RCU_NOCB_CPU_ALL
int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
{ {
*delta_jiffies = ULONG_MAX; *delta_jiffies = ULONG_MAX;
return rcu_cpu_has_callbacks(cpu, NULL); return rcu_cpu_has_callbacks(cpu, NULL);
} }
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
/* /*
* Because we do not have RCU_FAST_NO_HZ, don't bother cleaning up * Because we do not have RCU_FAST_NO_HZ, don't bother cleaning up
...@@ -1656,7 +1658,7 @@ extern int tick_nohz_active; ...@@ -1656,7 +1658,7 @@ extern int tick_nohz_active;
* only if it has been awhile since the last time we did so. Afterwards, * only if it has been awhile since the last time we did so. Afterwards,
* if there are any callbacks ready for immediate invocation, return true. * if there are any callbacks ready for immediate invocation, return true.
*/ */
static bool rcu_try_advance_all_cbs(void) static bool __maybe_unused rcu_try_advance_all_cbs(void)
{ {
bool cbs_ready = false; bool cbs_ready = false;
struct rcu_data *rdp; struct rcu_data *rdp;
...@@ -1696,6 +1698,7 @@ static bool rcu_try_advance_all_cbs(void) ...@@ -1696,6 +1698,7 @@ static bool rcu_try_advance_all_cbs(void)
* *
* The caller must have disabled interrupts. * The caller must have disabled interrupts.
*/ */
#ifndef CONFIG_RCU_NOCB_CPU_ALL
int rcu_needs_cpu(int cpu, unsigned long *dj) int rcu_needs_cpu(int cpu, unsigned long *dj)
{ {
struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
...@@ -1726,6 +1729,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj) ...@@ -1726,6 +1729,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
} }
return 0; return 0;
} }
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
/* /*
* Prepare a CPU for idle from an RCU perspective. The first major task * Prepare a CPU for idle from an RCU perspective. The first major task
...@@ -1739,6 +1743,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj) ...@@ -1739,6 +1743,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
*/ */
static void rcu_prepare_for_idle(int cpu) static void rcu_prepare_for_idle(int cpu)
{ {
#ifndef CONFIG_RCU_NOCB_CPU_ALL
struct rcu_data *rdp; struct rcu_data *rdp;
struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu); struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
struct rcu_node *rnp; struct rcu_node *rnp;
...@@ -1790,6 +1795,7 @@ static void rcu_prepare_for_idle(int cpu) ...@@ -1790,6 +1795,7 @@ static void rcu_prepare_for_idle(int cpu)
rcu_accelerate_cbs(rsp, rnp, rdp); rcu_accelerate_cbs(rsp, rnp, rdp);
raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
} }
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
} }
/* /*
...@@ -1799,11 +1805,12 @@ static void rcu_prepare_for_idle(int cpu) ...@@ -1799,11 +1805,12 @@ static void rcu_prepare_for_idle(int cpu)
*/ */
static void rcu_cleanup_after_idle(int cpu) static void rcu_cleanup_after_idle(int cpu)
{ {
#ifndef CONFIG_RCU_NOCB_CPU_ALL
if (rcu_is_nocb_cpu(cpu)) if (rcu_is_nocb_cpu(cpu))
return; return;
if (rcu_try_advance_all_cbs()) if (rcu_try_advance_all_cbs())
invoke_rcu_core(); invoke_rcu_core();
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
} }
/* /*
...@@ -2101,6 +2108,7 @@ static void rcu_init_one_nocb(struct rcu_node *rnp) ...@@ -2101,6 +2108,7 @@ static void rcu_init_one_nocb(struct rcu_node *rnp)
init_waitqueue_head(&rnp->nocb_gp_wq[1]); init_waitqueue_head(&rnp->nocb_gp_wq[1]);
} }
#ifndef CONFIG_RCU_NOCB_CPU_ALL
/* Is the specified CPU a no-CPUs CPU? */ /* Is the specified CPU a no-CPUs CPU? */
bool rcu_is_nocb_cpu(int cpu) bool rcu_is_nocb_cpu(int cpu)
{ {
...@@ -2108,6 +2116,7 @@ bool rcu_is_nocb_cpu(int cpu) ...@@ -2108,6 +2116,7 @@ bool rcu_is_nocb_cpu(int cpu)
return cpumask_test_cpu(cpu, rcu_nocb_mask); return cpumask_test_cpu(cpu, rcu_nocb_mask);
return false; return false;
} }
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
/* /*
* Enqueue the specified string of rcu_head structures onto the specified * Enqueue the specified string of rcu_head structures onto the specified
...@@ -2893,7 +2902,7 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp) ...@@ -2893,7 +2902,7 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
* CPU unless the grace period has extended for too long. * CPU unless the grace period has extended for too long.
* *
* This code relies on the fact that all NO_HZ_FULL CPUs are also * This code relies on the fact that all NO_HZ_FULL CPUs are also
* CONFIG_RCU_NOCB_CPUs. * CONFIG_RCU_NOCB_CPU CPUs.
*/ */
static bool rcu_nohz_full_cpu(struct rcu_state *rsp) static bool rcu_nohz_full_cpu(struct rcu_state *rsp)
{ {
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
...@@ -273,7 +273,7 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) ...@@ -273,7 +273,7 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n", seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
rsp->n_force_qs, rsp->n_force_qs_ngp, rsp->n_force_qs, rsp->n_force_qs_ngp,
rsp->n_force_qs - rsp->n_force_qs_ngp, rsp->n_force_qs - rsp->n_force_qs_ngp,
rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen); ACCESS_ONCE(rsp->n_force_qs_lh), rsp->qlen_lazy, rsp->qlen);
for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) { for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) {
if (rnp->level != level) { if (rnp->level != level) {
seq_puts(m, "\n"); seq_puts(m, "\n");
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, you can access it online at
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * http://www.gnu.org/licenses/gpl-2.0.html.
* *
* Copyright IBM Corporation, 2001 * Copyright IBM Corporation, 2001
* *
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
#include <linux/module.h> #include <linux/module.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/rcu.h>
#include "rcu.h" #include "rcu.h"
......
This diff is collapsed.
...@@ -980,6 +980,21 @@ config DEBUG_LOCKING_API_SELFTESTS ...@@ -980,6 +980,21 @@ config DEBUG_LOCKING_API_SELFTESTS
The following locking APIs are covered: spinlocks, rwlocks, The following locking APIs are covered: spinlocks, rwlocks,
mutexes and rwsems. mutexes and rwsems.
config LOCK_TORTURE_TEST
tristate "torture tests for locking"
depends on DEBUG_KERNEL
select TORTURE_TEST
default n
help
This option provides a kernel module that runs torture tests
on kernel locking primitives. The kernel module may be built
after the fact on the running kernel to be tested, if desired.
Say Y here if you want kernel locking-primitive torture tests
to be built into the kernel.
Say M if you want these torture tests to build as a module.
Say N if you are unsure.
endmenu # lock debugging endmenu # lock debugging
config TRACE_IRQFLAGS config TRACE_IRQFLAGS
...@@ -1141,9 +1156,14 @@ config SPARSE_RCU_POINTER ...@@ -1141,9 +1156,14 @@ config SPARSE_RCU_POINTER
Say N if you are unsure. Say N if you are unsure.
config TORTURE_TEST
tristate
default n
config RCU_TORTURE_TEST config RCU_TORTURE_TEST
tristate "torture tests for RCU" tristate "torture tests for RCU"
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
select TORTURE_TEST
default n default n
help help
This option provides a kernel module that runs torture tests This option provides a kernel module that runs torture tests
......
...@@ -96,6 +96,7 @@ identify_qemu () { ...@@ -96,6 +96,7 @@ identify_qemu () {
echo qemu-system-ppc64 echo qemu-system-ppc64
else else
echo Cannot figure out what qemu command to use! 1>&2 echo Cannot figure out what qemu command to use! 1>&2
echo file $1 output: $u
# Usually this will be one of /usr/bin/qemu-system-* # Usually this will be one of /usr/bin/qemu-system-*
# Use RCU_QEMU_CMD environment variable or appropriate # Use RCU_QEMU_CMD environment variable or appropriate
# argument to top-level script. # argument to top-level script.
......
#!/bin/bash
#
# Analyze a given results directory for locktorture progress.
#
# Usage: sh kvm-recheck-lock.sh resdir
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
#
# Copyright (C) IBM Corporation, 2014
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
i="$1"
if test -d $i
then
:
else
echo Unreadable results directory: $i
exit 1
fi
configfile=`echo $i | sed -e 's/^.*\///'`
ncs=`grep "Writes: Total:" $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* Total: //' -e 's/ .*$//'`
if test -z "$ncs"
then
echo $configfile
else
title="$configfile ------- $ncs acquisitions/releases"
dur=`sed -e 's/^.* locktorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
if test -z "$dur"
then
:
else
ncsps=`awk -v ncs=$ncs -v dur=$dur '
BEGIN { print ncs / dur }' < /dev/null`
title="$title ($ncsps per second)"
fi
echo $title
fi
#!/bin/bash
#
# Analyze a given results directory for rcutorture progress.
#
# Usage: sh kvm-recheck-rcu.sh resdir
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
#
# Copyright (C) IBM Corporation, 2014
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
i="$1"
if test -d $i
then
:
else
echo Unreadable results directory: $i
exit 1
fi
configfile=`echo $i | sed -e 's/^.*\///'`
ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'`
if test -z "$ngps"
then
echo $configfile
else
title="$configfile ------- $ngps grace periods"
dur=`sed -e 's/^.* rcutorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
if test -z "$dur"
then
:
else
ngpsps=`awk -v ngps=$ngps -v dur=$dur '
BEGIN { print ngps / dur }' < /dev/null`
title="$title ($ngpsps per second)"
fi
echo $title
fi
#!/bin/bash #!/bin/bash
# #
# Given the results directories for previous KVM runs of rcutorture, # Given the results directories for previous KVM-based torture runs,
# check the build and console output for errors. Given a directory # check the build and console output for errors. Given a directory
# containing results directories, this recursively checks them all. # containing results directories, this recursively checks them all.
# #
...@@ -27,11 +27,18 @@ ...@@ -27,11 +27,18 @@
PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
for rd in "$@" for rd in "$@"
do do
firsttime=1
dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u` dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u`
for i in $dirs for i in $dirs
do do
configfile=`echo $i | sed -e 's/^.*\///'` if test -n "$firsttime"
echo $configfile then
firsttime=""
resdir=`echo $i | sed -e 's,/$,,' -e 's,/[^/]*$,,'`
head -1 $resdir/log
fi
TORTURE_SUITE="`cat $i/../TORTURE_SUITE`"
kvm-recheck-${TORTURE_SUITE}.sh $i
configcheck.sh $i/.config $i/ConfigFragment configcheck.sh $i/.config $i/ConfigFragment
parse-build.sh $i/Make.out $configfile parse-build.sh $i/Make.out $configfile
parse-rcutorture.sh $i/console.log $configfile parse-rcutorture.sh $i/console.log $configfile
......
...@@ -6,15 +6,15 @@ ...@@ -6,15 +6,15 @@
# Execute this in the source tree. Do not run it as a background task # Execute this in the source tree. Do not run it as a background task
# because qemu does not seem to like that much. # because qemu does not seem to like that much.
# #
# Usage: sh kvm-test-1-rcu.sh config builddir resdir minutes qemu-args bootargs # Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
# #
# qemu-args defaults to "" -- you will want "-nographic" if running headless. # qemu-args defaults to "-nographic", along with arguments specifying the
# bootargs defaults to "root=/dev/sda noapic selinux=0 console=ttyS0" # number of CPUs and other options generated from
# "initcall_debug debug rcutorture.stat_interval=15" # the underlying CPU architecture.
# "rcutorture.shutdown_secs=$((minutes * 60))" # boot_args defaults to value returned by the per_version_boot_params
# "rcutorture.rcutorture_runnable=1" # shell function.
# #
# Anything you specify for either qemu-args or bootargs is appended to # Anything you specify for either qemu-args or boot_args is appended to
# the default values. The "-smp" value is deduced from the contents of # the default values. The "-smp" value is deduced from the contents of
# the config fragment. # the config fragment.
# #
...@@ -40,32 +40,34 @@ ...@@ -40,32 +40,34 @@
grace=120 grace=120
T=/tmp/kvm-test-1-rcu.sh.$$ T=/tmp/kvm-test-1-run.sh.$$
trap 'rm -rf $T' 0 trap 'rm -rf $T' 0
. $KVM/bin/functions.sh . $KVM/bin/functions.sh
. $KVPATH/ver_functions.sh . $KVPATH/ver_functions.sh
config_template=${1} config_template=${1}
config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'`
title=`echo $config_template | sed -e 's/^.*\///'` title=`echo $config_template | sed -e 's/^.*\///'`
builddir=${2} builddir=${2}
if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir" if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
then then
echo "kvm-test-1-rcu.sh :$builddir: Not a writable directory, cannot build into it" echo "kvm-test-1-run.sh :$builddir: Not a writable directory, cannot build into it"
exit 1 exit 1
fi fi
resdir=${3} resdir=${3}
if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir" if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir"
then then
echo "kvm-test-1-rcu.sh :$resdir: Not a writable directory, cannot build into it" echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it"
exit 1 exit 1
fi fi
cp $config_template $resdir/ConfigFragment cp $config_template $resdir/ConfigFragment
echo ' ---' `date`: Starting build echo ' ---' `date`: Starting build
echo ' ---' Kconfig fragment at: $config_template >> $resdir/log echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
cat << '___EOF___' >> $T if test -r "$config_dir/CFcommon"
CONFIG_RCU_TORTURE_TEST=y then
___EOF___ cat < $config_dir/CFcommon >> $T
fi
# Optimizations below this point # Optimizations below this point
# CONFIG_USB=n # CONFIG_USB=n
# CONFIG_SECURITY=n # CONFIG_SECURITY=n
...@@ -96,11 +98,23 @@ then ...@@ -96,11 +98,23 @@ then
cp $builddir/.config $resdir cp $builddir/.config $resdir
cp $builddir/arch/x86/boot/bzImage $resdir cp $builddir/arch/x86/boot/bzImage $resdir
parse-build.sh $resdir/Make.out $title parse-build.sh $resdir/Make.out $title
if test -f $builddir.wait
then
mv $builddir.wait $builddir.ready
fi
else else
cp $builddir/Make*.out $resdir cp $builddir/Make*.out $resdir
echo Build failed, not running KVM, see $resdir. echo Build failed, not running KVM, see $resdir.
if test -f $builddir.wait
then
mv $builddir.wait $builddir.ready
fi
exit 1 exit 1
fi fi
while test -f $builddir.ready
do
sleep 1
done
minutes=$4 minutes=$4
seconds=$(($minutes * 60)) seconds=$(($minutes * 60))
qemu_args=$5 qemu_args=$5
...@@ -111,9 +125,10 @@ kstarttime=`awk 'BEGIN { print systime() }' < /dev/null` ...@@ -111,9 +125,10 @@ kstarttime=`awk 'BEGIN { print systime() }' < /dev/null`
echo ' ---' `date`: Starting kernel echo ' ---' `date`: Starting kernel
# Determine the appropriate flavor of qemu command. # Determine the appropriate flavor of qemu command.
QEMU="`identify_qemu $builddir/vmlinux.o`" QEMU="`identify_qemu $builddir/vmlinux`"
# Generate -smp qemu argument. # Generate -smp qemu argument.
qemu_args="-nographic $qemu_args"
cpu_count=`configNR_CPUS.sh $config_template` cpu_count=`configNR_CPUS.sh $config_template`
vcpus=`identify_qemu_vcpus` vcpus=`identify_qemu_vcpus`
if test $cpu_count -gt $vcpus if test $cpu_count -gt $vcpus
...@@ -133,12 +148,8 @@ qemu_append="`identify_qemu_append "$QEMU"`" ...@@ -133,12 +148,8 @@ qemu_append="`identify_qemu_append "$QEMU"`"
# Pull in Kconfig-fragment boot parameters # Pull in Kconfig-fragment boot parameters
boot_args="`configfrag_boot_params "$boot_args" "$config_template"`" boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
# Generate CPU-hotplug boot parameters # Generate kernel-version-specific boot parameters
boot_args="`rcutorture_param_onoff "$boot_args" $builddir/.config`" boot_args="`per_version_boot_params "$boot_args" $builddir/.config $seconds`"
# Generate rcu_barrier() boot parameter
boot_args="`rcutorture_param_n_barrier_cbs "$boot_args"`"
# Pull in standard rcutorture boot arguments
boot_args="$boot_args rcutorture.stat_interval=15 rcutorture.shutdown_secs=$seconds rcutorture.rcutorture_runnable=1"
echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
if test -n "$RCU_BUILDONLY" if test -n "$RCU_BUILDONLY"
...@@ -188,5 +199,5 @@ then ...@@ -188,5 +199,5 @@ then
fi fi
cp $builddir/console.log $resdir cp $builddir/console.log $resdir
parse-rcutorture.sh $resdir/console.log $title parse-${TORTURE_SUITE}torture.sh $resdir/console.log $title
parse-console.sh $resdir/console.log $title parse-console.sh $resdir/console.log $title
...@@ -30,14 +30,21 @@ ...@@ -30,14 +30,21 @@
scriptname=$0 scriptname=$0
args="$*" args="$*"
T=/tmp/kvm.sh.$$
trap 'rm -rf $T' 0
mkdir $T
dur=30 dur=30
dryrun=""
KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
PATH=${KVM}/bin:$PATH; export PATH PATH=${KVM}/bin:$PATH; export PATH
builddir="${KVM}/b1" builddir="${KVM}/b1"
RCU_INITRD="$KVM/initrd"; export RCU_INITRD RCU_INITRD="$KVM/initrd"; export RCU_INITRD
RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG
TORTURE_SUITE=rcu
resdir="" resdir=""
configs="" configs=""
cpus=0
ds=`date +%Y.%m.%d-%H:%M:%S` ds=`date +%Y.%m.%d-%H:%M:%S`
kversion="" kversion=""
...@@ -49,7 +56,9 @@ usage () { ...@@ -49,7 +56,9 @@ usage () {
echo " --builddir absolute-pathname" echo " --builddir absolute-pathname"
echo " --buildonly" echo " --buildonly"
echo " --configs \"config-file list\"" echo " --configs \"config-file list\""
echo " --cpus N"
echo " --datestamp string" echo " --datestamp string"
echo " --dryrun sched|script"
echo " --duration minutes" echo " --duration minutes"
echo " --interactive" echo " --interactive"
echo " --kmake-arg kernel-make-arguments" echo " --kmake-arg kernel-make-arguments"
...@@ -58,8 +67,9 @@ usage () { ...@@ -58,8 +67,9 @@ usage () {
echo " --no-initrd" echo " --no-initrd"
echo " --qemu-args qemu-system-..." echo " --qemu-args qemu-system-..."
echo " --qemu-cmd qemu-system-..." echo " --qemu-cmd qemu-system-..."
echo " --results absolute-pathname"
echo " --relbuilddir relative-pathname" echo " --relbuilddir relative-pathname"
echo " --results absolute-pathname"
echo " --torture rcu"
exit 1 exit 1
} }
...@@ -85,11 +95,21 @@ do ...@@ -85,11 +95,21 @@ do
configs="$2" configs="$2"
shift shift
;; ;;
--cpus)
checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--'
cpus=$2
shift
;;
--datestamp) --datestamp)
checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--' checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
ds=$2 ds=$2
shift shift
;; ;;
--dryrun)
checkarg --dryrun "sched|script" $# "$2" 'sched\|script' '^--'
dryrun=$2
shift
;;
--duration) --duration)
checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
dur=$2 dur=$2
...@@ -138,6 +158,11 @@ do ...@@ -138,6 +158,11 @@ do
resdir=$2 resdir=$2
shift shift
;; ;;
--torture)
checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--'
TORTURE_SUITE=$2
shift
;;
*) *)
echo Unknown argument $1 echo Unknown argument $1
usage usage
...@@ -146,7 +171,7 @@ do ...@@ -146,7 +171,7 @@ do
shift shift
done done
CONFIGFRAG=${KVM}/configs; export CONFIGFRAG CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
KVPATH=${CONFIGFRAG}/$kversion; export KVPATH KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
if test -z "$configs" if test -z "$configs"
...@@ -157,54 +182,231 @@ fi ...@@ -157,54 +182,231 @@ fi
if test -z "$resdir" if test -z "$resdir"
then then
resdir=$KVM/res resdir=$KVM/res
if ! test -e $resdir fi
then
mkdir $resdir || : if test "$dryrun" = ""
fi then
else
if ! test -e $resdir if ! test -e $resdir
then then
mkdir -p "$resdir" || : mkdir -p "$resdir" || :
fi fi
fi mkdir $resdir/$ds
mkdir $resdir/$ds
touch $resdir/$ds/log
echo $scriptname $args >> $resdir/$ds/log
pwd > $resdir/$ds/testid.txt # Be noisy only if running the script.
if test -d .git echo Results directory: $resdir/$ds
then echo $scriptname $args
touch $resdir/$ds/log
echo $scriptname $args >> $resdir/$ds/log
echo ${TORTURE_SUITE} > $resdir/$ds/TORTURE_SUITE
pwd > $resdir/$ds/testid.txt
if test -d .git
then
git status >> $resdir/$ds/testid.txt git status >> $resdir/$ds/testid.txt
git rev-parse HEAD >> $resdir/$ds/testid.txt git rev-parse HEAD >> $resdir/$ds/testid.txt
fi fi
builddir=$KVM/b1
if ! test -e $builddir
then
mkdir $builddir || :
fi fi
# Create a file of test-name/#cpus pairs, sorted by decreasing #cpus.
touch $T/cfgcpu
for CF in $configs for CF in $configs
do do
# Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ... if test -f "$CONFIGFRAG/$kversion/$CF"
rd=$resdir/$ds/$CF
if test -d "${rd}"
then
n="`ls -d "${rd}"* | grep '\.[0-9]\+$' |
sed -e 's/^.*\.\([0-9]\+\)/\1/' |
sort -k1n | tail -1`"
if test -z "$n"
then then
rd="${rd}.2" echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu
else else
n="`expr $n + 1`" echo "The --configs file $CF does not exist, terminating."
rd="${rd}.${n}" exit 1
fi
fi fi
mkdir "${rd}"
echo Results directory: $rd
kvm-test-1-rcu.sh $CONFIGFRAG/$kversion/$CF $builddir $rd $dur "-nographic $RCU_QEMU_ARG" "rcutorture.test_no_idle_hz=1 rcutorture.verbose=1 $RCU_BOOTARGS"
done done
sort -k2nr $T/cfgcpu > $T/cfgcpu.sort
# Use a greedy bin-packing algorithm, sorting the list accordingly.
awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus '
BEGIN {
njobs = 0;
}
{
# Read file of tests and corresponding required numbers of CPUs.
cf[njobs] = $1;
cpus[njobs] = $2;
njobs++;
}
END {
alldone = 0;
batch = 0;
nc = -1;
# Each pass through the following loop creates on test batch
# that can be executed concurrently given ncpus. Note that a
# given test that requires more than the available CPUs will run in
# their own batch. Such tests just have to make do with what
# is available.
while (nc != ncpus) {
batch++;
nc = ncpus;
# Each pass through the following loop considers one
# test for inclusion in the current batch.
for (i = 0; i < njobs; i++) {
if (done[i])
continue; # Already part of a batch.
if (nc >= cpus[i] || nc == ncpus) {
# This test fits into the current batch.
done[i] = batch;
nc -= cpus[i];
if (nc <= 0)
break; # Too-big test in its own batch.
}
}
}
# Dump out the tests in batch order.
for (b = 1; b <= batch; b++)
for (i = 0; i < njobs; i++)
if (done[i] == b)
print cf[i], cpus[i];
}'
# Generate a script to execute the tests in appropriate batches.
cat << ___EOF___ > $T/script
TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE
___EOF___
awk < $T/cfgcpu.pack \
-v CONFIGDIR="$CONFIGFRAG/$kversion/" \
-v KVM="$KVM" \
-v ncpus=$cpus \
-v rd=$resdir/$ds/ \
-v dur=$dur \
-v RCU_QEMU_ARG=$RCU_QEMU_ARG \
-v RCU_BOOTARGS=$RCU_BOOTARGS \
'BEGIN {
i = 0;
}
{
cf[i] = $1;
cpus[i] = $2;
i++;
}
# Dump out the scripting required to run one test batch.
function dump(first, pastlast)
{
print "echo ----Start batch: `date`";
print "echo ----Start batch: `date` >> " rd "/log";
jn=1
for (j = first; j < pastlast; j++) {
builddir=KVM "/b" jn
cpusr[jn] = cpus[j];
if (cfrep[cf[j]] == "") {
cfr[jn] = cf[j];
cfrep[cf[j]] = 1;
} else {
cfrep[cf[j]]++;
cfr[jn] = cf[j] "." cfrep[cf[j]];
}
if (cpusr[jn] > ncpus && ncpus != 0)
ovf = "(!)";
else
ovf = "";
print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`";
print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` >> " rd "/log";
print "rm -f " builddir ".*";
print "touch " builddir ".wait";
print "mkdir " builddir " > /dev/null 2>&1 || :";
print "mkdir " rd cfr[jn] " || :";
print "kvm-test-1-run.sh " CONFIGDIR cf[j], builddir, rd cfr[jn], dur " \"" RCU_QEMU_ARG "\" \"" RCU_BOOTARGS "\" > " rd cfr[jn] "/kvm-test-1-run.sh.out 2>&1 &"
print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date`";
print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` >> " rd "/log";
print "while test -f " builddir ".wait"
print "do"
print "\tsleep 1"
print "done"
print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date`";
print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date` >> " rd "/log";
jn++;
}
for (j = 1; j < jn; j++) {
builddir=KVM "/b" j
print "rm -f " builddir ".ready"
print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date`";
print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log";
}
print "wait"
print "echo ---- All kernel runs complete. `date`";
print "echo ---- All kernel runs complete. `date` >> " rd "/log";
for (j = 1; j < jn; j++) {
builddir=KVM "/b" j
print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results:";
print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results: >> " rd "/log";
print "cat " rd cfr[j] "/kvm-test-1-run.sh.out";
print "cat " rd cfr[j] "/kvm-test-1-run.sh.out >> " rd "/log";
}
}
END {
njobs = i;
nc = ncpus;
first = 0;
# Each pass through the following loop considers one test.
for (i = 0; i < njobs; i++) {
if (ncpus == 0) {
# Sequential test specified, each test its own batch.
dump(i, i + 1);
first = i;
} else if (nc < cpus[i] && i != 0) {
# Out of CPUs, dump out a batch.
dump(first, i);
first = i;
nc = ncpus;
}
# Account for the CPUs needed by the current test.
nc -= cpus[i];
}
# Dump the last batch.
if (ncpus != 0)
dump(first, i);
}' >> $T/script
if test "$dryrun" = script
then
# Dump out the script, but define the environment variables that
# it needs to run standalone.
echo CONFIGFRAG="$CONFIGFRAG; export CONFIGFRAG"
echo KVM="$KVM; export KVM"
echo KVPATH="$KVPATH; export KVPATH"
echo PATH="$PATH; export PATH"
echo RCU_BUILDONLY="$RCU_BUILDONLY; export RCU_BUILDONLY"
echo RCU_INITRD="$RCU_INITRD; export RCU_INITRD"
echo RCU_KMAKE_ARG="$RCU_KMAKE_ARG; export RCU_KMAKE_ARG"
echo RCU_QEMU_CMD="$RCU_QEMU_CMD; export RCU_QEMU_CMD"
echo RCU_QEMU_INTERACTIVE="$RCU_QEMU_INTERACTIVE; export RCU_QEMU_INTERACTIVE"
echo RCU_QEMU_MAC="$RCU_QEMU_MAC; export RCU_QEMU_MAC"
echo "mkdir -p "$resdir" || :"
echo "mkdir $resdir/$ds"
cat $T/script
exit 0
elif test "$dryrun" = sched
then
# Extract the test run schedule from the script.
egrep 'start batch|Starting build\.' $T/script |
sed -e 's/:.*$//' -e 's/^echo //'
exit 0
else
# Not a dryru, so run the script.
sh $T/script
fi
# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier # Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier
echo
echo
echo " --- `date` Test summary:" echo " --- `date` Test summary:"
echo Results directory: $resdir/$ds
kvm-recheck.sh $resdir/$ds kvm-recheck.sh $resdir/$ds
CONFIG_SMP=y
CONFIG_NR_CPUS=4
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_LOCK_TORTURE_TEST=y
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#!/bin/bash
#
# Kernel-version-dependent shell functions for the rest of the scripts.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
#
# Copyright (C) IBM Corporation, 2014
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
# locktorture_param_onoff bootparam-string config-file
#
# Adds onoff locktorture module parameters to kernels having it.
locktorture_param_onoff () {
if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
then
echo CPU-hotplug kernel, adding locktorture onoff. 1>&2
echo locktorture.onoff_interval=3 locktorture.onoff_holdoff=30
fi
}
# per_version_boot_params bootparam-string config-file seconds
#
# Adds per-version torture-module parameters to kernels supporting them.
per_version_boot_params () {
echo $1 `locktorture_param_onoff "$1" "$2"` \
locktorture.stat_interval=15 \
locktorture.shutdown_secs=$3 \
locktorture.locktorture_runnable=1 \
locktorture.verbose=1
}
CONFIG_RCU_TRACE=n
CONFIG_SMP=y
CONFIG_NR_CPUS=4
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_RCU_TORTURE_TEST=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n CONFIG_RCU_TRACE=n
CONFIG_SMP=y CONFIG_SMP=y
CONFIG_NR_CPUS=8 CONFIG_NR_CPUS=4
CONFIG_HOTPLUG_CPU=y CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n CONFIG_PREEMPT=n
CONFIG_PRINTK_TIME=y
...@@ -5,4 +5,3 @@ CONFIG_HOTPLUG_CPU=y ...@@ -5,4 +5,3 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y CONFIG_PREEMPT=y
CONFIG_PRINTK_TIME=y
...@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=n ...@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=n
CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PREEMPT_COUNT=n CONFIG_PREEMPT_COUNT=n
CONFIG_PRINTK_TIME=y
...@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=y ...@@ -10,4 +10,3 @@ CONFIG_RCU_TRACE=y
CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PREEMPT_COUNT=y CONFIG_PREEMPT_COUNT=y
CONFIG_PRINTK_TIME=y
...@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_INFO=n ...@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n ...@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=y CONFIG_RCU_CPU_STALL_VERBOSE=y
CONFIG_RCU_BOOST=n CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_VERBOSE=n ...@@ -20,4 +20,3 @@ CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=y CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2 CONFIG_RCU_BOOST_PRIO=2
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=n ...@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=y CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_RCU_CPU_STALL_VERBOSE=y CONFIG_RCU_CPU_STALL_VERBOSE=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=y ...@@ -22,4 +22,3 @@ CONFIG_PROVE_RCU_DELAY=y
CONFIG_RCU_CPU_STALL_INFO=n CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -23,4 +23,3 @@ CONFIG_PROVE_RCU_DELAY=n ...@@ -23,4 +23,3 @@ CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_PRINTK_TIME=y
...@@ -21,4 +21,3 @@ CONFIG_PROVE_RCU_DELAY=n ...@@ -21,4 +21,3 @@ CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=y CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n ...@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n ...@@ -23,4 +23,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -18,4 +18,3 @@ CONFIG_RCU_CPU_STALL_INFO=n ...@@ -18,4 +18,3 @@ CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
...@@ -20,16 +20,14 @@ ...@@ -20,16 +20,14 @@
# #
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> # Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
# rcutorture_param_n_barrier_cbs bootparam-string # per_version_boot_params bootparam-string config-file seconds
# #
# Adds n_barrier_cbs rcutorture module parameter to kernels having it. # Adds per-version torture-module parameters to kernels supporting them.
rcutorture_param_n_barrier_cbs () { # Which old kernels do not.
echo $1 per_version_boot_params () {
} echo rcutorture.stat_interval=15 \
rcutorture.shutdown_secs=$3 \
# rcutorture_param_onoff bootparam-string config-file rcutorture.rcutorture_runnable=1 \
# rcutorture.test_no_idle_hz=1 \
# Adds onoff rcutorture module parameters to kernels having it. rcutorture.verbose=1
rcutorture_param_onoff () {
echo $1
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment