aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 13:16:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 13:16:42 -0400
commit620e77533f29796df7aff861e79bd72e08554ebb (patch)
tree844afce2333549bc5b8d7dc87a4875b9216a0023 /include/linux
parent6977b4c7736e8809b7959c66875a16c0bbcf2152 (diff)
parentfa34da708cbe1e2d9a2ee7fc68ea8fccbf095d12 (diff)
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RCU changes from Ingo Molnar: 0. 'idle RCU': Adds RCU APIs that allow non-idle tasks to enter RCU idle mode and provides x86 code to make use of them, allowing RCU to treat user-mode execution as an extended quiescent state when the new RCU_USER_QS kernel configuration parameter is specified. (Work is in progress to port this to a few other architectures, but is not part of this series.) 1. A fix for a latent bug that has been in RCU ever since the addition of CPU stall warnings. This bug results in false-positive stall warnings, but thus far only on embedded systems with severely cut-down userspace configurations. 2. Further reductions in latency spikes for huge systems, along with additional boot-time adaptation to the actual hardware. This is a large change, as it moves RCU grace-period initialization and cleanup, along with quiescent-state forcing, from softirq to a kthread. However, it appears to be in quite good shape (famous last words). 3. Updates to documentation and rcutorture, the latter category including keeping statistics on CPU-hotplug latencies and fixing some initialization-time races. 4. CPU-hotplug fixes and improvements. 5. Idle-loop fixes that were omitted on an earlier submission. 6. Miscellaneous fixes and improvements In certain RCU configurations new kernel threads will show up (rcu_bh, rcu_sched), showing RCU processing overhead. * 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (90 commits) rcu: Apply micro-optimization and int/bool fixes to RCU's idle handling rcu: Userspace RCU extended QS selftest x86: Exit RCU extended QS on notify resume x86: Use the new schedule_user API on userspace preemption rcu: Exit RCU extended QS on user preemption rcu: Exit RCU extended QS on kernel preemption after irq/exception x86: Exception hooks for userspace RCU extended QS x86: Unspaghettize do_general_protection() x86: Syscall hooks for userspace RCU extended QS rcu: Switch task's syscall hooks on context switch rcu: Ignore userspace extended quiescent state by default rcu: Allow rcu_user_enter()/exit() to nest rcu: Settle config for userspace extended quiescent state rcu: Make RCU_FAST_NO_HZ handle adaptive ticks rcu: New rcu_user_enter_after_irq() and rcu_user_exit_after_irq() APIs rcu: New rcu_user_enter() and rcu_user_exit() APIs ia64: Add missing RCU idle APIs on idle loop xtensa: Add missing RCU idle APIs on idle loop score: Add missing RCU idle APIs on idle loop parisc: Add missing RCU idle APIs on idle loop ...
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--include/linux/kthread.h11
-rw-r--r--include/linux/rcupdate.h21
-rw-r--r--include/linux/sched.h8
-rw-r--r--include/linux/smpboot.h43
-rw-r--r--include/linux/tracepoint.h28
6 files changed, 98 insertions, 15 deletions
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index c5f856a040b9..5e4e6170f43a 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -430,6 +430,8 @@ enum
430 NR_SOFTIRQS 430 NR_SOFTIRQS
431}; 431};
432 432
433#define SOFTIRQ_STOP_IDLE_MASK (~(1 << RCU_SOFTIRQ))
434
433/* map softirq index to softirq name. update 'softirq_to_name' in 435/* map softirq index to softirq name. update 'softirq_to_name' in
434 * kernel/softirq.c when adding a new softirq. 436 * kernel/softirq.c when adding a new softirq.
435 */ 437 */
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index 22ccf9dee177..8d816646f766 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -14,6 +14,11 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
14 kthread_create_on_node(threadfn, data, -1, namefmt, ##arg) 14 kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)
15 15
16 16
17struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
18 void *data,
19 unsigned int cpu,
20 const char *namefmt);
21
17/** 22/**
18 * kthread_run - create and wake a thread. 23 * kthread_run - create and wake a thread.
19 * @threadfn: the function to run until signal_pending(current). 24 * @threadfn: the function to run until signal_pending(current).
@@ -34,9 +39,13 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
34 39
35void kthread_bind(struct task_struct *k, unsigned int cpu); 40void kthread_bind(struct task_struct *k, unsigned int cpu);
36int kthread_stop(struct task_struct *k); 41int kthread_stop(struct task_struct *k);
37int kthread_should_stop(void); 42bool kthread_should_stop(void);
43bool kthread_should_park(void);
38bool kthread_freezable_should_stop(bool *was_frozen); 44bool kthread_freezable_should_stop(bool *was_frozen);
39void *kthread_data(struct task_struct *k); 45void *kthread_data(struct task_struct *k);
46int kthread_park(struct task_struct *k);
47void kthread_unpark(struct task_struct *k);
48void kthread_parkme(void);
40 49
41int kthreadd(void *unused); 50int kthreadd(void *unused);
42extern struct task_struct *kthreadd_task; 51extern struct task_struct *kthreadd_task;
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 115ead2b5155..7c968e4f929e 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -191,6 +191,21 @@ extern void rcu_idle_enter(void);
191extern void rcu_idle_exit(void); 191extern void rcu_idle_exit(void);
192extern void rcu_irq_enter(void); 192extern void rcu_irq_enter(void);
193extern void rcu_irq_exit(void); 193extern void rcu_irq_exit(void);
194
195#ifdef CONFIG_RCU_USER_QS
196extern void rcu_user_enter(void);
197extern void rcu_user_exit(void);
198extern void rcu_user_enter_after_irq(void);
199extern void rcu_user_exit_after_irq(void);
200extern void rcu_user_hooks_switch(struct task_struct *prev,
201 struct task_struct *next);
202#else
203static inline void rcu_user_enter(void) { }
204static inline void rcu_user_exit(void) { }
205static inline void rcu_user_enter_after_irq(void) { }
206static inline void rcu_user_exit_after_irq(void) { }
207#endif /* CONFIG_RCU_USER_QS */
208
194extern void exit_rcu(void); 209extern void exit_rcu(void);
195 210
196/** 211/**
@@ -210,14 +225,12 @@ extern void exit_rcu(void);
210 * to nest RCU_NONIDLE() wrappers, but the nesting level is currently 225 * to nest RCU_NONIDLE() wrappers, but the nesting level is currently
211 * quite limited. If deeper nesting is required, it will be necessary 226 * quite limited. If deeper nesting is required, it will be necessary
212 * to adjust DYNTICK_TASK_NESTING_VALUE accordingly. 227 * to adjust DYNTICK_TASK_NESTING_VALUE accordingly.
213 *
214 * This macro may be used from process-level code only.
215 */ 228 */
216#define RCU_NONIDLE(a) \ 229#define RCU_NONIDLE(a) \
217 do { \ 230 do { \
218 rcu_idle_exit(); \ 231 rcu_irq_enter(); \
219 do { a; } while (0); \ 232 do { a; } while (0); \
220 rcu_idle_enter(); \ 233 rcu_irq_exit(); \
221 } while (0) 234 } while (0)
222 235
223/* 236/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 23bddac4bad8..335720a1fc33 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1885,6 +1885,14 @@ static inline void rcu_copy_process(struct task_struct *p)
1885 1885
1886#endif 1886#endif
1887 1887
1888static inline void rcu_switch(struct task_struct *prev,
1889 struct task_struct *next)
1890{
1891#ifdef CONFIG_RCU_USER_QS
1892 rcu_user_hooks_switch(prev, next);
1893#endif
1894}
1895
1888static inline void tsk_restore_flags(struct task_struct *task, 1896static inline void tsk_restore_flags(struct task_struct *task,
1889 unsigned long orig_flags, unsigned long flags) 1897 unsigned long orig_flags, unsigned long flags)
1890{ 1898{
diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h
new file mode 100644
index 000000000000..e0106d8581d3
--- /dev/null
+++ b/include/linux/smpboot.h
@@ -0,0 +1,43 @@
1#ifndef _LINUX_SMPBOOT_H
2#define _LINUX_SMPBOOT_H
3
4#include <linux/types.h>
5
6struct task_struct;
7/* Cookie handed to the thread_fn*/
8struct smpboot_thread_data;
9
10/**
11 * struct smp_hotplug_thread - CPU hotplug related thread descriptor
12 * @store: Pointer to per cpu storage for the task pointers
13 * @list: List head for core management
14 * @thread_should_run: Check whether the thread should run or not. Called with
15 * preemption disabled.
16 * @thread_fn: The associated thread function
17 * @setup: Optional setup function, called when the thread gets
18 * operational the first time
19 * @cleanup: Optional cleanup function, called when the thread
20 * should stop (module exit)
21 * @park: Optional park function, called when the thread is
22 * parked (cpu offline)
23 * @unpark: Optional unpark function, called when the thread is
24 * unparked (cpu online)
25 * @thread_comm: The base name of the thread
26 */
27struct smp_hotplug_thread {
28 struct task_struct __percpu **store;
29 struct list_head list;
30 int (*thread_should_run)(unsigned int cpu);
31 void (*thread_fn)(unsigned int cpu);
32 void (*setup)(unsigned int cpu);
33 void (*cleanup)(unsigned int cpu, bool online);
34 void (*park)(unsigned int cpu);
35 void (*unpark)(unsigned int cpu);
36 const char *thread_comm;
37};
38
39int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread);
40void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread);
41int smpboot_thread_schedule(void);
42
43#endif
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 802de56c41e8..2f322c38bd4d 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -136,6 +136,22 @@ static inline void tracepoint_synchronize_unregister(void)
136 postrcu; \ 136 postrcu; \
137 } while (0) 137 } while (0)
138 138
139#ifndef MODULE
140#define __DECLARE_TRACE_RCU(name, proto, args, cond, data_proto, data_args) \
141 static inline void trace_##name##_rcuidle(proto) \
142 { \
143 if (static_key_false(&__tracepoint_##name.key)) \
144 __DO_TRACE(&__tracepoint_##name, \
145 TP_PROTO(data_proto), \
146 TP_ARGS(data_args), \
147 TP_CONDITION(cond), \
148 rcu_idle_exit(), \
149 rcu_idle_enter()); \
150 }
151#else
152#define __DECLARE_TRACE_RCU(name, proto, args, cond, data_proto, data_args)
153#endif
154
139/* 155/*
140 * Make sure the alignment of the structure in the __tracepoints section will 156 * Make sure the alignment of the structure in the __tracepoints section will
141 * not add unwanted padding between the beginning of the section and the 157 * not add unwanted padding between the beginning of the section and the
@@ -151,16 +167,8 @@ static inline void tracepoint_synchronize_unregister(void)
151 TP_ARGS(data_args), \ 167 TP_ARGS(data_args), \
152 TP_CONDITION(cond),,); \ 168 TP_CONDITION(cond),,); \
153 } \ 169 } \
154 static inline void trace_##name##_rcuidle(proto) \ 170 __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args), \
155 { \ 171 PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \
156 if (static_key_false(&__tracepoint_##name.key)) \
157 __DO_TRACE(&__tracepoint_##name, \
158 TP_PROTO(data_proto), \
159 TP_ARGS(data_args), \
160 TP_CONDITION(cond), \
161 rcu_idle_exit(), \
162 rcu_idle_enter()); \
163 } \
164 static inline int \ 172 static inline int \
165 register_trace_##name(void (*probe)(data_proto), void *data) \ 173 register_trace_##name(void (*probe)(data_proto), void *data) \
166 { \ 174 { \