Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rcu: Separate the RCU synchronization types and APIs into <linux/rcupdate_wait.h>

So rcupdate.h is a pretty complex header, in particular it includes
<linux/completion.h> which includes <linux/wait.h> - creating a
dependency that includes <linux/wait.h> in <linux/sched.h>,
which prevents the isolation of <linux/sched.h> from the derived
<linux/wait.h> header.

Solve part of the problem by decoupling rcupdate.h from completions:
this can be done by separating out the rcu_synchronize types and APIs,
and updating their usage sites.

Since this is a mostly RCU-internal types this will not just simplify
<linux/sched.h>'s dependencies, but will make all the hundreds of
.c files that include rcupdate.h but not completions or wait.h build
faster.

( For rcutiny this means that two dependent APIs have to be uninlined,
but that shouldn't be much of a problem as they are rare variants. )

Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+71 -52
+1
fs/autofs4/autofs_i.h
··· 14 14 #include <linux/mutex.h> 15 15 #include <linux/spinlock.h> 16 16 #include <linux/list.h> 17 + #include <linux/completion.h> 17 18 18 19 /* This is the range of ioctl() numbers we claim as ours */ 19 20 #define AUTOFS_IOC_FIRST AUTOFS_IOC_READY
+1
include/linux/dcache.h
··· 11 11 #include <linux/rcupdate.h> 12 12 #include <linux/lockref.h> 13 13 #include <linux/stringhash.h> 14 + #include <linux/wait.h> 14 15 15 16 struct path; 16 17 struct vfsmount;
-40
include/linux/rcupdate.h
··· 40 40 #include <linux/cpumask.h> 41 41 #include <linux/seqlock.h> 42 42 #include <linux/lockdep.h> 43 - #include <linux/completion.h> 44 43 #include <linux/debugobjects.h> 45 44 #include <linux/bug.h> 46 45 #include <linux/compiler.h> ··· 224 225 rcu_callback_t func); 225 226 226 227 void synchronize_sched(void); 227 - 228 - /* 229 - * Structure allowing asynchronous waiting on RCU. 230 - */ 231 - struct rcu_synchronize { 232 - struct rcu_head head; 233 - struct completion completion; 234 - }; 235 - void wakeme_after_rcu(struct rcu_head *head); 236 - 237 - void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array, 238 - struct rcu_synchronize *rs_array); 239 - 240 - #define _wait_rcu_gp(checktiny, ...) \ 241 - do { \ 242 - call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \ 243 - struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)]; \ 244 - __wait_rcu_gp(checktiny, ARRAY_SIZE(__crcu_array), \ 245 - __crcu_array, __rs_array); \ 246 - } while (0) 247 - 248 - #define wait_rcu_gp(...) _wait_rcu_gp(false, __VA_ARGS__) 249 - 250 - /** 251 - * synchronize_rcu_mult - Wait concurrently for multiple grace periods 252 - * @...: List of call_rcu() functions for the flavors to wait on. 253 - * 254 - * This macro waits concurrently for multiple flavors of RCU grace periods. 255 - * For example, synchronize_rcu_mult(call_rcu, call_rcu_bh) would wait 256 - * on concurrent RCU and RCU-bh grace periods. Waiting on a give SRCU 257 - * domain requires you to write a wrapper function for that SRCU domain's 258 - * call_srcu() function, supplying the corresponding srcu_struct. 259 - * 260 - * If Tiny RCU, tell _wait_rcu_gp() not to bother waiting for RCU 261 - * or RCU-bh, given that anywhere synchronize_rcu_mult() can be called 262 - * is automatically a grace period. 263 - */ 264 - #define synchronize_rcu_mult(...) \ 265 - _wait_rcu_gp(IS_ENABLED(CONFIG_TINY_RCU), __VA_ARGS__) 266 228 267 229 /** 268 230 * call_rcu_tasks() - Queue an RCU for invocation task-based grace period
+50
include/linux/rcupdate_wait.h
··· 1 + #ifndef _LINUX_SCHED_RCUPDATE_WAIT_H 2 + #define _LINUX_SCHED_RCUPDATE_WAIT_H 3 + 4 + /* 5 + * RCU synchronization types and methods: 6 + */ 7 + 8 + #include <linux/rcupdate.h> 9 + #include <linux/completion.h> 10 + 11 + /* 12 + * Structure allowing asynchronous waiting on RCU. 13 + */ 14 + struct rcu_synchronize { 15 + struct rcu_head head; 16 + struct completion completion; 17 + }; 18 + void wakeme_after_rcu(struct rcu_head *head); 19 + 20 + void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array, 21 + struct rcu_synchronize *rs_array); 22 + 23 + #define _wait_rcu_gp(checktiny, ...) \ 24 + do { \ 25 + call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \ 26 + struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)]; \ 27 + __wait_rcu_gp(checktiny, ARRAY_SIZE(__crcu_array), \ 28 + __crcu_array, __rs_array); \ 29 + } while (0) 30 + 31 + #define wait_rcu_gp(...) _wait_rcu_gp(false, __VA_ARGS__) 32 + 33 + /** 34 + * synchronize_rcu_mult - Wait concurrently for multiple grace periods 35 + * @...: List of call_rcu() functions for the flavors to wait on. 36 + * 37 + * This macro waits concurrently for multiple flavors of RCU grace periods. 38 + * For example, synchronize_rcu_mult(call_rcu, call_rcu_bh) would wait 39 + * on concurrent RCU and RCU-bh grace periods. Waiting on a give SRCU 40 + * domain requires you to write a wrapper function for that SRCU domain's 41 + * call_srcu() function, supplying the corresponding srcu_struct. 42 + * 43 + * If Tiny RCU, tell _wait_rcu_gp() not to bother waiting for RCU 44 + * or RCU-bh, given that anywhere synchronize_rcu_mult() can be called 45 + * is automatically a grace period. 46 + */ 47 + #define synchronize_rcu_mult(...) \ 48 + _wait_rcu_gp(IS_ENABLED(CONFIG_TINY_RCU), __VA_ARGS__) 49 + 50 + #endif /* _LINUX_SCHED_RCUPDATE_WAIT_H */
+2 -9
include/linux/rcutiny.h
··· 53 53 might_sleep(); 54 54 } 55 55 56 - static inline void rcu_barrier_bh(void) 57 - { 58 - wait_rcu_gp(call_rcu_bh); 59 - } 60 - 61 - static inline void rcu_barrier_sched(void) 62 - { 63 - wait_rcu_gp(call_rcu_sched); 64 - } 56 + extern void rcu_barrier_bh(void); 57 + extern void rcu_barrier_sched(void); 65 58 66 59 static inline void synchronize_rcu_expedited(void) 67 60 {
+1 -1
kernel/rcu/srcu.c
··· 30 30 #include <linux/mutex.h> 31 31 #include <linux/percpu.h> 32 32 #include <linux/preempt.h> 33 - #include <linux/rcupdate.h> 33 + #include <linux/rcupdate_wait.h> 34 34 #include <linux/sched.h> 35 35 #include <linux/smp.h> 36 36 #include <linux/delay.h>
+13 -1
kernel/rcu/tiny.c
··· 25 25 #include <linux/completion.h> 26 26 #include <linux/interrupt.h> 27 27 #include <linux/notifier.h> 28 - #include <linux/rcupdate.h> 28 + #include <linux/rcupdate_wait.h> 29 29 #include <linux/kernel.h> 30 30 #include <linux/export.h> 31 31 #include <linux/mutex.h> ··· 46 46 struct rcu_ctrlblk *rcp); 47 47 48 48 #include "tiny_plugin.h" 49 + 50 + void rcu_barrier_bh(void) 51 + { 52 + wait_rcu_gp(call_rcu_bh); 53 + } 54 + EXPORT_SYMBOL(rcu_barrier_bh); 55 + 56 + void rcu_barrier_sched(void) 57 + { 58 + wait_rcu_gp(call_rcu_sched); 59 + } 60 + EXPORT_SYMBOL(rcu_barrier_sched); 49 61 50 62 #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) 51 63
+1 -1
kernel/rcu/tree.c
··· 32 32 #include <linux/init.h> 33 33 #include <linux/spinlock.h> 34 34 #include <linux/smp.h> 35 - #include <linux/rcupdate.h> 35 + #include <linux/rcupdate_wait.h> 36 36 #include <linux/interrupt.h> 37 37 #include <linux/sched.h> 38 38 #include <linux/nmi.h>
+1
kernel/rcu/update.c
··· 49 49 #include <linux/moduleparam.h> 50 50 #include <linux/kthread.h> 51 51 #include <linux/tick.h> 52 + #include <linux/rcupdate_wait.h> 52 53 53 54 #define CREATE_TRACE_POINTS 54 55
+1
kernel/sched/core.c
··· 10 10 #include <linux/delayacct.h> 11 11 #include <linux/init_task.h> 12 12 #include <linux/context_tracking.h> 13 + #include <linux/rcupdate_wait.h> 13 14 14 15 #include <linux/blkdev.h> 15 16 #include <linux/kprobes.h>