RCU changes for v4.6
Subsystems (8)
Linus,
Please pull the latest core-rcu-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core-rcu-for-linus
# HEAD: 670191572e929ca351e65f532ff51b1f61f424dc Merge commit 'torture.2015.02.23a' into core/rcu
This tree excludes the documentation changes of yesterday. It's the same commits that were tested in linux-next, just the octopus merge was redone.
The main changes in this cycle were:
- Miscellaneous fixes, cleanups, restructuring.
- RCU torture-test updates.
Thanks,
Ingo
------------------>
Boqun Feng (3):
sparse: Add __private to privatize members of structs
RCU: Privatize rcu_node::lock
irq: Privatize irq_common_data::state_use_accessors
Chen Gang (1):
rcu: Remove useless rcu_data_p when !PREEMPT_RCU
Paul E. McKenney (11):
rcutorture: Add checks for rcutorture writer starvation
rcutorture: Don't keep empty console.log.diags files
rcutorture: Check for self-detected stalls
rcu: Assign false instead of 0 for ->core_needs_qs
rcu: Update rcu_report_qs_rsp() comment
rcu: Stop treating in-kernel CPU-bound workloads as errors
rcu: Set rdp->gpwrap when CPU is idle
rcutorture: Correct no-expedite console messages
rcu: Document unique-name limitation for DEFINE_STATIC_SRCU()
rcu: Catch up rcu_report_qs_rdp() comment with reality
rcu: Export rcu_gp_is_normal()
Paul Gortmaker (1):
rcu: Make rcu/tiny_plugin.h explicitly non-modular
Yang Shi (1):
rcu: Remove rcu_user_hooks_switch
include/linux/compiler.h | 12 +- include/linux/irq.h | 6 +- include/linux/rcupdate.h | 2 - include/linux/srcu.h | 19 ++- kernel/irq/internals.h | 4 + kernel/rcu/rcutorture.c | 14 +- kernel/rcu/tiny_plugin.h | 15 +-- kernel/rcu/tree.c | 143 ++++++++++----------- kernel/rcu/tree.h | 42 ++++-- kernel/rcu/tree_plugin.h | 27 ++-- kernel/rcu/update.c | 1 + scripts/checkpatch.pl | 3 +- .../selftests/rcutorture/bin/parse-console.sh | 6 +- 13 files changed, 164 insertions(+), 130 deletions(-)
include/linux/compiler.h +8 -4
@@ -20,12 +20,14 @@# define __pmem __attribute__((noderef, address_space(5)))#ifdef CONFIG_SPARSE_RCU_POINTER # define __rcu __attribute__((noderef, address_space(4))) -#else +#else /* CONFIG_SPARSE_RCU_POINTER */ # define __rcu -#endif +#endif /* CONFIG_SPARSE_RCU_POINTER */ +# define __private __attribute__((noderef))extern void __chk_user_ptr (const volatile void __user *);extern void __chk_io_ptr (const volatile void __iomem *); -#else +# define ACCESS_PRIVATE (p, member) (*((typeof((p)->member) __force *) &(p)->member)) +#else /* __CHECKER__ */ # define __user# define __kernel# define __safe
@@ -44,7 +46,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);# define __percpu# define __rcu# define __pmem -#endif +# define __private +# define ACCESS_PRIVATE (p, member) ((p)->member) +#endif /* __CHECKER__ */ /* Indirect macros required for expanded argument pasting, eg. __LINE__. */ #define ___PASTE (a,b) a##b
include/linux/irq.h +4 -2
@@ -137,7 +137,7 @@ struct irq_domain;* @msi_desc: MSI descriptor */ struct irq_common_data { -unsigned int state_use_accessors; +unsigned int __private state_use_accessors;#ifdef CONFIG_NUMA unsigned int node;#endif
@@ -208,7 +208,7 @@ enum { IRQD_FORWARDED_TO_VCPU = (1 << 20), }; -#define __irqd_to_state (d) ((d)->common->state_use_accessors) +#define __irqd_to_state (d) ACCESS_PRIVATE((d)->common, state_use_accessors)static inline bool irqd_is_setaffinity_pending (struct irq_data *d) {
@@ -299,6 +299,8 @@ static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d)__irqd_to_state (d) &= ~IRQD_FORWARDED_TO_VCPU ; } +#undef __irqd_to_state +static inline irq_hw_number_t irqd_to_hwirq (struct irq_data *d) {return d->hwirq;
include/linux/rcupdate.h +0 -2
@@ -360,8 +360,6 @@ void rcu_user_exit(void);#else static inline void rcu_user_enter (void ) { }static inline void rcu_user_exit (void ) { } -static inline void rcu_user_hooks_switch (struct task_struct *prev, -struct task_struct *next) { }#endif /* CONFIG_NO_HZ_FULL */ #ifdef CONFIG_RCU_NOCB_CPU
include/linux/srcu.h +17 -2
@@ -99,8 +99,23 @@ void process_srcu(struct work_struct *work); }/* -* define and init a srcu struct at build time. -* dont't call init_srcu_struct() nor cleanup_srcu_struct() on it. +* Define and initialize a srcu struct at build time. +* Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it. +* +* Note that although DEFINE_STATIC_SRCU() hides the name from other +* files, the per-CPU variable rules nevertheless require that the +* chosen name be globally unique. These rules also prohibit use of +* DEFINE_STATIC_SRCU() within a function. If these rules are too +* restrictive, declare the srcu_struct manually. For example, in +* each file: +* +* static struct srcu_struct my_srcu; +* +* Then, before the first use of each my_srcu, manually initialize it: +* +* init_srcu_struct(&my_srcu); +* +* See include/linux/percpu-defs.h for the rules on per-CPU variables. */ #define __DEFINE_SRCU (name, is_static) \ static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
kernel/irq/internals.h +4 -0
@@ -160,6 +160,8 @@ irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags)__irq_put_desc_unlock (desc, flags, false); } +#define __irqd_to_state (d) ACCESS_PRIVATE((d)->common, state_use_accessors) +/* * Manipulation functions for irq_data.state */
@@ -188,6 +190,8 @@ static inline bool irqd_has_set(struct irq_data *d, unsigned int mask)return __irqd_to_state (d) & mask; } +#undef __irqd_to_state +static inline void kstat_incr_irqs_this_cpu (struct irq_desc *desc) {__this_cpu_inc (*desc->kstat_irqs);
kernel/rcu/rcutorture.c +8 -6
@@ -932,12 +932,14 @@ rcu_torture_writer(void *arg)int nsynctypes =0 ;VERBOSE_TOROUT_STRING ("rcu_torture_writer task started" ); -pr_alert ("%s" TORTURE_FLAG -" Grace periods expedited from boot/sysfs for %s,\n" , - torture_type, cur_ops->name); -pr_alert ("%s" TORTURE_FLAG -" Testing of dynamic grace-period expediting diabled.\n" , - torture_type); +if (!can_expedite) { +pr_alert ("%s" TORTURE_FLAG +" Grace periods expedited from boot/sysfs for %s,\n" , + torture_type, cur_ops->name); +pr_alert ("%s" TORTURE_FLAG +" Disabled dynamic grace-period expediting.\n" , + torture_type); + }/* Initialize synctype[] array. If none set, take default. */ if (!gp_cond1 && !gp_exp1 && !gp_normal1 && !gp_sync1)
kernel/rcu/tiny_plugin.h +2 -13
@@ -23,7 +23,7 @@*/ #include <linux/kthread.h> -#include <linux/module.h> +#include <linux/init.h> #include <linux/debugfs.h> #include <linux/seq_file.h>
@@ -122,18 +122,7 @@ static int __init rcutiny_trace_init(void)debugfs_remove_recursive (rcudir);return 1 ; } - -static void __exit rcutiny_trace_cleanup(void) -{ -debugfs_remove_recursive (rcudir); -} - -module_init (rcutiny_trace_init); -module_exit (rcutiny_trace_cleanup); - -MODULE_AUTHOR ("Paul E. McKenney" ); -MODULE_DESCRIPTION ("Read-Copy Update tracing for tiny implementation" ); -MODULE_LICENSE ("GPL" ); +device_initcall (rcutiny_trace_init);static void check_cpu_stall (struct rcu_ctrlblk *rcp) {
kernel/rcu/tree.c +70 -73
467 lines not on this page · raw message
kernel/rcu/tree.h +31 -11
75 lines not on this page · raw message
kernel/rcu/tree_plugin.h +13 -14
@@ -235,7 +235,7 @@ static void rcu_preempt_ctxt_queue(struct rcu_node *rnp, struct rcu_data *rdp) rnp->gp_tasks = &t->rcu_node_entry;if (!rnp->exp_tasks && (blkd_state &RCU_EXP_BLKD )) rnp->exp_tasks = &t->rcu_node_entry; -raw_spin_unlock (&rnp->lock);/* rrupts remain disabled. */ +raw_spin_unlock_rcu_node (rnp);/* interrupts remain disabled. */ /* * Report the quiescent state for the expedited GP. This expedited
@@ -489,7 +489,7 @@ void rcu_read_unlock_special(struct task_struct *t) !!rnp->gp_tasks);rcu_report_unblock_qs_rnp (rcu_state_p, rnp, flags); }else { -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags); }/* Unboost if we were boosted. */
@@ -518,14 +518,14 @@ static void rcu_print_detail_task_stall_rnp(struct rcu_node *rnp)raw_spin_lock_irqsave_rcu_node (rnp, flags);if (!rcu_preempt_blocked_readers_cgp (rnp)) { -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags);return ; } t =list_entry (rnp->gp_tasks->prev, struct task_struct, rcu_node_entry);list_for_each_entry_continue (t, &rnp->blkd_tasks, rcu_node_entry)sched_show_task (t); -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags); }/*
@@ -807,7 +807,6 @@ void exit_rcu(void)#else /* #ifdef CONFIG_PREEMPT_RCU */ static struct rcu_state *const rcu_state_p = &rcu_sched_state; -static struct rcu_data __percpu *const rcu_data_p = &rcu_sched_data;/* * Tell them what RCU they are running.
@@ -991,7 +990,7 @@ static int rcu_boost(struct rcu_node *rnp)* might exit their RCU read-side critical sections on their own. */ if (rnp->exp_tasks ==NULL && rnp->boost_tasks ==NULL ) { -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags);return 0 ; }
@@ -1028,7 +1027,7 @@ static int rcu_boost(struct rcu_node *rnp)*/ t = container_of(tb, struct task_struct, rcu_node_entry);rt_mutex_init_proxy_locked (&rnp->boost_mtx, t); -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags);/* Lock only for side effect: boosts task t's priority. */ rt_mutex_lock (&rnp->boost_mtx);rt_mutex_unlock (&rnp->boost_mtx);/* Then keep lockdep happy. */
@@ -1088,7 +1087,7 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)if (!rcu_preempt_blocked_readers_cgp (rnp) && rnp->exp_tasks ==NULL ) { rnp->n_balk_exp_gp_tasks++; -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags);return ; } if (rnp->exp_tasks != NULL ||
@@ -1098,13 +1097,13 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags) ULONG_CMP_GE(jiffies, rnp->boost_time))) {if (rnp->exp_tasks ==NULL ) rnp->boost_tasks = rnp->gp_tasks; -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags); t = rnp->boost_kthread_task;if (t)rcu_wake_cond (t, rnp->boost_kthread_status); } else {rcu_initiate_boost_trace (rnp); -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags); } }
@@ -1172,7 +1171,7 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,return PTR_ERR (t);raw_spin_lock_irqsave_rcu_node (rnp, flags); rnp->boost_kthread_task = t; -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags); sp.sched_priority = kthread_prio;sched_setscheduler_nocheck (t,SCHED_FIFO , &sp);wake_up_process (t);/* get to TASK_INTERRUPTIBLE quickly. */
@@ -1308,7 +1307,7 @@ static void rcu_prepare_kthreads(int cpu)static void rcu_initiate_boost (struct rcu_node *rnp,unsigned long flags) __releases(rnp->lock) { -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags); }static void invoke_rcu_callbacks_kthread (void )
@@ -1559,7 +1558,7 @@ static void rcu_prepare_for_idle(void) rnp = rdp->mynode;raw_spin_lock_rcu_node (rnp);/* irqs already disabled. */ needwake =rcu_accelerate_cbs (rsp, rnp, rdp); -raw_spin_unlock (&rnp->lock);/* irqs remain disabled. */ +raw_spin_unlock_rcu_node (rnp);/* irqs remain disabled. */ if (needwake)rcu_gp_kthread_wake (rsp); }
@@ -2064,7 +2063,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp)raw_spin_lock_irqsave_rcu_node (rnp, flags); needwake =rcu_start_future_gp (rnp, rdp, &c); -raw_spin_unlock_irqrestore (&rnp->lock, flags); +raw_spin_unlock_irqrestore_rcu_node (rnp, flags);if (needwake)rcu_gp_kthread_wake (rdp->rsp);
kernel/rcu/update.c +1 -0
@@ -128,6 +128,7 @@ bool rcu_gp_is_normal(void) {return READ_ONCE (rcu_normal); } +EXPORT_SYMBOL_GPL (rcu_gp_is_normal);static atomic_t rcu_expedited_nesting =ATOMIC_INIT (IS_ENABLED (CONFIG_RCU_EXPEDITE_BOOT ) ?1 :0 );
scripts/checkpatch.pl +2 -1
@@ -269,7 +269,8 @@ our $Sparse = qr{ __init_refok| __kprobes| __ref| - __rcu + __rcu| + __private }x; our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
tools/testing/selftests/rcutorture/bin/parse-console.sh +4 -2
@@ -33,7 +33,7 @@ if grep -Pq '\x00' < $file then print_warning Console output contains nul bytes, old qemu still running? fi -egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|Stall ended before state dump start' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags +egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags if test -s $1.diags then print_warning Assertion failure in $file $title
@@ -64,10 +64,12 @@ then then summary="$summary lockdep: $n_badness" fi - n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|Stall ended before state dump start' $1` + n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' $1` if test "$n_stalls" -ne 0 then summary="$summary Stalls: $n_stalls" fi print_warning Summary: $summary +else + rm $1.diags fi