Commit a693c46e 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:
 - add RCU torture scripts/tooling
 - static analysis improvements
 - update RCU documentation
 - miscellaneous fixes

* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (52 commits)
  rcu: Remove "extern" from function declarations in kernel/rcu/rcu.h
  rcu: Remove "extern" from function declarations in include/linux/*rcu*.h
  rcu/torture: Dynamically allocate SRCU output buffer to avoid overflow
  rcu: Don't activate RCU core on NO_HZ_FULL CPUs
  rcu: Warn on allegedly impossible rcu_read_unlock_special() from irq
  rcu: Add an RCU_INITIALIZER for global RCU-protected pointers
  rcu: Make rcu_assign_pointer's assignment volatile and type-safe
  bonding: Use RCU_INIT_POINTER() for better overhead and for sparse
  rcu: Add comment on evaluate-once properties of rcu_assign_pointer().
  rcu: Provide better diagnostics for blocking in RCU callback functions
  rcu: Improve SRCU's grace-period comments
  rcu: Fix CONFIG_RCU_FANOUT_EXACT for odd fanout/leaf values
  rcu: Fix coccinelle warnings
  rcutorture: Stop tracking FSF's postal address
  rcutorture: Move checkarg to functions.sh
  rcutorture: Flag errors and warnings with color coding
  rcutorture: Record results from repeated runs of the same test scenario
  rcutorture: Test summary at end of run with less chattiness
  rcutorture: Update comment in kvm.sh listing typical RCU trace events
  rcutorture: Add tracing-enabled version of TREE08
  ...
parents 6ffbe7d1 73a7ac28
...@@ -396,14 +396,14 @@ o Each element of the form "3/3 ..>. 0:7 ^0" represents one rcu_node ...@@ -396,14 +396,14 @@ o Each element of the form "3/3 ..>. 0:7 ^0" represents one rcu_node
The output of "cat rcu/rcu_sched/rcu_pending" looks as follows: The output of "cat rcu/rcu_sched/rcu_pending" looks as follows:
0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903 0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903 ndw=0
1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113 1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113 ndw=0
2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889 2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889 ndw=0
3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469 3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469 ndw=0
4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042 4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042 ndw=0
5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422 5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422 ndw=0
6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699 6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699 ndw=0
7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147 7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147 ndw=0
The fields are as follows: The fields are as follows:
...@@ -432,6 +432,10 @@ o "gpc" is the number of times that an old grace period had ...@@ -432,6 +432,10 @@ o "gpc" is the number of times that an old grace period had
o "gps" is the number of times that a new grace period had started, o "gps" is the number of times that a new grace period had started,
but this CPU was not yet aware of it. but this CPU was not yet aware of it.
o "ndw" is the number of times that a wakeup of an rcuo
callback-offload kthread had to be deferred in order to avoid
deadlock.
o "nn" is the number of times that this CPU needed nothing. o "nn" is the number of times that this CPU needed nothing.
...@@ -443,7 +447,7 @@ The output of "cat rcu/rcuboost" looks as follows: ...@@ -443,7 +447,7 @@ The output of "cat rcu/rcuboost" looks as follows:
balk: nt=0 egt=6541 bt=0 nb=0 ny=126 nos=0 balk: nt=0 egt=6541 bt=0 nb=0 ny=126 nos=0
This information is output only for rcu_preempt. Each two-line entry This information is output only for rcu_preempt. Each two-line entry
corresponds to a leaf rcu_node strcuture. The fields are as follows: corresponds to a leaf rcu_node structure. The fields are as follows:
o "n:m" is the CPU-number range for the corresponding two-line o "n:m" is the CPU-number range for the corresponding two-line
entry. In the sample output above, the first entry covers entry. In the sample output above, the first entry covers
......
...@@ -160,6 +160,7 @@ The producer will look something like this: ...@@ -160,6 +160,7 @@ The producer will look something like this:
spin_lock(&producer_lock); spin_lock(&producer_lock);
unsigned long head = buffer->head; unsigned long head = buffer->head;
/* The spin_unlock() and next spin_lock() provide needed ordering. */
unsigned long tail = ACCESS_ONCE(buffer->tail); unsigned long tail = ACCESS_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) { if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
...@@ -168,9 +169,8 @@ The producer will look something like this: ...@@ -168,9 +169,8 @@ The producer will look something like this:
produce_item(item); produce_item(item);
smp_wmb(); /* commit the item before incrementing the head */ smp_store_release(buffer->head,
(head + 1) & (buffer->size - 1));
buffer->head = (head + 1) & (buffer->size - 1);
/* wake_up() will make sure that the head is committed before /* wake_up() will make sure that the head is committed before
* waking anyone up */ * waking anyone up */
...@@ -183,9 +183,14 @@ This will instruct the CPU that the contents of the new item must be written ...@@ -183,9 +183,14 @@ This will instruct the CPU that the contents of the new item must be written
before the head index makes it available to the consumer and then instructs the before the head index makes it available to the consumer and then instructs the
CPU that the revised head index must be written before the consumer is woken. CPU that the revised head index must be written before the consumer is woken.
Note that wake_up() doesn't have to be the exact mechanism used, but whatever Note that wake_up() does not guarantee any sort of barrier unless something
is used must guarantee a (write) memory barrier between the update of the head is actually awakened. We therefore cannot rely on it for ordering. However,
index and the change of state of the consumer, if a change of state occurs. there is always one element of the array left empty. Therefore, the
producer must produce two elements before it could possibly corrupt the
element currently being read by the consumer. Therefore, the unlock-lock
pair between consecutive invocations of the consumer provides the necessary
ordering between the read of the index indicating that the consumer has
vacated a given element and the write by the producer to that same element.
THE CONSUMER THE CONSUMER
...@@ -195,21 +200,20 @@ The consumer will look something like this: ...@@ -195,21 +200,20 @@ The consumer will look something like this:
spin_lock(&consumer_lock); spin_lock(&consumer_lock);
unsigned long head = ACCESS_ONCE(buffer->head); /* Read index before reading contents at that index. */
unsigned long head = smp_load_acquire(buffer->head);
unsigned long tail = buffer->tail; unsigned long tail = buffer->tail;
if (CIRC_CNT(head, tail, buffer->size) >= 1) { if (CIRC_CNT(head, tail, buffer->size) >= 1) {
/* read index before reading contents at that index */
smp_read_barrier_depends();
/* extract one item from the buffer */ /* extract one item from the buffer */
struct item *item = buffer[tail]; struct item *item = buffer[tail];
consume_item(item); consume_item(item);
smp_mb(); /* finish reading descriptor before incrementing tail */ /* Finish reading descriptor before incrementing tail. */
smp_store_release(buffer->tail,
buffer->tail = (tail + 1) & (buffer->size - 1); (tail + 1) & (buffer->size - 1));
} }
spin_unlock(&consumer_lock); spin_unlock(&consumer_lock);
...@@ -218,12 +222,17 @@ This will instruct the CPU to make sure the index is up to date before reading ...@@ -218,12 +222,17 @@ This will instruct the CPU to make sure the index is up to date before reading
the new item, and then it shall make sure the CPU has finished reading the item the new item, and then it shall make sure the CPU has finished reading the item
before it writes the new tail pointer, which will erase the item. before it writes the new tail pointer, which will erase the item.
Note the use of ACCESS_ONCE() and smp_load_acquire() to read the
Note the use of ACCESS_ONCE() in both algorithms to read the opposition index. opposition index. This prevents the compiler from discarding and
This prevents the compiler from discarding and reloading its cached value - reloading its cached value - which some compilers will do across
which some compilers will do across smp_read_barrier_depends(). This isn't smp_read_barrier_depends(). This isn't strictly needed if you can
strictly needed if you can be sure that the opposition index will _only_ be be sure that the opposition index will _only_ be used the once.
used the once. The smp_load_acquire() additionally forces the CPU to order against
subsequent memory references. Similarly, smp_store_release() is used
in both algorithms to write the thread's index. This documents the
fact that we are writing to something that can be read concurrently,
prevents the compiler from tearing the store, and enforces ordering
against previous accesses.
=============== ===============
......
...@@ -2627,7 +2627,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2627,7 +2627,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
for RCU-preempt, and "s" for RCU-sched, and "N" for RCU-preempt, and "s" for RCU-sched, and "N"
is the CPU number. This reduces OS jitter on the is the CPU number. This reduces OS jitter on the
offloaded CPUs, which can be useful for HPC and offloaded CPUs, which can be useful for HPC and
real-time workloads. It can also improve energy real-time workloads. It can also improve energy
efficiency for asymmetric multiprocessors. efficiency for asymmetric multiprocessors.
...@@ -2643,8 +2642,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2643,8 +2642,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
periodically wake up to do the polling. periodically wake up to do the polling.
rcutree.blimit= [KNL] rcutree.blimit= [KNL]
Set maximum number of finished RCU callbacks to process Set maximum number of finished RCU callbacks to
in one batch. process in one batch.
rcutree.rcu_fanout_leaf= [KNL] rcutree.rcu_fanout_leaf= [KNL]
Increase the number of CPUs assigned to each Increase the number of CPUs assigned to each
...@@ -2663,8 +2662,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2663,8 +2662,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
value is one, and maximum value is HZ. value is one, and maximum value is HZ.
rcutree.qhimark= [KNL] rcutree.qhimark= [KNL]
Set threshold of queued Set threshold of queued RCU callbacks beyond which
RCU callbacks over which batch limiting is disabled. batch limiting is disabled.
rcutree.qlowmark= [KNL] rcutree.qlowmark= [KNL]
Set threshold of queued RCU callbacks below which Set threshold of queued RCU callbacks below which
......
...@@ -7104,6 +7104,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git ...@@ -7104,6 +7104,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
F: Documentation/RCU/torture.txt F: Documentation/RCU/torture.txt
F: kernel/rcu/torture.c F: kernel/rcu/torture.c
RCUTORTURE TEST FRAMEWORK
M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
F: tools/testing/selftests/rcutorture
RDC R-321X SoC RDC R-321X SoC
M: Florian Fainelli <florian@openwrt.org> M: Florian Fainelli <florian@openwrt.org>
S: Maintained S: Maintained
......
...@@ -1763,7 +1763,7 @@ static int __bond_release_one(struct net_device *bond_dev, ...@@ -1763,7 +1763,7 @@ static int __bond_release_one(struct net_device *bond_dev,
} }
if (all) { if (all) {
rcu_assign_pointer(bond->curr_active_slave, NULL); RCU_INIT_POINTER(bond->curr_active_slave, NULL);
} else if (oldcurrent == slave) { } else if (oldcurrent == slave) {
/* /*
* Note that we hold RTNL over this sequence, so there * Note that we hold RTNL over this sequence, so there
......
...@@ -55,7 +55,7 @@ static inline void __list_add_rcu(struct list_head *new, ...@@ -55,7 +55,7 @@ static inline void __list_add_rcu(struct list_head *new,
next->prev = new; next->prev = new;
} }
#else #else
extern void __list_add_rcu(struct list_head *new, void __list_add_rcu(struct list_head *new,
struct list_head *prev, struct list_head *next); struct list_head *prev, struct list_head *next);
#endif #endif
......
...@@ -50,9 +50,9 @@ extern int rcutorture_runnable; /* for sysctl */ ...@@ -50,9 +50,9 @@ extern int rcutorture_runnable; /* for sysctl */
#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
extern void rcutorture_record_test_transition(void); void rcutorture_record_test_transition(void);
extern void rcutorture_record_progress(unsigned long vernum); void rcutorture_record_progress(unsigned long vernum);
extern void do_trace_rcu_torture_read(const char *rcutorturename, void do_trace_rcu_torture_read(const char *rcutorturename,
struct rcu_head *rhp, struct rcu_head *rhp,
unsigned long secs, unsigned long secs,
unsigned long c_old, unsigned long c_old,
...@@ -65,7 +65,7 @@ static inline void rcutorture_record_progress(unsigned long vernum) ...@@ -65,7 +65,7 @@ static inline void rcutorture_record_progress(unsigned long vernum)
{ {
} }
#ifdef CONFIG_RCU_TRACE #ifdef CONFIG_RCU_TRACE
extern void do_trace_rcu_torture_read(const char *rcutorturename, void do_trace_rcu_torture_read(const char *rcutorturename,
struct rcu_head *rhp, struct rcu_head *rhp,
unsigned long secs, unsigned long secs,
unsigned long c_old, unsigned long c_old,
...@@ -118,7 +118,7 @@ extern void do_trace_rcu_torture_read(const char *rcutorturename, ...@@ -118,7 +118,7 @@ extern void do_trace_rcu_torture_read(const char *rcutorturename,
* if CPU A and CPU B are the same CPU (but again only if the system has * if CPU A and CPU B are the same CPU (but again only if the system has
* more than one CPU). * more than one CPU).
*/ */
extern void call_rcu(struct rcu_head *head, void call_rcu(struct rcu_head *head,
void (*func)(struct rcu_head *head)); void (*func)(struct rcu_head *head));
#else /* #ifdef CONFIG_PREEMPT_RCU */ #else /* #ifdef CONFIG_PREEMPT_RCU */
...@@ -149,7 +149,7 @@ extern void call_rcu(struct rcu_head *head, ...@@ -149,7 +149,7 @@ extern void call_rcu(struct rcu_head *head,
* See the description of call_rcu() for more detailed information on * See the description of call_rcu() for more detailed information on
* memory ordering guarantees. * memory ordering guarantees.
*/ */
extern void call_rcu_bh(struct rcu_head *head, void call_rcu_bh(struct rcu_head *head,
void (*func)(struct rcu_head *head)); void (*func)(struct rcu_head *head));
/** /**
...@@ -171,16 +171,16 @@ extern void call_rcu_bh(struct rcu_head *head, ...@@ -171,16 +171,16 @@ extern void call_rcu_bh(struct rcu_head *head,
* See the description of call_rcu() for more detailed information on * See the description of call_rcu() for more detailed information on
* memory ordering guarantees. * memory ordering guarantees.
*/ */
extern void call_rcu_sched(struct rcu_head *head, void call_rcu_sched(struct rcu_head *head,
void (*func)(struct rcu_head *rcu)); void (*func)(struct rcu_head *rcu));
extern void synchronize_sched(void); void synchronize_sched(void);
#ifdef CONFIG_PREEMPT_RCU #ifdef CONFIG_PREEMPT_RCU
extern void __rcu_read_lock(void); void __rcu_read_lock(void);
extern void __rcu_read_unlock(void); void __rcu_read_unlock(void);
extern void rcu_read_unlock_special(struct task_struct *t); void rcu_read_unlock_special(struct task_struct *t);
void synchronize_rcu(void); void synchronize_rcu(void);
/* /*
...@@ -216,19 +216,19 @@ static inline int rcu_preempt_depth(void) ...@@ -216,19 +216,19 @@ static inline int rcu_preempt_depth(void)
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */ #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
/* Internal to kernel */ /* Internal to kernel */
extern void rcu_init(void); void rcu_init(void);
extern void rcu_sched_qs(int cpu); void rcu_sched_qs(int cpu);
extern void rcu_bh_qs(int cpu); void rcu_bh_qs(int cpu);
extern void rcu_check_callbacks(int cpu, int user); void rcu_check_callbacks(int cpu, int user);
struct notifier_block; struct notifier_block;
extern void rcu_idle_enter(void); void rcu_idle_enter(void);
extern void rcu_idle_exit(void); void rcu_idle_exit(void);
extern void rcu_irq_enter(void); void rcu_irq_enter(void);
extern void rcu_irq_exit(void); void rcu_irq_exit(void);
#ifdef CONFIG_RCU_USER_QS #ifdef CONFIG_RCU_USER_QS
extern void rcu_user_enter(void); void rcu_user_enter(void);
extern void rcu_user_exit(void); void rcu_user_exit(void);
#else #else
static inline void rcu_user_enter(void) { } static inline void rcu_user_enter(void) { }
static inline void rcu_user_exit(void) { } static inline void rcu_user_exit(void) { }
...@@ -262,7 +262,7 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev, ...@@ -262,7 +262,7 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev,
} while (0) } while (0)
#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
extern bool __rcu_is_watching(void); bool __rcu_is_watching(void);
#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */
/* /*
...@@ -289,8 +289,8 @@ void wait_rcu_gp(call_rcu_func_t crf); ...@@ -289,8 +289,8 @@ void wait_rcu_gp(call_rcu_func_t crf);
* initialization. * initialization.
*/ */
#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
extern void init_rcu_head_on_stack(struct rcu_head *head); void init_rcu_head_on_stack(struct rcu_head *head);
extern void destroy_rcu_head_on_stack(struct rcu_head *head); void destroy_rcu_head_on_stack(struct rcu_head *head);
#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ #else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
static inline void init_rcu_head_on_stack(struct rcu_head *head) static inline void init_rcu_head_on_stack(struct rcu_head *head)
{ {
...@@ -325,6 +325,7 @@ static inline void rcu_lock_release(struct lockdep_map *map) ...@@ -325,6 +325,7 @@ static inline void rcu_lock_release(struct lockdep_map *map)
extern struct lockdep_map rcu_lock_map; extern struct lockdep_map rcu_lock_map;
extern struct lockdep_map rcu_bh_lock_map; extern struct lockdep_map rcu_bh_lock_map;
extern struct lockdep_map rcu_sched_lock_map; extern struct lockdep_map rcu_sched_lock_map;
extern struct lockdep_map rcu_callback_map;
extern int debug_lockdep_rcu_enabled(void); extern int debug_lockdep_rcu_enabled(void);
/** /**
...@@ -362,7 +363,7 @@ static inline int rcu_read_lock_held(void) ...@@ -362,7 +363,7 @@ static inline int rcu_read_lock_held(void)
* rcu_read_lock_bh_held() is defined out of line to avoid #include-file * rcu_read_lock_bh_held() is defined out of line to avoid #include-file
* hell. * hell.
*/ */
extern int rcu_read_lock_bh_held(void); int rcu_read_lock_bh_held(void);
/** /**
* rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
...@@ -448,7 +449,7 @@ static inline int rcu_read_lock_sched_held(void) ...@@ -448,7 +449,7 @@ static inline int rcu_read_lock_sched_held(void)
#ifdef CONFIG_PROVE_RCU #ifdef CONFIG_PROVE_RCU
extern int rcu_my_thread_group_empty(void); int rcu_my_thread_group_empty(void);
/** /**
* rcu_lockdep_assert - emit lockdep splat if specified condition not met * rcu_lockdep_assert - emit lockdep splat if specified condition not met
...@@ -548,10 +549,48 @@ static inline void rcu_preempt_sleep_check(void) ...@@ -548,10 +549,48 @@ static inline void rcu_preempt_sleep_check(void)
smp_read_barrier_depends(); \ smp_read_barrier_depends(); \
(_________p1); \ (_________p1); \
}) })
#define __rcu_assign_pointer(p, v, space) \
/**
* RCU_INITIALIZER() - statically initialize an RCU-protected global variable
* @v: The value to statically initialize with.
*/
#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
/**
* rcu_assign_pointer() - assign to RCU-protected pointer
* @p: pointer to assign to
* @v: value to assign (publish)
*
* Assigns the specified value to the specified RCU-protected
* pointer, ensuring that any concurrent RCU readers will see
* any prior initialization.
*
* Inserts memory barriers on architectures that require them
* (which is most of them), and also prevents the compiler from
* reordering the code that initializes the structure after the pointer
* assignment. More importantly, this call documents which pointers
* will be dereferenced by RCU read-side code.
*
* In some special cases, you may use RCU_INIT_POINTER() instead
* of rcu_assign_pointer(). RCU_INIT_POINTER() is a bit faster due
* to the fact that it does not constrain either the CPU or the compiler.
* That said, using RCU_INIT_POINTER() when you should have used
* rcu_assign_pointer() is a very bad thing that results in
* impossible-to-diagnose memory corruption. So please be careful.
* See the RCU_INIT_POINTER() comment header for details.
*
* Note that rcu_assign_pointer() evaluates each of its arguments only
* once, appearances notwithstanding. One of the "extra" evaluations
* is in typeof() and the other visible only to sparse (__CHECKER__),
* neither of which actually execute the argument. As with most cpp
* macros, this execute-arguments-only-once property is important, so
* please be careful when making changes to rcu_assign_pointer() and the
* other macros that it invokes.
*/
#define rcu_assign_pointer(p, v) \
do { \ do { \
smp_wmb(); \ smp_wmb(); \
(p) = (typeof(*v) __force space *)(v); \ ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
} while (0) } while (0)
...@@ -889,32 +928,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -889,32 +928,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
preempt_enable_notrace(); preempt_enable_notrace();
} }
/**
* rcu_assign_pointer() - assign to RCU-protected pointer
* @p: pointer to assign to
* @v: value to assign (publish)
*
* Assigns the specified value to the specified RCU-protected
* pointer, ensuring that any concurrent RCU readers will see
* any prior initialization.
*
* Inserts memory barriers on architectures that require them
* (which is most of them), and also prevents the compiler from
* reordering the code that initializes the structure after the pointer
* assignment. More importantly, this call documents which pointers
* will be dereferenced by RCU read-side code.
*
* In some special cases, you may use RCU_INIT_POINTER() instead
* of rcu_assign_pointer(). RCU_INIT_POINTER() is a bit faster due
* to the fact that it does not constrain either the CPU or the compiler.
* That said, using RCU_INIT_POINTER() when you should have used
* rcu_assign_pointer() is a very bad thing that results in
* impossible-to-diagnose memory corruption. So please be careful.
* See the RCU_INIT_POINTER() comment header for details.
*/
#define rcu_assign_pointer(p, v) \
__rcu_assign_pointer((p), (v), __rcu)
/** /**
* RCU_INIT_POINTER() - initialize an RCU protected pointer * RCU_INIT_POINTER() - initialize an RCU protected pointer
* *
...@@ -949,7 +962,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -949,7 +962,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
*/ */
#define RCU_INIT_POINTER(p, v) \ #define RCU_INIT_POINTER(p, v) \
do { \ do { \
p = (typeof(*v) __force __rcu *)(v); \ p = RCU_INITIALIZER(v); \
} while (0) } while (0)
/** /**
...@@ -958,7 +971,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -958,7 +971,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
* GCC-style initialization for an RCU-protected pointer in a structure field. * GCC-style initialization for an RCU-protected pointer in a structure field.
*/ */
#define RCU_POINTER_INITIALIZER(p, v) \ #define RCU_POINTER_INITIALIZER(p, v) \
.p = (typeof(*v) __force __rcu *)(v) .p = RCU_INITIALIZER(v)
/* /*
* Does the specified offset indicate that the corresponding rcu_head * Does the specified offset indicate that the corresponding rcu_head
...@@ -1005,7 +1018,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -1005,7 +1018,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
__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 #ifdef CONFIG_RCU_NOCB_CPU
extern 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 /* #else #ifdef CONFIG_RCU_NOCB_CPU */
...@@ -1013,8 +1026,8 @@ static inline bool rcu_is_nocb_cpu(int cpu) { return false; } ...@@ -1013,8 +1026,8 @@ static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
/* Only for use by adaptive-ticks code. */ /* Only for use by adaptive-ticks code. */
#ifdef CONFIG_NO_HZ_FULL_SYSIDLE #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
extern bool rcu_sys_is_idle(void); bool rcu_sys_is_idle(void);
extern void rcu_sysidle_force_exit(void); void rcu_sysidle_force_exit(void);
#else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
static inline bool rcu_sys_is_idle(void) static inline bool rcu_sys_is_idle(void)
......
...@@ -125,7 +125,7 @@ static inline void exit_rcu(void) ...@@ -125,7 +125,7 @@ static inline void exit_rcu(void)
#ifdef CONFIG_DEBUG_LOCK_ALLOC #ifdef CONFIG_DEBUG_LOCK_ALLOC
extern int rcu_scheduler_active __read_mostly; extern int rcu_scheduler_active __read_mostly;
extern void rcu_scheduler_starting(void); void rcu_scheduler_starting(void);
#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
static inline void rcu_scheduler_starting(void) static inline void rcu_scheduler_starting(void)
{ {
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
#ifndef __LINUX_RCUTREE_H #ifndef __LINUX_RCUTREE_H
#define __LINUX_RCUTREE_H #define __LINUX_RCUTREE_H
extern void rcu_note_context_switch(int cpu); void rcu_note_context_switch(int cpu);
extern int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
extern void rcu_cpu_stall_reset(void); void rcu_cpu_stall_reset(void);
/* /*
* Note a virtualization-based context switch. This is simply a * Note a virtualization-based context switch. This is simply a
...@@ -44,9 +44,9 @@ static inline void rcu_virt_note_context_switch(int cpu) ...@@ -44,9 +44,9 @@ static inline void rcu_virt_note_context_switch(int cpu)
rcu_note_context_switch(cpu); rcu_note_context_switch(cpu);
} }
extern void synchronize_rcu_bh(void); void synchronize_rcu_bh(void);
extern void synchronize_sched_expedited(void); void synchronize_sched_expedited(void);
extern void synchronize_rcu_expedited(void); void synchronize_rcu_expedited(void);
void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
...@@ -71,25 +71,25 @@ static inline void synchronize_rcu_bh_expedited(void) ...@@ -71,25 +71,25 @@ static inline void synchronize_rcu_bh_expedited(void)
synchronize_sched_expedited(); synchronize_sched_expedited();
} }
extern void rcu_barrier(void); void rcu_barrier(void);
extern void rcu_barrier_bh(void); void rcu_barrier_bh(void);
extern void rcu_barrier_sched(void); void rcu_barrier_sched(void);
extern unsigned long rcutorture_testseq; extern unsigned long rcutorture_testseq;
extern unsigned long rcutorture_vernum; extern unsigned long rcutorture_vernum;
extern long rcu_batches_completed(void); long rcu_batches_completed(void);
extern long rcu_batches_completed_bh(void); long rcu_batches_completed_bh(void);
extern long rcu_batches_completed_sched(void); long rcu_batches_completed_sched(void);
extern void rcu_force_quiescent_state(void); void rcu_force_quiescent_state(void);
extern void rcu_bh_force_quiescent_state(void); void rcu_bh_force_quiescent_state(void);
extern void rcu_sched_force_quiescent_state(void); void rcu_sched_force_quiescent_state(void);
extern void exit_rcu(void); void exit_rcu(void);
extern void rcu_scheduler_starting(void); void rcu_scheduler_starting(void);
extern int rcu_scheduler_active __read_mostly; extern int rcu_scheduler_active __read_mostly;
extern bool rcu_is_watching(void); bool rcu_is_watching(void);
#endif /* __LINUX_RCUTREE_H */ #endif /* __LINUX_RCUTREE_H */
...@@ -96,19 +96,22 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) ...@@ -96,19 +96,22 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
} }
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
extern void kfree(const void *); void kfree(const void *);
static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
{ {
unsigned long offset = (unsigned long)head->func; unsigned long offset = (unsigned long)head->func;
rcu_lock_acquire(&rcu_callback_map);
if (__is_kfree_rcu_offset(offset)) { if (__is_kfree_rcu_offset(offset)) {
RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset)); RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset));
kfree((void *)head - offset); kfree((void *)head - offset);
rcu_lock_release(&rcu_callback_map);
return 1; return 1;
} else { } else {
RCU_TRACE(trace_rcu_invoke_callback(rn, head)); RCU_TRACE(trace_rcu_invoke_callback(rn, head));
head->func(head); head->func(head);
rcu_lock_release(&rcu_callback_map);
return 0; return 0;
} }
} }
......
...@@ -363,6 +363,29 @@ static void srcu_flip(struct srcu_struct *sp) ...@@ -363,6 +363,29 @@ static void srcu_flip(struct srcu_struct *sp)
/* /*
* Enqueue an SRCU callback on the specified srcu_struct structure, * Enqueue an SRCU callback on the specified srcu_struct structure,
* initiating grace-period processing if it is not already running. * initiating grace-period processing if it is not already running.
*
* Note that all CPUs must agree that the grace period extended beyond
* all pre-existing SRCU read-side critical section. On systems with
* more than one CPU, this means that when "func()" is invoked, each CPU
* is guaranteed to have executed a full memory barrier since the end of
* its last corresponding SRCU read-side critical section whose beginning
* preceded the call to call_rcu(). It also means that each CPU executing
* an SRCU read-side critical section that continues beyond the start of
* "func()" must have executed a memory barrier after the call_rcu()
* but before the beginning of that SRCU read-side critical section.
* Note that these guarantees include CPUs that are offline, idle, or
* executing in user mode, as well as CPUs that are executing in the kernel.
*
* Furthermore, if CPU A invoked call_rcu() and CPU B invoked the
* resulting SRCU callback function "func()", then both CPU A and CPU
* B are guaranteed to execute a full memory barrier during the time
* interval between the call to call_rcu() and the invocation of "func()".
* This guarantee applies even if CPU A and CPU B are the same CPU (but
* again only if the system has more than one CPU).
*
* Of course, these guarantees apply only for invocations of call_srcu(),
* srcu_read_lock(), and srcu_read_unlock() that are all passed the same
* srcu_struct structure.
*/ */
void call_srcu(struct srcu_struct *sp, struct rcu_head *head, void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
void (*func)(struct rcu_head *head)) void (*func)(struct rcu_head *head))
...@@ -459,7 +482,30 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount) ...@@ -459,7 +482,30 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
* Note that it is illegal to call synchronize_srcu() from the corresponding * Note that it is illegal to call synchronize_srcu() from the corresponding
* SRCU read-side critical section; doing so will result in deadlock. * SRCU read-side critical section; doing so will result in deadlock.
* However, it is perfectly legal to call synchronize_srcu() on one * However, it is perfectly legal to call synchronize_srcu() on one
* srcu_struct from some other srcu_struct's read-side critical section. * srcu_struct from some other srcu_struct's read-side critical section,
* as long as the resulting graph of srcu_structs is acyclic.
*
* There are memory-ordering constraints implied by synchronize_srcu().
* On systems with more than one CPU, when synchronize_srcu() returns,
* each CPU is guaranteed to have executed a full memory barrier since
* the end of its last corresponding SRCU-sched read-side critical section
* whose beginning preceded the call to synchronize_srcu(). In addition,
* each CPU having an SRCU read-side critical section that extends beyond
* the return from synchronize_srcu() is guaranteed to have executed a
* full memory barrier after the beginning of synchronize_srcu() and before
* the beginning of that SRCU read-side critical section. Note that these
* guarantees include CPUs that are offline, idle, or executing in user mode,
* as well as CPUs that are executing in the kernel.
*
* Furthermore, if CPU A invoked synchronize_srcu(), which returned
* to its caller on CPU B, then both CPU A and CPU B are guaranteed
* to have executed a full memory barrier during the execution of
* synchronize_srcu(). This guarantee applies even if CPU A and CPU B
* are the same CPU, but again only if the system has more than one CPU.
*
* Of course, these memory-ordering guarantees apply only when
* synchronize_srcu(), srcu_read_lock(), and srcu_read_unlock() are
* passed the same srcu_struct structure.
*/ */
void synchronize_srcu(struct srcu_struct *sp) void synchronize_srcu(struct srcu_struct *sp)
{ {
...@@ -476,12 +522,8 @@ EXPORT_SYMBOL_GPL(synchronize_srcu); ...@@ -476,12 +522,8 @@ EXPORT_SYMBOL_GPL(synchronize_srcu);
* Wait for an SRCU grace period to elapse, but be more aggressive about * Wait for an SRCU grace period to elapse, but be more aggressive about
* spinning rather than blocking when waiting. * spinning rather than blocking when waiting.
* *
* Note that it is also illegal to call synchronize_srcu_expedited() * Note that synchronize_srcu_expedited() has the same deadlock and
* from the corresponding SRCU read-side critical section; * memory-ordering properties as does synchronize_srcu().
* doing so will result in deadlock. However, it is perfectly legal
* to call synchronize_srcu_expedited() on one srcu_struct from some
* other srcu_struct's read-side critical section, as long as
* the resulting graph of srcu_structs is acyclic.
*/ */
void synchronize_srcu_expedited(struct srcu_struct *sp) void synchronize_srcu_expedited(struct srcu_struct *sp)
{ {
...@@ -491,6 +533,7 @@ EXPORT_SYMBOL_GPL(synchronize_srcu_expedited); ...@@ -491,6 +533,7 @@ EXPORT_SYMBOL_GPL(synchronize_srcu_expedited);
/** /**
* srcu_barrier - Wait until all in-flight call_srcu() callbacks complete. * srcu_barrier - Wait until all in-flight call_srcu() callbacks complete.
* @sp: srcu_struct on which to wait for in-flight callbacks.
*/ */
void srcu_barrier(struct srcu_struct *sp) void srcu_barrier(struct srcu_struct *sp)
{ {
......
...@@ -139,8 +139,6 @@ MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s"); ...@@ -139,8 +139,6 @@ MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
#define VERBOSE_PRINTK_ERRSTRING(s) \ #define VERBOSE_PRINTK_ERRSTRING(s) \
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0) do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
static char printk_buf[4096];
static int nrealreaders; static int nrealreaders;
static struct task_struct *writer_task; static struct task_struct *writer_task;
static struct task_struct **fakewriter_tasks; static struct task_struct **fakewriter_tasks;
...@@ -376,7 +374,7 @@ struct rcu_torture_ops { ...@@ -376,7 +374,7 @@ struct rcu_torture_ops {
void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
void (*cb_barrier)(void); void (*cb_barrier)(void);
void (*fqs)(void); void (*fqs)(void);
int (*stats)(char *page); void (*stats)(char *page);
int irq_capable; int irq_capable;
int can_boost; int can_boost;
const char *name; const char *name;
...@@ -578,21 +576,19 @@ static void srcu_torture_barrier(void) ...@@ -578,21 +576,19 @@ static void srcu_torture_barrier(void)
srcu_barrier(&srcu_ctl); srcu_barrier(&srcu_ctl);
} }
static int srcu_torture_stats(char *page) static void srcu_torture_stats(char *page)
{ {
int cnt = 0;
int cpu; int cpu;
int idx = srcu_ctl.completed & 0x1; int idx = srcu_ctl.completed & 0x1;
cnt += sprintf(&page[cnt], "%s%s per-CPU(idx=%d):", page += sprintf(page, "%s%s per-CPU(idx=%d):",
torture_type, TORTURE_FLAG, idx); torture_type, TORTURE_FLAG, idx);
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
cnt += sprintf(&page[cnt], " %d(%lu,%lu)", cpu, page += sprintf(page, " %d(%lu,%lu)", cpu,
per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx], per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx],
per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]); per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]);
} }
cnt += sprintf(&page[cnt], "\n"); sprintf(page, "\n");
return cnt;
} }
static void srcu_torture_synchronize_expedited(void) static void srcu_torture_synchronize_expedited(void)
...@@ -1052,10 +1048,9 @@ rcu_torture_reader(void *arg) ...@@ -1052,10 +1048,9 @@ rcu_torture_reader(void *arg)
/* /*
* Create an RCU-torture statistics message in the specified buffer. * Create an RCU-torture statistics message in the specified buffer.
*/ */
static int static void
rcu_torture_printk(char *page) rcu_torture_printk(char *page)
{ {
int cnt = 0;
int cpu; int cpu;
int i; int i;
long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
...@@ -1071,8 +1066,8 @@ rcu_torture_printk(char *page) ...@@ -1071,8 +1066,8 @@ rcu_torture_printk(char *page)
if (pipesummary[i] != 0) if (pipesummary[i] != 0)
break; break;
} }
cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG); page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG);
cnt += sprintf(&page[cnt], page += sprintf(page,
"rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ", "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
rcu_torture_current, rcu_torture_current,
rcu_torture_current_version, rcu_torture_current_version,
...@@ -1080,53 +1075,52 @@ rcu_torture_printk(char *page) ...@@ -1080,53 +1075,52 @@ rcu_torture_printk(char *page)
atomic_read(&n_rcu_torture_alloc), atomic_read(&n_rcu_torture_alloc),
atomic_read(&n_rcu_torture_alloc_fail), atomic_read(&n_rcu_torture_alloc_fail),
atomic_read(&n_rcu_torture_free)); atomic_read(&n_rcu_torture_free));
cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ", page += sprintf(page, "rtmbe: %d rtbke: %ld rtbre: %ld ",
atomic_read(&n_rcu_torture_mberror), atomic_read(&n_rcu_torture_mberror),
n_rcu_torture_boost_ktrerror, n_rcu_torture_boost_ktrerror,
n_rcu_torture_boost_rterror); n_rcu_torture_boost_rterror);
cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ", page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ",
n_rcu_torture_boost_failure, n_rcu_torture_boost_failure,
n_rcu_torture_boosts, n_rcu_torture_boosts,
n_rcu_torture_timers); n_rcu_torture_timers);
cnt += sprintf(&page[cnt], page += sprintf(page,
"onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ", "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
n_online_successes, n_online_attempts, n_online_successes, n_online_attempts,
n_offline_successes, n_offline_attempts, n_offline_successes, n_offline_attempts,
min_online, max_online, min_online, max_online,
min_offline, max_offline, min_offline, max_offline,
sum_online, sum_offline, HZ); sum_online, sum_offline, HZ);
cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld", page += sprintf(page, "barrier: %ld/%ld:%ld",
n_barrier_successes, n_barrier_successes,
n_barrier_attempts, n_barrier_attempts,
n_rcu_torture_barrier_error); n_rcu_torture_barrier_error);
cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
if (atomic_read(&n_rcu_torture_mberror) != 0 || if (atomic_read(&n_rcu_torture_mberror) != 0 ||
n_rcu_torture_barrier_error != 0 || n_rcu_torture_barrier_error != 0 ||
n_rcu_torture_boost_ktrerror != 0 || n_rcu_torture_boost_ktrerror != 0 ||
n_rcu_torture_boost_rterror != 0 || n_rcu_torture_boost_rterror != 0 ||
n_rcu_torture_boost_failure != 0 || n_rcu_torture_boost_failure != 0 ||
i > 1) { i > 1) {
cnt += sprintf(&page[cnt], "!!! "); page += sprintf(page, "!!! ");
atomic_inc(&n_rcu_torture_error); atomic_inc(&n_rcu_torture_error);
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
cnt += sprintf(&page[cnt], "Reader Pipe: "); page += sprintf(page, "Reader Pipe: ");
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
cnt += sprintf(&page[cnt], " %ld", pipesummary[i]); page += sprintf(page, " %ld", pipesummary[i]);
cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
cnt += sprintf(&page[cnt], "Reader Batch: "); page += sprintf(page, "Reader Batch: ");
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
cnt += sprintf(&page[cnt], " %ld", batchsummary[i]); page += sprintf(page, " %ld", batchsummary[i]);
cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
cnt += sprintf(&page[cnt], "Free-Block Circulation: "); page += sprintf(page, "Free-Block Circulation: ");
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
cnt += sprintf(&page[cnt], " %d", page += sprintf(page, " %d",
atomic_read(&rcu_torture_wcount[i])); atomic_read(&rcu_torture_wcount[i]));
} }
cnt += sprintf(&page[cnt], "\n"); page += sprintf(page, "\n");
if (cur_ops->stats) if (cur_ops->stats)
cnt += cur_ops->stats(&page[cnt]); cur_ops->stats(page);
return cnt;
} }
/* /*
...@@ -1140,10 +1134,17 @@ rcu_torture_printk(char *page) ...@@ -1140,10 +1134,17 @@ rcu_torture_printk(char *page)
static void static void
rcu_torture_stats_print(void) rcu_torture_stats_print(void)
{ {
int cnt; int size = nr_cpu_ids * 200 + 8192;
char *buf;
cnt = rcu_torture_printk(printk_buf); buf = kmalloc(size, GFP_KERNEL);
pr_alert("%s", printk_buf); if (!buf) {
pr_err("rcu-torture: Out of memory, need: %d", size);
return;
}
rcu_torture_printk(buf);
pr_alert("%s", buf);
kfree(buf);
} }
/* /*
...@@ -1578,6 +1579,7 @@ static int rcu_torture_barrier_cbs(void *arg) ...@@ -1578,6 +1579,7 @@ static int rcu_torture_barrier_cbs(void *arg)
{ {
long myid = (long)arg; long myid = (long)arg;
bool lastphase = 0; bool lastphase = 0;
bool newphase;
struct rcu_head rcu; struct rcu_head rcu;
init_rcu_head_on_stack(&rcu); init_rcu_head_on_stack(&rcu);
...@@ -1585,10 +1587,11 @@ static int rcu_torture_barrier_cbs(void *arg) ...@@ -1585,10 +1587,11 @@ static int rcu_torture_barrier_cbs(void *arg)
set_user_nice(current, 19); set_user_nice(current, 19);
do { do {
wait_event(barrier_cbs_wq[myid], wait_event(barrier_cbs_wq[myid],
barrier_phase != lastphase || (newphase =
ACCESS_ONCE(barrier_phase)) != lastphase ||
kthread_should_stop() || kthread_should_stop() ||
fullstop != FULLSTOP_DONTSTOP); fullstop != FULLSTOP_DONTSTOP);
lastphase = barrier_phase; lastphase = newphase;
smp_mb(); /* ensure barrier_phase load before ->call(). */ smp_mb(); /* ensure barrier_phase load before ->call(). */
if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
break; break;
...@@ -1625,7 +1628,7 @@ static int rcu_torture_barrier(void *arg) ...@@ -1625,7 +1628,7 @@ static int rcu_torture_barrier(void *arg)
if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP) if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
break; break;
n_barrier_attempts++; n_barrier_attempts++;
cur_ops->cb_barrier(); cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */
if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) { if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) {
n_rcu_torture_barrier_error++; n_rcu_torture_barrier_error++;
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
......
...@@ -369,6 +369,9 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp) ...@@ -369,6 +369,9 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp)
static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
bool user) bool user)
{ {
struct rcu_state *rsp;
struct rcu_data *rdp;
trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting); trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting);
if (!user && !is_idle_task(current)) { if (!user && !is_idle_task(current)) {
struct task_struct *idle __maybe_unused = struct task_struct *idle __maybe_unused =
...@@ -380,6 +383,10 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, ...@@ -380,6 +383,10 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
current->pid, current->comm, current->pid, current->comm,
idle->pid, idle->comm); /* must be idle task! */ idle->pid, idle->comm); /* must be idle task! */
} }
for_each_rcu_flavor(rsp) {
rdp = this_cpu_ptr(rsp->rda);
do_nocb_deferred_wakeup(rdp);
}
rcu_prepare_for_idle(smp_processor_id()); rcu_prepare_for_idle(smp_processor_id());
/* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */ /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */
smp_mb__before_atomic_inc(); /* See above. */ smp_mb__before_atomic_inc(); /* See above. */
...@@ -411,11 +418,12 @@ static void rcu_eqs_enter(bool user) ...@@ -411,11 +418,12 @@ static void rcu_eqs_enter(bool user)
rdtp = this_cpu_ptr(&rcu_dynticks); rdtp = this_cpu_ptr(&rcu_dynticks);
oldval = rdtp->dynticks_nesting; oldval = rdtp->dynticks_nesting;
WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0); WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0);
if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) {
rdtp->dynticks_nesting = 0; rdtp->dynticks_nesting = 0;
else
rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE;
rcu_eqs_enter_common(rdtp, oldval, user); rcu_eqs_enter_common(rdtp, oldval, user);
} else {
rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE;
}
} }
/** /**
...@@ -533,11 +541,12 @@ static void rcu_eqs_exit(bool user) ...@@ -533,11 +541,12 @@ static void rcu_eqs_exit(bool user)
rdtp = this_cpu_ptr(&rcu_dynticks); rdtp = this_cpu_ptr(&rcu_dynticks);
oldval = rdtp->dynticks_nesting; oldval = rdtp->dynticks_nesting;
WARN_ON_ONCE(oldval < 0); WARN_ON_ONCE(oldval < 0);
if (oldval & DYNTICK_TASK_NEST_MASK) if (oldval & DYNTICK_TASK_NEST_MASK) {
rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE; rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE;
else } else {
rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
rcu_eqs_exit_common(rdtp, oldval, user); rcu_eqs_exit_common(rdtp, oldval, user);
}
} }
/** /**
...@@ -716,7 +725,7 @@ bool rcu_lockdep_current_cpu_online(void) ...@@ -716,7 +725,7 @@ bool rcu_lockdep_current_cpu_online(void)
bool ret; bool ret;
if (in_nmi()) if (in_nmi())
return 1; return true;
preempt_disable(); preempt_disable();
rdp = this_cpu_ptr(&rcu_sched_data); rdp = this_cpu_ptr(&rcu_sched_data);
rnp = rdp->mynode; rnp = rdp->mynode;
...@@ -754,6 +763,12 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp, ...@@ -754,6 +763,12 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp,
return (rdp->dynticks_snap & 0x1) == 0; return (rdp->dynticks_snap & 0x1) == 0;
} }
/*
* This function really isn't for public consumption, but RCU is special in
* that context switches can allow the state machine to make progress.
*/
extern void resched_cpu(int cpu);
/* /*
* Return true if the specified CPU has passed through a quiescent * Return true if the specified CPU has passed through a quiescent
* state by virtue of being in or having passed through an dynticks * state by virtue of being in or having passed through an dynticks
...@@ -812,16 +827,34 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp, ...@@ -812,16 +827,34 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
*/ */
rcu_kick_nohz_cpu(rdp->cpu); rcu_kick_nohz_cpu(rdp->cpu);
/*
* Alternatively, the CPU might be running in the kernel
* for an extended period of time without a quiescent state.
* Attempt to force the CPU through the scheduler to gain the
* needed quiescent state, but only if the grace period has gone
* on for an uncommonly long time. If there are many stuck CPUs,
* we will beat on the first one until it gets unstuck, then move
* to the next. Only do this for the primary flavor of RCU.
*/
if (rdp->rsp == rcu_state &&
ULONG_CMP_GE(ACCESS_ONCE(jiffies), rdp->rsp->jiffies_resched)) {
rdp->rsp->jiffies_resched += 5;
resched_cpu(rdp->cpu);
}
return 0; return 0;
} }
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 = ACCESS_ONCE(jiffies);
unsigned long j1;
rsp->gp_start = j; rsp->gp_start = j;
smp_wmb(); /* Record start time before stall time. */ smp_wmb(); /* Record start time before stall time. */
rsp->jiffies_stall = j + rcu_jiffies_till_stall_check(); j1 = rcu_jiffies_till_stall_check();
rsp->jiffies_stall = j + j1;
rsp->jiffies_resched = j + j1 / 2;
} }
/* /*
...@@ -1517,6 +1550,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) ...@@ -1517,6 +1550,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
rdp = this_cpu_ptr(rsp->rda); rdp = this_cpu_ptr(rsp->rda);
if (rnp == rdp->mynode) if (rnp == rdp->mynode)
__note_gp_changes(rsp, rnp, rdp); __note_gp_changes(rsp, rnp, rdp);
/* smp_mb() provided by prior unlock-lock pair. */
nocb += rcu_future_gp_cleanup(rsp, rnp); nocb += rcu_future_gp_cleanup(rsp, rnp);
raw_spin_unlock_irq(&rnp->lock); raw_spin_unlock_irq(&rnp->lock);
cond_resched(); cond_resched();
...@@ -1562,6 +1596,7 @@ static int __noreturn rcu_gp_kthread(void *arg) ...@@ -1562,6 +1596,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
wait_event_interruptible(rsp->gp_wq, wait_event_interruptible(rsp->gp_wq,
ACCESS_ONCE(rsp->gp_flags) & ACCESS_ONCE(rsp->gp_flags) &
RCU_GP_FLAG_INIT); RCU_GP_FLAG_INIT);
/* Locking provides needed memory barrier. */
if (rcu_gp_init(rsp)) if (rcu_gp_init(rsp))
break; break;
cond_resched(); cond_resched();
...@@ -1591,6 +1626,7 @@ static int __noreturn rcu_gp_kthread(void *arg) ...@@ -1591,6 +1626,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
(!ACCESS_ONCE(rnp->qsmask) && (!ACCESS_ONCE(rnp->qsmask) &&
!rcu_preempt_blocked_readers_cgp(rnp)), !rcu_preempt_blocked_readers_cgp(rnp)),
j); j);
/* Locking provides needed memory barriers. */
/* If grace period done, leave loop. */ /* If grace period done, leave loop. */
if (!ACCESS_ONCE(rnp->qsmask) && if (!ACCESS_ONCE(rnp->qsmask) &&
!rcu_preempt_blocked_readers_cgp(rnp)) !rcu_preempt_blocked_readers_cgp(rnp))
...@@ -1912,13 +1948,13 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp, ...@@ -1912,13 +1948,13 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
* Adopt the RCU callbacks from the specified rcu_state structure's * Adopt the RCU callbacks from the specified rcu_state structure's
* orphanage. The caller must hold the ->orphan_lock. * orphanage. The caller must hold the ->orphan_lock.
*/ */
static void rcu_adopt_orphan_cbs(struct rcu_state *rsp) static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
{ {
int i; int i;
struct rcu_data *rdp = __this_cpu_ptr(rsp->rda); struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
/* No-CBs CPUs are handled specially. */ /* No-CBs CPUs are handled specially. */
if (rcu_nocb_adopt_orphan_cbs(rsp, rdp)) if (rcu_nocb_adopt_orphan_cbs(rsp, rdp, flags))
return; return;
/* Do the accounting first. */ /* Do the accounting first. */
...@@ -1997,7 +2033,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) ...@@ -1997,7 +2033,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
/* Orphan the dead CPU's callbacks, and adopt them if appropriate. */ /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp); rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
rcu_adopt_orphan_cbs(rsp); rcu_adopt_orphan_cbs(rsp, flags);
/* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */ /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */
mask = rdp->grpmask; /* rnp->grplo is constant. */ mask = rdp->grpmask; /* rnp->grplo is constant. */
...@@ -2318,6 +2354,9 @@ __rcu_process_callbacks(struct rcu_state *rsp) ...@@ -2318,6 +2354,9 @@ __rcu_process_callbacks(struct rcu_state *rsp)
/* If there are callbacks ready, invoke them. */ /* If there are callbacks ready, invoke them. */
if (cpu_has_callbacks_ready_to_invoke(rdp)) if (cpu_has_callbacks_ready_to_invoke(rdp))
invoke_rcu_callbacks(rsp, rdp); invoke_rcu_callbacks(rsp, rdp);
/* Do any needed deferred wakeups of rcuo kthreads. */
do_nocb_deferred_wakeup(rdp);
} }
/* /*
...@@ -2453,7 +2492,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), ...@@ -2453,7 +2492,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
if (cpu != -1) if (cpu != -1)
rdp = per_cpu_ptr(rsp->rda, cpu); rdp = per_cpu_ptr(rsp->rda, cpu);
offline = !__call_rcu_nocb(rdp, head, lazy); offline = !__call_rcu_nocb(rdp, head, lazy, flags);
WARN_ON_ONCE(offline); WARN_ON_ONCE(offline);
/* _call_rcu() is illegal on offline CPU; leak the callback. */ /* _call_rcu() is illegal on offline CPU; leak the callback. */
local_irq_restore(flags); local_irq_restore(flags);
...@@ -2773,6 +2812,10 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) ...@@ -2773,6 +2812,10 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
/* Check for CPU stalls, if enabled. */ /* Check for CPU stalls, if enabled. */
check_cpu_stall(rsp, rdp); check_cpu_stall(rsp, rdp);
/* Is this CPU a NO_HZ_FULL CPU that should ignore RCU? */
if (rcu_nohz_full_cpu(rsp))
return 0;
/* Is the RCU core waiting for a quiescent state from this CPU? */ /* Is the RCU core waiting for a quiescent state from this CPU? */
if (rcu_scheduler_fully_active && if (rcu_scheduler_fully_active &&
rdp->qs_pending && !rdp->passed_quiesce) { rdp->qs_pending && !rdp->passed_quiesce) {
...@@ -2806,6 +2849,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) ...@@ -2806,6 +2849,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
return 1; return 1;
} }
/* Does this CPU need a deferred NOCB wakeup? */
if (rcu_nocb_need_deferred_wakeup(rdp)) {
rdp->n_rp_nocb_defer_wakeup++;
return 1;
}
/* nothing to do */ /* nothing to do */
rdp->n_rp_need_nothing++; rdp->n_rp_need_nothing++;
return 0; return 0;
...@@ -3230,9 +3279,9 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp) ...@@ -3230,9 +3279,9 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
{ {
int i; int i;
for (i = rcu_num_lvls - 1; i > 0; i--) rsp->levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
for (i = rcu_num_lvls - 2; i >= 0; i--)
rsp->levelspread[i] = CONFIG_RCU_FANOUT; rsp->levelspread[i] = CONFIG_RCU_FANOUT;
rsp->levelspread[0] = rcu_fanout_leaf;
} }
#else /* #ifdef CONFIG_RCU_FANOUT_EXACT */ #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
static void __init rcu_init_levelspread(struct rcu_state *rsp) static void __init rcu_init_levelspread(struct rcu_state *rsp)
...@@ -3362,6 +3411,8 @@ static void __init rcu_init_geometry(void) ...@@ -3362,6 +3411,8 @@ static void __init rcu_init_geometry(void)
if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF && if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF &&
nr_cpu_ids == NR_CPUS) nr_cpu_ids == NR_CPUS)
return; return;
pr_info("RCU: Adjusting geometry for rcu_fanout_leaf=%d, nr_cpu_ids=%d\n",
rcu_fanout_leaf, nr_cpu_ids);
/* /*
* Compute number of nodes that can be handled an rcu_node tree * Compute number of nodes that can be handled an rcu_node tree
......
...@@ -317,6 +317,7 @@ struct rcu_data { ...@@ -317,6 +317,7 @@ struct rcu_data {
unsigned long n_rp_cpu_needs_gp; unsigned long n_rp_cpu_needs_gp;
unsigned long n_rp_gp_completed; unsigned long n_rp_gp_completed;
unsigned long n_rp_gp_started; unsigned long n_rp_gp_started;
unsigned long n_rp_nocb_defer_wakeup;
unsigned long n_rp_need_nothing; unsigned long n_rp_need_nothing;
/* 6) _rcu_barrier() and OOM callbacks. */ /* 6) _rcu_barrier() and OOM callbacks. */
...@@ -335,6 +336,7 @@ struct rcu_data { ...@@ -335,6 +336,7 @@ struct rcu_data {
int nocb_p_count_lazy; /* (approximate). */ int nocb_p_count_lazy; /* (approximate). */
wait_queue_head_t nocb_wq; /* For nocb kthreads to sleep on. */ wait_queue_head_t nocb_wq; /* For nocb kthreads to sleep on. */
struct task_struct *nocb_kthread; struct task_struct *nocb_kthread;
bool nocb_defer_wakeup; /* Defer wakeup of nocb_kthread. */
#endif /* #ifdef CONFIG_RCU_NOCB_CPU */ #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
/* 8) RCU CPU stall data. */ /* 8) RCU CPU stall data. */
...@@ -453,6 +455,8 @@ struct rcu_state { ...@@ -453,6 +455,8 @@ struct rcu_state {
/* but in jiffies. */ /* but in jiffies. */
unsigned long jiffies_stall; /* Time at which to check */ unsigned long jiffies_stall; /* Time at which to check */
/* for CPU stalls. */ /* for CPU stalls. */
unsigned long jiffies_resched; /* Time at which to resched */
/* a reluctant CPU. */
unsigned long gp_max; /* Maximum GP duration in */ unsigned long gp_max; /* Maximum GP duration in */
/* jiffies. */ /* jiffies. */
const char *name; /* Name of structure. */ const char *name; /* Name of structure. */
...@@ -548,9 +552,12 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq); ...@@ -548,9 +552,12 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq);
static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp); static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp);
static void rcu_init_one_nocb(struct rcu_node *rnp); static void rcu_init_one_nocb(struct rcu_node *rnp);
static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
bool lazy); bool lazy, unsigned long flags);
static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
struct rcu_data *rdp); struct rcu_data *rdp,
unsigned long flags);
static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
static void do_nocb_deferred_wakeup(struct rcu_data *rdp);
static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp); static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp); static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
static void rcu_kick_nohz_cpu(int cpu); static void rcu_kick_nohz_cpu(int cpu);
...@@ -564,6 +571,7 @@ static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle, ...@@ -564,6 +571,7 @@ static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle,
unsigned long maxj); unsigned long maxj);
static void rcu_bind_gp_kthread(void); static void rcu_bind_gp_kthread(void);
static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp); static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp);
static bool rcu_nohz_full_cpu(struct rcu_state *rsp);
#endif /* #ifndef RCU_TREE_NONCORE */ #endif /* #ifndef RCU_TREE_NONCORE */
......
...@@ -363,10 +363,14 @@ void rcu_read_unlock_special(struct task_struct *t) ...@@ -363,10 +363,14 @@ void rcu_read_unlock_special(struct task_struct *t)
special = t->rcu_read_unlock_special; special = t->rcu_read_unlock_special;
if (special & RCU_READ_UNLOCK_NEED_QS) { if (special & RCU_READ_UNLOCK_NEED_QS) {
rcu_preempt_qs(smp_processor_id()); rcu_preempt_qs(smp_processor_id());
if (!t->rcu_read_unlock_special) {
local_irq_restore(flags);
return;
}
} }
/* Hardware IRQ handlers cannot block. */ /* Hardware IRQ handlers cannot block, complain if they get here. */
if (in_irq() || in_serving_softirq()) { if (WARN_ON_ONCE(in_irq() || in_serving_softirq())) {
local_irq_restore(flags); local_irq_restore(flags);
return; return;
} }
...@@ -785,8 +789,10 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, ...@@ -785,8 +789,10 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
} }
if (rnp->parent == NULL) { if (rnp->parent == NULL) {
raw_spin_unlock_irqrestore(&rnp->lock, flags); raw_spin_unlock_irqrestore(&rnp->lock, flags);
if (wake) if (wake) {
smp_mb(); /* EGP done before wake_up(). */
wake_up(&sync_rcu_preempt_exp_wq); wake_up(&sync_rcu_preempt_exp_wq);
}
break; break;
} }
mask = rnp->grpmask; mask = rnp->grpmask;
...@@ -1864,6 +1870,7 @@ static int rcu_oom_notify(struct notifier_block *self, ...@@ -1864,6 +1870,7 @@ static int rcu_oom_notify(struct notifier_block *self,
/* Wait for callbacks from earlier instance to complete. */ /* Wait for callbacks from earlier instance to complete. */
wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0); wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0);
smp_mb(); /* Ensure callback reuse happens after callback invocation. */
/* /*
* Prevent premature wakeup: ensure that all increments happen * Prevent premature wakeup: ensure that all increments happen
...@@ -2113,7 +2120,8 @@ bool rcu_is_nocb_cpu(int cpu) ...@@ -2113,7 +2120,8 @@ bool rcu_is_nocb_cpu(int cpu)
static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
struct rcu_head *rhp, struct rcu_head *rhp,
struct rcu_head **rhtp, struct rcu_head **rhtp,
int rhcount, int rhcount_lazy) int rhcount, int rhcount_lazy,
unsigned long flags)
{ {
int len; int len;
struct rcu_head **old_rhpp; struct rcu_head **old_rhpp;
...@@ -2134,9 +2142,16 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, ...@@ -2134,9 +2142,16 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
} }
len = atomic_long_read(&rdp->nocb_q_count); len = atomic_long_read(&rdp->nocb_q_count);
if (old_rhpp == &rdp->nocb_head) { if (old_rhpp == &rdp->nocb_head) {
wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */ if (!irqs_disabled_flags(flags)) {
wake_up(&rdp->nocb_wq); /* ... if queue was empty ... */
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
TPS("WakeEmpty"));
} else {
rdp->nocb_defer_wakeup = true;
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
TPS("WakeEmptyIsDeferred"));
}
rdp->qlen_last_fqs_check = 0; rdp->qlen_last_fqs_check = 0;
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty"));
} else if (len > rdp->qlen_last_fqs_check + qhimark) { } else if (len > rdp->qlen_last_fqs_check + qhimark) {
wake_up_process(t); /* ... or if many callbacks queued. */ wake_up_process(t); /* ... or if many callbacks queued. */
rdp->qlen_last_fqs_check = LONG_MAX / 2; rdp->qlen_last_fqs_check = LONG_MAX / 2;
...@@ -2157,12 +2172,12 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp, ...@@ -2157,12 +2172,12 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
* "rcuo" kthread can find it. * "rcuo" kthread can find it.
*/ */
static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
bool lazy) bool lazy, unsigned long flags)
{ {
if (!rcu_is_nocb_cpu(rdp->cpu)) if (!rcu_is_nocb_cpu(rdp->cpu))
return 0; return 0;
__call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy); __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy, flags);
if (__is_kfree_rcu_offset((unsigned long)rhp->func)) if (__is_kfree_rcu_offset((unsigned long)rhp->func))
trace_rcu_kfree_callback(rdp->rsp->name, rhp, trace_rcu_kfree_callback(rdp->rsp->name, rhp,
(unsigned long)rhp->func, (unsigned long)rhp->func,
...@@ -2180,7 +2195,8 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, ...@@ -2180,7 +2195,8 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
* not a no-CBs CPU. * not a no-CBs CPU.
*/ */
static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
struct rcu_data *rdp) struct rcu_data *rdp,
unsigned long flags)
{ {
long ql = rsp->qlen; long ql = rsp->qlen;
long qll = rsp->qlen_lazy; long qll = rsp->qlen_lazy;
...@@ -2194,14 +2210,14 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, ...@@ -2194,14 +2210,14 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
/* First, enqueue the donelist, if any. This preserves CB ordering. */ /* First, enqueue the donelist, if any. This preserves CB ordering. */
if (rsp->orphan_donelist != NULL) { if (rsp->orphan_donelist != NULL) {
__call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist, __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist,
rsp->orphan_donetail, ql, qll); rsp->orphan_donetail, ql, qll, flags);
ql = qll = 0; ql = qll = 0;
rsp->orphan_donelist = NULL; rsp->orphan_donelist = NULL;
rsp->orphan_donetail = &rsp->orphan_donelist; rsp->orphan_donetail = &rsp->orphan_donelist;
} }
if (rsp->orphan_nxtlist != NULL) { if (rsp->orphan_nxtlist != NULL) {
__call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist, __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist,
rsp->orphan_nxttail, ql, qll); rsp->orphan_nxttail, ql, qll, flags);
ql = qll = 0; ql = qll = 0;
rsp->orphan_nxtlist = NULL; rsp->orphan_nxtlist = NULL;
rsp->orphan_nxttail = &rsp->orphan_nxtlist; rsp->orphan_nxttail = &rsp->orphan_nxtlist;
...@@ -2263,6 +2279,7 @@ static int rcu_nocb_kthread(void *arg) ...@@ -2263,6 +2279,7 @@ static int rcu_nocb_kthread(void *arg)
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
TPS("Sleep")); TPS("Sleep"));
wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head); wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);
/* Memory barrier provide by xchg() below. */
} else if (firsttime) { } else if (firsttime) {
firsttime = 0; firsttime = 0;
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
...@@ -2323,6 +2340,22 @@ static int rcu_nocb_kthread(void *arg) ...@@ -2323,6 +2340,22 @@ static int rcu_nocb_kthread(void *arg)
return 0; return 0;
} }
/* Is a deferred wakeup of rcu_nocb_kthread() required? */
static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp)
{
return ACCESS_ONCE(rdp->nocb_defer_wakeup);
}
/* Do a deferred wakeup of rcu_nocb_kthread(). */
static void do_nocb_deferred_wakeup(struct rcu_data *rdp)
{
if (!rcu_nocb_need_deferred_wakeup(rdp))
return;
ACCESS_ONCE(rdp->nocb_defer_wakeup) = false;
wake_up(&rdp->nocb_wq);
trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("DeferredWakeEmpty"));
}
/* Initialize per-rcu_data variables for no-CBs CPUs. */ /* Initialize per-rcu_data variables for no-CBs CPUs. */
static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
{ {
...@@ -2378,13 +2411,14 @@ static void rcu_init_one_nocb(struct rcu_node *rnp) ...@@ -2378,13 +2411,14 @@ static void rcu_init_one_nocb(struct rcu_node *rnp)
} }
static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp, static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
bool lazy) bool lazy, unsigned long flags)
{ {
return 0; return 0;
} }
static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp, static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
struct rcu_data *rdp) struct rcu_data *rdp,
unsigned long flags)
{ {
return 0; return 0;
} }
...@@ -2393,6 +2427,15 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp) ...@@ -2393,6 +2427,15 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
{ {
} }
static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp)
{
return false;
}
static void do_nocb_deferred_wakeup(struct rcu_data *rdp)
{
}
static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp) static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp)
{ {
} }
...@@ -2842,3 +2885,23 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp) ...@@ -2842,3 +2885,23 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
} }
#endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */ #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
/*
* Is this CPU a NO_HZ_FULL CPU that should ignore RCU so that the
* grace-period kthread will do force_quiescent_state() processing?
* The idea is to avoid waking up RCU core processing on such a
* CPU unless the grace period has extended for too long.
*
* This code relies on the fact that all NO_HZ_FULL CPUs are also
* CONFIG_RCU_NOCB_CPUs.
*/
static bool rcu_nohz_full_cpu(struct rcu_state *rsp)
{
#ifdef CONFIG_NO_HZ_FULL
if (tick_nohz_full_cpu(smp_processor_id()) &&
(!rcu_gp_in_progress(rsp) ||
ULONG_CMP_LT(jiffies, ACCESS_ONCE(rsp->gp_start) + HZ)))
return 1;
#endif /* #ifdef CONFIG_NO_HZ_FULL */
return 0;
}
...@@ -364,9 +364,10 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) ...@@ -364,9 +364,10 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
rdp->n_rp_report_qs, rdp->n_rp_report_qs,
rdp->n_rp_cb_ready, rdp->n_rp_cb_ready,
rdp->n_rp_cpu_needs_gp); rdp->n_rp_cpu_needs_gp);
seq_printf(m, "gpc=%ld gps=%ld nn=%ld\n", seq_printf(m, "gpc=%ld gps=%ld nn=%ld ndw%ld\n",
rdp->n_rp_gp_completed, rdp->n_rp_gp_completed,
rdp->n_rp_gp_started, rdp->n_rp_gp_started,
rdp->n_rp_nocb_defer_wakeup,
rdp->n_rp_need_nothing); rdp->n_rp_need_nothing);
} }
......
...@@ -128,6 +128,11 @@ struct lockdep_map rcu_sched_lock_map = ...@@ -128,6 +128,11 @@ struct lockdep_map rcu_sched_lock_map =
STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key); STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key);
EXPORT_SYMBOL_GPL(rcu_sched_lock_map); EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
static struct lock_class_key rcu_callback_key;
struct lockdep_map rcu_callback_map =
STATIC_LOCKDEP_MAP_INIT("rcu_callback", &rcu_callback_key);
EXPORT_SYMBOL_GPL(rcu_callback_map);
int notrace debug_lockdep_rcu_enabled(void) int notrace debug_lockdep_rcu_enabled(void)
{ {
return rcu_scheduler_active && debug_locks && return rcu_scheduler_active && debug_locks &&
......
initrd
linux-2.6
b[0-9]*
rcu-test-image
res
*.swp
#!/bin/sh
# Usage: sh config2frag.sh < .config > configfrag
#
# Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the
# resulting file becomes a legitimate Kconfig fragment.
#
# 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, 2013
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
LANG=C sed -e 's/^# CONFIG_\([a-zA-Z0-9_]*\) is not set$/CONFIG_\1=n/'
#!/bin/bash
#
# Extract the number of CPUs expected from the specified Kconfig-file
# fragment by checking CONFIG_SMP and CONFIG_NR_CPUS. If the specified
# file gives no clue, base the number on the number of idle CPUs on
# the system.
#
# Usage: configNR_CPUS.sh config-frag
#
# 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, 2013
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
cf=$1
if test ! -r $cf
then
echo Unreadable config fragment $cf 1>&2
exit -1
fi
if grep -q '^CONFIG_SMP=n$' $cf
then
echo 1
exit 0
fi
if grep -q '^CONFIG_NR_CPUS=' $cf
then
grep '^CONFIG_NR_CPUS=' $cf |
sed -e 's/^CONFIG_NR_CPUS=\([0-9]*\).*$/\1/'
exit 0
fi
cpus2use.sh
#!/bin/sh
# Usage: sh configcheck.sh .config .config-template
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=/tmp/abat-chk-config.sh.$$
trap 'rm -rf $T' 0
mkdir $T
cat $1 > $T/.config
cat $2 | sed -e 's/\(.*\)=n/# \1 is not set/' -e 's/^#CHECK#//' |
awk '
BEGIN {
print "if grep -q \"" $0 "\" < '"$T/.config"'";
print "then";
print "\t:";
print "else";
if ($1 == "#") {
print "\tif grep -q \"" $2 "\" < '"$T/.config"'";
print "\tthen";
print "\t\tif test \"$firsttime\" = \"\""
print "\t\tthen"
print "\t\t\tfirsttime=1"
print "\t\tfi"
print "\t\techo \":" $2 ": improperly set\"";
print "\telse";
print "\t\t:";
print "\tfi";
} else {
print "\tif test \"$firsttime\" = \"\""
print "\tthen"
print "\t\tfirsttime=1"
print "\tfi"
print "\techo \":" $0 ": improperly set\"";
}
print "fi";
}' | sh
#!/bin/sh
#
# sh configinit.sh config-spec-file [ build output dir ]
#
# Create a .config file from the spec file. Run from the kernel source tree.
# Exits with 0 if all went well, with 1 if all went well but the config
# did not match, and some other number for other failures.
#
# The first argument is the .config specification file, which contains
# desired settings, for example, "CONFIG_NO_HZ=y". For best results,
# this should be a full pathname.
#
# The second argument is a optional path to a build output directory,
# for example, "O=/tmp/foo". If this argument is omitted, the .config
# file will be generated directly in the current directory.
#
# 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, 2013
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=/tmp/configinit.sh.$$
trap 'rm -rf $T' 0
mkdir $T
# Capture config spec file.
c=$1
buildloc=$2
builddir=
if test -n $buildloc
then
if echo $buildloc | grep -q '^O='
then
builddir=`echo $buildloc | sed -e 's/^O=//'`
if test ! -d $builddir
then
mkdir $builddir
fi
else
echo Bad build directory: \"$builddir\"
exit 2
fi
fi
sed -e 's/^\(CONFIG[0-9A-Z_]*\)=.*$/grep -v "^# \1" |/' < $c > $T/u.sh
sed -e 's/^\(CONFIG[0-9A-Z_]*=\).*$/grep -v \1 |/' < $c >> $T/u.sh
grep '^grep' < $T/u.sh > $T/upd.sh
echo "cat - $c" >> $T/upd.sh
make mrproper
make $buildloc distclean > $builddir/Make.distclean 2>&1
make $buildloc defconfig > $builddir/Make.defconfig.out 2>&1
mv $builddir/.config $builddir/.config.sav
sh $T/upd.sh < $builddir/.config.sav > $builddir/.config
cp $builddir/.config $builddir/.config.new
yes '' | make $buildloc oldconfig > $builddir/Make.modconfig.out 2>&1
# verify new config matches specification.
configcheck.sh $builddir/.config $c
exit 0
#!/bin/bash
#
# Get an estimate of how CPU-hoggy to be.
#
# Usage: cpus2use.sh
#
# 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, 2013
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
ncpus=`grep '^processor' /proc/cpuinfo | wc -l`
idlecpus=`mpstat | tail -1 | \
awk -v ncpus=$ncpus '{ print ncpus * ($7 + $12) / 100 }'`
awk -v ncpus=$ncpus -v idlecpus=$idlecpus < /dev/null '
BEGIN {
cpus2use = idlecpus;
if (cpus2use < 1)
cpus2use = 1;
if (cpus2use < ncpus / 10)
cpus2use = ncpus / 10;
if (cpus2use == int(cpus2use))
cpus2use = int(cpus2use)
else
cpus2use = int(cpus2use) + 1
print cpus2use;
}'
#!/bin/bash
#
# 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, 2013
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
# bootparam_hotplug_cpu bootparam-string
#
# Returns 1 if the specified boot-parameter string tells rcutorture to
# test CPU-hotplug operations.
bootparam_hotplug_cpu () {
echo "$1" | grep -q "rcutorture\.onoff_"
}
# checkarg --argname argtype $# arg mustmatch cannotmatch
#
# Checks the specified argument "arg" against the mustmatch and cannotmatch
# patterns.
checkarg () {
if test $3 -le 1
then
echo $1 needs argument $2 matching \"$5\"
usage
fi
if echo "$4" | grep -q -e "$5"
then
:
else
echo $1 $2 \"$4\" must match \"$5\"
usage
fi
if echo "$4" | grep -q -e "$6"
then
echo $1 $2 \"$4\" must not match \"$6\"
usage
fi
}
# configfrag_boot_params bootparam-string config-fragment-file
#
# Adds boot parameters from the .boot file, if any.
configfrag_boot_params () {
if test -r "$2.boot"
then
echo $1 `grep -v '^#' "$2.boot" | tr '\012' ' '`
else
echo $1
fi
}
# configfrag_hotplug_cpu config-fragment-file
#
# Returns 1 if the config fragment specifies hotplug CPU.
configfrag_hotplug_cpu () {
if test ! -r "$1"
then
echo Unreadable config fragment "$1" 1>&2
exit -1
fi
grep -q '^CONFIG_HOTPLUG_CPU=y$' "$1"
}
# identify_qemu builddir
#
# Returns our best guess as to which qemu command is appropriate for
# the kernel at hand. Override with the RCU_QEMU_CMD environment variable.
identify_qemu () {
local u="`file "$1"`"
if test -n "$RCU_QEMU_CMD"
then
echo $RCU_QEMU_CMD
elif echo $u | grep -q x86-64
then
echo qemu-system-x86_64
elif echo $u | grep -q "Intel 80386"
then
echo qemu-system-i386
elif uname -a | grep -q ppc64
then
echo qemu-system-ppc64
else
echo Cannot figure out what qemu command to use! 1>&2
# Usually this will be one of /usr/bin/qemu-system-*
# Use RCU_QEMU_CMD environment variable or appropriate
# argument to top-level script.
exit 1
fi
}
# identify_qemu_append qemu-cmd
#
# Output arguments for the qemu "-append" string based on CPU type
# and the RCU_QEMU_INTERACTIVE environment variable.
identify_qemu_append () {
case "$1" in
qemu-system-x86_64|qemu-system-i386)
echo noapic selinux=0 initcall_debug debug
;;
esac
if test -n "$RCU_QEMU_INTERACTIVE"
then
echo root=/dev/sda
else
echo console=ttyS0
fi
}
# identify_qemu_args qemu-cmd serial-file
#
# Output arguments for qemu arguments based on the RCU_QEMU_MAC
# and RCU_QEMU_INTERACTIVE environment variables.
identify_qemu_args () {
case "$1" in
qemu-system-x86_64|qemu-system-i386)
;;
qemu-system-ppc64)
echo -enable-kvm -M pseries -cpu POWER7 -nodefaults
echo -device spapr-vscsi
if test -n "$RCU_QEMU_INTERACTIVE" -a -n "$RCU_QEMU_MAC"
then
echo -device spapr-vlan,netdev=net0,mac=$RCU_QEMU_MAC
echo -netdev bridge,br=br0,id=net0
elif test -n "$RCU_QEMU_INTERACTIVE"
then
echo -net nic -net user
fi
;;
esac
if test -n "$RCU_QEMU_INTERACTIVE"
then
echo -monitor stdio -serial pty -S
else
echo -serial file:$2
fi
}
# identify_qemu_vcpus
#
# Returns the number of virtual CPUs available to the aggregate of the
# guest OSes.
identify_qemu_vcpus () {
lscpu | grep '^CPU(s):' | sed -e 's/CPU(s)://'
}
# print_bug
#
# Prints "BUG: " in red followed by remaining arguments
print_bug () {
printf '\033[031mBUG: \033[m'
echo $*
}
# print_warning
#
# Prints "WARNING: " in yellow followed by remaining arguments
print_warning () {
printf '\033[033mWARNING: \033[m'
echo $*
}
# specify_qemu_cpus qemu-cmd qemu-args #cpus
#
# Appends a string containing "-smp XXX" to qemu-args, unless the incoming
# qemu-args already contains "-smp".
specify_qemu_cpus () {
local nt;
if echo $2 | grep -q -e -smp
then
echo $2
else
case "$1" in
qemu-system-x86_64|qemu-system-i386)
echo $2 -smp $3
;;
qemu-system-ppc64)
nt="`lscpu | grep '^NUMA node0' | sed -e 's/^[^,]*,\([0-9]*\),.*$/\1/'`"
echo $2 -smp cores=`expr \( $3 + $nt - 1 \) / $nt`,threads=$nt
;;
esac
fi
}
#!/bin/bash
#
# Build a kvm-ready Linux kernel from the tree in the current directory.
#
# Usage: sh kvm-build.sh config-template build-dir more-configs
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
config_template=${1}
if test -z "$config_template" -o ! -f "$config_template" -o ! -r "$config_template"
then
echo "kvm-build.sh :$config_template: Not a readable file"
exit 1
fi
builddir=${2}
if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
then
echo "kvm-build.sh :$builddir: Not a writable directory, cannot build into it"
exit 1
fi
moreconfigs=${3}
if test -z "$moreconfigs" -o ! -r "$moreconfigs"
then
echo "kvm-build.sh :$moreconfigs: Not a readable file"
exit 1
fi
T=/tmp/test-linux.sh.$$
trap 'rm -rf $T' 0
mkdir $T
cat ${config_template} | grep -v CONFIG_RCU_TORTURE_TEST > $T/config
cat << ___EOF___ >> $T/config
CONFIG_INITRAMFS_SOURCE="$RCU_INITRD"
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_CONSOLE=y
___EOF___
cat $moreconfigs >> $T/config
configinit.sh $T/config O=$builddir
retval=$?
if test $retval -gt 1
then
exit 2
fi
ncpus=`cpus2use.sh`
make O=$builddir -j$ncpus $RCU_KMAKE_ARG > $builddir/Make.out 2>&1
retval=$?
if test $retval -ne 0 || grep "rcu[^/]*": < $builddir/Make.out | egrep -q "Stop|Error|error:|warning:" || egrep -q "Stop|Error|error:" < $builddir/Make.out
then
echo Kernel build error
egrep "Stop|Error|error:|warning:" < $builddir/Make.out
echo Run aborted.
exit 3
fi
#!/bin/bash
#
# Given the results directories for previous KVM runs of rcutorture,
# check the build and console output for errors. Given a directory
# containing results directories, this recursively checks them all.
#
# Usage: sh kvm-recheck.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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
for rd in "$@"
do
dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u`
for i in $dirs
do
configfile=`echo $i | sed -e 's/^.*\///'`
echo $configfile
configcheck.sh $i/.config $i/ConfigFragment
parse-build.sh $i/Make.out $configfile
parse-rcutorture.sh $i/console.log $configfile
parse-console.sh $i/console.log $configfile
if test -r $i/Warnings
then
cat $i/Warnings
fi
done
done
#!/bin/bash
#
# Run a kvm-based test of the specified tree on the specified configs.
# Fully automated run and error checking, no graphics console.
#
# Execute this in the source tree. Do not run it as a background task
# because qemu does not seem to like that much.
#
# Usage: sh kvm-test-1-rcu.sh config builddir resdir minutes qemu-args bootargs
#
# qemu-args defaults to "" -- you will want "-nographic" if running headless.
# bootargs defaults to "root=/dev/sda noapic selinux=0 console=ttyS0"
# "initcall_debug debug rcutorture.stat_interval=15"
# "rcutorture.shutdown_secs=$((minutes * 60))"
# "rcutorture.rcutorture_runnable=1"
#
# Anything you specify for either qemu-args or bootargs is appended to
# the default values. The "-smp" value is deduced from the contents of
# the config fragment.
#
# More sophisticated argument parsing is clearly needed.
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
grace=120
T=/tmp/kvm-test-1-rcu.sh.$$
trap 'rm -rf $T' 0
. $KVM/bin/functions.sh
. $KVPATH/ver_functions.sh
config_template=${1}
title=`echo $config_template | sed -e 's/^.*\///'`
builddir=${2}
if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
then
echo "kvm-test-1-rcu.sh :$builddir: Not a writable directory, cannot build into it"
exit 1
fi
resdir=${3}
if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir"
then
echo "kvm-test-1-rcu.sh :$resdir: Not a writable directory, cannot build into it"
exit 1
fi
cp $config_template $resdir/ConfigFragment
echo ' ---' `date`: Starting build
echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
cat << '___EOF___' >> $T
CONFIG_RCU_TORTURE_TEST=y
___EOF___
# Optimizations below this point
# CONFIG_USB=n
# CONFIG_SECURITY=n
# CONFIG_NFS_FS=n
# CONFIG_SOUND=n
# CONFIG_INPUT_JOYSTICK=n
# CONFIG_INPUT_TABLET=n
# CONFIG_INPUT_TOUCHSCREEN=n
# CONFIG_INPUT_MISC=n
# CONFIG_INPUT_MOUSE=n
# # CONFIG_NET=n # disables console access, so accept the slower build.
# CONFIG_SCSI=n
# CONFIG_ATA=n
# CONFIG_FAT_FS=n
# CONFIG_MSDOS_FS=n
# CONFIG_VFAT_FS=n
# CONFIG_ISO9660_FS=n
# CONFIG_QUOTA=n
# CONFIG_HID=n
# CONFIG_CRYPTO=n
# CONFIG_PCCARD=n
# CONFIG_PCMCIA=n
# CONFIG_CARDBUS=n
# CONFIG_YENTA=n
if kvm-build.sh $config_template $builddir $T
then
cp $builddir/Make*.out $resdir
cp $builddir/.config $resdir
cp $builddir/arch/x86/boot/bzImage $resdir
parse-build.sh $resdir/Make.out $title
else
cp $builddir/Make*.out $resdir
echo Build failed, not running KVM, see $resdir.
exit 1
fi
minutes=$4
seconds=$(($minutes * 60))
qemu_args=$5
boot_args=$6
cd $KVM
kstarttime=`awk 'BEGIN { print systime() }' < /dev/null`
echo ' ---' `date`: Starting kernel
# Determine the appropriate flavor of qemu command.
QEMU="`identify_qemu $builddir/vmlinux.o`"
# Generate -smp qemu argument.
cpu_count=`configNR_CPUS.sh $config_template`
vcpus=`identify_qemu_vcpus`
if test $cpu_count -gt $vcpus
then
echo CPU count limited from $cpu_count to $vcpus
touch $resdir/Warnings
echo CPU count limited from $cpu_count to $vcpus >> $resdir/Warnings
cpu_count=$vcpus
fi
qemu_args="`specify_qemu_cpus "$QEMU" "$qemu_args" "$cpu_count"`"
# Generate architecture-specific and interaction-specific qemu arguments
qemu_args="$qemu_args `identify_qemu_args "$QEMU" "$builddir/console.log"`"
# Generate qemu -append arguments
qemu_append="`identify_qemu_append "$QEMU"`"
# Pull in Kconfig-fragment boot parameters
boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
# Generate CPU-hotplug boot parameters
boot_args="`rcutorture_param_onoff "$boot_args" $builddir/.config`"
# 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
if test -n "$RCU_BUILDONLY"
then
echo Build-only run specified, boot/test omitted.
exit 0
fi
$QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append "$qemu_append $boot_args" &
qemu_pid=$!
commandcompleted=0
echo Monitoring qemu job at pid $qemu_pid
for ((i=0;i<$seconds;i++))
do
if kill -0 $qemu_pid > /dev/null 2>&1
then
sleep 1
else
commandcompleted=1
kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null`
if test $kruntime -lt $seconds
then
echo Completed in $kruntime vs. $seconds >> $resdir/Warnings 2>&1
else
echo ' ---' `date`: Kernel done
fi
break
fi
done
if test $commandcompleted -eq 0
then
echo Grace period for qemu job at pid $qemu_pid
for ((i=0;i<=$grace;i++))
do
if kill -0 $qemu_pid > /dev/null 2>&1
then
sleep 1
else
break
fi
if test $i -eq $grace
then
kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }'`
echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1
kill -KILL $qemu_pid
fi
done
fi
cp $builddir/console.log $resdir
parse-rcutorture.sh $resdir/console.log $title
parse-console.sh $resdir/console.log $title
#!/bin/bash
#
# Run a series of 14 tests under KVM. These are not particularly
# well-selected or well-tuned, but are the current set. Run from the
# top level of the source tree.
#
# Edit the definitions below to set the locations of the various directories,
# as well as the test duration.
#
# Usage: sh kvm.sh [ options ]
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
scriptname=$0
args="$*"
dur=30
KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
PATH=${KVM}/bin:$PATH; export PATH
builddir="${KVM}/b1"
RCU_INITRD="$KVM/initrd"; export RCU_INITRD
RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG
resdir=""
configs=""
ds=`date +%Y.%m.%d-%H:%M:%S`
kversion=""
. functions.sh
usage () {
echo "Usage: $scriptname optional arguments:"
echo " --bootargs kernel-boot-arguments"
echo " --builddir absolute-pathname"
echo " --buildonly"
echo " --configs \"config-file list\""
echo " --datestamp string"
echo " --duration minutes"
echo " --interactive"
echo " --kmake-arg kernel-make-arguments"
echo " --kversion vN.NN"
echo " --mac nn:nn:nn:nn:nn:nn"
echo " --no-initrd"
echo " --qemu-args qemu-system-..."
echo " --qemu-cmd qemu-system-..."
echo " --results absolute-pathname"
echo " --relbuilddir relative-pathname"
exit 1
}
while test $# -gt 0
do
case "$1" in
--bootargs)
checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--'
RCU_BOOTARGS="$2"
shift
;;
--builddir)
checkarg --builddir "(absolute pathname)" "$#" "$2" '^/' '^error'
builddir=$2
gotbuilddir=1
shift
;;
--buildonly)
RCU_BUILDONLY=1; export RCU_BUILDONLY
;;
--configs)
checkarg --configs "(list of config files)" "$#" "$2" '^[^/]*$' '^--'
configs="$2"
shift
;;
--datestamp)
checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
ds=$2
shift
;;
--duration)
checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
dur=$2
shift
;;
--interactive)
RCU_QEMU_INTERACTIVE=1; export RCU_QEMU_INTERACTIVE
;;
--kmake-arg)
checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
RCU_KMAKE_ARG="$2"; export RCU_KMAKE_ARG
shift
;;
--kversion)
checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error'
kversion=$2
shift
;;
--mac)
checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error
RCU_QEMU_MAC=$2; export RCU_QEMU_MAC
shift
;;
--no-initrd)
RCU_INITRD=""; export RCU_INITRD
;;
--qemu-args)
checkarg --qemu-args "-qemu args" $# "$2" '^-' '^error'
RCU_QEMU_ARG="$2"
shift
;;
--qemu-cmd)
checkarg --qemu-cmd "(qemu-system-...)" $# "$2" 'qemu-system-' '^--'
RCU_QEMU_CMD="$2"; export RCU_QEMU_CMD
shift
;;
--relbuilddir)
checkarg --relbuilddir "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
relbuilddir=$2
gotrelbuilddir=1
builddir=${KVM}/${relbuilddir}
shift
;;
--results)
checkarg --results "(absolute pathname)" "$#" "$2" '^/' '^error'
resdir=$2
shift
;;
*)
echo Unknown argument $1
usage
;;
esac
shift
done
CONFIGFRAG=${KVM}/configs; export CONFIGFRAG
KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
if test -z "$configs"
then
configs="`cat $CONFIGFRAG/$kversion/CFLIST`"
fi
if test -z "$resdir"
then
resdir=$KVM/res
if ! test -e $resdir
then
mkdir $resdir || :
fi
else
if ! test -e $resdir
then
mkdir -p "$resdir" || :
fi
fi
mkdir $resdir/$ds
touch $resdir/$ds/log
echo $scriptname $args >> $resdir/$ds/log
pwd > $resdir/$ds/testid.txt
if test -d .git
then
git status >> $resdir/$ds/testid.txt
git rev-parse HEAD >> $resdir/$ds/testid.txt
fi
builddir=$KVM/b1
if ! test -e $builddir
then
mkdir $builddir || :
fi
for CF in $configs
do
# Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ...
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
rd="${rd}.2"
else
n="`expr $n + 1`"
rd="${rd}.${n}"
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
# 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 " --- `date` Test summary:"
kvm-recheck.sh $resdir/$ds
#!/bin/sh
#
# Check the build output from an rcutorture run for goodness.
# The "file" is a pathname on the local system, and "title" is
# a text string for error-message purposes.
#
# The file must contain kernel build output.
#
# Usage:
# sh parse-build.sh file title
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=$1
title=$2
. functions.sh
if grep -q CC < $T
then
:
else
print_bug $title no build
exit 1
fi
if grep -q "error:" < $T
then
print_bug $title build errors:
grep "error:" < $T
exit 2
fi
exit 0
if egrep -q "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T
then
print_warning $title build errors:
egrep "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T
exit 2
fi
exit 0
#!/bin/sh
#
# Check the console output from an rcutorture run for oopses.
# The "file" is a pathname on the local system, and "title" is
# a text string for error-message purposes.
#
# Usage:
# sh parse-console.sh file title
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=/tmp/abat-chk-badness.sh.$$
trap 'rm -f $T' 0
file="$1"
title="$2"
. functions.sh
egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T
if test -s $T
then
print_warning Assertion failure in $file $title
cat $T
fi
#!/bin/sh
#
# Check the console output from an rcutorture run for goodness.
# The "file" is a pathname on the local system, and "title" is
# a text string for error-message purposes.
#
# The file must contain rcutorture output, but can be interspersed
# with other dmesg text.
#
# Usage:
# sh parse-rcutorture.sh file title
#
# 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, 2011
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=/tmp/parse-rcutorture.sh.$$
file="$1"
title="$2"
trap 'rm -f $T.seq' 0
. functions.sh
# check for presence of rcutorture.txt file
if test -f "$file" -a -r "$file"
then
:
else
echo $title unreadable rcutorture.txt file: $file
exit 1
fi
# check for abject failure
if grep -q FAILURE $file || grep -q -e '-torture.*!!!' $file
then
nerrs=`grep --binary-files=text '!!!' $file | tail -1 | awk '{for (i=NF-8;i<=NF;i++) sum+=$i; } END {print sum}'`
print_bug $title FAILURE, $nerrs instances
echo " " $url
exit
fi
grep --binary-files=text 'torture:.*ver:' $file | grep --binary-files=text -v '(null)' | sed -e 's/^(initramfs)[^]]*] //' -e 's/^\[[^]]*] //' |
awk '
BEGIN {
ver = 0;
badseq = 0;
}
{
if (!badseq && ($5 + 0 != $5 || $5 <= ver)) {
badseqno1 = ver;
badseqno2 = $5;
badseqnr = NR;
badseq = 1;
}
ver = $5
}
END {
if (badseq) {
if (badseqno1 == badseqno2 && badseqno2 == ver)
print "RCU GP HANG at " ver " rcutorture stat " badseqnr;
else
print "BAD SEQ " badseqno1 ":" badseqno2 " last:" ver " RCU version " badseqnr;
}
}' > $T.seq
if grep -q SUCCESS $file
then
if test -s $T.seq
then
print_warning $title $title `cat $T.seq`
echo " " $file
exit 2
fi
else
if grep -q RCU_HOTPLUG $file
then
print_warning HOTPLUG FAILURES $title `cat $T.seq`
echo " " $file
exit 3
fi
echo $title no success message, `grep --binary-files=text 'ver:' $file | wc -l` successful RCU version messages
if test -s $T.seq
then
print_warning $title `cat $T.seq`
fi
exit 2
fi
TREE01
TREE02
TREE03
TREE04
TREE05
TREE06
TREE07
TREE08
TREE09
SRCU-N
SRCU-P
TINY01
TINY02
CONFIG_RCU_TRACE=n
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_PRINTK_TIME=y
CONFIG_SMP=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TINY_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_TRACE=n
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PREEMPT_COUNT=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TINY_RCU=y
CONFIG_HZ_PERIODIC=y
CONFIG_NO_HZ_IDLE=n
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_TRACE=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PREEMPT_COUNT=y
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_RCU_TRACE=y
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_FANOUT=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_ZERO=y
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_FAST_NO_HZ=n
CONFIG_RCU_TRACE=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_RCU_FANOUT=3
CONFIG_RCU_FANOUT_LEAF=3
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_RCU_NOCB_CPU=n
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=y
CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_HZ_PERIODIC=y
CONFIG_NO_HZ_IDLE=n
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_TRACE=y
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_FANOUT=4
CONFIG_RCU_FANOUT_LEAF=4
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_RCU_NOCB_CPU=n
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=n
CONFIG_NO_HZ_FULL=y
CONFIG_NO_HZ_FULL_ALL=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_RCU_TRACE=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_RCU_FANOUT=2
CONFIG_RCU_FANOUT_LEAF=2
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_RCU_NOCB_CPU=n
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_RCU_CPU_STALL_VERBOSE=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_FAST_NO_HZ=n
CONFIG_RCU_TRACE=n
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_FANOUT=6
CONFIG_RCU_FANOUT_LEAF=6
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_NONE=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_PROVE_RCU_DELAY=y
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_FAST_NO_HZ=n
CONFIG_RCU_TRACE=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_RCU_FANOUT=6
CONFIG_RCU_FANOUT_LEAF=6
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_RCU_NOCB_CPU=n
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=16
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=n
CONFIG_NO_HZ_FULL=y
CONFIG_NO_HZ_FULL_ALL=y
CONFIG_NO_HZ_FULL_SYSIDLE=y
CONFIG_RCU_FAST_NO_HZ=n
CONFIG_RCU_TRACE=y
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_FANOUT=2
CONFIG_RCU_FANOUT_LEAF=2
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_RCU_NOCB_CPU=n
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=16
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_FAST_NO_HZ=n
CONFIG_RCU_TRACE=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_RCU_FANOUT=3
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_RCU_FANOUT_LEAF=2
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_ALL=y
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=y
CONFIG_NR_CPUS=16
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_FAST_NO_HZ=n
CONFIG_RCU_TRACE=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_RCU_FANOUT=3
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_RCU_FANOUT_LEAF=2
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_ALL=y
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
CONFIG_SMP=n
CONFIG_NR_CPUS=1
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_HZ_PERIODIC=n
CONFIG_NO_HZ_IDLE=y
CONFIG_NO_HZ_FULL=n
CONFIG_RCU_TRACE=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_RCU_NOCB_CPU=n
CONFIG_DEBUG_LOCK_ALLOC=n
CONFIG_PROVE_RCU_DELAY=n
CONFIG_RCU_CPU_STALL_INFO=n
CONFIG_RCU_CPU_STALL_VERBOSE=n
CONFIG_RCU_BOOST=n
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
CONFIG_PRINTK_TIME=y
P1-S-T-NH-SD-SMP-HP
P2-2-t-nh-sd-SMP-hp
P3-3-T-nh-SD-SMP-hp
P4-A-t-NH-sd-SMP-HP
P5-U-T-NH-sd-SMP-hp
N1-S-T-NH-SD-SMP-HP
N2-2-t-nh-sd-SMP-hp
N3-3-T-nh-SD-SMP-hp
N4-A-t-NH-sd-SMP-HP
N5-U-T-NH-sd-SMP-hp
PT1-nh
PT2-NH
NT1-nh
NT3-NH
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=8
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=4
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_DEBUG_KERNEL=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
#CHECK#CONFIG_TINY_RCU=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=n
#
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
#CHECK#CONFIG_TINY_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=y
#
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=8
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=4
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_RT_MUTEXES=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_DEBUG_KERNEL=y
CONFIG_PROVE_RCU_DELAY=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_RT_MUTEXES=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_TINY_PREEMPT_RCU=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_RCU_TRACE=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=n
#
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_TINY_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=y
#
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=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, 2013
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
# rcutorture_param_n_barrier_cbs bootparam-string
#
# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
rcutorture_param_n_barrier_cbs () {
echo $1
}
# rcutorture_param_onoff bootparam-string config-file
#
# Adds onoff rcutorture module parameters to kernels having it.
rcutorture_param_onoff () {
echo $1
}
sysidleY.2013.06.19a
sysidleN.2013.06.19a
P1-S-T-NH-SD-SMP-HP
P2-2-t-nh-sd-SMP-hp
P3-3-T-nh-SD-SMP-hp
P4-A-t-NH-sd-SMP-HP
P5-U-T-NH-sd-SMP-hp
P6---t-nh-SD-smp-hp
N1-S-T-NH-SD-SMP-HP
N2-2-t-nh-sd-SMP-hp
N3-3-T-nh-SD-SMP-hp
N4-A-t-NH-sd-SMP-HP
N5-U-T-NH-sd-SMP-hp
PT1-nh
PT2-NH
NT1-nh
NT3-NH
CONFIG_RCU_TRACE=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=8
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=4
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_DEBUG_KERNEL=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_NR_CPUS=1
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_DEBUG_KERNEL=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=16
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_NONE=y
CONFIG_RCU_NOCB_CPU_ZERO=n
CONFIG_RCU_NOCB_CPU_ALL=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_DEBUG_KERNEL=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=14
CONFIG_NR_CPUS=16
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_HOTPLUG_CPU=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
#CHECK#CONFIG_TINY_RCU=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=n
#
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
#CHECK#CONFIG_TINY_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=y
#
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=8
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=4
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_RT_MUTEXES=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_DEBUG_KERNEL=y
CONFIG_PROVE_RCU_DELAY=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_RT_MUTEXES=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=n
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=16
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_NONE=n
CONFIG_RCU_NOCB_CPU_ZERO=n
CONFIG_RCU_NOCB_CPU_ALL=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_SLUB=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=16
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_NONE=y
CONFIG_RCU_NOCB_CPU_ZERO=n
CONFIG_RCU_NOCB_CPU_ALL=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_SLUB=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=16
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_NONE=y
CONFIG_RCU_NOCB_CPU_ZERO=n
CONFIG_RCU_NOCB_CPU_ALL=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_SLUB=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=16
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_NOCB_CPU_NONE=n
CONFIG_RCU_NOCB_CPU_ZERO=y
CONFIG_RCU_NOCB_CPU_ALL=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_SLUB=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_TINY_PREEMPT_RCU=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIO=2
CONFIG_RCU_TRACE=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=n
#
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_TINY_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=y
#
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
P1-S-T-NH-SD-SMP-HP
P2-2-t-nh-sd-SMP-hp
P3-3-T-nh-SD-SMP-hp
P4-A-t-NH-sd-SMP-HP
P5-U-T-NH-sd-SMP-hp
N1-S-T-NH-SD-SMP-HP
N2-2-t-nh-sd-SMP-hp
N3-3-T-nh-SD-SMP-hp
N4-A-t-NH-sd-SMP-HP
N5-U-T-NH-sd-SMP-hp
PT1-nh
PT2-NH
NT1-nh
NT3-NH
CONFIG_RCU_TRACE=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=8
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=4
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=2
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_DEBUG_KERNEL=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=6
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=y
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
#CHECK#CONFIG_TREE_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
#CHECK#CONFIG_TINY_RCU=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=n
#
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
#CHECK#CONFIG_TINY_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
#
CONFIG_SMP=n
#
CONFIG_HOTPLUG_CPU=n
#
CONFIG_NO_HZ=y
#
CONFIG_PREEMPT_NONE=y
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=n
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=y
CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_NO_HZ=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_SMP=y
CONFIG_RCU_FANOUT=8
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
CONFIG_RCU_TRACE=n
CONFIG_NO_HZ=n
CONFIG_SMP=y
CONFIG_RCU_FANOUT=4
CONFIG_NR_CPUS=8
CONFIG_RCU_FANOUT_EXACT=n
CONFIG_HOTPLUG_CPU=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n
CONFIG_PREEMPT_NONE=n
CONFIG_PREEMPT_VOLUNTARY=n
CONFIG_PREEMPT=y
#CHECK#CONFIG_TREE_PREEMPT_RCU=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_MODULE_UNLOAD=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_PRINTK_TIME=y
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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