Add kernel-offset file and make rcu_read_[un]lock() included
Subsystems (21)
cover Add kernel-offset file and make rcu_read_[un]lock() included
__rcu_read_[un]lock() are so simple functions and called so frequent, it is not good that a function call overhead is required when use them. It would be better if we declare them inline and let the compiler do the choice.
We add kernel-offset.c for TASK_RCU_OFFSET, which enable we declare rcu_read_[un]lock() as inline function.
Adding kernel-offset.c does not have any effect for the result compiled kernel, it just adds a small and fast step in the kbuid stage.
Lai Jiangshan (5):
task_rcu_struct
kbuild_dedumplicated
add_kernel_offset
access task's task_rcu_struct without include sched.h rcu inline
Kbuild | 99 ++++++++++++++++--------------- include/linux/init_task.h | 25 +-------- include/linux/rcupdate.h | 144 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/sched.h | 39 +------------ kernel/kernel-offsets.c | 17 +++++ kernel/rcutiny_plugin.h | 58 ++++-------------- kernel/rcutree_plugin.h | 69 ++++++---------------- 7 files changed, 243 insertions(+), 208 deletions(-) create mode 100644 kernel/kernel-offsets.c
Signature · 1 line
1.7.4
RFC PATCH 1/5 Move task's RCU code to rcupdate.h
Add struct task_rcu_struct to make code clearer and move them to rcupdate.h which help us for code maitainment.
task_rcu_struct(), current_task_rcu_struct(), task_of_task_rcu() and rcu_copy_process() have to be implemented as MACRO,
it is because we cann't access task's task_rcu_strut without linux/sched.h included. These MACROs can only
be used with linux/sched.h included or used in some other MACROs which make this requirement propagate.
--- include/linux/init_task.h | 25 +---------------- include/linux/rcupdate.h | 68 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/sched.h | 39 +------------------------- kernel/rcutiny_plugin.h | 26 +++++++++-------- kernel/rcutree_plugin.h | 37 ++++++++++++------------ 5 files changed, 102 insertions(+), 93 deletions(-)
include/linux/init_task.h +1 -24
@@ -90,29 +90,6 @@ extern struct group_info init_groups;*/ # define CAP_INIT_BSET CAP_FULL_SET -#ifdef CONFIG_RCU_BOOST -#define INIT_TASK_RCU_BOOST () \ - .rcu_boost_mutex = NULL, -#else -#define INIT_TASK_RCU_BOOST () -#endif -#ifdef CONFIG_TREE_PREEMPT_RCU -#define INIT_TASK_RCU_TREE_PREEMPT () \ - .rcu_blocked_node = NULL, -#else -#define INIT_TASK_RCU_TREE_PREEMPT (tsk) -#endif -#ifdef CONFIG_PREEMPT_RCU -#define INIT_TASK_RCU_PREEMPT (tsk) \ - .rcu_read_lock_nesting = 0, \ - .rcu_read_unlock_special = 0, \ - .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry), \ - INIT_TASK_RCU_TREE_PREEMPT() \ - INIT_TASK_RCU_BOOST() -#else -#define INIT_TASK_RCU_PREEMPT (tsk) -#endif -extern struct cred init_cred;#ifdef CONFIG_PERF_EVENTS
@@ -191,7 +168,7 @@ extern struct cred init_cred;INIT_LOCKDEP \ INIT_FTRACE_GRAPH \ INIT_TRACE_RECURSION \ - INIT_TASK_RCU_PREEMPT(tsk) \ + .task_rcu_struct = INIT_TASK_RCU_STRUCT(tsk.task_rcu_struct), \ }
include/linux/rcupdate.h +67 -1
80 lines not on this page · raw message
include/linux/sched.h +1 -38
@@ -1232,17 +1232,7 @@ struct task_struct {unsigned int policy;cpumask_t cpus_allowed; -#ifdef CONFIG_PREEMPT_RCU -int rcu_read_lock_nesting; -char rcu_read_unlock_special; -struct list_head rcu_node_entry; -#endif /* #ifdef CONFIG_PREEMPT_RCU */ -#ifdef CONFIG_TREE_PREEMPT_RCU -struct rcu_node *rcu_blocked_node; -#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -#ifdef CONFIG_RCU_BOOST -struct rt_mutex *rcu_boost_mutex; -#endif /* #ifdef CONFIG_RCU_BOOST */ +struct task_rcu_struct task_rcu_struct;#if defined(CONFIG_SCHEDSTATS ) || defined(CONFIG_TASK_DELAY_ACCT )struct sched_info sched_info;
@@ -1772,33 +1762,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *#define tsk_used_math (p) ((p)->flags & PF_USED_MATH)#define used_math () tsk_used_math(current) -#ifdef CONFIG_PREEMPT_RCU - -#define RCU_READ_UNLOCK_BLOCKED (1 << 0)/* blocked while in RCU read-side. */ -#define RCU_READ_UNLOCK_BOOSTED (1 << 1)/* boosted while in RCU read-side. */ -#define RCU_READ_UNLOCK_NEED_QS (1 << 2)/* RCU core needs CPU response. */ - -static inline void rcu_copy_process (struct task_struct *p) -{ - p->rcu_read_lock_nesting =0 ; - p->rcu_read_unlock_special =0 ; -#ifdef CONFIG_TREE_PREEMPT_RCU - p->rcu_blocked_node =NULL ; -#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -#ifdef CONFIG_RCU_BOOST - p->rcu_boost_mutex =NULL ; -#endif /* #ifdef CONFIG_RCU_BOOST */ -INIT_LIST_HEAD (&p->rcu_node_entry); -} - -#else - -static inline void rcu_copy_process (struct task_struct *p) -{ -} - -#endif -#ifdef CONFIG_SMP extern int set_cpus_allowed_ptr (struct task_struct *p,const struct cpumask *new_mask);
kernel/rcutiny_plugin.h +14 -12
@@ -150,7 +150,7 @@ static int rcu_cpu_blocking_cur_gp(void)*/ static int rcu_preempt_running_reader (void ) { -return current->rcu_read_lock_nesting; +return current_task_rcu_struct ()->rcu_read_lock_nesting; }/*
@@ -192,7 +192,7 @@ static int rcu_preempt_gp_in_progress(void)* Advance a ->blkd_tasks-list pointer to the next entry, instead * returning NULL if at the end of the list. */ -static struct list_head *rcu_next_node_entry (struct task_struct *t) +static struct list_head *rcu_next_node_entry (struct task_rcu_struct *t) {struct list_head *np;
@@ -255,7 +255,7 @@ static int rcu_boost(void) {unsigned long flags;struct rt_mutex mtx; -struct task_struct *t; +struct task_rcu_struct *t;struct list_head *tb; if (rcu_preempt_ctrlblk.boost_tasks == NULL &&
@@ -298,8 +298,8 @@ static int rcu_boost(void)* simply acquiring this artificial rt_mutex will boost task * t's priority. (Thanks to tglx for suggesting this approach!) */ - t = container_of(tb, struct task_struct, rcu_node_entry); -rt_mutex_init_proxy_locked (&mtx, t); + t = container_of(tb, struct task_rcu_struct, rcu_node_entry); +rt_mutex_init_proxy_locked (&mtx,task_of_task_rcu (t)); t->rcu_boost_mutex = &mtx; t->rcu_read_unlock_special |=RCU_READ_UNLOCK_BOOSTED ;raw_local_irq_restore (flags);
@@ -402,9 +402,11 @@ static void rcu_preempt_boost_start_gp(void)*/ static void rcu_preempt_cpu_qs (void ) { +struct task_rcu_struct *t =current_task_rcu_struct (); +/* Record both CPU and task as having responded to current GP. */ rcu_preempt_ctrlblk.gpcpu = rcu_preempt_ctrlblk.gpnum; - current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; + t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ;/* If there is no GP then there is nothing more to do. */ if (!rcu_preempt_gp_in_progress ())
@@ -473,7 +475,7 @@ static void rcu_preempt_start_gp(void)*/ void rcu_preempt_note_context_switch (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();unsigned long flags;local_irq_save (flags);/* must exclude scheduler_tick(). */
@@ -518,7 +520,7 @@ void rcu_preempt_note_context_switch(void)*/ void __rcu_read_lock (void ) { - current->rcu_read_lock_nesting++; +current_task_rcu_struct ()->rcu_read_lock_nesting++;barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ }EXPORT_SYMBOL_GPL (__rcu_read_lock);
@@ -528,7 +530,7 @@ EXPORT_SYMBOL_GPL(__rcu_read_lock);* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +static void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -617,7 +619,7 @@ static void rcu_read_unlock_special(struct task_struct *t)*/ void __rcu_read_unlock (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ --t->rcu_read_lock_nesting;
@@ -640,7 +642,7 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);*/ static void rcu_preempt_check_callbacks (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct (); if (rcu_preempt_gp_in_progress() && (!rcu_preempt_running_reader() ||
@@ -841,7 +843,7 @@ int rcu_preempt_needs_cpu(void)*/ void exit_rcu (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();if (t->rcu_read_lock_nesting ==0 )return ;
kernel/rcutree_plugin.h +19 -18
@@ -120,11 +120,12 @@ EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);static void rcu_preempt_qs (int cpu) {struct rcu_data *rdp = &per_cpu (rcu_preempt_data, cpu); +struct task_rcu_struct *t =current_task_rcu_struct (); rdp->passed_quiesc_completed = rdp->gpnum -1 ;barrier (); rdp->passed_quiesc =1 ; - current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; + t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; }/*
@@ -142,7 +143,7 @@ static void rcu_preempt_qs(int cpu)*/ static void rcu_preempt_note_context_switch (int cpu) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();unsigned long flags;struct rcu_data *rdp;struct rcu_node *rnp;
@@ -213,7 +214,7 @@ static void rcu_preempt_note_context_switch(int cpu)*/ void __rcu_read_lock (void ) { - current->rcu_read_lock_nesting++; +current_task_rcu_struct ()->rcu_read_lock_nesting++;barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ }EXPORT_SYMBOL_GPL (__rcu_read_lock);
@@ -268,7 +269,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)* Advance a ->blkd_tasks-list pointer to the next entry, instead * returning NULL if at the end of the list. */ -static struct list_head *rcu_next_node_entry (struct task_struct *t, +static struct list_head *rcu_next_node_entry (struct task_rcu_struct *t,struct rcu_node *rnp) {struct list_head *np;
@@ -284,7 +285,7 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +static void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -384,7 +385,7 @@ static void rcu_read_unlock_special(struct task_struct *t)*/ void __rcu_read_unlock (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ --t->rcu_read_lock_nesting;
@@ -407,15 +408,15 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);static void rcu_print_detail_task_stall_rnp (struct rcu_node *rnp) {unsigned long flags; -struct task_struct *t; +struct task_rcu_struct *t;if (!rcu_preempt_blocked_readers_cgp (rnp))return ;raw_spin_lock_irqsave (&rnp->lock, flags); t =list_entry (rnp->gp_tasks, - struct task_struct, rcu_node_entry); + struct task_rcu_struct, rcu_node_entry);list_for_each_entry_continue (t, &rnp->blkd_tasks, rcu_node_entry) -sched_show_task (t); +sched_show_task (task_of_task_rcu (t));raw_spin_unlock_irqrestore (&rnp->lock, flags); }
@@ -446,14 +447,14 @@ static void rcu_print_detail_task_stall(struct rcu_state *rsp)*/ static void rcu_print_task_stall (struct rcu_node *rnp) { -struct task_struct *t; +struct task_rcu_struct *t;if (!rcu_preempt_blocked_readers_cgp (rnp))return ; t =list_entry (rnp->gp_tasks, - struct task_struct, rcu_node_entry); + struct task_rcu_struct, rcu_node_entry);list_for_each_entry_continue (t, &rnp->blkd_tasks, rcu_node_entry) -printk (" P%d" , t->pid); +printk (" P%d" ,task_of_task_rcu (t)->pid); }/*
@@ -508,7 +509,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,struct list_head *lp_root;int retval =0 ;struct rcu_node *rnp_root =rcu_get_root (rsp); -struct task_struct *t; +struct task_rcu_struct *t;if (rnp == rnp_root) {WARN_ONCE (1 ,"Last CPU thought to be offlined?" );
@@ -581,7 +582,7 @@ static void rcu_preempt_offline_cpu(int cpu)*/ static void rcu_preempt_check_callbacks (int cpu) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();if (t->rcu_read_lock_nesting ==0 ) {rcu_preempt_qs (cpu);
@@ -851,7 +852,7 @@ static void __init __rcu_init_preempt(void)*/ void exit_rcu (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();if (t->rcu_read_lock_nesting ==0 )return ;
@@ -1110,7 +1111,7 @@ static int rcu_boost(struct rcu_node *rnp) {unsigned long flags;struct rt_mutex mtx; -struct task_struct *t; +struct task_rcu_struct *t;struct list_head *tb;if (rnp->exp_tasks ==NULL && rnp->boost_tasks ==NULL )
@@ -1158,8 +1159,8 @@ static int rcu_boost(struct rcu_node *rnp)* and task t's exiting its outermost RCU read-side critical * section. */ - t = container_of(tb, struct task_struct, rcu_node_entry); -rt_mutex_init_proxy_locked (&mtx, t); + t = container_of(tb, struct task_rcu_struct, rcu_node_entry); +rt_mutex_init_proxy_locked (&mtx,task_of_task_rcu (t)); t->rcu_boost_mutex = &mtx; t->rcu_read_unlock_special |=RCU_READ_UNLOCK_BOOSTED ;raw_spin_unlock_irqrestore (&rnp->lock, flags);
Signature · 1 line
1.7.4
Peter Zijlstra
maintainerRe: [RFC PATCH 1/5] Move task's RCU code to rcupdate.h
include/linux/rcupdate.h static inline void __rcu_read_unlock_bh(void) · line 93
Quoted 4 lines · Lai Jiangshan
include/linux/rcupdate.h +4
-0+struct task_rcu_struct { +#ifdef CONFIG_PREEMPT_RCU +int rcu_read_lock_nesting; +char rcu_read_unlock_special;
Is there a good reason that's a char? It'll leave a 3 byte hole in this location.
Quoted 9 lines
include/linux/rcupdate.h +9
-0+struct list_head rcu_node_entry; +#ifdef CONFIG_TREE_PREEMPT_RCU +struct rcu_node *rcu_blocked_node; +#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ +#ifdef CONFIG_RCU_BOOST +struct rt_mutex *rcu_boost_mutex; +#endif /* #ifdef CONFIG_RCU_BOOST */ +#endif /* #ifdef CONFIG_PREEMPT_RCU */ +};
Re: [RFC PATCH 1/5] Move task's RCU code to rcupdate.h
Quoted 8 lines · Peter Zijlstra
include/linux/rcupdate.h static inline void __rcu_read_unlock_bh(void) · line 93
Quoted 4 lines · Lai Jiangshan
include/linux/rcupdate.h +4
-0+struct task_rcu_struct { +#ifdef CONFIG_PREEMPT_RCU +int rcu_read_lock_nesting; +char rcu_read_unlock_special;Is there a good reason that's a char? It'll leave a 3 byte hole in this location.
No good reason. Lai just copied the existing char from the task struct into his task_rcu_struct, so not his fault. ;-)
Thanx, Paul
Quoted 9 lines
Quoted 9 lines
include/linux/rcupdate.h +9
-0+struct list_head rcu_node_entry; +#ifdef CONFIG_TREE_PREEMPT_RCU +struct rcu_node *rcu_blocked_node; +#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ +#ifdef CONFIG_RCU_BOOST +struct rt_mutex *rcu_boost_mutex; +#endif /* #ifdef CONFIG_RCU_BOOST */ +#endif /* #ifdef CONFIG_PREEMPT_RCU */ +};
RFC PATCH 2/5 kbuild: dedumplicated the generating code
In reply to Lai Jiangshancmd_bounds and cmd_offsets are almost the same, dedumplicated them. The definition of sed-y is also moved up the top of the file.
--- Kbuild | 60 +++++++++++++++++++++--------------------------------------- 1 files changed, 21 insertions(+), 39 deletions(-)
Kbuild +21 -39
@@ -5,19 +5,19 @@ # 2) Generate asm-offsets.h (may need bounds.h) # 3) Check for missing system calls -##### -# 1) Generate bounds.h - -bounds-file := include/generated/bounds.h - -always := $(bounds-file) -targets := $(bounds-file) kernel/bounds.s +# Default sed regexp - multiline due to syntax constraints +define sed-y + "/^->/{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:->::; p;}" +endef -quiet_cmd_bounds = GEN $@ -define cmd_bounds +quiet_cmd_kbuild_gen = GEN $@ +define cmd_kbuild_gen (set -e; \ - echo "#ifndef __LINUX_BOUNDS_H__"; \ - echo "#define __LINUX_BOUNDS_H__"; \ + echo "#ifndef __$$(echo $@ | tr -- '-./a-z' '___A-Z')__"; \ + echo "#define __$$(echo $@ | tr -- '-./a-z' '___A-Z')__"; \ echo "/*"; \ echo " * DO NOT MODIFY."; \ echo " *"; \
@@ -30,6 +30,14 @@ define cmd_bounds echo "#endif" ) > $@ endef +##### +# 1) Generate bounds.h + +bounds-file := include/generated/bounds.h + +always := $(bounds-file) +targets := $(bounds-file) kernel/bounds.s + # We use internal kbuild rules to avoid the "is up to date" message from make kernel/bounds.s: kernel/bounds.c FORCE $(Q)mkdir -p $(dir $@)
@@ -37,7 +45,7 @@ kernel/bounds.s: kernel/bounds.c FORCE $(obj)/$(bounds-file): kernel/bounds.s Kbuild $(Q)mkdir -p $(dir $@) - $(call cmd,bounds) + $(call cmd,kbuild_gen) ##### # 2) Generate asm-offsets.h
@@ -49,32 +57,6 @@ always += $(offsets-file) targets += $(offsets-file) targets += arch/$(SRCARCH)/kernel/asm-offsets.s - -# Default sed regexp - multiline due to syntax constraints -define sed-y - "/^->/{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}" -endef - -quiet_cmd_offsets = GEN $@ -define cmd_offsets - (set -e; \ - echo "#ifndef __ASM_OFFSETS_H__"; \ - echo "#define __ASM_OFFSETS_H__"; \ - echo "/*"; \ - echo " * DO NOT MODIFY."; \ - echo " *"; \ - echo " * This file was generated by Kbuild"; \ - echo " *"; \ - echo " */"; \ - echo ""; \ - sed -ne $(sed-y) $<; \ - echo ""; \ - echo "#endif" ) > $@ -endef - # We use internal kbuild rules to avoid the "is up to date" message from make arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \ $(obj)/$(bounds-file) FORCE
@@ -82,7 +64,7 @@ arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \ $(call if_changed_dep,cc_s_c) $(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild - $(call cmd,offsets) + $(call cmd,kbuild_gen) ##### # 3) Check for missing system calls
Signature · 1 line
1.7.4
Re: [RFC PATCH 2/5] kbuild: dedumplicated the generating code
Quoted 21 lines
Quoted 1 line
Quoted 1 line · Lai Jiangshan
cmd_boundsandcmd_offsetsare almost the same, dedumplicated them. The definition of sed-y is also moved up the top of the file.Signed-off-by Lai Jiangshan <[email protected]>--- Kbuild | 60 +++++++++++++++++++++--------------------------------------- 1 files changed, 21 insertions(+), 39 deletions(-)Kbuild +0
-2@@ -5,19 +5,19 @@ # 2) Generate asm-offsets.h (may need bounds.h) # 3) Check for missing system calls -##### -# 1) Generate bounds.h
Kbuild line 12
Quoted 10 lines
Kbuild +5
-5- -bounds-file := include/generated/bounds.h - -always := $(bounds-file) -targets := $(bounds-file) kernel/bounds.s +# Default sed regexp - multiline due to syntax constraints +define sed-y + "/^->/{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
Having to touch (move) this code would imo be a very good opportunity to simplify it again: The replacement string is the same for those two lines, and the second match expression is a super set of the first one. That is, the first one can be dropped, and hence the whole thing changed back to its pre-3234282f33b29d349bcada40204fc7c8fda7fe72 form.
Jan
Quoted 87 lines
Kbuild +14
-4+ s:->::; p;}" +endef -quiet_cmd_bounds = GEN $@ -define cmd_bounds +quiet_cmd_kbuild_gen = GEN $@ +define cmd_kbuild_gen (set -e; \ - echo "#ifndef __LINUX_BOUNDS_H__"; \ - echo "#define __LINUX_BOUNDS_H__"; \ + echo "#ifndef __$$(echo $@ | tr -- '-./a-z' '___A-Z')__"; \ + echo "#define __$$(echo $@ | tr -- '-./a-z' '___A-Z')__"; \ echo "/*"; \ echo " * DO NOT MODIFY."; \ echo " *"; \@@ -30,6 +30,14 @@ define cmd_bounds echo "#endif" ) > $@ endef +##### +# 1) Generate bounds.h + +bounds-file := include/generated/bounds.h + +always := $(bounds-file) +targets := $(bounds-file) kernel/bounds.s + # We use internal kbuild rules to avoid the "is up to date" message frommake
kernel/bounds.s:kernel/bounds.cFORCEKbuild +1
-27$(Q)mkdir -p $(dir $@)@@ -37,7 +45,7 @@ kernel/bounds.s: kernel/bounds.c FORCE $(obj)/$(bounds-file): kernel/bounds.s Kbuild $(Q)mkdir -p $(dir $@) - $(call cmd,bounds) + $(call cmd,kbuild_gen) ##### # 2) Generate asm-offsets.h@@ -49,32 +57,6 @@ always += $(offsets-file) targets += $(offsets-file) targets += arch/$(SRCARCH)/kernel/asm-offsets.s - -# Default sed regexp - multiline due to syntax constraints -define sed-y - "/^->/{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}" -endef - -quiet_cmd_offsets = GEN $@ -define cmd_offsets - (set -e; \ - echo "#ifndef __ASM_OFFSETS_H__"; \ - echo "#define __ASM_OFFSETS_H__"; \ - echo "/*"; \ - echo " * DO NOT MODIFY."; \ - echo " *"; \ - echo " * This file was generated by Kbuild"; \ - echo " *"; \ - echo " */"; \ - echo ""; \ - sed -ne $(sed-y) $<; \ - echo ""; \ - echo "#endif" ) > $@ -endef - # We use internal kbuild rules to avoid the "is up to date" message frommake
arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c\ $(obj)/$(bounds-file) FORCEKbuild +1
-1@@ -82,7 +64,7 @@ arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \ $(call if_changed_dep,cc_s_c) $(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild - $(call cmd,offsets) + $(call cmd,kbuild_gen) ###### 3) Check for missing system calls
Signature · 1 line
1.7.4
David Howells
maintainerRe: [RFC PATCH 2/5] kbuild: dedumplicated the generating code
In reply to Lai Jiangshan'dedumplicated'? Did you mean 'deduplicated'?
David
RFC PATCH 3/5 kbuild: add kernel-offset file
In reply to Lai JiangshanAdd kernel/kernel-offset.c, include/generated/kernel-offsets.h will be generated from this file and some difines need by kernel is generated in this file.
This generating is assigned as the last step of the kbuild generating, it would require the other earier generated files.
__KBUILD_GENARATING__ is defined when generating, it will be used to avoid compiling errror when generating.
--- Kbuild | 41 ++++++++++++++++++++++++++++++++--------- kernel/kernel-offsets.c | 14 ++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-)
Kbuild +32 -9
@@ -3,7 +3,8 @@ # This file takes care of the following: # 1) Generate bounds.h # 2) Generate asm-offsets.h (may need bounds.h) -# 3) Check for missing system calls +# 3) Generate kernel-offsets.h (may need bounds.h and asm-offsets.h) +# 4) Check for missing system calls # Default sed regexp - multiline due to syntax constraints define sed-y
@@ -30,6 +31,10 @@ define cmd_kbuild_gen echo "#endif" ) > $@ endef +quiet_cmd_gen_cc_s_c = CC $(quiet_modtag) $@ +cmd_gen_cc_s_c = $(CC) -D__KBUILD_GENARATING__ \ + $(c_flags) -fverbose-asm -S -o $@ $< + ##### # 1) Generate bounds.h
@@ -41,7 +46,7 @@ targets := $(bounds-file) kernel/bounds.s # We use internal kbuild rules to avoid the "is up to date" message from make kernel/bounds.s: kernel/bounds.c FORCE $(Q)mkdir -p $(dir $@) - $(call if_changed_dep,cc_s_c) + $(call if_changed_dep,gen_cc_s_c) $(obj)/$(bounds-file): kernel/bounds.s Kbuild $(Q)mkdir -p $(dir $@)
@@ -51,23 +56,41 @@ $(obj)/$(bounds-file): kernel/bounds.s Kbuild # 2) Generate asm-offsets.h # -offsets-file := include/generated/asm-offsets.h +asm-offsets-file := include/generated/asm-offsets.h -always += $(offsets-file) -targets += $(offsets-file) +always += $(asm-offsets-file) +targets += $(asm-offsets-file) targets += arch/$(SRCARCH)/kernel/asm-offsets.s # We use internal kbuild rules to avoid the "is up to date" message from make arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \ $(obj)/$(bounds-file) FORCE $(Q)mkdir -p $(dir $@) - $(call if_changed_dep,cc_s_c) + $(call if_changed_dep,gen_cc_s_c) + +$(obj)/$(asm-offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild + $(call cmd,kbuild_gen) + +##### +# 3) Generate kernel-offsets.h +# + +kernel-offsets-file := include/generated/kernel-offsets.h + +always += $(kernel-offsets-file) +targets += $(kernel-offsets-file) kernel/kernel-offsets.s + +# We use internal kbuild rules to avoid the "is up to date" message from make +kernel/kernel-offsets.s: kernel/kernel-offsets.c $(obj)/$(asm-offsets-file) \ + $(obj)/$(bounds-file) FORCE + $(Q)mkdir -p $(dir $@) + $(call if_changed_dep,gen_cc_s_c) -$(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild +$(obj)/$(kernel-offsets-file): kernel/kernel-offsets.s Kbuild $(call cmd,kbuild_gen) ##### -# 3) Check for missing system calls +# 4) Check for missing system calls # quiet_cmd_syscalls = CALL $<
@@ -78,4 +101,4 @@ missing-syscalls: scripts/checksyscalls.sh FORCE $(call cmd,syscalls) # Keep these two files during make clean -no-clean-files := $(bounds-file) $(offsets-file) +no-clean-files := $(bounds-file) $(asm-offsets-file) $(kernel-offsets-file)
kernel/kernel-offsets.c new file +14 -0
@@ -0,0 +1,14 @@ +/* +* Generate definitions needed by assembly language modules. +* +* Copyright (C) 2010 Lai Jiangshan +*/ + +#include <linux/kbuild.h> + +void foo (void ); + +void foo (void ) +{ +} +
Signature · 1 line
1.7.4
David Howells
maintainerRe: [RFC PATCH 3/5] kbuild: add kernel-offset file
Quoted 1 line · Lai Jiangshan
__KBUILD_GENARATING__
Should that be __KBUILD_GENERATING__?
David
RFC PATCH 4/5 RCU: Add TASK_RCU_OFFSET
In reply to Lai JiangshanWe can not include linux/sched.h in linux/rcupdate.h. If we access task's task_rcu_strut without linux/sched.h included, We will failed with compiling error.
So we add TASK_RCU_OFFSET, which help us access
task's task_rcu_strut without linux/sched.h included.
Now, task_rcu_struct(), current_task_rcu_struct(), task_of_task_rcu() and rcu_copy_process() can be used anywhere without linux/sched.h included.
--- include/linux/rcupdate.h | 49 +++++++++++++++++++++++++++++++++++++++++---- kernel/kernel-offsets.c | 3 ++ 2 files changed, 47 insertions(+), 5 deletions(-)
include/linux/rcupdate.h +44 -5
@@ -140,11 +140,50 @@ static inline void init_task_rcu_struct(struct task_rcu_struct *task_rcu)#endif } -#define task_rcu_struct (t) (&(t)->task_rcu_struct) -#define current_task_rcu_struct () task_rcu_struct(current) -#define task_of_task_rcu (task_rcu) container_of(task_rcu, struct task_struct,\ - task_rcu_struct) -#define rcu_copy_process (tsk) init_task_rcu_struct(task_rcu_struct(tsk)) +#ifdef __KBUILD_GENARATING__ +/* +* Very eary kbuild stage, many important defines including TASK_RCU_OFFSET +* are not available, use dummies to avoid compiling errors. +*/ +static inline +struct task_rcu_struct *task_rcu_struct (struct task_struct *t) +{ + (void )t; +return (struct task_rcu_struct *)0x3L ; +} + +static inline +struct task_struct *task_of_task_rcu (struct task_rcu_struct *task_rcu) +{ + (void )task_rcu; +return (struct task_struct *)-0x3L ; +} +#else +/* for generated TASK_RCU_OFFSET */ +#include <generated/kernel-offsets.h> + +static inline +struct task_rcu_struct *task_rcu_struct (struct task_struct *t) +{ +return (struct task_rcu_struct *)(((void *)t) +TASK_RCU_OFFSET ); +} + +static inline +struct task_struct *task_of_task_rcu (struct task_rcu_struct *task_rcu) +{ +return (struct task_struct *)(((void *)task_rcu) -TASK_RCU_OFFSET ); +} +#endif + +static inline struct task_rcu_struct *current_task_rcu_struct (void ) +{ +return task_rcu_struct (current); +} + +static inline void rcu_copy_process (struct task_struct *tsk) +{ +init_task_rcu_struct (task_rcu_struct (tsk)); +}#ifdef CONFIG_PREEMPT_RCU
kernel/kernel-offsets.c +3 -0
@@ -4,11 +4,14 @@* Copyright (C) 2010 Lai Jiangshan */ +#include <linux/rcupdate.h> +#include <linux/sched.h> #include <linux/kbuild.h> void foo (void );void foo (void ) { +OFFSET (TASK_RCU_OFFSET , task_struct, task_rcu_struct); }
Signature · 1 line
1.7.4
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 10 lines
Quoted 1 line
Quoted 1 line · Lai Jiangshan
We can not include
linux/sched.hinlinux/rcupdate.h. If we access task'stask_rcu_strutwithoutlinux/sched.hincluded, We will failed with compiling error.So we add
TASK_RCU_OFFSET, which help us access
task'stask_rcu_strutwithoutlinux/sched.hincluded.
Now,task_rcu_struct(),current_task_rcu_struct(),task_of_task_rcu()andrcu_copy_process()can be used anywhere withoutlinux/sched.hincluded.
Aren't the offsets-generation methods meant for assembly consumption only? Header dependency problems normally can be solved by splitting headers into a type declaration one and a second one carrying inline function implementations. Is that indeed completely impossible here?
Jan
Quoted 90 lines
Signed-off-by Lai Jiangshan <[email protected]>--- include/linux/rcupdate.h | 49 +++++++++++++++++++++++++++++++++++++++++---- kernel/kernel-offsets.c | 3 ++ 2 files changed, 47 insertions(+), 5 deletions(-)include/linux/rcupdate.h +44
-5@@ -140,11 +140,50 @@ static inline void init_task_rcu_struct(struct task_rcu_struct *task_rcu)#endif } -#define task_rcu_struct (t) (&(t)->task_rcu_struct) -#define current_task_rcu_struct () task_rcu_struct(current) -#define task_of_task_rcu (task_rcu) container_of(task_rcu, struct task_struct,\ - task_rcu_struct) -#define rcu_copy_process (tsk) init_task_rcu_struct(task_rcu_struct(tsk)) +#ifdef __KBUILD_GENARATING__ +/* +* Very eary kbuild stage, many important defines including TASK_RCU_OFFSET +* are not available, use dummies to avoid compiling errors. +*/ +static inline +struct task_rcu_struct *task_rcu_struct (struct task_struct *t) +{ + (void )t; +return (struct task_rcu_struct *)0x3L ; +} + +static inline +struct task_struct *task_of_task_rcu (struct task_rcu_struct *task_rcu) +{ + (void )task_rcu; +return (struct task_struct *)-0x3L ; +} +#else +/* for generated TASK_RCU_OFFSET */ +#include <generated/kernel-offsets.h> + +static inline +struct task_rcu_struct *task_rcu_struct (struct task_struct *t) +{ +return (struct task_rcu_struct *)(((void *)t) +TASK_RCU_OFFSET ); +} + +static inline +struct task_struct *task_of_task_rcu (struct task_rcu_struct *task_rcu) +{ +return (struct task_struct *)(((void *)task_rcu) -TASK_RCU_OFFSET ); +} +#endif + +static inline struct task_rcu_struct *current_task_rcu_struct (void ) +{ +return task_rcu_struct (current); +} + +static inline void rcu_copy_process (struct task_struct *tsk) +{ +init_task_rcu_struct (task_rcu_struct (tsk)); +}#ifdef
CONFIG_PREEMPT_RCUkernel/kernel-offsets.c +3
-0@@ -4,11 +4,14 @@* Copyright (C) 2010 Lai Jiangshan */ +#include <linux/rcupdate.h> +#include <linux/sched.h> #include <linux/kbuild.h> void foo (void );void foo (void ) { +OFFSET (TASK_RCU_OFFSET , task_struct, task_rcu_struct); }Signature · 1 line
1.7.4
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 11 lines · Jan Beulich
Quoted 10 lines
Quoted 1 line
Quoted 1 line · Lai Jiangshan
We can not include
linux/sched.hinlinux/rcupdate.h. If we access task'stask_rcu_strutwithoutlinux/sched.hincluded, We will failed with compiling error.So we add
TASK_RCU_OFFSET, which help us access
task'stask_rcu_strutwithoutlinux/sched.hincluded.
Now,task_rcu_struct(),current_task_rcu_struct(),task_of_task_rcu()andrcu_copy_process()can be used anywhere withoutlinux/sched.hincluded.
Quoted 6 lines
Aren't the offsets-generation methods meant for assembly consumption only? Header dependency problems normally can be solved by splitting headers into a type declaration one and a second one carrying inline function implementations. Is that indeed completely impossible here?
That will need to split >100 header files, it is almost impossible.
Thanks,
Lai
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Jan BeulichQuoted 11 lines · Jan Beulich
Quoted 10 lines
Quoted 1 line
Quoted 1 line · Lai Jiangshan
We can not include
linux/sched.hinlinux/rcupdate.h. If we access task'stask_rcu_strutwithoutlinux/sched.hincluded, We will failed with compiling error.So we add
TASK_RCU_OFFSET, which help us access
task'stask_rcu_strutwithoutlinux/sched.hincluded.
Now,task_rcu_struct(),current_task_rcu_struct(),task_of_task_rcu()andrcu_copy_process()can be used anywhere withoutlinux/sched.hincluded.
Quoted 6 lines
Aren't the offsets-generation methods meant for assembly consumption only? Header dependency problems normally can be solved by splitting headers into a type declaration one and a second one carrying inline function implementations. Is that indeed completely impossible here?
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
-hpa
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 12 lines · H. Peter Anvin
Quoted 11 lines · Jan Beulich
Quoted 10 lines
Quoted 1 line
Quoted 1 line · Lai Jiangshan
We can not include
linux/sched.hinlinux/rcupdate.h. If we access task'stask_rcu_strutwithoutlinux/sched.hincluded, We will failed with compiling error.So we add
TASK_RCU_OFFSET, which help us access
task'stask_rcu_strutwithoutlinux/sched.hincluded.
Now,task_rcu_struct(),current_task_rcu_struct(),task_of_task_rcu()andrcu_copy_process()can be used anywhere withoutlinux/sched.hincluded.
Quoted 8 lines
Quoted 5 lines
Aren't the offsets-generation methods meant for assembly consumption only? Header dependency problems normally can be solved by splitting headers into a type declaration one and a second one carrying inline function implementations. Is that indeed completely impossible here?
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 9 lines · Paul E. McKenney
Quoted 3 lines
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Yes. The point is if we have to pull out these kinds of hacks in *C* code, we are doing it wrong. Not just a little wrong, but completely and totally bonkers wrong.
-hpa
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Paul E. McKenney
Quoted 3 lines
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
Quoted 8 lines
Quoted 4 lines
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Yes. The point is if we have to pull out these kinds of hacks in *C* code, we are doing it wrong. Not just a little wrong, but completely and totally bonkers wrong.
OK, maybe we are doing it wrong.
But in that case, how do you suggest restructuring include/linux/sched.h so that struct task_struct can be safely included everywhere rcu_read_lock() and friends are invoked? Or, on the other hand, what should we be doing so that we don't need to include task_struct everywhere?
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 15 lines · Paul E. McKenney
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Paul E. McKenney
Quoted 3 lines
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
Quoted 8 lines
Quoted 4 lines
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Yes. The point is if we have to pull out these kinds of hacks in *C* code, we are doing it wrong. Not just a little wrong, but completely and totally bonkers wrong.
Quoted 8 lines
OK, maybe we are doing it wrong.
But in that case, how do you suggest restructuring
include/linux/sched.hso that structtask_structcan be safely included everywherercu_read_lock()and friends are invoked? Or, on the other hand, what should we be doing so that we don't need to includetask_structeverywhere?
Lai's text doesn't give any hint as to the specific nature of the conflict, which makes it hard to come up with a better alternative without having to rediscover the problem from first principles. However, a somewhat logical assumption is that the problem is that struct task_struct includes struct rcu_head, in which case the easiest thing to do is almost certainly to move the definition of struct rcu_head to its own header file, <linux/rcuhead.h>, and include that in <linux/sched.h>, which should make it possible to include <linux/sched.h> in <linux/rcupdate.h>.
-hpa
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 24 lines · H. Peter Anvin
Quoted 15 lines · Paul E. McKenney
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Paul E. McKenney
Quoted 3 lines
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
Quoted 8 lines
Quoted 4 lines
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Yes. The point is if we have to pull out these kinds of hacks in *C* code, we are doing it wrong. Not just a little wrong, but completely and totally bonkers wrong.
Quoted 7 lines
OK, maybe we are doing it wrong.
But in that case, how do you suggest restructuring
include/linux/sched.hso that structtask_structcan be safely included everywherercu_read_lock()and friends are invoked? Or, on the other hand, what should we be doing so that we don't need to includetask_structeverywhere?
Quoted 9 lines
Lai's text doesn't give any hint as to the specific nature of the conflict, which makes it hard to come up with a better alternative without having to rediscover the problem from first principles. However, a somewhat logical assumption is that the problem is that struct
task_structincludes structrcu_head, in which case the easiest thing to do is almost certainly to move the definition of structrcu_headto its own header file, <linux/rcuhead.h>, and include that in <linux/sched.h>, which should make it possible to include <linux/sched.h> in <linux/rcupdate.h>.
I believe that there are other circular dependencies -- there certainly were a few years back -- but I will defer to Lai.
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 35 lines · Paul E. McKenney
Quoted 24 lines · H. Peter Anvin
Quoted 15 lines · Paul E. McKenney
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Paul E. McKenney
Quoted 3 lines
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
Quoted 8 lines
Quoted 4 lines
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Yes. The point is if we have to pull out these kinds of hacks in *C* code, we are doing it wrong. Not just a little wrong, but completely and totally bonkers wrong.
Quoted 7 lines
OK, maybe we are doing it wrong.
But in that case, how do you suggest restructuring
include/linux/sched.hso that structtask_structcan be safely included everywherercu_read_lock()and friends are invoked? Or, on the other hand, what should we be doing so that we don't need to includetask_structeverywhere?Quoted 9 lines
Lai's text doesn't give any hint as to the specific nature of the conflict, which makes it hard to come up with a better alternative without having to rediscover the problem from first principles. However, a somewhat logical assumption is that the problem is that struct
task_structincludes structrcu_head, in which case the easiest thing to do is almost certainly to move the definition of structrcu_headto its own header file, <linux/rcuhead.h>, and include that in <linux/sched.h>, which should make it possible to include <linux/sched.h> in <linux/rcupdate.h>.
Quoted 5 lines
I believe that there are other circular dependencies -- there certainly were a few years back -- but I will defer to Lai.
Thanx, Paul
Yes, there are other circular dependencies, <linux/sched.h> includes many files which include or indirectly include <linux/rcupdate.h> for struct rcu_head or RCU apis. There are too many to be split all.
Even we just create a <linux/task_struct_def.h>, it also needs to include many files which have included or indirectly included <linux/rcupdate.h> for struct rcu_head already. It is still not a easy work to split them, it still requires many subsystem maintainers to participate in.
RCU is one of the most import subsystem,
I think it is worth to do such "wrong" way.
Thanks,
Lai
P.S.
Circular dependencies is one of the original sins of C language. If it is a good change for lots of linux hackers participating in to split all un-split kernel headers, I'd like to do so too.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 39 lines · Lai Jiangshan
Quoted 38 lines · Paul E. McKenney
Quoted 24 lines · H. Peter Anvin
Quoted 15 lines · Paul E. McKenney
Quoted 5 lines · H. Peter Anvin
Quoted 4 lines · Paul E. McKenney
Quoted 3 lines
I have to say that if we have to use hardcoded offsets in C then we have bigger problems.
Quoted 8 lines
Quoted 4 lines
In this case, the offsets are mechanically generated from the structure definitions.
Or am I missing your point?
Yes. The point is if we have to pull out these kinds of hacks in *C* code, we are doing it wrong. Not just a little wrong, but completely and totally bonkers wrong.
Quoted 7 lines
OK, maybe we are doing it wrong.
But in that case, how do you suggest restructuring
include/linux/sched.hso that structtask_structcan be safely included everywherercu_read_lock()and friends are invoked? Or, on the other hand, what should we be doing so that we don't need to includetask_structeverywhere?Quoted 9 lines
Lai's text doesn't give any hint as to the specific nature of the conflict, which makes it hard to come up with a better alternative without having to rediscover the problem from first principles. However, a somewhat logical assumption is that the problem is that struct
task_structincludes structrcu_head, in which case the easiest thing to do is almost certainly to move the definition of structrcu_headto its own header file, <linux/rcuhead.h>, and include that in <linux/sched.h>, which should make it possible to include <linux/sched.h> in <linux/rcupdate.h>.I believe that there are other circular dependencies -- there certainly were a few years back -- but I will defer to Lai.
Quoted 7 lines
Quoted 2 lines
Thanx, Paul
Yes, there are other circular dependencies, <
linux/sched.h> includes many files which include or indirectly include <linux/rcupdate.h> for structrcu_heador RCU apis. There are too many to be split all.
<linux/rcupdate.h> is so generic that it is included in many headers. <linux/sched.h> is so complex that it includes many headers.
How many files which include(or indirectly include) <linux/rcupdate.h> are included(or indirectly included) by <linux/sched.h>?
714 files! So I can guess 100 files at least is needed to be touched if we resolve this problem by splitting.
include/linux/sched.hinclude/linux/kernel.hinclude/linux/timex.hinclude/linux/jiffies.hinclude/linux/rbtree.hinclude/linux/thread_info.hinclude/linux/cpumask.hinclude/linux/nodemask.hinclude/linux/mm_types.harch/alpha/include/asm/system.harch/arm/include/asm/system.harch/avr32/include/asm/system.harch/blackfin/include/asm/system.harch/cris/include/asm/system.harch/frv/include/asm/system.harch/h8300/include/asm/system.harch/ia64/include/asm/system.harch/m32r/include/asm/system.harch/microblaze/include/asm/system.harch/mips/include/asm/system.harch/mn10300/include/asm/system.harch/parisc/include/asm/system.harch/powerpc/include/asm/system.harch/s390/include/asm/system.harch/score/include/asm/system.harch/sh/include/asm/system.harch/sparc/include/asm/system.harch/tile/include/asm/system.harch/unicore32/include/asm/system.harch/x86/include/asm/system.harch/xtensa/include/asm/system.harch/mips/include/asm/page.harch/sh/include/asm/page.harch/powerpc/include/asm/ptrace.harch/sh/include/asm/ptrace.harch/sparc/include/asm/ptrace.harch/alpha/include/asm/cputime.harch/arm/include/asm/cputime.harch/avr32/include/asm/cputime.harch/blackfin/include/asm/cputime.harch/cris/include/asm/cputime.harch/frv/include/asm/cputime.harch/h8300/include/asm/cputime.harch/ia64/include/asm/cputime.harch/m32r/include/asm/cputime.harch/m68k/include/asm/cputime.harch/microblaze/include/asm/cputime.harch/mips/include/asm/cputime.harch/mn10300/include/asm/cputime.harch/parisc/include/asm/cputime.harch/powerpc/include/asm/cputime.harch/s390/include/asm/cputime.harch/score/include/asm/cputime.harch/sh/include/asm/cputime.harch/sparc/include/asm/cputime.harch/tile/include/asm/cputime.harch/um/include/asm/cputime.harch/x86/include/asm/cputime.harch/xtensa/include/asm/cputime.hinclude/linux/smp.hinclude/linux/sem.hinclude/linux/signal.hinclude/linux/completion.hinclude/linux/pid.hinclude/linux/percpu.hinclude/linux/topology.hinclude/linux/proportions.hinclude/linux/seccomp.hinclude/linux/rculist.hinclude/linux/rtmutex.hinclude/linux/time.hinclude/linux/resource.hinclude/linux/timer.hinclude/linux/hrtimer.hinclude/linux/cred.harch/cris/include/asm/processor.harch/h8300/include/asm/processor.harch/ia64/include/asm/processor.harch/m32r/include/asm/processor.harch/m68k/include/asm/processor.harch/mips/include/asm/processor.harch/mn10300/include/asm/processor.harch/parisc/include/asm/processor.harch/powerpc/include/asm/processor.harch/score/include/asm/processor.harch/sparc/include/asm/processor.harch/x86/include/asm/processor.hinclude/linux/spinlock.hinclude/linux/aio.harch/alpha/include/asm/current.harch/arm/include/asm/current.harch/avr32/include/asm/current.harch/blackfin/include/asm/current.harch/cris/include/asm/current.harch/h8300/include/asm/current.harch/m32r/include/asm/current.harch/m68k/include/asm/current.harch/mips/include/asm/current.harch/mn10300/include/asm/current.harch/parisc/include/asm/current.harch/powerpc/include/asm/current.harch/score/include/asm/current.harch/sh/include/asm/current.harch/sparc/include/asm/current.harch/tile/include/asm/current.harch/x86/include/asm/current.harch/xtensa/include/asm/current.hinclude/linux/bitops.hinclude/linux/log2.harch/s390/include/asm/bug.harch/arm/include/asm/div64.harch/ia64/include/asm/timex.harch/mips/include/asm/timex.harch/mn10300/include/asm/timex.harch/parisc/include/asm/timex.harch/sparc/include/asm/timex.harch/x86/include/asm/timex.hinclude/linux/math64.harch/cris/include/asm/thread_info.harch/ia64/include/asm/thread_info.harch/m32r/include/asm/thread_info.harch/m68k/include/asm/thread_info.harch/mips/include/asm/thread_info.harch/parisc/include/asm/thread_info.harch/powerpc/include/asm/thread_info.harch/score/include/asm/thread_info.harch/sh/include/asm/thread_info.harch/sparc/include/asm/thread_info.harch/x86/include/asm/thread_info.hinclude/linux/bitmap.hinclude/linux/list.hinclude/linux/rwsem.harch/sh/include/asm/mmu.harch/x86/include/asm/mmu.hinclude/linux/irqflags.hinclude/asm-generic/cmpxchg-local.harch/blackfin/include/asm/irq.harch/mips/include/asm/cmpxchg.harch/mips/include/asm/dsp.harch/mips/include/asm/watch.harch/mn10300/include/asm/atomic.harch/powerpc/include/asm/hw_irq.harch/sh/include/asm/uncached.harch/sparc/include/asm/system_64.harch/sparc/include/asm/system_32.harch/x86/include/asm/cpufeature.harch/x86/include/asm/paravirt.harch/mips/include/asm/io.hinclude/asm-generic/cputime.harch/powerpc/include/asm/time.hinclude/linux/preempt.harch/alpha/include/asm/smp.harch/arm/include/asm/smp.harch/blackfin/include/asm/smp.harch/cris/include/asm/smp.harch/ia64/include/asm/smp.harch/m32r/include/asm/smp.harch/mips/include/asm/smp.harch/mn10300/include/asm/smp.harch/parisc/include/asm/smp.harch/powerpc/include/asm/smp.harch/s390/include/asm/smp.harch/sh/include/asm/smp.harch/sparc/include/asm/smp.harch/tile/include/asm/smp.harch/x86/include/asm/smp.hinclude/linux/ipc.harch/alpha/include/asm/atomic.harch/arm/include/asm/atomic.harch/avr32/include/asm/atomic.harch/blackfin/include/asm/atomic.harch/cris/include/asm/atomic.harch/frv/include/asm/atomic.harch/h8300/include/asm/atomic.harch/ia64/include/asm/atomic.harch/m32r/include/asm/atomic.harch/microblaze/include/asm/atomic.harch/mips/include/asm/atomic.harch/parisc/include/asm/atomic.harch/powerpc/include/asm/atomic.harch/s390/include/asm/atomic.harch/score/include/asm/atomic.harch/sh/include/asm/atomic.harch/sparc/include/asm/atomic.harch/tile/include/asm/atomic.harch/x86/include/asm/atomic.harch/xtensa/include/asm/atomic.hinclude/linux/cache.harch/blackfin/include/asm/signal.harch/frv/include/asm/signal.harch/m32r/include/asm/signal.harch/microblaze/include/asm/signal.harch/s390/include/asm/signal.harch/score/include/asm/signal.harch/sh/include/asm/signal.harch/sparc/include/asm/signal.harch/tile/include/asm/signal.harch/x86/include/asm/signal.harch/sparc/include/asm/siginfo.hinclude/linux/wait.harch/powerpc/include/asm/percpu.harch/x86/include/asm/percpu.hinclude/linux/mmzone.harch/alpha/include/asm/topology.harch/ia64/include/asm/topology.harch/powerpc/include/asm/topology.harch/s390/include/asm/topology.harch/sparc/include/asm/topology.harch/tile/include/asm/topology.harch/x86/include/asm/topology.hinclude/linux/percpu_counter.hinclude/linux/mutex.hinclude/linux/plist.hinclude/linux/spinlock_types.hinclude/linux/seqlock.hinclude/linux/ktime.hinclude/linux/debugobjects.hinclude/linux/timerqueue.hinclude/linux/key.harch/mips/include/asm/mipsregs.harch/mn10300/include/asm/uaccess.harch/sparc/include/asm/processor_64.harch/sparc/include/asm/processor_32.harch/x86/include/asm/msr.harch/alpha/include/asm/spinlock.harch/blackfin/include/asm/spinlock.harch/ia64/include/asm/spinlock.harch/m32r/include/asm/spinlock.harch/mn10300/include/asm/spinlock.harch/parisc/include/asm/spinlock.harch/powerpc/include/asm/spinlock.harch/s390/include/asm/spinlock.harch/tile/include/asm/spinlock.harch/x86/include/asm/spinlock.harch/xtensa/include/asm/spinlock.hinclude/linux/workqueue.hinclude/asm-generic/current.harch/powerpc/include/asm/paca.harch/arm/include/asm/bitops.harch/avr32/include/asm/bitops.harch/blackfin/include/asm/bitops.harch/cris/include/asm/bitops.harch/h8300/include/asm/bitops.harch/m32r/include/asm/bitops.harch/microblaze/include/asm/bitops.harch/mips/include/asm/bitops.harch/parisc/include/asm/bitops.harch/score/include/asm/bitops.harch/sh/include/asm/bitops.harch/tile/include/asm/bitops.harch/unicore32/include/asm/bitops.harch/x86/include/asm/bitops.harch/xtensa/include/asm/bitops.harch/mn10300/include/asm/hardirq.harch/sparc/include/asm/timex_64.harch/x86/include/asm/tsc.harch/sparc/include/asm/thread_info_64.harch/sparc/include/asm/thread_info_32.hinclude/linux/prefetch.harch/alpha/include/asm/irqflags.harch/m68k/include/asm/irqflags.harch/mn10300/include/asm/irqflags.harch/powerpc/include/asm/irqflags.harch/x86/include/asm/irqflags.hinclude/asm-generic/atomic.hinclude/linux/bug.harch/sparc/include/asm/visasm.harch/powerpc/include/asm/iseries/hv_call.harch/ia64/include/asm/io.harch/mips/include/asm/smp-ops.harch/s390/include/asm/sigp.harch/sparc/include/asm/smp_64.harch/sparc/include/asm/smp_32.harch/x86/include/asm/apic.harch/x86/include/asm/cpumask.harch/sparc/include/asm/atomic_64.harch/sparc/include/asm/atomic_32.harch/x86/include/asm/alternative.hinclude/asm-generic/signal.harch/sparc/include/asm/sigcontext.hinclude/linux/compat.hinclude/linux/memory_hotplug.harch/alpha/include/asm/mmzone.harch/m32r/include/asm/mmzone.harch/mips/include/asm/mmzone.harch/powerpc/include/asm/mmzone.harch/sparc/include/asm/mmzone.harch/ia64/include/asm/acpi.harch/ia64/include/asm/numa.harch/sparc/include/asm/topology_64.hinclude/linux/lockdep.hinclude/linux/mutex-debug.hinclude/linux/sysctl.harch/tile/include/asm/spinlock_32.harch/powerpc/include/asm/lppaca.hinclude/asm-generic/bitops/atomic.hinclude/asm-generic/bitops.harch/tile/include/asm/bitops_32.hinclude/linux/irq.harch/sparc/include/asm/timer.hinclude/linux/hardirq.harch/ia64/include/asm/unaligned.hinclude/linux/delay.hinclude/linux/pm.harch/x86/include/asm/fixmap.harch/powerpc/include/asm/sigcontext.hinclude/linux/stat.harch/mips/include/asm/compat.harch/parisc/include/asm/compat.harch/powerpc/include/asm/compat.harch/s390/include/asm/compat.harch/tile/include/asm/compat.harch/x86/include/asm/compat.hinclude/linux/notifier.hinclude/linux/debug_locks.hinclude/linux/gfp.hinclude/linux/irqnr.harch/ia64/include/asm/irq.harch/m68k/include/asm/irq.harch/mips/include/asm/irq.harch/parisc/include/asm/irq.harch/powerpc/include/asm/irq.harch/s390/include/asm/irq.harch/sh/include/asm/irq.harch/sparc/include/asm/irq.harch/tile/include/asm/irq.harch/x86/include/asm/irq.harch/alpha/include/asm/irq_regs.harch/arm/include/asm/irq_regs.harch/avr32/include/asm/irq_regs.harch/blackfin/include/asm/irq_regs.harch/cris/include/asm/irq_regs.harch/h8300/include/asm/irq_regs.harch/ia64/include/asm/irq_regs.harch/m32r/include/asm/irq_regs.harch/m68k/include/asm/irq_regs.harch/microblaze/include/asm/irq_regs.harch/mips/include/asm/irq_regs.harch/parisc/include/asm/irq_regs.harch/powerpc/include/asm/irq_regs.harch/s390/include/asm/irq_regs.harch/score/include/asm/irq_regs.harch/sh/include/asm/irq_regs.harch/sparc/include/asm/irq_regs.harch/tile/include/asm/irq_regs.harch/um/include/asm/irq_regs.harch/x86/include/asm/irq_regs.harch/xtensa/include/asm/irq_regs.harch/ia64/include/asm/hw_irq.harch/mips/include/asm/hw_irq.harch/sh/include/asm/hw_irq.harch/x86/include/asm/hw_irq.harch/sparc/include/asm/timer_32.harch/alpha/include/asm/hardirq.harch/arm/include/asm/hardirq.harch/avr32/include/asm/hardirq.harch/blackfin/include/asm/hardirq.harch/cris/include/asm/hardirq.harch/frv/include/asm/hardirq.harch/h8300/include/asm/hardirq.harch/ia64/include/asm/hardirq.harch/m32r/include/asm/hardirq.harch/microblaze/include/asm/hardirq.harch/mips/include/asm/hardirq.harch/parisc/include/asm/hardirq.harch/powerpc/include/asm/hardirq.harch/score/include/asm/hardirq.harch/sh/include/asm/hardirq.harch/sparc/include/asm/hardirq.harch/tile/include/asm/hardirq.harch/um/include/asm/hardirq.harch/x86/include/asm/hardirq.harch/xtensa/include/asm/hardirq.hinclude/linux/unaligned/le_struct.harch/ia64/include/asm/delay.harch/parisc/include/asm/delay.harch/powerpc/include/asm/delay.harch/sparc/include/asm/delay.harch/x86/include/asm/acpi.harch/x86/include/asm/vsyscall.harch/powerpc/include/asm/elf.hinclude/linux/srcu.harch/mips/include/asm/mipsmtregs.hinclude/linux/radix-tree.harch/sh/include/asm/machvec.harch/sparc/include/asm/irq_64.harch/sparc/include/asm/irq_32.hinclude/asm-generic/irq_regs.hinclude/linux/interrupt.hinclude/linux/profile.harch/ia64/include/asm/paravirt.harch/x86/include/asm/sections.hinclude/asm-generic/hardirq.harch/sparc/include/asm/hardirq_64.harch/sparc/include/asm/hardirq_32.hinclude/linux/unaligned/packed_struct.harch/sparc/include/asm/delay_32.harch/x86/include/asm/numa.harch/x86/include/asm/trampoline.hinclude/trace/events/irq.harch/x86/include/asm/uaccess.harch/sparc/include/asm/cpudata.harch/x86/include/asm/io.hinclude/linux/tracepoint.hinclude/trace/define_trace.harch/sparc/include/asm/cpudata_64.harch/sparc/include/asm/cpudata_32.hinclude/xen/xen.hinclude/linux/vmalloc.hinclude/linux/module.hinclude/trace/ftrace.harch/ia64/include/asm/xen/hypervisor.harch/x86/include/asm/xen/hypervisor.hinclude/linux/kmod.hinclude/linux/elf.hinclude/linux/kobject.hinclude/linux/moduleparam.harch/mips/include/asm/module.harch/powerpc/include/asm/module.harch/score/include/asm/module.hinclude/trace/events/module.hinclude/linux/ftrace_event.harch/mn10300/include/asm/elf.harch/s390/include/asm/elf.harch/score/include/asm/elf.harch/sh/include/asm/elf.harch/sparc/include/asm/elf.harch/tile/include/asm/elf.harch/x86/include/asm/elf.hinclude/linux/sysfs.harch/mips/include/asm/uaccess.harch/score/include/asm/uaccess.hinclude/linux/ring_buffer.hinclude/linux/trace_seq.hinclude/linux/perf_event.hinclude/linux/utsname.harch/mn10300/include/asm/user.harch/s390/include/asm/mmu_context.hinclude/linux/ptrace.harch/sh/include/asm/user.harch/sparc/include/asm/elf_64.harch/sparc/include/asm/elf_32.harch/x86/include/asm/desc.hinclude/linux/kmemcheck.hinclude/linux/mm.hinclude/linux/seq_file.hinclude/linux/fs.hinclude/linux/cgroup.harch/powerpc/include/asm/perf_event.harch/sparc/include/asm/perf_event.harch/x86/include/asm/perf_event.harch/alpha/include/asm/local64.harch/arm/include/asm/local64.harch/avr32/include/asm/local64.harch/blackfin/include/asm/local64.harch/cris/include/asm/local64.harch/frv/include/asm/local64.harch/h8300/include/asm/local64.harch/ia64/include/asm/local64.harch/m32r/include/asm/local64.harch/m68k/include/asm/local64.harch/microblaze/include/asm/local64.harch/mips/include/asm/local64.harch/mn10300/include/asm/local64.harch/parisc/include/asm/local64.harch/powerpc/include/asm/local64.harch/s390/include/asm/local64.harch/score/include/asm/local64.harch/sh/include/asm/local64.harch/sparc/include/asm/local64.harch/x86/include/asm/local64.harch/xtensa/include/asm/local64.harch/powerpc/include/asm/hw_breakpoint.harch/sh/include/asm/hw_breakpoint.harch/x86/include/asm/hw_breakpoint.hinclude/linux/pid_namespace.hinclude/linux/ftrace.hinclude/linux/cpu.hinclude/linux/jump_label_ref.harch/alpha/include/asm/local.harch/arm/include/asm/local.harch/avr32/include/asm/local.harch/blackfin/include/asm/local.harch/cris/include/asm/local.harch/frv/include/asm/local.harch/h8300/include/asm/local.harch/ia64/include/asm/local.harch/m32r/include/asm/local.harch/m68k/include/asm/local.harch/microblaze/include/asm/local.harch/mips/include/asm/local.harch/mn10300/include/asm/local.harch/parisc/include/asm/local.harch/powerpc/include/asm/local.harch/s390/include/asm/local.harch/score/include/asm/local.harch/sh/include/asm/local.harch/sparc/include/asm/local.harch/tile/include/asm/local.harch/x86/include/asm/local.harch/xtensa/include/asm/local.hinclude/linux/nsproxy.harch/s390/include/asm/pgalloc.harch/s390/include/asm/uaccess.harch/s390/include/asm/tlbflush.harch/sparc/include/asm/uaccess.harch/sparc/include/asm/mbus.hinclude/linux/bit_spinlock.harch/alpha/include/asm/pgtable.harch/arm/include/asm/pgtable.harch/avr32/include/asm/pgtable.harch/blackfin/include/asm/pgtable.harch/cris/include/asm/pgtable.harch/frv/include/asm/pgtable.harch/h8300/include/asm/pgtable.harch/ia64/include/asm/pgtable.harch/m32r/include/asm/pgtable.harch/microblaze/include/asm/pgtable.harch/mips/include/asm/pgtable.harch/mn10300/include/asm/pgtable.harch/parisc/include/asm/pgtable.harch/powerpc/include/asm/pgtable.harch/s390/include/asm/pgtable.harch/score/include/asm/pgtable.harch/sh/include/asm/pgtable.harch/sparc/include/asm/pgtable.harch/tile/include/asm/pgtable.harch/um/include/asm/pgtable.harch/unicore32/include/asm/pgtable.harch/x86/include/asm/pgtable.harch/xtensa/include/asm/pgtable.hinclude/linux/page-flags.hinclude/linux/vmstat.hinclude/linux/dcache.hinclude/linux/semaphore.hinclude/linux/rculist_bl.hinclude/linux/quota.hinclude/linux/nfs_fs_i.hinclude/linux/prio_heap.hinclude/linux/idr.harch/powerpc/include/asm/perf_event_server.harch/powerpc/include/asm/perf_event_fsl_emb.harch/x86/include/asm/stacktrace.hinclude/asm-generic/local64.hinclude/linux/kdebug.hinclude/linux/kallsyms.harch/blackfin/include/asm/ftrace.hinclude/linux/sysdev.hinclude/linux/node.hinclude/asm-generic/local.harch/sparc/include/asm/uaccess_64.harch/sparc/include/asm/uaccess_32.harch/sparc/include/asm/viking.hinclude/asm-generic/pgtable.hinclude/linux/slab.harch/ia64/include/asm/cacheflush.harch/ia64/include/asm/mmu_context.harch/mips/include/asm/pgtable-32.harch/mips/include/asm/pgtable-64.harch/powerpc/include/asm/pgtable-ppc64.harch/powerpc/include/asm/pgtable-ppc32.harch/sh/include/asm/fixmap.harch/sh/include/asm/pgtable_64.harch/sparc/include/asm/pgtable_64.harch/sparc/include/asm/pgtable_32.harch/tile/include/asm/fixmap.hinclude/linux/list_bl.hinclude/linux/uaccess.harch/mips/include/asm/kdebug.harch/sparc/include/asm/kdebug.harch/x86/include/asm/kdebug.harch/sparc/include/asm/pgtsrmmu.hinclude/linux/slub_def.hinclude/linux/slab_def.harch/mips/include/asm/fixmap.harch/powerpc/include/asm/tlbflush.harch/powerpc/include/asm/io.hinclude/linux/swap.harch/sparc/include/asm/oplib.harch/alpha/include/asm/uaccess.harch/arm/include/asm/uaccess.harch/avr32/include/asm/uaccess.harch/blackfin/include/asm/uaccess.harch/cris/include/asm/uaccess.harch/frv/include/asm/uaccess.harch/h8300/include/asm/uaccess.harch/ia64/include/asm/uaccess.harch/m32r/include/asm/uaccess.harch/microblaze/include/asm/uaccess.harch/parisc/include/asm/uaccess.harch/powerpc/include/asm/uaccess.harch/sh/include/asm/uaccess.harch/tile/include/asm/uaccess.harch/unicore32/include/asm/uaccess.harch/xtensa/include/asm/uaccess.harch/sparc/include/asm/kdebug_32.hinclude/trace/events/kmem.hinclude/linux/device.hinclude/linux/io.harch/powerpc/include/asm/eeh.hinclude/linux/memcontrol.harch/sparc/include/asm/oplib_64.harch/sparc/include/asm/oplib_32.hinclude/asm-generic/uaccess.harch/sparc/include/asm/openprom.hinclude/linux/klist.harch/sparc/include/asm/device.harch/alpha/include/asm/io.harch/arm/include/asm/io.harch/avr32/include/asm/io.harch/blackfin/include/asm/io.harch/cris/include/asm/io.harch/frv/include/asm/io.harch/microblaze/include/asm/io.harch/mn10300/include/asm/io.harch/parisc/include/asm/io.harch/score/include/asm/io.harch/sh/include/asm/io.harch/sparc/include/asm/io.harch/tile/include/asm/io.harch/unicore32/include/asm/io.harch/xtensa/include/asm/io.harch/xtensa/include/asm/segment.hinclude/linux/of.harch/alpha/include/asm/core_lca.harch/alpha/include/asm/core_marvel.harch/alpha/include/asm/core_t2.hinclude/asm-generic/io.harch/mn10300/include/asm/cacheflush.harch/sh/include/asm/io_trapped.harch/sparc/include/asm/io_64.harch/sparc/include/asm/io_32.harch/microblaze/include/asm/prom.harch/powerpc/include/asm/prom.harch/sparc/include/asm/prom.harch/x86/include/asm/prom.harch/alpha/include/asm/cacheflush.harch/arm/include/asm/cacheflush.harch/avr32/include/asm/cacheflush.harch/blackfin/include/asm/cacheflush.harch/cris/include/asm/cacheflush.harch/frv/include/asm/cacheflush.harch/m32r/include/asm/cacheflush.harch/microblaze/include/asm/cacheflush.harch/mips/include/asm/cacheflush.harch/parisc/include/asm/cacheflush.harch/powerpc/include/asm/cacheflush.harch/s390/include/asm/cacheflush.harch/score/include/asm/cacheflush.harch/sh/include/asm/cacheflush.harch/sparc/include/asm/cacheflush.harch/tile/include/asm/cacheflush.harch/unicore32/include/asm/cacheflush.harch/x86/include/asm/cacheflush.harch/xtensa/include/asm/cacheflush.hinclude/linux/of_irq.hinclude/linux/platform_device.hinclude/linux/of_address.hinclude/linux/proc_fs.hinclude/linux/pci.hinclude/asm-generic/cacheflush.harch/sparc/include/asm/cacheflush_64.harch/sparc/include/asm/cacheflush_32.hinclude/linux/dmapool.harch/alpha/include/asm/pci.harch/arm/include/asm/pci.harch/avr32/include/asm/pci.harch/blackfin/include/asm/pci.harch/cris/include/asm/pci.harch/frv/include/asm/pci.harch/ia64/include/asm/pci.harch/m68k/include/asm/pci.harch/microblaze/include/asm/pci.harch/mips/include/asm/pci.harch/mn10300/include/asm/pci.harch/parisc/include/asm/pci.harch/powerpc/include/asm/pci.harch/sh/include/asm/pci.harch/sparc/include/asm/pci.harch/tile/include/asm/pci.harch/unicore32/include/asm/pci.harch/x86/include/asm/pci.harch/xtensa/include/asm/pci.harch/powerpc/include/asm/scatterlist.hinclude/linux/dma-mapping.hinclude/asm-generic/pci-dma-compat.harch/microblaze/include/asm/pci-bridge.harch/powerpc/include/asm/machdep.harch/powerpc/include/asm/pci-bridge.harch/sparc/include/asm/pci_64.harch/sparc/include/asm/pci_32.harch/powerpc/include/asm/dma.hinclude/linux/dma-attrs.hinclude/linux/scatterlist.harch/alpha/include/asm/dma-mapping.harch/arm/include/asm/dma-mapping.harch/avr32/include/asm/dma-mapping.harch/blackfin/include/asm/dma-mapping.harch/cris/include/asm/dma-mapping.harch/frv/include/asm/dma-mapping.harch/ia64/include/asm/dma-mapping.harch/microblaze/include/asm/dma-mapping.harch/mips/include/asm/dma-mapping.harch/mn10300/include/asm/dma-mapping.harch/parisc/include/asm/dma-mapping.harch/powerpc/include/asm/dma-mapping.harch/sh/include/asm/dma-mapping.harch/sparc/include/asm/dma-mapping.harch/tile/include/asm/dma-mapping.harch/unicore32/include/asm/dma-mapping.harch/x86/include/asm/dma-mapping.harch/xtensa/include/asm/dma-mapping.hinclude/asm-generic/dma-mapping-common.harch/ia64/include/asm/swiotlb.h
#!/bin/python
import reinclude_re = re.compile(r'#\s*include\s*<([_\-\w]*)([/\._\-\w]*)>') leaf_file = ('linux', '/rcupdate.h')archs_dir = (
'arch/alpha/',
'arch/arm/',
'arch/avr32/',
'arch/blackfin/',
'arch/cris/',
'arch/frv/',
'arch/h8300/',
'arch/ia64/',
'arch/m32r/',
'arch/m68k/',
'arch/m68knommu/',
'arch/microblaze/',
'arch/mips/',
'arch/mn10300/',
'arch/parisc/',
'arch/powerpc/',
'arch/s390/',
'arch/score/',
'arch/sh/',
'arch/sparc/',
'arch/tile/',
'arch/um/',
'arch/unicore32/',
'arch/x86/',
'arch/xtensa/',
)
generic_dir = 'include/'
searched = {('include/linux','/rcupdate.h'):1}
searchqueue = []
def add(f):
if searched.has_key(f):
return
searched[f] = 0
searchqueue.append(f)
def addall():
i = 0
while i < len(searchqueue):
f=searchqueue[i]
i=i+1
try:
ff = file(f[0]+f[1])
except:
continue
for ch in include_re.findall(ff.read()):
if ch[0] == 'asm':
if f[0][0:4] == 'arch':
add((f[0], ch[1]))
continue
for dir in archs_dir:
add((dir+'include/asm', ch[1]))
else:
add((generic_dir+ch[0], ch[1]))def markall():
for f in searchqueue:
res = 0
try:
ff = file(f[0]+f[1])
except:
continue
for ch in include_re.findall(ff.read()):
if ch[0] == 'asm':
if f[0][0:4] == 'arch':
res = res or searched[(f[0], ch[1])]
continue
for dir in archs_dir:
res = res or searched[(dir+'include/asm', ch[1])]
else:
res = res or searched[(generic_dir+ch[0], ch[1])]
searched[f]=resadd(('include/linux', '/sched.h'))addall()
# I'm lazy to build a map and the reverse map..., thousands of headers is not
# too much for this. add enough markall() until the result output is not changed
markall()
markall()
markall()
markall()
markall()
markall()
markall()
markall()
markall()
markall()
markall()
#markall()
#print len(searchqueue)
for f in searchqueue:
if searched[f]:
print f[0]+f[1]Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 6 lines · Lai Jiangshan
Quoted 4 lines · Lai Jiangshan
Yes, there are other circular dependencies, <
linux/sched.h> includes many files which include or indirectly include <linux/rcupdate.h> for structrcu_heador RCU apis. There are too many to be split all.
Quoted 8 lines
<
linux/rcupdate.h> is so generic that it is included in many headers. <linux/sched.h> is so complex that it includes many headers.How many files which include(or indirectly include) <
linux/rcupdate.h> are included(or indirectly included) by <linux/sched.h>?714 files! So I can guess 100 files at least is needed to be touched if we resolve this problem by splitting.
It goes down quickly if you start reducing the dependencies. I wrote a quick&dirty patch that splits 9 headers and the preprocessed result of #include <linux/sched_types.h> is about 7800 lines. Most of it is caused by linux/signal.h which I skipped. What do you think?
Michal
Subject: [PATCH] headers: Allow for lightweight inclusion of task_struct definition
Factor out a couple of type definitions to <header>_types.h to allow using task_struct without pulling tons of new dependencies via sched.h.
--- include/linux/Kbuild | 1 + include/linux/mutex.h | 18 +-- include/linux/mutex_types.h | 22 ++ include/linux/nodemask.h | 2 +- include/linux/nodemask_types.h | 11 + include/linux/pid.h | 15 +- include/linux/pid_types.h | 18 ++ include/linux/proportions.h | 24 +-- include/linux/proportions_types.h | 29 ++ include/linux/rbtree.h | 8 +- include/linux/rbtree_types.h | 11 + include/linux/rcupdate.h | 11 +- include/linux/rcupdate_types.h | 14 + include/linux/sched.h | 481 +----------------------------------- include/linux/sched_types.h | 493 ++++++++++++++++++++++++++++++++++++ include/linux/seccomp.h | 5 +- include/linux/seccomp_types.h | 12 + include/linux/sem.h | 5 +- include/linux/sem_types.h | 10 + include/linux/task_io_accounting.h | 2 + 20 files changed, 633 insertions(+), 559 deletions(-)
include/linux/Kbuild +1 -0
@@ -325,6 +325,7 @@ header-y += sdla.h header-y += securebits.h header-y += selinux_netlink.h header-y += sem.h +header-y += sem_types.h header-y += serial.h header-y += serial_core.h header-y += serial_reg.h
include/linux/mutex.h +1 -17
@@ -14,8 +14,8 @@#include <linux/spinlock_types.h> #include <linux/linkage.h> #include <linux/lockdep.h> -#include <asm/atomic.h> +#include <linux/mutex_types.h> /* * Simple, straightforward mutexes with strict semantics:
@@ -45,22 +45,6 @@* - detects multi-task circular deadlocks and prints out all affected * locks and tasks (and only those tasks) */ -struct mutex { -/* 1: unlocked, 0: locked, negative: locked, possible waiters */ -atomic_t count; -spinlock_t wait_lock; -struct list_head wait_list; -#if defined(CONFIG_DEBUG_MUTEXES ) || defined(CONFIG_SMP ) -struct thread_info *owner; -#endif -#ifdef CONFIG_DEBUG_MUTEXES -const char *name; -void *magic; -#endif -#ifdef CONFIG_DEBUG_LOCK_ALLOC -struct lockdep_map dep_map; -#endif -};/* * This is the control structure for tasks blocked on mutex,
include/linux/mutex_types.h new file +22 -0
@@ -0,0 +1,22 @@ +#ifndef _LINUX_MUTEX_TYPES_H +#define _LINUX_MUTEX_TYPES_H + + +struct mutex { +/* 1: unlocked, 0: locked, negative: locked, possible waiters */ +atomic_t count; +spinlock_t wait_lock; +struct list_head wait_list; +#if defined(CONFIG_DEBUG_MUTEXES ) || defined(CONFIG_SMP ) +struct thread_info *owner; +#endif +#ifdef CONFIG_DEBUG_MUTEXES +const char *name; +void *magic; +#endif +#ifdef CONFIG_DEBUG_LOCK_ALLOC +struct lockdep_map dep_map; +#endif +}; + +#endif
include/linux/nodemask.h +1 -1
@@ -92,8 +92,8 @@#include <linux/threads.h> #include <linux/bitmap.h> #include <linux/numa.h> +#include <linux/nodemask_types.h> -typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t;extern nodemask_t _unused_nodemask_arg_;#define node_set (node, dst) __node_set((node), &(dst))
include/linux/nodemask_types.h new file +11 -0
@@ -0,0 +1,11 @@ +#ifndef _LINUX_NODEMASK_TYPES_H +#define _LINUX_NODEMASK_TYPES_H + +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/numa.h> + +typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t; + +#endif
include/linux/pid.h +1 -14
@@ -2,14 +2,7 @@#define _LINUX_PID_H#include <linux/rcupdate.h> - -enum pid_type -{ -PIDTYPE_PID , -PIDTYPE_PGID , -PIDTYPE_SID , -PIDTYPE_MAX -}; +#include <linux/pid_types.h> /* * What is struct pid?
@@ -66,12 +59,6 @@ struct pidextern struct pid init_struct_pid; -struct pid_link -{ -struct hlist_node node; -struct pid *pid; -}; -static inline struct pid *get_pid (struct pid *pid) {if (pid)
include/linux/pid_types.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef _LINUX_PID_TYPES_H +#define _LINUX_PID_TYPES_H + +struct pid ; + +enum pid_type { +PIDTYPE_PID , +PIDTYPE_PGID , +PIDTYPE_SID , +PIDTYPE_MAX +}; + +struct pid_link { +struct hlist_node node; +struct pid *pid; +}; + +#endif
include/linux/proportions.h +1 -23
@@ -12,6 +12,7 @@#include <linux/percpu_counter.h> #include <linux/spinlock.h> #include <linux/mutex.h> +#include <linux/proportions_types.h> struct prop_global {/*
@@ -90,29 +91,6 @@ void __prop_inc_percpu_max(struct prop_descriptor *pd, struct prop_local_percpu *pl, long frac); -/* -* ----- SINGLE ------ -*/ - -struct prop_local_single { -/* -* the local events counter -*/ -unsigned long events; - -/* -* snapshot of the last seen global state -* and a lock protecting this state -*/ -unsigned long period; -int shift; -spinlock_t lock;/* protect the snapshot state */ -}; - -#define INIT_PROP_LOCAL_SINGLE (name) \ -{ .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ -} -int prop_local_init_single (struct prop_local_single *pl);void prop_local_destroy_single (struct prop_local_single *pl);void __prop_inc_single (struct prop_descriptor *pd,struct prop_local_single *pl);
include/linux/proportions_types.h new file +29 -0
@@ -0,0 +1,29 @@ +#ifndef _LINUX_PROPORTIONS_TYPES_H +#define _LINUX_PROPORTIONS_TYPES_H + +/* +* ----- SINGLE ------ +*/ + +#include <linux/spinlock_types.h> + +struct prop_local_single { +/* +* the local events counter +*/ +unsigned long events; + +/* +* snapshot of the last seen global state +* and a lock protecting this state +*/ +unsigned long period; +int shift; +spinlock_t lock;/* protect the snapshot state */ +}; + +#define INIT_PROP_LOCAL_SINGLE (name) \ +{ .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ +} + +#endif
include/linux/rbtree.h +1 -7
@@ -96,16 +96,10 @@ static inline struct page * rb_insert_page_cache(struct inode * inode,#include <linux/kernel.h> #include <linux/stddef.h> +#include <linux/rbtree_types.h> -struct rb_node -{ -unsigned long rb_parent_color;#define RB_RED 0#define RB_BLACK 1 -struct rb_node *rb_right; -struct rb_node *rb_left; -} __attribute__((aligned (sizeof (long )))); -/* The alignment might seem pointless, but allegedly CRIS needs it */ struct rb_root {
include/linux/rbtree_types.h new file +11 -0
@@ -0,0 +1,11 @@ +#ifndef _LINUX_RBTREE_TYPES_H +#define _LINUX_RBTREE_TYPES_H + +struct rb_node { +unsigned long rb_parent_color; +struct rb_node *rb_right; +struct rb_node *rb_left; +} __attribute__((aligned (sizeof (long )))); +/* The alignment might seem pointless, but allegedly CRIS needs it */ + +#endif
include/linux/rcupdate.h +1 -10
@@ -42,6 +42,7 @@#include <linux/completion.h> #include <linux/debugobjects.h> #include <linux/compiler.h> +#include <linux/rcupdate_types.h> #ifdef CONFIG_RCU_TORTURE_TEST extern int rcutorture_runnable;/* for sysctl */
@@ -52,16 +53,6 @@ extern int rcutorture_runnable; /* for sysctl */#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; -/* Exported common interfaces */ extern void call_rcu_sched (struct rcu_head *head,void (*func)(struct rcu_head *rcu));
include/linux/rcupdate_types.h new file +14 -0
@@ -0,0 +1,14 @@ +#ifndef _LINUX_RCUPDATE_TYPES_H +#define _LINUX_RCUPDATE_TYPES_H + +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; + +#endif
include/linux/sched.h +2 -479
516 lines not on this page · raw message
include/linux/sched_types.h new file +493 -0
493 lines not on this page · raw message
include/linux/seccomp.h +1 -4
@@ -1,14 +1,13 @@ #ifndef _LINUX_SECCOMP_H #define _LINUX_SECCOMP_H +#include <linux/seccomp_types.h> #ifdef CONFIG_SECCOMP #include <linux/thread_info.h> #include <asm/seccomp.h> -typedef struct { int mode; } seccomp_t; - extern void __secure_computing(int); static inline void secure_computing(int this_syscall) {
@@ -23,8 +22,6 @@ extern long prctl_set_seccomp(unsigned long);#include <linux/errno.h> -typedef struct { }seccomp_t ; -#define secure_computing (x) do { } while (0)static inline long prctl_get_seccomp (void )
include/linux/seccomp_types.h new file +12 -0
@@ -0,0 +1,12 @@ +#ifndef _LINUX_SECCOMP_TYPES_H +#define _LINUX_SECCOMP_TYPES_H + + +#ifdef CONFIG_SECCOMP +typedef struct {int mode; }seccomp_t ; +#else +typedef struct { }seccomp_t ; +#endif + +#endif +
include/linux/sem.h +1 -4
@@ -2,6 +2,7 @@#define _LINUX_SEM_H#include <linux/ipc.h> +#include <linux/sem_types.h> /* semop flags */ #define SEM_UNDO 0x1000/* undo the operation on exit */
@@ -138,10 +139,6 @@ struct sem_undo_list {struct list_head list_proc; }; -struct sysv_sem { -struct sem_undo_list *undo_list; -}; -#ifdef CONFIG_SYSVIPC extern int copy_semundo (unsigned long clone_flags,struct task_struct *tsk);
include/linux/sem_types.h new file +10 -0
@@ -0,0 +1,10 @@ +#ifndef _LINUX_SEM_TYPES_H +#define _LINUX_SEM_TYPES_H + +struct sem_undo_list ; + +struct sysv_sem { +struct sem_undo_list *undo_list; +}; + +#endif
include/linux/task_io_accounting.h +2 -0
@@ -8,6 +8,8 @@* Blame Andrew Morton for all this. */ +#include <linux/types.h> +struct task_io_accounting {#ifdef CONFIG_TASK_XACCT /* bytes read */
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.
Urgh, not pretty.. so why not clean up sched.h properly? There's way too much cruft in there.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 8 lines · Peter Zijlstra
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.Urgh, not pretty.. so why not clean up
sched.hproperly? There's way too much cruft in there.
It was a proof-of-concept to show that it is doable to have proper definition of task_struct in rcupdate.h. Not an entry for any code beauty contest.
Michal
Lai Jiangshan
Acked-byRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 7 lines · Michal Marek
Quoted 6 lines · Peter Zijlstra
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.
Quoted 9 lines
Quoted 2 lines
Urgh, not pretty.. so why not clean up
sched.hproperly? There's way too much cruft in there.It was a proof-of-concept to show that it is doable to have proper definition of
task_structinrcupdate.h. Not an entry for any code beauty contest.Michal
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 15 lines · Lai Jiangshan
Quoted 14 lines · Michal Marek
Quoted 8 lines · Peter Zijlstra
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.Urgh, not pretty.. so why not clean up
sched.hproperly? There's way too much cruft in there.It was a proof-of-concept to show that it is doable to have proper definition of
task_structinrcupdate.h. Not an entry for any code beauty contest.
Quoted 8 lines
Quoted 2 lines
Michal
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
Acked-by Lai Jiangshan <[email protected]>
I certainly like the idea of being able to inline TREE_PREEMPT_RCU's rcu_read_lock() and rcu_read_unlock() using normal C code!
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 21 lines · Paul E. McKenney
Quoted 20 lines · Lai Jiangshan
Quoted 7 lines · Michal Marek
Quoted 6 lines · Peter Zijlstra
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.Quoted 9 lines
Quoted 2 lines
Urgh, not pretty.. so why not clean up
sched.hproperly? There's way too much cruft in there.It was a proof-of-concept to show that it is doable to have proper definition of
task_structinrcupdate.h. Not an entry for any code beauty contest.Michal
I like this cleanup, could you continue for this hard job? I will help you if required.
Quoted 9 lines
Quoted 3 lines
Ingo & Peter - will you accept the patches when it is done.
Acked-by Lai Jiangshan <[email protected]>I certainly like the idea of being able to inline TREE_PREEMPT_RCU's
rcu_read_lock()andrcu_read_unlock()using normal C code!Thanx, Paul
kernel-offset.c can be merged to some branch of your tree for testing inlined TREE_PREEMPT_RCU's rcu_read_lock() and rcu_read_unlock() before the kernel headers splitting is done.
Can the [patch 1/5] be merged to mainline earlier? could you add it to origin/rcu/next?
Thanks,
Lai
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 29 lines · Lai Jiangshan
Quoted 28 lines · Paul E. McKenney
Quoted 15 lines · Lai Jiangshan
Quoted 14 lines · Michal Marek
Quoted 8 lines · Peter Zijlstra
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.Urgh, not pretty.. so why not clean up
sched.hproperly? There's way too much cruft in there.It was a proof-of-concept to show that it is doable to have proper definition of
task_structinrcupdate.h. Not an entry for any code beauty contest.Quoted 8 lines
Quoted 2 lines
Michal
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
Acked-by Lai Jiangshan <[email protected]>I certainly like the idea of being able to inline TREE_PREEMPT_RCU's
rcu_read_lock()andrcu_read_unlock()using normal C code!
Quoted 8 lines
Quoted 2 lines
Thanx, Paul
kernel-offset.ccan be merged to some branch of your tree for testing inlined TREE_PREEMPT_RCU'srcu_read_lock()andrcu_read_unlock()before the kernel headers splitting is done.Can the [patch 1/5] be merged to mainline earlier? could you add it to origin/rcu/next?
Let's first settle on the overall direction, on the off-chance that someone comes up with an approach that doesn't require task_rcu_struct, or that requires it to be located somewhere other than include/linux/rcupdate.h.
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 37 lines · Paul E. McKenney
Quoted 36 lines · Lai Jiangshan
Quoted 21 lines · Paul E. McKenney
Quoted 20 lines · Lai Jiangshan
Quoted 7 lines · Michal Marek
Quoted 6 lines · Peter Zijlstra
Quoted 4 lines · Michal Marek
Subject: [PATCH] headers: Allow for lightweight inclusion of
task_structdefinitionFactor out a couple of type definitions to <header>_types.h to allow using
task_structwithout pulling tons of new dependencies viasched.h.Quoted 9 lines
Quoted 2 lines
Urgh, not pretty.. so why not clean up
sched.hproperly? There's way too much cruft in there.It was a proof-of-concept to show that it is doable to have proper definition of
task_structinrcupdate.h. Not an entry for any code beauty contest.Michal
I like this cleanup, could you continue for this hard job? I will help you if required.
Quoted 9 lines
Quoted 3 lines
Ingo & Peter - will you accept the patches when it is done.
Acked-by Lai Jiangshan <[email protected]>I certainly like the idea of being able to inline TREE_PREEMPT_RCU's
rcu_read_lock()andrcu_read_unlock()using normal C code!Thanx, Paul
kernel-offset.ccan be merged to some branch of your tree for testing inlined TREE_PREEMPT_RCU'srcu_read_lock()andrcu_read_unlock()before the kernel headers splitting is done.
Quoted 5 lines
Quoted 1 line
Can the [patch 1/5] be merged to mainline earlier? could you add it to origin/rcu/next?
Let's first settle on the overall direction, on the off-chance that someone comes up with an approach that doesn't require
task_rcu_struct, or that requires it to be located somewhere other thaninclude/linux/rcupdate.h.
And I have created a branch rcu/dev that contains the commits that I don't yet trust enough to send to -next. As before, rcu/kfree_rcu contains the commits that apply kfree_rcu() elsewhere in the kernel.
Thanx, Paul
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Lai JiangshanQuoted 5 lines · Lai Jiangshan
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
No, like I said, I think the proposed patch is utterly horrid.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 8 lines · Peter Zijlstra
Quoted 5 lines · Lai Jiangshan
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
No, like I said, I think the proposed patch is utterly horrid.
But how about my kernel-offset.c patch? It is clean & simple, it just seems not so normal.
If the proposed splitting patch is horrid, I think we will try to update it as you expect.
If splitting sched.h is wrong, I will try to persuade more people accept the kernel-offset.c patch.
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 10 lines · Lai Jiangshan
Quoted 8 lines · Peter Zijlstra
Quoted 5 lines · Lai Jiangshan
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
No, like I said, I think the proposed patch is utterly horrid.
Quoted 8 lines
But how about my
kernel-offset.cpatch? It is clean & simple, it just seems not so normal.If the proposed splitting patch is horrid, I think we will try to update it as you expect.
If splitting
sched.his wrong, I will try to persuade more people accept thekernel-offset.cpatch.
Well, I'm all for cleaning up sched.h, it includes way too much things not strongly related to kernel/sched*.c like a lot of the signal things and the misnamed signal_struct (should be called process_struct or somesuch).
That also causes the inversion between sched.h and wait.h
What I don't like is those _types.h headers, and definitely not the massive explosion of those as per the proposed patch.
Nor do I quite get why all that is needed, sched_types which would define task_struct still needs the new task_rcu_struct bits, and as per the patch you need to split the rcu headers into two. Once you've done that, I don't see why sched.h still needs splitting too.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 27 lines · Peter Zijlstra
Quoted 10 lines · Lai Jiangshan
Quoted 8 lines · Peter Zijlstra
Quoted 5 lines · Lai Jiangshan
I like this cleanup, could you continue for this hard job? I will help you if required.
Ingo & Peter - will you accept the patches when it is done.
No, like I said, I think the proposed patch is utterly horrid.
Quoted 8 lines
But how about my
kernel-offset.cpatch? It is clean & simple, it just seems not so normal.If the proposed splitting patch is horrid, I think we will try to update it as you expect.
If splitting
sched.his wrong, I will try to persuade more people accept thekernel-offset.cpatch.Well, I'm all for cleaning up
sched.h, it includes way too much things not strongly related tokernel/sched*.clike a lot of the signal things and the misnamedsignal_struct(should be calledprocess_structor somesuch).That also causes the inversion between
sched.handwait.h
Quoted 9 lines
What I don't like is those
_types.hheaders, and definitely not the massive explosion of those as per the proposed patch.Nor do I quite get why all that is needed,
sched_typeswhich would definetask_structstill needs the newtask_rcu_structbits, and as per the patch you need to split the rcu headers into two. Once you've done that, I don't see whysched.hstill needs splitting too.
"struct task_rcu_struct" is just a cleanup patch.
We are trying to use inlined read_read_[un]lock(), it is required that sched.h needs include rcupdate.h which causes many recursive including. Splitting rcupdate.h only does not help.
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 4 lines · Lai Jiangshan
We are trying to use inlined read_read_[un]lock(), it is required that
sched.hneeds includercupdate.hwhich causes many recursive including. Splittingrcupdate.honly does not help.
You're not making any kind of sense there.
linux-2.6# cat kernel/sched_tmp.c
#include <linux/sched.h>
linux-2.6# make kernel/sched_tmp.i
linux-2.6# awk '/^#/ { t=$0 } /rcu_read_lock/ { print t " " $0 }' kernel/sched_tmp.i
# 60 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline void __rcu_read_lock_bh(void)
# 60 "/usr/src/linux-2.6/include/linux/rcupdate.h" extern void __rcu_read_lock(void);
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline int rcu_read_lock_held(void)
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline int rcu_read_lock_bh_held(void)
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline int rcu_read_lock_sched_held(void)
# 559 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline void rcu_read_lock(void)
# 559 "/usr/src/linux-2.6/include/linux/rcupdate.h" __rcu_read_lock();
# 600 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline void rcu_read_lock_bh(void)
# 600 "/usr/src/linux-2.6/include/linux/rcupdate.h" __rcu_read_lock_bh();
# 627 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline void rcu_read_lock_sched(void)
# 627 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline __attribute__((no_instrument_function)) void rcu_read_lock_sched_notrace(void) # 70 "/usr/src/linux-2.6/include/linux/srcu.h" int __srcu_read_lock(struct srcu_struct *sp) ;
# 103 "/usr/src/linux-2.6/include/linux/srcu.h" static inline int srcu_read_lock_held(struct srcu_struct *sp)
# 149 "/usr/src/linux-2.6/include/linux/srcu.h" static inline int srcu_read_lock(struct srcu_struct *sp)
# 149 "/usr/src/linux-2.6/include/linux/srcu.h" int retval = __srcu_read_lock(sp);
# 1227 "/usr/src/linux-2.6/include/linux/sched.h" int rcu_read_lock_nesting;
# 1786 "/usr/src/linux-2.6/include/linux/sched.h" p->rcu_read_lock_nesting = 0;
There isn't a single rcu_read_lock() user in the include chain of sched.h, therefore its possible to split rcupdate.h such that one part includes the bits needed for sched.h and another part that includes sched.h and provides rcu_read_lock().
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 32 lines · Peter Zijlstra
Quoted 4 lines · Lai Jiangshan
We are trying to use inlined read_read_[un]lock(), it is required that
sched.hneeds includercupdate.hwhich causes many recursive including. Splittingrcupdate.honly does not help.You're not making any kind of sense there.
linux-2.6# cat
kernel/sched_tmp.c#include <
linux/sched.h>linux-2.6# make
kernel/sched_tmp.i
linux-2.6# awk '/^#/ { t=$0 } /rcu_read_lock/ { print t " " $0 }'kernel/sched_tmp.i
# 60 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline void__rcu_read_lock_bh(void)
# 60 "/usr/src/linux-2.6/include/linux/rcupdate.h" extern void__rcu_read_lock(void);
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline intrcu_read_lock_held(void)
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline intrcu_read_lock_bh_held(void)
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline intrcu_read_lock_sched_held(void)
# 559 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline voidrcu_read_lock(void)
# 559 "/usr/src/linux-2.6/include/linux/rcupdate.h"__rcu_read_lock();
# 600 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline voidrcu_read_lock_bh(void)
# 600 "/usr/src/linux-2.6/include/linux/rcupdate.h"__rcu_read_lock_bh();
# 627 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline voidrcu_read_lock_sched(void)
# 627 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline __attribute__((no_instrument_function)) voidrcu_read_lock_sched_notrace(void)# 70 "/usr/src/linux-2.6/include/linux/srcu.h" int__srcu_read_lock(struct srcu_struct *sp);
# 103 "/usr/src/linux-2.6/include/linux/srcu.h" static inline intsrcu_read_lock_held(struct srcu_struct *sp)
# 149 "/usr/src/linux-2.6/include/linux/srcu.h" static inline intsrcu_read_lock(struct srcu_struct *sp)
# 149 "/usr/src/linux-2.6/include/linux/srcu.h" int retval =__srcu_read_lock(sp);
# 1227 "/usr/src/linux-2.6/include/linux/sched.h" intrcu_read_lock_nesting;
# 1786 "/usr/src/linux-2.6/include/linux/sched.h"p->rcu_read_lock_nesting= 0;
Quoted 4 lines
There isn't a single
rcu_read_lock()user in the include chain ofsched.h, therefore its possible to splitrcupdate.hsuch that one part includes the bits needed forsched.hand another part that includessched.hand providesrcu_read_lock().
Yep, you can easily split struct rcu_head out into its own header file, and then include that into sched.h in place of rcupdate.h without trouble (at least in the few builds I tried).
The trouble comes when you take the next step and include sched.h into include/linux/rcutree.h, which would be needed to allow TREE_PREEMPT_RCU's rcu_read_lock() and rcu_read_unlock() to be inlined. This pulls sched.h into files that it was not already included into, and we do get build failures (the first of which requires changes local to RCU, FWIW).
Of course, it would be good to straighten this out.
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 42 lines · Paul E. McKenney
Quoted 32 lines · Peter Zijlstra
Quoted 4 lines · Lai Jiangshan
We are trying to use inlined read_read_[un]lock(), it is required that
sched.hneeds includercupdate.hwhich causes many recursive including. Splittingrcupdate.honly does not help.You're not making any kind of sense there.
linux-2.6# cat
kernel/sched_tmp.c#include <
linux/sched.h>linux-2.6# make
kernel/sched_tmp.i
linux-2.6# awk '/^#/ { t=$0 } /rcu_read_lock/ { print t " " $0 }'kernel/sched_tmp.i
# 60 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline void__rcu_read_lock_bh(void)
# 60 "/usr/src/linux-2.6/include/linux/rcupdate.h" extern void__rcu_read_lock(void);
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline intrcu_read_lock_held(void)
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline intrcu_read_lock_bh_held(void)
# 258 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline intrcu_read_lock_sched_held(void)
# 559 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline voidrcu_read_lock(void)
# 559 "/usr/src/linux-2.6/include/linux/rcupdate.h"__rcu_read_lock();
# 600 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline voidrcu_read_lock_bh(void)
# 600 "/usr/src/linux-2.6/include/linux/rcupdate.h"__rcu_read_lock_bh();
# 627 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline voidrcu_read_lock_sched(void)
# 627 "/usr/src/linux-2.6/include/linux/rcupdate.h" static inline __attribute__((no_instrument_function)) voidrcu_read_lock_sched_notrace(void)# 70 "/usr/src/linux-2.6/include/linux/srcu.h" int__srcu_read_lock(struct srcu_struct *sp);
# 103 "/usr/src/linux-2.6/include/linux/srcu.h" static inline intsrcu_read_lock_held(struct srcu_struct *sp)
# 149 "/usr/src/linux-2.6/include/linux/srcu.h" static inline intsrcu_read_lock(struct srcu_struct *sp)
# 149 "/usr/src/linux-2.6/include/linux/srcu.h" int retval =__srcu_read_lock(sp);
# 1227 "/usr/src/linux-2.6/include/linux/sched.h" intrcu_read_lock_nesting;
# 1786 "/usr/src/linux-2.6/include/linux/sched.h"p->rcu_read_lock_nesting= 0;Quoted 4 lines
There isn't a single
rcu_read_lock()user in the include chain ofsched.h, therefore its possible to splitrcupdate.hsuch that one part includes the bits needed forsched.hand another part that includessched.hand providesrcu_read_lock().Yep, you can easily split struct
rcu_headout into its own header file, and then include that intosched.hin place ofrcupdate.hwithout trouble (at least in the few builds I tried).
Quoted 8 lines
The trouble comes when you take the next step and include
sched.hintoinclude/linux/rcutree.h, which would be needed to allow TREE_PREEMPT_RCU'srcu_read_lock()andrcu_read_unlock()to be inlined. This pullssched.hinto files that it was not already included into, and we do get build failures (the first of which requires changes local to RCU, FWIW).Of course, it would be good to straighten this out.
And here is a start -- the build is -much- quieter with this patch.
The next layer on this onion is the use of the ctl_table typedef in include/linux/key.h -- which is defined to be struct ctl_table. Anyone know where struct ctl_table is defined? Color me blind, but I am not seeing it...
Thanx, Paul
------------------------------------------------------------------------
include/linux/rcu_head.h new file +46 -0
@@ -0,0 +1,46 @@ +/* +* Read-Copy Update mechanism for mutual exclusion: base structures +* +* 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, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Copyright IBM Corporation, 2001 +* +* Author: Dipankar Sarma <[email protected]> +* +* Based on the original work by Paul McKenney <[email protected]> +* and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. +* Papers: +* http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf +* http://lse.sourceforge.net/locking/rclock_OLS.2001.05.01c.sc.pdf (OLS2001) +* +* For detailed explanation of Read-Copy Update mechanism see - +* http://lse.sourceforge.net/locking/rcupdate.html +* +*/ + +#ifndef __LINUX_RCU_HEAD_H +#define __LINUX_RCU_HEAD_H + +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; + +#endif /* __LINUX_RCU_HEAD_H */
include/linux/rcupdate.h +9 -17
@@ -52,15 +52,7 @@ extern int rcutorture_runnable; /* for sysctl */#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; +#include <linux/rcu_head.h> /* Exported common interfaces */ extern void call_rcu_sched(struct rcu_head *head,
@@ -141,14 +133,6 @@ static inline void rcu_exit_nohz(void)#endif /* #else #ifdef CONFIG_NO_HZ */ -#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) -#include <linux/rcutree.h> -#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) -#include <linux/rcutiny.h> -#else -#error "Unknown RCU implementation specified to kernel configuration" -#endif -/* * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic * initialization and destruction of rcu_head on the stack. rcu_head structures
@@ -797,4 +781,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) +#include <linux/rcutree.h> +#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) +#include <linux/rcutiny.h> +#else +#error "Unknown RCU implementation specified to kernel configuration" +#endif +#endif /* __LINUX_RCUPDATE_H */
include/linux/rcutree.h +2 -0
@@ -30,6 +30,8 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +#include <linux/sched.h> +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);
include/linux/sched.h +4 -6
@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/rcu_head.h> #include <linux/rculist.h> #include <linux/rtmutex.h>
@@ -2241,11 +2241,9 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)return p1->tgid == p2->tgid; } -static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)static inline int thread_group_empty (struct task_struct *p) {
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 5 lines · Paul E. McKenney
The next layer on this onion is the use of the
ctl_tabletypedef ininclude/linux/key.h-- which is defined to be structctl_table. Anyone know where structctl_tableis defined? Color me blind, but I am not seeing it...
include/linux/sysctl.h:1015
/* A sysctl table is an array of struct ctl_table: */ struct ctl_table
{
const char *procname; /* Text ID for /proc/sys, or zero */
void *data;
int maxlen;
mode_t mode;
struct ctl_table *child;
struct ctl_table *parent; /* Automatically set */
proc_handler *proc_handler; /* Callback for text formatting */
void *extra1;
void *extra2;
};Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 8 lines · Peter Zijlstra
Quoted 5 lines · Paul E. McKenney
The next layer on this onion is the use of the
ctl_tabletypedef ininclude/linux/key.h-- which is defined to be structctl_table. Anyone know where structctl_tableis defined? Color me blind, but I am not seeing it...
include/linux/sysctl.h:1015
Thank you!
Thanx, Paul
Quoted 14 lines
/* A sysctl table is an array of struct
ctl_table: */ structctl_table{ const char *procname; /* Text ID for /proc/sys, or zero */ void *data; int maxlen; mode_t mode; struct ctl_table *child; struct ctl_table *parent; /* Automatically set */ proc_handler *proc_handler; /* Callback for text formatting */ void *extra1; void *extra2; };
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 11 lines · Paul E. McKenney
Quoted 8 lines · Peter Zijlstra
Quoted 5 lines · Paul E. McKenney
The next layer on this onion is the use of the
ctl_tabletypedef ininclude/linux/key.h-- which is defined to be structctl_table. Anyone know where structctl_tableis defined? Color me blind, but I am not seeing it...
include/linux/sysctl.h:1015Thank you!
And the following patch builds correctly for defconfig x86 builds, while allowing rcupdate.h to see the sched.h definitions as needed to inline rcu_read_lock() and rcu_read_unlock().
I will try allyesconfig builds and see what else breaks.
Thanx, Paul
include/linux/pid.h | 2 +- include/linux/rcupdate.h | 27 +++++++++------------------ include/linux/rcutree.h | 2 ++ include/linux/sched.h | 10 ++++------ include/linux/sem.h | 2 +- include/linux/sysctl.h | 5 +++-- include/linux/types.h | 10 ++++++++++ kernel/pid_namespace.c | 2 ++ 8 files changed, 32 insertions(+), 28 deletions(-)
include/linux/pid.h +1 -1
@@ -1,7 +1,7 @@#ifndef _LINUX_PID_H#define _LINUX_PID_H -#include <linux/rcupdate.h> +#include <linux/types.h> enum pid_type {
include/linux/rcupdate.h +9 -18
@@ -33,6 +33,7 @@#ifndef __LINUX_RCUPDATE_H#define __LINUX_RCUPDATE_H +#include <linux/types.h> #include <linux/cache.h> #include <linux/spinlock.h> #include <linux/threads.h>
@@ -52,16 +53,6 @@ extern int rcutorture_runnable; /* for sysctl */#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; -/* Exported common interfaces */ extern void call_rcu_sched (struct rcu_head *head,void (*func)(struct rcu_head *rcu));
@@ -141,14 +132,6 @@ static inline void rcu_exit_nohz(void)#endif /* #else #ifdef CONFIG_NO_HZ */ -#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) -#include <linux/rcutree.h> -#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) -#include <linux/rcutiny.h> -#else -#error "Unknown RCU implementation specified to kernel configuration" -#endif -/* * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic * initialization and destruction of rcu_head on the stack. rcu_head structures
@@ -797,4 +780,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) +#include <linux/rcutree.h> +#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) +#include <linux/rcutiny.h> +#else +#error "Unknown RCU implementation specified to kernel configuration" +#endif +#endif /* __LINUX_RCUPDATE_H */
include/linux/rcutree.h +2 -0
@@ -30,6 +30,8 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +#include <linux/sched.h> +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);
include/linux/sched.h +4 -6
@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/rculist.h> #include <linux/rtmutex.h>
@@ -2241,11 +2241,9 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)return p1->tgid == p2->tgid; } -static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)static inline int thread_group_empty (struct task_struct *p) {
include/linux/sem.h +1 -1
@@ -78,7 +78,7 @@ struct seminfo {#ifdef __KERNEL__#include <asm/atomic.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/cache.h> struct task_struct ;
include/linux/sysctl.h +3 -2
@@ -19,6 +19,8 @@**************************************************************** */ +#include <linux/key.h> +#ifndef _LINUX_SYSCTL_H#define _LINUX_SYSCTL_H
@@ -1012,8 +1014,7 @@ extern int proc_do_large_bitmap(struct ctl_table *, int,*/ /* A sysctl table is an array of struct ctl_table: */ -struct ctl_table -{ +struct ctl_table {const char *procname;/* Text ID for /proc/sys, or zero */ void *data;int maxlen;
include/linux/types.h +10 -0
@@ -231,6 +231,16 @@ struct hlist_node {struct hlist_node *next, **pprev; }; +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; +struct ustat {__kernel_daddr_t f_tfree;__kernel_ino_t f_tinode;
kernel/pid_namespace.c +2 -0
@@ -8,6 +8,8 @@* */ +#include <linux/types.h> +#include <asm/atomic.h> #include <linux/pid.h> #include <linux/pid_namespace.h> #include <linux/syscalls.h>
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().
Looks like an entirely reasonable patch to me ;-)
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
-hpa
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Thanx, Paul
------------------------------------------------------------------------
rcu: cleanups in CHECK portion of kernel build
Silence some complaints about kernel-only functionality being exposed to userspace.
include/linux/kernel.h +3 -0
@@ -648,6 +648,8 @@ struct sysinfo {#define BUILD_BUG_ON_ZERO (e) (sizeof(struct { int:-!!(e); }))#define BUILD_BUG_ON_NULL (e) ((void *)sizeof(struct { int:-!!(e); })) +#ifdef __KERNEL__ +/** * BUILD_BUG_ON - break compile if a condition is true. * @condition: the condition which the compiler should know is false.
@@ -673,6 +675,7 @@ extern int __build_bug_on_failed;if (condition) __build_bug_on_failed =1 ; \ } while(0) #endif +#endif /* __KERNEL__ */ /* Trap pasters of __FUNCTION__ at compile-time */ #define __FUNCTION__ (__func__)
include/linux/soundcard.h +2 -0
@@ -1064,7 +1064,9 @@ typedef struct mixer_vol_table {*/ #define SEQ_DECLAREBUF () SEQ_USE_EXTBUF() +#ifdef __KERNEL__void seqbuf_dump (void );/* This function must be provided by programs */ +#endif #define SEQ_PM_DEFINES int __foo_bar___
include/linux/sysctl.h +2 -0
@@ -19,7 +19,9 @@**************************************************************** */ +#ifdef __KERNEL__#include <linux/key.h> +#endif #ifndef _LINUX_SYSCTL_H#define _LINUX_SYSCTL_H
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 20 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Quoted 6 lines
Sam, Jan, Michal, help?
Thanx, Paul
------------------------------------------------------------------------
Easy to split rcupdate.h, hard to resolve the dependence problem.
You can apply the next additional patch when you test:
include/linux/rcupdate.h +6 -0
@@ -788,4 +788,10 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)#error "Unknown RCU implementation specified to kernel configuration"#endif +#include <linux/sched.h> +static inline long test_use_task_struct (void ) +{ +return current->state; +} +#endif /* __LINUX_RCUPDATE_H */
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
I am moving _rcu_read_lock() and _rcu_read_unlock() into include/linux/rcutree.h and include/linux/rcutiny.h, and I am sure that more pain will ensue.
One thing I don't understand... How does is it helping to group the task_struct RCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?
Also, does your patchset address the CHECK warnings?
Thanx, Paul
Quoted 20 lines
include/linux/rcupdate.h +6
-1@@ -788,4 +788,10 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)#error "Unknown RCU implementation specified to kernel configuration"#endif +#include <linux/sched.h> +static inline long test_use_task_struct (void ) +{ +return current->state; +} +#endif /* __LINUX_RCUPDATE_H */ --To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 39 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.
Quoted 5 lines
One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
One possible difference -- I did this work on top of a recent Linus git commit (b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.
Thanx, Paul
------------------------------------------------------------------------
rcu: inline preemptible rcu_read_lock() and rcu_read_unlock()
Move the definitions of __rcu_read_lock() and __rcu_read_unlock() from kernel/rcutree_plugin.h to include/linux/rcutree.h and from kernel/rcutiny_plugin.h to include/linux/rcutiny.h, allowing these functions to be inlined.
include/linux/rcutiny.h | 34 ++++++++++++++++++++++++++++++++++ include/linux/rcutree.h | 34 ++++++++++++++++++++++++++++++++++ kernel/rcutiny_plugin.h | 38 ++------------------------------------ kernel/rcutree_plugin.h | 38 ++------------------------------------ 4 files changed, 72 insertions(+), 72 deletions(-)
rcu: inline preemptible rcu_read_lock() and rcu_read_unlock()
Move the definitions of __rcu_read_lock() and __rcu_read_unlock() from kernel/rcutree_plugin.h to include/linux/rcutree.h and from kernel/rcutiny_plugin.h to include/linux/rcutiny.h, allowing these functions to be inlined.
include/linux/rcutiny.h +34 -0
@@ -47,6 +47,40 @@ static inline void rcu_barrier(void)void rcu_barrier (void );void synchronize_rcu_expedited (void ); +void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tiny-preemptible RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tiny-preemptible RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}#endif /* #else #ifdef CONFIG_TINY_RCU */
include/linux/rcutree.h +34 -0
@@ -40,6 +40,40 @@ extern void rcu_cpu_stall_reset(void);#ifdef CONFIG_TREE_PREEMPT_RCU extern void exit_rcu (void ); +extern void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tree-preemptable RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tree-preemptable RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
kernel/rcutiny_plugin.h +2 -36
@@ -520,23 +520,11 @@ void rcu_preempt_note_context_switch(void) }/* -* Tiny-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Handle special cases during rcu_read_unlock(), such as needing to * notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;
@@ -616,29 +604,7 @@ static void rcu_read_unlock_special(struct task_struct *t)#endif /* #ifdef CONFIG_RCU_BOOST */ local_irq_restore (flags); } - -/* -* Tiny-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);/* * Check for a quiescent state from the current CPU. When a task blocks,
kernel/rcutree_plugin.h +2 -36
@@ -196,18 +196,6 @@ static void rcu_preempt_note_context_switch(int cpu) }/* -* Tree-preemptable RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Check for preempted RCU readers blocking the current grace period * for the specified rcu_node structure. If the caller needs a reliable * answer, it must hold the rcu_node's ->lock.
@@ -261,7 +249,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;
@@ -332,29 +320,7 @@ static void rcu_read_unlock_special(struct task_struct *t)local_irq_restore (flags); } } - -/* -* Tree-preemptable RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 36 lines · Paul E. McKenney
Quoted 35 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
Quoted 7 lines
Quoted 7 lines
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?
You don't like task_rcu_struct patch? I think it can make code clearer, and it can also check the code even when CONFIG_PREEMPT_RCU=n.
For rcu_read_[un]lock(), it generates the same code, no better, no worse.
It is just a cleanup patch, it is helpless for making rcu_read_[un]lock() inline, if you don't like it, I will give up it.
Quoted 7 lines
Quoted 2 lines
Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
Quoted 7 lines
One possible difference -- I did this work on top of a recent Linus git commit (
b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.Thanx, Paul
when defconfig or allyesconfig, CONFIG_PREEMPT=n and CONFIG_TREE_PREEMPT_RCU=n when you make them "y":
In file included from include/linux/rcupdate.h:764:0,
from include/linux/tracepoint.h:19,
from include/linux/module.h:18,
from include/linux/crypto.h:21,
from arch/x86/kernel/asm-offsets.c:8:include/linux/rcutree.h:50:20: error: static declaration of ‘__rcu_read_lock’ follows non-static declaration include/linux/rcupdate.h:76:13: note: previous declaration of ‘__rcu_read_lock’ was here include/linux/rcutree.h:63:20: error: static declaration of ‘__rcu_read_unlock’ follows non-static declaration include/linux/rcupdate.h:77:13: note: previous declaration of ‘__rcu_read_unlock’ was here make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
make: *** [prepare0] Error 2
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 45 lines · Lai Jiangshan
Quoted 36 lines · Paul E. McKenney
Quoted 35 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
Quoted 7 lines
Quoted 7 lines
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?
Quoted 7 lines
You don't like
task_rcu_structpatch? I think it can make code clearer, and it can also check the code even whenCONFIG_PREEMPT_RCU=n.For rcu_read_[un]lock(), it generates the same code, no better, no worse.
It is just a cleanup patch, it is helpless for making rcu_read_[un]lock() inline, if you don't like it, I will give up it.
I don't know that I feel strongly either way about it. It was necessary with the integer-offset approach, but optional now.
Quoted 22 lines
Quoted 6 lines
Quoted 1 line
Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
Quoted 7 lines
One possible difference -- I did this work on top of a recent Linus git commit (
b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.Thanx, Paul
when defconfig or allyesconfig,
CONFIG_PREEMPT=nandCONFIG_TREE_PREEMPT_RCU=nwhen you make them "y":In file included from
include/linux/rcupdate.h:764:0,from include/linux/tracepoint.h:19, from include/linux/module.h:18, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets.c:8:
Quoted 6 lines
include/linux/rcutree.h:50:20: error: static declaration of ‘__rcu_read_lock’ follows non-static declarationinclude/linux/rcupdate.h:76:13: note: previous declaration of ‘__rcu_read_lock’ was hereinclude/linux/rcutree.h:63:20: error: static declaration of ‘__rcu_read_unlock’ follows non-static declarationinclude/linux/rcupdate.h:77:13: note: previous declaration of ‘__rcu_read_unlock’ was here make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
make: *** [prepare0] Error 2
Yep. I need to move the rcu_read_lock() APIs to follow the inclusion of rcutree.h and rcutiny.h. Also add include of sched.h to rcutiny.h. The code movement does bloat the patch a bit. But rcu_assign_pointer() must precede the inclusion of rcutree.h and rcutiny.h, so it is not possible to simply move the inclusions. See below.
Thanx, Paul
------------------------------------------------------------------------
include/linux/kernel.h +3 -0
@@ -648,6 +648,8 @@ struct sysinfo {#define BUILD_BUG_ON_ZERO (e) (sizeof(struct { int:-!!(e); }))#define BUILD_BUG_ON_NULL (e) ((void *)sizeof(struct { int:-!!(e); })) +#ifdef __KERNEL__ +/** * BUILD_BUG_ON - break compile if a condition is true. * @condition: the condition which the compiler should know is false.
@@ -673,6 +675,7 @@ extern int __build_bug_on_failed;if (condition) __build_bug_on_failed =1 ; \ } while(0) #endif +#endif /* __KERNEL__ */ /* Trap pasters of __FUNCTION__ at compile-time */ #define __FUNCTION__ (__func__)
include/linux/pid.h +1 -1
@@ -1,7 +1,7 @@#ifndef _LINUX_PID_H#define _LINUX_PID_H -#include <linux/rcupdate.h> +#include <linux/types.h> enum pid_type {
include/linux/rcupdate.h +129 -140
303 lines not on this page · raw message
include/linux/rcutiny.h +35 -0
@@ -26,6 +26,7 @@#define __LINUX_TINY_H#include <linux/cache.h> +#include <linux/sched.h> static inline void rcu_init (void ) {
@@ -47,6 +48,40 @@ static inline void rcu_barrier(void)void rcu_barrier (void );void synchronize_rcu_expedited (void ); +void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tiny-preemptible RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tiny-preemptible RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}#endif /* #else #ifdef CONFIG_TINY_RCU */
include/linux/rcutree.h +36 -0
@@ -30,6 +30,8 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +#include <linux/sched.h> +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);
@@ -38,6 +40,40 @@ extern void rcu_cpu_stall_reset(void);#ifdef CONFIG_TREE_PREEMPT_RCU extern void exit_rcu (void ); +extern void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tree-preemptable RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tree-preemptable RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
include/linux/sched.h +4 -6
@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/rculist.h> #include <linux/rtmutex.h>
@@ -2241,11 +2241,9 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)return p1->tgid == p2->tgid; } -static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)static inline int thread_group_empty (struct task_struct *p) {
include/linux/sem.h +1 -1
@@ -78,7 +78,7 @@ struct seminfo {#ifdef __KERNEL__#include <asm/atomic.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/cache.h> struct task_struct ;
include/linux/soundcard.h +2 -0
@@ -1064,7 +1064,9 @@ typedef struct mixer_vol_table {*/ #define SEQ_DECLAREBUF () SEQ_USE_EXTBUF() +#ifdef __KERNEL__void seqbuf_dump (void );/* This function must be provided by programs */ +#endif #define SEQ_PM_DEFINES int __foo_bar___
include/linux/sysctl.h +5 -2
@@ -19,6 +19,10 @@**************************************************************** */ +#ifdef __KERNEL__ +#include <linux/key.h> +#endif +#ifndef _LINUX_SYSCTL_H#define _LINUX_SYSCTL_H
@@ -1012,8 +1016,7 @@ extern int proc_do_large_bitmap(struct ctl_table *, int,*/ /* A sysctl table is an array of struct ctl_table: */ -struct ctl_table -{ +struct ctl_table {const char *procname;/* Text ID for /proc/sys, or zero */ void *data;int maxlen;
include/linux/types.h +10 -0
@@ -231,6 +231,16 @@ struct hlist_node {struct hlist_node *next, **pprev; }; +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; +struct ustat {__kernel_daddr_t f_tfree;__kernel_ino_t f_tinode;
kernel/pid_namespace.c +2 -0
@@ -8,6 +8,8 @@* */ +#include <linux/types.h> +#include <asm/atomic.h> #include <linux/pid.h> #include <linux/pid_namespace.h> #include <linux/syscalls.h>
kernel/rcutiny_plugin.h +2 -36
@@ -520,23 +520,11 @@ void rcu_preempt_note_context_switch(void) }/* -* Tiny-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Handle special cases during rcu_read_unlock(), such as needing to * notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;
@@ -616,29 +604,7 @@ static void rcu_read_unlock_special(struct task_struct *t)#endif /* #ifdef CONFIG_RCU_BOOST */ local_irq_restore (flags); } - -/* -* Tiny-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);/* * Check for a quiescent state from the current CPU. When a task blocks,
kernel/rcutree_plugin.h +2 -36
@@ -196,18 +196,6 @@ static void rcu_preempt_note_context_switch(int cpu) }/* -* Tree-preemptable RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Check for preempted RCU readers blocking the current grace period * for the specified rcu_node structure. If the caller needs a reliable * answer, it must hold the rcu_node's ->lock.
@@ -261,7 +249,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;
@@ -332,29 +320,7 @@ static void rcu_read_unlock_special(struct task_struct *t)local_irq_restore (flags); } } - -/* -* Tree-preemptable RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 86 lines · Paul E. McKenney
Quoted 45 lines · Lai Jiangshan
Quoted 36 lines · Paul E. McKenney
Quoted 35 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
Quoted 7 lines
Quoted 7 lines
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?Quoted 7 lines
You don't like
task_rcu_structpatch? I think it can make code clearer, and it can also check the code even whenCONFIG_PREEMPT_RCU=n.For rcu_read_[un]lock(), it generates the same code, no better, no worse.
It is just a cleanup patch, it is helpless for making rcu_read_[un]lock() inline, if you don't like it, I will give up it.
I don't know that I feel strongly either way about it. It was necessary with the integer-offset approach, but optional now.
Quoted 22 lines
Quoted 6 lines
Quoted 1 line
Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
Quoted 7 lines
One possible difference -- I did this work on top of a recent Linus git commit (
b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.Thanx, Paul
when defconfig or allyesconfig,
CONFIG_PREEMPT=nandCONFIG_TREE_PREEMPT_RCU=nwhen you make them "y":In file included from
include/linux/rcupdate.h:764:0,from include/linux/tracepoint.h:19, from include/linux/module.h:18, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets.c:8:Quoted 6 lines
include/linux/rcutree.h:50:20: error: static declaration of ‘__rcu_read_lock’ follows non-static declarationinclude/linux/rcupdate.h:76:13: note: previous declaration of ‘__rcu_read_lock’ was hereinclude/linux/rcutree.h:63:20: error: static declaration of ‘__rcu_read_unlock’ follows non-static declarationinclude/linux/rcupdate.h:77:13: note: previous declaration of ‘__rcu_read_unlock’ was here make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
make: *** [prepare0] Error 2
Quoted 8 lines
Yep. I need to move the
rcu_read_lock()APIs to follow the inclusion ofrcutree.handrcutiny.h. Also add include ofsched.htorcutiny.h. The code movement does bloat the patch a bit. Butrcu_assign_pointer()must precede the inclusion ofrcutree.handrcutiny.h, so it is not possible to simply move the inclusions. See below.Thanx, Paul
sched.h still contains rcupdate.h after applied this patch. See my [PATCH 2/4] for more info.
# make lib/is_single_threaded.o
CHK include/linux/version.h
CHK include/generated/utsrelease.h
CALL scripts/checksyscalls.sh
CC lib/is_single_threaded.o
In file included from include/linux/rcupdate.h:639:0,
from include/linux/rculist.h:10,
from include/linux/sched.h:82,
from lib/is_single_threaded.c:13:
include/linux/rcutree.h: In function ‘__rcu_read_lock’:
include/linux/rcutree.h:52:15: error: dereferencing pointer to incomplete type
In file included from include/linux/rcupdate.h:639:0,
from include/linux/rculist.h:10,
from include/linux/sched.h:82,
from lib/is_single_threaded.c:13:
include/linux/rcutree.h: In function ‘__rcu_read_unlock’:
include/linux/rcutree.h:68:5: error: dereferencing pointer to incomplete type
include/linux/rcutree.h:70:7: error: dereferencing pointer to incomplete type
include/linux/rcutree.h:71:46: error: dereferencing pointer to incomplete type
include/linux/rcutree.h:71:78: error: dereferencing pointer to incomplete type
include/linux/rcutree.h:71:6: warning: type defaults to ‘int’ in type name
make[1]: *** [lib/is_single_threaded.o] Error 1
make: *** [lib/is_single_threaded.o] Error 2Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 93 lines · Lai Jiangshan
Quoted 92 lines · Paul E. McKenney
Quoted 45 lines · Lai Jiangshan
Quoted 36 lines · Paul E. McKenney
Quoted 35 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
Quoted 7 lines
Quoted 7 lines
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?Quoted 7 lines
You don't like
task_rcu_structpatch? I think it can make code clearer, and it can also check the code even whenCONFIG_PREEMPT_RCU=n.For rcu_read_[un]lock(), it generates the same code, no better, no worse.
It is just a cleanup patch, it is helpless for making rcu_read_[un]lock() inline, if you don't like it, I will give up it.
I don't know that I feel strongly either way about it. It was necessary with the integer-offset approach, but optional now.
Quoted 22 lines
Quoted 6 lines
Quoted 1 line
Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
Quoted 7 lines
One possible difference -- I did this work on top of a recent Linus git commit (
b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.Thanx, Paul
when defconfig or allyesconfig,
CONFIG_PREEMPT=nandCONFIG_TREE_PREEMPT_RCU=nwhen you make them "y":In file included from
include/linux/rcupdate.h:764:0,from include/linux/tracepoint.h:19, from include/linux/module.h:18, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets.c:8:Quoted 6 lines
include/linux/rcutree.h:50:20: error: static declaration of ‘__rcu_read_lock’ follows non-static declarationinclude/linux/rcupdate.h:76:13: note: previous declaration of ‘__rcu_read_lock’ was hereinclude/linux/rcutree.h:63:20: error: static declaration of ‘__rcu_read_unlock’ follows non-static declarationinclude/linux/rcupdate.h:77:13: note: previous declaration of ‘__rcu_read_unlock’ was here make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
make: *** [prepare0] Error 2Yep. I need to move the
rcu_read_lock()APIs to follow the inclusion ofrcutree.handrcutiny.h. Also add include ofsched.htorcutiny.h. The code movement does bloat the patch a bit. Butrcu_assign_pointer()must precede the inclusion ofrcutree.handrcutiny.h, so it is not possible to simply move the inclusions. See below.
Quoted 4 lines
Quoted 2 lines
Thanx, Paul
sched.hstill containsrcupdate.hafter applied this patch.
Then we are not in sync -- sched.h does not include rcupdate.h in my tree. It instead gets the struct rcu_head definition from include/linux/types.h. See below for a consolidated patch.
Thanx, Paul
Quoted 18 lines
See my [PATCH 2/4] for more info.
# make lib/is_single_threaded.o CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CC lib/is_single_threaded.o In file included from include/linux/rcupdate.h:639:0, from include/linux/rculist.h:10, from include/linux/sched.h:82, from lib/is_single_threaded.c:13: include/linux/rcutree.h: In function ‘__rcu_read_lock’: include/linux/rcutree.h:52:15: error: dereferencing pointer to incomplete type In file included from include/linux/rcupdate.h:639:0, from include/linux/rculist.h:10, from include/linux/sched.h:82, from lib/is_single_threaded.c:13:
Quoted 8 lines
include/linux/rcutree.h: In function ‘__rcu_read_unlock’: include/linux/rcutree.h:68:5: error: dereferencing pointer to incomplete type include/linux/rcutree.h:70:7: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:46: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:78: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:6: warning: type defaults to ‘int’ in type name make[1]: *** [lib/is_single_threaded.o] Error 1 make: *** [lib/is_single_threaded.o] Error 2
drivers/scsi/scsi_sysctl.c | 1 + fs/proc/proc_sysctl.c | 1 + include/linux/kernel.h | 3 +++ include/linux/pid.h | 2 +- include/linux/rcupdate.h | 29 +++++++++-------------------- include/linux/rcutiny.h | 35 +++++++++++++++++++++++++++++++++++ include/linux/rcutree.h | 37 +++++++++++++++++++++++++++++++++++++ include/linux/sched.h | 10 ++++------ include/linux/sem.h | 2 +- include/linux/soundcard.h | 2 ++ include/linux/sysctl.h | 5 +++-- include/linux/types.h | 10 ++++++++++ kernel/pid_namespace.c | 2 ++ kernel/rcutiny_plugin.h | 38 ++------------------------------------ kernel/rcutree_plugin.h | 38 ++------------------------------------ kernel/sysctl_binary.c | 1 + kernel/sysctl_check.c | 1 + net/core/sysctl_net_core.c | 1 + net/dccp/sysctl.c | 1 + net/ipv6/sysctl_net_ipv6.c | 1 + net/irda/irsysctl.c | 1 + net/phonet/sysctl.c | 1 + net/rds/ib_sysctl.c | 1 + net/rds/iw_sysctl.c | 1 + net/rds/sysctl.c | 1 + net/sctp/sysctl.c | 1 + net/sunrpc/sysctl.c | 1 + net/unix/sysctl_net_unix.c | 1 + net/xfrm/xfrm_sysctl.c | 1 + 29 files changed, 127 insertions(+), 102 deletions(-)
drivers/scsi/scsi_sysctl.c +1 -0
@@ -6,6 +6,7 @@#include <linux/errno.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "scsi_logging.h"
fs/proc/proc_sysctl.c +1 -0
@@ -2,6 +2,7 @@* /proc/sys support */ #include <linux/init.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/security.h>
include/linux/kernel.h +3 -0
@@ -648,6 +648,8 @@ struct sysinfo {#define BUILD_BUG_ON_ZERO (e) (sizeof(struct { int:-!!(e); }))#define BUILD_BUG_ON_NULL (e) ((void *)sizeof(struct { int:-!!(e); })) +#ifdef __KERNEL__ +/** * BUILD_BUG_ON - break compile if a condition is true. * @condition: the condition which the compiler should know is false.
@@ -673,6 +675,7 @@ extern int __build_bug_on_failed;if (condition) __build_bug_on_failed =1 ; \ } while(0) #endif +#endif /* __KERNEL__ */ /* Trap pasters of __FUNCTION__ at compile-time */ #define __FUNCTION__ (__func__)
include/linux/pid.h +1 -1
@@ -1,7 +1,7 @@#ifndef _LINUX_PID_H#define _LINUX_PID_H -#include <linux/rcupdate.h> +#include <linux/types.h> enum pid_type {
include/linux/rcupdate.h +9 -20
@@ -33,6 +33,7 @@#ifndef __LINUX_RCUPDATE_H#define __LINUX_RCUPDATE_H +#include <linux/types.h> #include <linux/cache.h> #include <linux/spinlock.h> #include <linux/threads.h>
@@ -52,16 +53,6 @@ extern int rcutorture_runnable; /* for sysctl */#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; -/* Exported common interfaces */ extern void call_rcu_sched (struct rcu_head *head,void (*func)(struct rcu_head *rcu));
@@ -82,8 +73,6 @@ static inline void __rcu_read_unlock_bh(void)#ifdef CONFIG_PREEMPT_RCU -extern void __rcu_read_lock (void ); -extern void __rcu_read_unlock (void );void synchronize_rcu (void );/*
@@ -141,14 +130,6 @@ static inline void rcu_exit_nohz(void)#endif /* #else #ifdef CONFIG_NO_HZ */ -#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) -#include <linux/rcutree.h> -#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) -#include <linux/rcutiny.h> -#else -#error "Unknown RCU implementation specified to kernel configuration" -#endif -/* * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic * initialization and destruction of rcu_head on the stack. rcu_head structures
@@ -797,4 +778,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) +#include <linux/rcutree.h> +#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) +#include <linux/rcutiny.h> +#else +#error "Unknown RCU implementation specified to kernel configuration" +#endif +#endif /* __LINUX_RCUPDATE_H */
include/linux/rcutiny.h +35 -0
@@ -26,6 +26,7 @@#define __LINUX_TINY_H#include <linux/cache.h> +#include <linux/sched.h> static inline void rcu_init (void ) {
@@ -47,6 +48,40 @@ static inline void rcu_barrier(void)void rcu_barrier (void );void synchronize_rcu_expedited (void ); +void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tiny-preemptible RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tiny-preemptible RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}#endif /* #else #ifdef CONFIG_TINY_RCU */
include/linux/rcutree.h +37 -0
@@ -30,6 +30,8 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +#include <linux/sched.h> +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);
@@ -37,6 +39,41 @@ extern void rcu_cpu_stall_reset(void);#ifdef CONFIG_TREE_PREEMPT_RCU +extern void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tree-preemptable RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tree-preemptable RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +} +extern void exit_rcu (void );#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
include/linux/sched.h +4 -6
@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/rculist.h> #include <linux/rtmutex.h>
@@ -2241,11 +2241,9 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)return p1->tgid == p2->tgid; } -static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)static inline int thread_group_empty (struct task_struct *p) {
include/linux/sem.h +1 -1
@@ -78,7 +78,7 @@ struct seminfo {#ifdef __KERNEL__#include <asm/atomic.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/cache.h> struct task_struct ;
include/linux/soundcard.h +2 -0
@@ -1064,7 +1064,9 @@ typedef struct mixer_vol_table {*/ #define SEQ_DECLAREBUF () SEQ_USE_EXTBUF() +#ifdef __KERNEL__void seqbuf_dump (void );/* This function must be provided by programs */ +#endif #define SEQ_PM_DEFINES int __foo_bar___
include/linux/sysctl.h +3 -2
@@ -19,6 +19,8 @@**************************************************************** */ +#include <linux/key.h> +#ifndef _LINUX_SYSCTL_H#define _LINUX_SYSCTL_H
@@ -1012,8 +1014,7 @@ extern int proc_do_large_bitmap(struct ctl_table *, int,*/ /* A sysctl table is an array of struct ctl_table: */ -struct ctl_table -{ +struct ctl_table {const char *procname;/* Text ID for /proc/sys, or zero */ void *data;int maxlen;
include/linux/types.h +10 -0
@@ -231,6 +231,16 @@ struct hlist_node {struct hlist_node *next, **pprev; }; +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; +struct ustat {__kernel_daddr_t f_tfree;__kernel_ino_t f_tinode;
kernel/pid_namespace.c +2 -0
@@ -8,6 +8,8 @@* */ +#include <linux/types.h> +#include <asm/atomic.h> #include <linux/pid.h> #include <linux/pid_namespace.h> #include <linux/syscalls.h>
kernel/rcutiny_plugin.h +2 -36
@@ -520,23 +520,11 @@ void rcu_preempt_note_context_switch(void) }/* -* Tiny-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Handle special cases during rcu_read_unlock(), such as needing to * notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;
@@ -616,29 +604,7 @@ static void rcu_read_unlock_special(struct task_struct *t)#endif /* #ifdef CONFIG_RCU_BOOST */ local_irq_restore (flags); } - -/* -* Tiny-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);/* * Check for a quiescent state from the current CPU. When a task blocks,
kernel/rcutree_plugin.h +2 -36
@@ -196,18 +196,6 @@ static void rcu_preempt_note_context_switch(int cpu) }/* -* Tree-preemptable RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Check for preempted RCU readers blocking the current grace period * for the specified rcu_node structure. If the caller needs a reliable * answer, it must hold the rcu_node's ->lock.
@@ -261,7 +249,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;
@@ -332,29 +320,7 @@ static void rcu_read_unlock_special(struct task_struct *t)local_irq_restore (flags); } } - -/* -* Tree-preemptable RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
kernel/sysctl_binary.c +1 -0
@@ -1,4 +1,5 @@#include <linux/stat.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "../fs/xfs/linux-2.6/xfs_sysctl.h" #include <linux/sunrpc/debug.h>
kernel/sysctl_check.c +1 -0
@@ -1,4 +1,5 @@#include <linux/stat.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "../fs/xfs/linux-2.6/xfs_sysctl.h" #include <linux/sunrpc/debug.h>
net/core/sysctl_net_core.c +1 -0
@@ -6,6 +6,7 @@*/ #include <linux/mm.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/module.h> #include <linux/socket.h>
net/dccp/sysctl.c +1 -0
@@ -10,6 +10,7 @@*/ #include <linux/mm.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "dccp.h" #include "feat.h"
net/ipv6/sysctl_net_ipv6.c +1 -0
@@ -6,6 +6,7 @@*/ #include <linux/mm.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/in6.h> #include <linux/ipv6.h>
net/irda/irsysctl.c +1 -0
@@ -25,6 +25,7 @@#include <linux/mm.h> #include <linux/ctype.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/init.h>
net/phonet/sysctl.c +1 -0
@@ -23,6 +23,7 @@*/ #include <linux/seqlock.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/errno.h> #include <linux/init.h>
net/rds/ib_sysctl.c +1 -0
@@ -31,6 +31,7 @@* */ #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h>
net/rds/iw_sysctl.c +1 -0
@@ -31,6 +31,7 @@* */ #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h>
net/rds/sysctl.c +1 -0
@@ -31,6 +31,7 @@* */ #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h>
net/sctp/sysctl.c +1 -0
@@ -43,6 +43,7 @@#include <net/sctp/structs.h> #include <net/sctp/sctp.h> +#include <linux/key.h> #include <linux/sysctl.h> static int zero =0 ;
net/sunrpc/sysctl.c +1 -0
@@ -11,6 +11,7 @@#include <linux/linkage.h> #include <linux/ctype.h> #include <linux/fs.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/module.h>
net/unix/sysctl_net_unix.c +1 -0
@@ -11,6 +11,7 @@#include <linux/mm.h> #include <linux/slab.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <net/af_unix.h>
net/xfrm/xfrm_sysctl.c +1 -0
@@ -1,3 +1,4 @@ +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/slab.h> #include <net/net_namespace.h>
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 97 lines · Paul E. McKenney
Quoted 96 lines · Lai Jiangshan
Quoted 94 lines · Paul E. McKenney
Quoted 45 lines · Lai Jiangshan
Quoted 36 lines · Paul E. McKenney
Quoted 35 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
Quoted 7 lines
Quoted 7 lines
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?Quoted 7 lines
You don't like
task_rcu_structpatch? I think it can make code clearer, and it can also check the code even whenCONFIG_PREEMPT_RCU=n.For rcu_read_[un]lock(), it generates the same code, no better, no worse.
It is just a cleanup patch, it is helpless for making rcu_read_[un]lock() inline, if you don't like it, I will give up it.
I don't know that I feel strongly either way about it. It was necessary with the integer-offset approach, but optional now.
Quoted 22 lines
Quoted 6 lines
Quoted 1 line
Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
Quoted 7 lines
One possible difference -- I did this work on top of a recent Linus git commit (
b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.Thanx, Paul
when defconfig or allyesconfig,
CONFIG_PREEMPT=nandCONFIG_TREE_PREEMPT_RCU=nwhen you make them "y":In file included from
include/linux/rcupdate.h:764:0,from include/linux/tracepoint.h:19, from include/linux/module.h:18, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets.c:8:Quoted 6 lines
include/linux/rcutree.h:50:20: error: static declaration of ‘__rcu_read_lock’ follows non-static declarationinclude/linux/rcupdate.h:76:13: note: previous declaration of ‘__rcu_read_lock’ was hereinclude/linux/rcutree.h:63:20: error: static declaration of ‘__rcu_read_unlock’ follows non-static declarationinclude/linux/rcupdate.h:77:13: note: previous declaration of ‘__rcu_read_unlock’ was here make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
make: *** [prepare0] Error 2Yep. I need to move the
rcu_read_lock()APIs to follow the inclusion ofrcutree.handrcutiny.h. Also add include ofsched.htorcutiny.h. The code movement does bloat the patch a bit. Butrcu_assign_pointer()must precede the inclusion ofrcutree.handrcutiny.h, so it is not possible to simply move the inclusions. See below.Thanx, Paul
Quoted 34 lines
Quoted 1 line
sched.hstill containsrcupdate.hafter applied this patch.Then we are not in sync --
sched.hdoes not includercupdate.hin my tree. It instead gets the structrcu_headdefinition frominclude/linux/types.h. See below for a consolidated patch.Thanx, Paul
Quoted 26 lines
See my [PATCH 2/4] for more info.
# make lib/is_single_threaded.o CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CC lib/is_single_threaded.o In file included from include/linux/rcupdate.h:639:0, from include/linux/rculist.h:10, from include/linux/sched.h:82, from lib/is_single_threaded.c:13: include/linux/rcutree.h: In function ‘__rcu_read_lock’: include/linux/rcutree.h:52:15: error: dereferencing pointer to incomplete type In file included from include/linux/rcupdate.h:639:0, from include/linux/rculist.h:10, from include/linux/sched.h:82, from lib/is_single_threaded.c:13: include/linux/rcutree.h: In function ‘__rcu_read_unlock’: include/linux/rcutree.h:68:5: error: dereferencing pointer to incomplete type include/linux/rcutree.h:70:7: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:46: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:78: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:6: warning: type defaults to ‘int’ in type name make[1]: *** [lib/is_single_threaded.o] Error 1 make: *** [lib/is_single_threaded.o] Error 2
sched.h still contains rcupdate.h after applied this patch. so it still fails.
Is your .config with CONFIG_TREE_PREEMPT_RCU=y ?
Quoted 661 lines
drivers/scsi/scsi_sysctl.c | 1 + fs/proc/proc_sysctl.c | 1 + include/linux/kernel.h | 3 +++ include/linux/pid.h | 2 +- include/linux/rcupdate.h | 29 +++++++++-------------------- include/linux/rcutiny.h | 35 +++++++++++++++++++++++++++++++++++ include/linux/rcutree.h | 37 +++++++++++++++++++++++++++++++++++++ include/linux/sched.h | 10 ++++------ include/linux/sem.h | 2 +- include/linux/soundcard.h | 2 ++ include/linux/sysctl.h | 5 +++-- include/linux/types.h | 10 ++++++++++ kernel/pid_namespace.c | 2 ++ kernel/rcutiny_plugin.h | 38 ++------------------------------------ kernel/rcutree_plugin.h | 38 ++------------------------------------ kernel/sysctl_binary.c | 1 + kernel/sysctl_check.c | 1 + net/core/sysctl_net_core.c | 1 + net/dccp/sysctl.c | 1 + net/ipv6/sysctl_net_ipv6.c | 1 + net/irda/irsysctl.c | 1 + net/phonet/sysctl.c | 1 + net/rds/ib_sysctl.c | 1 + net/rds/iw_sysctl.c | 1 + net/rds/sysctl.c | 1 + net/sctp/sysctl.c | 1 + net/sunrpc/sysctl.c | 1 + net/unix/sysctl_net_unix.c | 1 + net/xfrm/xfrm_sysctl.c | 1 + 29 files changed, 127 insertions(+), 102 deletions(-)drivers/scsi/scsi_sysctl.c +1
-0@@ -6,6 +6,7 @@#include <linux/errno.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "scsi_logging.h" fs/proc/proc_sysctl.c +1
-0@@ -2,6 +2,7 @@* /proc/sys support */ #include <linux/init.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/security.h> include/linux/kernel.h +3
-0@@ -648,6 +648,8 @@ struct sysinfo {#define BUILD_BUG_ON_ZERO (e) (sizeof(struct { int:-!!(e); }))#define BUILD_BUG_ON_NULL (e) ((void *)sizeof(struct { int:-!!(e); })) +#ifdef __KERNEL__ +/** * BUILD_BUG_ON - break compile if a condition is true. * @condition: the condition which the compiler should know is false. @@ -673,6 +675,7 @@ extern int __build_bug_on_failed;if (condition) __build_bug_on_failed =1 ; \ } while(0) #endif +#endif /* __KERNEL__ */ /* Trap pasters of __FUNCTION__ at compile-time */ #define __FUNCTION__ (__func__)include/linux/pid.h +1
-1@@ -1,7 +1,7 @@#ifndef _LINUX_PID_H#define _LINUX_PID_H -#include <linux/rcupdate.h> +#include <linux/types.h> enum pid_type {include/linux/rcupdate.h +9
-20@@ -33,6 +33,7 @@#ifndef __LINUX_RCUPDATE_H#define __LINUX_RCUPDATE_H +#include <linux/types.h> #include <linux/cache.h> #include <linux/spinlock.h> #include <linux/threads.h> @@ -52,16 +53,6 @@ extern int rcutorture_runnable; /* for sysctl */#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; -/* Exported common interfaces */ extern void call_rcu_sched (struct rcu_head *head,void (*func)(struct rcu_head *rcu));@@ -82,8 +73,6 @@ static inline void __rcu_read_unlock_bh(void)#ifdef CONFIG_PREEMPT_RCU -extern void __rcu_read_lock (void ); -extern void __rcu_read_unlock (void );void synchronize_rcu (void );/* @@ -141,14 +130,6 @@ static inline void rcu_exit_nohz(void)#endif /* #else #ifdef CONFIG_NO_HZ */ -#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) -#include <linux/rcutree.h> -#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) -#include <linux/rcutiny.h> -#else -#error "Unknown RCU implementation specified to kernel configuration" -#endif -/* * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic * initialization and destruction of rcu_head on the stack. rcu_head structures @@ -797,4 +778,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) +#include <linux/rcutree.h> +#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) +#include <linux/rcutiny.h> +#else +#error "Unknown RCU implementation specified to kernel configuration" +#endif +#endif /* __LINUX_RCUPDATE_H */ include/linux/rcutiny.h +35
-0@@ -26,6 +26,7 @@#define __LINUX_TINY_H#include <linux/cache.h> +#include <linux/sched.h> static inline void rcu_init (void ) {@@ -47,6 +48,40 @@ static inline void rcu_barrier(void)void rcu_barrier (void );void synchronize_rcu_expedited (void ); +void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tiny-preemptible RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tiny-preemptible RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}#endif /* #else #ifdef CONFIG_TINY_RCU */ include/linux/rcutree.h +37
-0@@ -30,6 +30,8 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +#include <linux/sched.h> +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);@@ -37,6 +39,41 @@ extern void rcu_cpu_stall_reset(void);#ifdef CONFIG_TREE_PREEMPT_RCU +extern void rcu_read_unlock_special (struct task_struct *t); + +/* +* Tree-preemptable RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ + current->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Tree-preemptable RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_struct *t = current; + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +} +extern void exit_rcu (void );#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */ include/linux/sched.h +4
-6@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/rculist.h> #include <linux/rtmutex.h> @@ -2241,11 +2241,9 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)return p1->tgid == p2->tgid; } -static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)static inline int thread_group_empty (struct task_struct *p) {include/linux/sem.h +1
-1@@ -78,7 +78,7 @@ struct seminfo {#ifdef __KERNEL__#include <asm/atomic.h> -#include <linux/rcupdate.h> +#include <linux/types.h> #include <linux/cache.h> struct task_struct ;include/linux/soundcard.h +2
-0@@ -1064,7 +1064,9 @@ typedef struct mixer_vol_table {*/ #define SEQ_DECLAREBUF () SEQ_USE_EXTBUF() +#ifdef __KERNEL__void seqbuf_dump (void );/* This function must be provided by programs */ +#endif #define SEQ_PM_DEFINES int __foo_bar___include/linux/sysctl.h +3
-2@@ -19,6 +19,8 @@**************************************************************** */ +#include <linux/key.h> +#ifndef _LINUX_SYSCTL_H#define _LINUX_SYSCTL_H@@ -1012,8 +1014,7 @@ extern int proc_do_large_bitmap(struct ctl_table *, int,*/ /* A sysctl table is an array of struct ctl_table: */ -struct ctl_table -{ +struct ctl_table {const char *procname;/* Text ID for /proc/sys, or zero */ void *data;int maxlen;include/linux/types.h +10
-0@@ -231,6 +231,16 @@ struct hlist_node {struct hlist_node *next, **pprev; }; +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; +struct ustat {__kernel_daddr_t f_tfree;__kernel_ino_t f_tinode;kernel/pid_namespace.c +2
-0@@ -8,6 +8,8 @@* */ +#include <linux/types.h> +#include <asm/atomic.h> #include <linux/pid.h> #include <linux/pid_namespace.h> #include <linux/syscalls.h> kernel/rcutiny_plugin.h +2
-36@@ -520,23 +520,11 @@ void rcu_preempt_note_context_switch(void) }/* -* Tiny-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Handle special cases during rcu_read_unlock(), such as needing to * notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;@@ -616,29 +604,7 @@ static void rcu_read_unlock_special(struct task_struct *t)#endif /* #ifdef CONFIG_RCU_BOOST */ local_irq_restore (flags); } - -/* -* Tiny-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);/* * Check for a quiescent state from the current CPU. When a task blocks, kernel/rcutree_plugin.h +2
-36@@ -196,18 +196,6 @@ static void rcu_preempt_note_context_switch(int cpu) }/* -* Tree-preemptable RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ - current->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Check for preempted RCU readers blocking the current grace period * for the specified rcu_node structure. If the caller needs a reliable * answer, it must hold the rcu_node's ->lock. @@ -261,7 +249,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +void rcu_read_unlock_special (struct task_struct *t) {int empty;int empty_exp;@@ -332,29 +320,7 @@ static void rcu_read_unlock_special(struct task_struct *t)local_irq_restore (flags); } } - -/* -* Tree-preemptable RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_struct *t = current; - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);#ifdef CONFIG_RCU_CPU_STALL_DETECTOR kernel/sysctl_binary.c +1
-0@@ -1,4 +1,5 @@#include <linux/stat.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "../fs/xfs/linux-2.6/xfs_sysctl.h" #include <linux/sunrpc/debug.h> kernel/sysctl_check.c +1
-0@@ -1,4 +1,5 @@#include <linux/stat.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "../fs/xfs/linux-2.6/xfs_sysctl.h" #include <linux/sunrpc/debug.h> net/core/sysctl_net_core.c +1
-0@@ -6,6 +6,7 @@*/ #include <linux/mm.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/module.h> #include <linux/socket.h> net/dccp/sysctl.c +1
-0@@ -10,6 +10,7 @@*/ #include <linux/mm.h> +#include <linux/key.h> #include <linux/sysctl.h> #include "dccp.h" #include "feat.h" net/ipv6/sysctl_net_ipv6.c +1
-0@@ -6,6 +6,7 @@*/ #include <linux/mm.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/in6.h> #include <linux/ipv6.h> net/irda/irsysctl.c +1
-0@@ -25,6 +25,7 @@#include <linux/mm.h> #include <linux/ctype.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/init.h> net/phonet/sysctl.c +1
-0@@ -23,6 +23,7 @@*/ #include <linux/seqlock.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/errno.h> #include <linux/init.h> net/rds/ib_sysctl.c +1
-0@@ -31,6 +31,7 @@* */ #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> net/rds/iw_sysctl.c +1
-0@@ -31,6 +31,7 @@* */ #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> net/rds/sysctl.c +1
-0@@ -31,6 +31,7 @@* */ #include <linux/kernel.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> net/sctp/sysctl.c +1
-0@@ -43,6 +43,7 @@#include <net/sctp/structs.h> #include <net/sctp/sctp.h> +#include <linux/key.h> #include <linux/sysctl.h> static int zero =0 ;net/sunrpc/sysctl.c +1
-0@@ -11,6 +11,7 @@#include <linux/linkage.h> #include <linux/ctype.h> #include <linux/fs.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/module.h> net/unix/sysctl_net_unix.c +1
-0@@ -11,6 +11,7 @@#include <linux/mm.h> #include <linux/slab.h> +#include <linux/key.h> #include <linux/sysctl.h> #include <net/af_unix.h> net/xfrm/xfrm_sysctl.c +1
-0@@ -1,3 +1,4 @@ +#include <linux/key.h> #include <linux/sysctl.h> #include <linux/slab.h> #include <net/net_namespace.h>
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Paul E. McKenneyinclude/linux/sched.h int same_thread_group(struct task_struct *p1, struct task_struct *p2) · line 2246
Quoted 9 lines · Paul E. McKenney
include/linux/sched.h +3
-5-static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)
It is strange for me.
The user of the API "next_thread(p)" must has two headers included, sched.h and rculist.h
I know this is a very popular pattern of user space code, is it OK for kernel? I think a file(even a header file) uses API(Marco), it should includes the the corresponding headers, it reduces surprises(example, the name of "next_thread()" has no "rcu", it is not expected that rcuxxxx.h is required).
I admit the work will become very much simpler if this pattern is allowed.
man fcntl:
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 16 lines · Lai Jiangshan
include/linux/sched.h int same_thread_group(struct task_struct *p1, struct task_struct *p2) · line 2246
Quoted 9 lines · Paul E. McKenney
include/linux/sched.h +3
-5-static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)It is strange for me.
The user of the API "next_thread(p)" must has two headers included,sched.handrculist.h
Quoted 6 lines
I know this is a very popular pattern of user space code, is it OK for kernel? I think a file(even a header file) uses API(Marco), it should includes the the corresponding headers, it reduces
surprises(example, the name of "next_thread()" has no "rcu", it is not expected that rcuxxxx.h is required).I admit the work will become very much simpler if this pattern is allowed.
The guy who maintains much of sched.h suggested it. ;-)
Thanx, Paul
Quoted 10 lines
man fcntl:
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 15 lines · Paul E. McKenney
Quoted 13 lines · Lai Jiangshan
include/linux/sched.h int same_thread_group(struct task_struct *p1, struct task_struct *p2) · line 2246
Quoted 9 lines · Paul E. McKenney
include/linux/sched.h +3
-5-static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)I admit the work will become very much simpler if this pattern is allowed.
Quoted 1 line
The guy who maintains much of
sched.hsuggested it. ;-)
While its not the nicest thing its something that's on more than one occasion there's an existing site in sched.h and there's on in key.h and iirc there's another one that's relevant.
A nice solution would be to move a lot of things out of sched.h into something like process.h, a header that deals with task groups and processes.
But until that time, I see no problem with using this.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Paul E. McKenneyQuoted 38 lines · Paul E. McKenney
Quoted 16 lines · Lai Jiangshan
include/linux/sched.h int same_thread_group(struct task_struct *p1, struct task_struct *p2) · line 2246
Quoted 9 lines · Paul E. McKenney
include/linux/sched.h +3
-5-static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)It is strange for me.
The user of the API "next_thread(p)" must has two headers included,sched.handrculist.hQuoted 6 lines
I know this is a very popular pattern of user space code, is it OK for kernel? I think a file(even a header file) uses API(Marco), it should includes the the corresponding headers, it reduces
surprises(example, the name of "next_thread()" has no "rcu", it is not expected that rcuxxxx.h is required).I admit the work will become very much simpler if this pattern is allowed.
The guy who maintains much of
sched.hsuggested it. ;-)Thanx, Paul
Quoted 10 lines
man fcntl:
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 6 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Hi, Paul
What is the solution you prefer to?
I insist on the solution which split rcupdate.h into 2 parts,
the first part is rcupdate_defs.h which only contains:
1) struct rcu_head
2) MACRO rcu_dereference*
3) MACRO rcu_access_pointer rcu_access_index rcu_assign_pointer RCU_INIT_POINTER
4) rcu_*_lock_held() which is required by 2)
All of these is required by sched.h, it is all about 450 lines of code.
It does not just separate struct rcu_head out only, because rcu_dereference*() and APIs in rculist.h are required by in sched.h or headers included by sched.h.
Any suggestion?
Thanks,
Lai
Peter Zijlstra
maintainerRe: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 10 lines · Lai Jiangshan
What is the solution you prefer to?
I insist on the solution which split
rcupdate.hinto 2 parts,
the first part isrcupdate_defs.hwhich only contains:
1) structrcu_head
2) MACRO rcu_dereference*
3) MACROrcu_access_pointerrcu_access_indexrcu_assign_pointerRCU_INIT_POINTER
4) rcu_*_lock_held() which is required by 2)
Quoted 4 lines
All of these is required by
sched.h, it is all about 450 lines of code.It does not just separate struct
rcu_headout only, because rcu_dereference*() and APIs inrculist.hare required by insched.hor headers included bysched.h.
The only usage of rculist.h in the whole of sched.h is that _one_ list_entry_rcu, of which we already have a macro user, so why not make that one a macro too and safe ourselves a ton of grief?
You're just making stuff harder than it needs to be.
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
Quoted 13 lines · Peter Zijlstra
Quoted 12 lines · Lai Jiangshan
What is the solution you prefer to?
I insist on the solution which split
rcupdate.hinto 2 parts,
the first part isrcupdate_defs.hwhich only contains:
1) structrcu_head
2) MACRO rcu_dereference*
3) MACROrcu_access_pointerrcu_access_indexrcu_assign_pointerRCU_INIT_POINTER
4) rcu_*_lock_held() which is required by 2)All of these is required by
sched.h, it is all about 450 lines of code.
Quoted 9 lines
Quoted 2 lines
It does not just separate struct
rcu_headout only, because rcu_dereference*() and APIs inrculist.hare required by insched.hor headers included bysched.h.The only usage of
rculist.hin the whole ofsched.his that _one_list_entry_rcu, of which we already have a macro user, so why not make that one a macro too and safe ourselves a ton of grief?You're just making stuff harder than it needs to be.
No, opposite.
the more things(except rcu_read_[un]lock*()) are moved to rcupdate_defs.h the more easy. the less things are moved to rcupdate_defs.h the more hard.
example, if rcu_dereference* is not moved to rcupdate_defs.h,
I have to do 2 more things:
1) convert inline functions next_thread() to macro.
2) find all .c which uses next_thread()/next_task() and ensure they all have rcupdate.h included. 3?) handle the complaints from LKML and told them should convert their new APIs to macro and should also do the same work like 2)
I'm just expressing my thinking, I will accept your requirement and make things progress.
Thanks,
Lai
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Lai JiangshanQuoted 57 lines · Lai Jiangshan
Quoted 38 lines · Paul E. McKenney
Quoted 16 lines · Lai Jiangshan
include/linux/sched.h int same_thread_group(struct task_struct *p1, struct task_struct *p2) · line 2246
Quoted 9 lines · Paul E. McKenney
include/linux/sched.h +3
-5-static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)It is strange for me.
The user of the API "next_thread(p)" must has two headers included,sched.handrculist.hQuoted 6 lines
I know this is a very popular pattern of user space code, is it OK for kernel? I think a file(even a header file) uses API(Marco), it should includes the the corresponding headers, it reduces
surprises(example, the name of "next_thread()" has no "rcu", it is not expected that rcuxxxx.h is required).I admit the work will become very much simpler if this pattern is allowed.
The guy who maintains much of
sched.hsuggested it. ;-)Thanx, Paul
Quoted 10 lines
man fcntl:
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/Quoted 6 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/Hi, Paul
What is the solution you prefer to?
I insist on the solution which split
rcupdate.hinto 2 parts,
the first part isrcupdate_defs.hwhich only contains:
1) structrcu_head
2) MACRO rcu_dereference*
3) MACROrcu_access_pointerrcu_access_indexrcu_assign_pointerRCU_INIT_POINTER
4) rcu_*_lock_held() which is required by 2)
Quoted 6 lines
All of these is required by
sched.h, it is all about 450 lines of code.It does not just separate struct
rcu_headout only, because rcu_dereference*() and APIs inrculist.hare required by insched.hor headers included bysched.h.Any suggestion?
My belief is that the Linux kernel's include files need to have a designed approach to reduce the include-file problems. For example, one approach would be to split out the data declarations from the access functions -- but it is not clear to me that this is the right approach. But whatever approach is chosen, that approach needs to have a clear design behind it, because otherwise we will end up continually refactoring. And whatever approach is chosen, putting simple/small data/type declarations into types.h is very likely to be part of the approach, given that types.h has worked well in a great many projects over a long period of time. I do hope that whatever overall approach we evolve to, that this approach will allow use of inline functions rather than macros. But it is easy to change these back and forth, so I am not too worried about them.
In the meantime, for rcupdate.h, it appears that putting struct rcu_head into types.h and then converting a few inline functions to macros will suffice. Furthermore, this split of the rcupdate.h functionality will likely hold up for quite some time.
You have been doing a much more thorough job of testing this change than I have, so it does make sense that you carry out the change.
So, could you please try out this approach? Put rcu_head into types.h, re-order rcupdate.h as needed, and convert a few inline functions to macros?
As I have said before, it will be really cool to allow rcu_read_lock() and rcu_read_unlock() to be inline functions for preemptible RCU!!!
Thanx, Paul
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Paul E. McKenneyQuoted 154 lines · Paul E. McKenney
Quoted 93 lines · Lai Jiangshan
Quoted 92 lines · Paul E. McKenney
Quoted 45 lines · Lai Jiangshan
Quoted 36 lines · Paul E. McKenney
Quoted 35 lines · Paul E. McKenney
Quoted 23 lines · Lai Jiangshan
Quoted 22 lines · Paul E. McKenney
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
And the following patch builds correctly for defconfig x86 builds, while allowing
rcupdate.hto see thesched.hdefinitions as needed to inlinercu_read_lock()andrcu_read_unlock().Looks like an entirely reasonable patch to me ;-)
Quite... a lot better than the original proposal!
Glad you both like it!
When I do an allyesconfig build, I do get errors during the "CHECK" phase, when it is putting things into the usr/include in the build tree. I believe that this is because I am exposing different header files to the library-export scripts. The following patch silences some of them, but I am really out of my depth here.
Sam, Jan, Michal, help?
Quoted 8 lines
Quoted 4 lines
Thanx, Paul
------------------------------------------------------------------------
Easy to split
rcupdate.h, hard to resolve the dependence problem.You can apply the next additional patch when you test:
I am sure that you are quite correct. ;-)
Quoted 7 lines
Quoted 7 lines
I am moving
_rcu_read_lock()and_rcu_read_unlock()intoinclude/linux/rcutree.handinclude/linux/rcutiny.h, and I am sure that more pain will ensue.One thing I don't understand... How does is it helping to group the
task_structRCU-related fields into a structure? Is that generating better code on your platform due to smaller offsets or something?Quoted 7 lines
You don't like
task_rcu_structpatch? I think it can make code clearer, and it can also check the code even whenCONFIG_PREEMPT_RCU=n.For rcu_read_[un]lock(), it generates the same code, no better, no worse.
It is just a cleanup patch, it is helpless for making rcu_read_[un]lock() inline, if you don't like it, I will give up it.
I don't know that I feel strongly either way about it. It was necessary with the integer-offset approach, but optional now.
Quoted 22 lines
Quoted 6 lines
Quoted 1 line
Also, does your patchset address the CHECK warnings?
I take it back... I applied the following patch on top of my earlier one, and a defconfig x86 build completed without error. (Though I have not tested the results of the build.)
Quoted 7 lines
One possible difference -- I did this work on top of a recent Linus git commit (
b2a8b4b81966) rather than on top of my -rcu tree. Also, I have not yet tried an allyesconfig build, which will no doubt locate some more problems.Thanx, Paul
when defconfig or allyesconfig,
CONFIG_PREEMPT=nandCONFIG_TREE_PREEMPT_RCU=nwhen you make them "y":In file included from
include/linux/rcupdate.h:764:0,from include/linux/tracepoint.h:19, from include/linux/module.h:18, from include/linux/crypto.h:21, from arch/x86/kernel/asm-offsets.c:8:Quoted 6 lines
include/linux/rcutree.h:50:20: error: static declaration of ‘__rcu_read_lock’ follows non-static declarationinclude/linux/rcupdate.h:76:13: note: previous declaration of ‘__rcu_read_lock’ was hereinclude/linux/rcutree.h:63:20: error: static declaration of ‘__rcu_read_unlock’ follows non-static declarationinclude/linux/rcupdate.h:77:13: note: previous declaration of ‘__rcu_read_unlock’ was here make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
make: *** [prepare0] Error 2Yep. I need to move the
rcu_read_lock()APIs to follow the inclusion ofrcutree.handrcutiny.h. Also add include ofsched.htorcutiny.h. The code movement does bloat the patch a bit. Butrcu_assign_pointer()must precede the inclusion ofrcutree.handrcutiny.h, so it is not possible to simply move the inclusions. See below.Quoted 4 lines
Quoted 2 lines
Thanx, Paul
sched.hstill containsrcupdate.hafter applied this patch.Then we are not in sync --
sched.hdoes not includercupdate.hin my tree. It instead gets the structrcu_headdefinition frominclude/linux/types.h. See below for a consolidated patch.Thanx, Paul
Quoted 18 lines
See my [PATCH 2/4] for more info.
# make lib/is_single_threaded.o CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CC lib/is_single_threaded.o In file included from include/linux/rcupdate.h:639:0, from include/linux/rculist.h:10, from include/linux/sched.h:82, from lib/is_single_threaded.c:13: include/linux/rcutree.h: In function ‘__rcu_read_lock’: include/linux/rcutree.h:52:15: error: dereferencing pointer to incomplete type In file included from include/linux/rcupdate.h:639:0, from include/linux/rculist.h:10, from include/linux/sched.h:82, from lib/is_single_threaded.c:13:Quoted 8 lines
include/linux/rcutree.h: In function ‘__rcu_read_unlock’: include/linux/rcutree.h:68:5: error: dereferencing pointer to incomplete type include/linux/rcutree.h:70:7: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:46: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:78: error: dereferencing pointer to incomplete type include/linux/rcutree.h:71:6: warning: type defaults to ‘int’ in type name make[1]: *** [lib/is_single_threaded.o] Error 1 make: *** [lib/is_single_threaded.o] Error 2drivers/scsi/scsi_sysctl.c | 1 + fs/proc/proc_sysctl.c | 1 + include/linux/kernel.h | 3 +++ include/linux/pid.h | 2 +- include/linux/rcupdate.h | 29 +++++++++-------------------- include/linux/rcutiny.h | 35 +++++++++++++++++++++++++++++++++++ include/linux/rcutree.h | 37 +++++++++++++++++++++++++++++++++++++ include/linux/sched.h | 10 ++++------ include/linux/sem.h | 2 +- include/linux/soundcard.h | 2 ++ include/linux/sysctl.h | 5 +++-- include/linux/types.h | 10 ++++++++++ kernel/pid_namespace.c | 2 ++ kernel/rcutiny_plugin.h | 38 ++------------------------------------ kernel/rcutree_plugin.h | 38 ++------------------------------------ kernel/sysctl_binary.c | 1 + kernel/sysctl_check.c | 1 + net/core/sysctl_net_core.c | 1 + net/dccp/sysctl.c | 1 + net/ipv6/sysctl_net_ipv6.c | 1 + net/irda/irsysctl.c | 1 + net/phonet/sysctl.c | 1 +
Quoted 9 lines
net/rds/ib_sysctl.c | 1 + net/rds/iw_sysctl.c | 1 + net/rds/sysctl.c | 1 + net/sctp/sysctl.c | 1 + net/sunrpc/sysctl.c | 1 + net/unix/sysctl_net_unix.c | 1 + net/xfrm/xfrm_sysctl.c | 1 + 29 files changed, 127 insertions(+), 102 deletions(-)
sched.h still contains rcupdate.h after applied this patch. so it still fails.
Is other part of patch(or patch 2/2) not sent?
PATCH 1/4 rcu: split rcupdate.h
In reply to Paul E. McKenneySplit rcupdate.h and move basic defines to rcupdate_defs.h. It allows rcupdate.h using struct task_struct.
Only rcu_read_lock*() (which require struct task_struct) are left in rcupdate.h. Some other code(example, the declaration of synchronize_rcu()) can also be left in rcupdate.h actually, but it is not required and it will make the works more complex. So I also move them.
The result rcupdate_defs.h is a little big, but it just contains the RCU defines and declarations, it is OK. Maybe rcupdate_basic.h is a better name?
--- include/linux/rcupdate.h | 616 +-------------------------------------- include/linux/rcupdate_defs.h | 653 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 654 insertions(+), 615 deletions(-)
include/linux/rcupdate.h +1 -615
@@ -33,42 +33,7 @@#ifndef __LINUX_RCUPDATE_H#define __LINUX_RCUPDATE_H -#include <linux/cache.h> -#include <linux/spinlock.h> -#include <linux/threads.h> -#include <linux/cpumask.h> -#include <linux/seqlock.h> -#include <linux/lockdep.h> -#include <linux/completion.h> -#include <linux/debugobjects.h> -#include <linux/compiler.h> - -#ifdef CONFIG_RCU_TORTURE_TEST -extern int rcutorture_runnable;/* for sysctl */ -#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ - -#define UINT_CMP_GE (a, b) (UINT_MAX / 2 >= (a) - (b)) -#define UINT_CMP_LT (a, b) (UINT_MAX / 2 < (a) - (b)) -#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b)) -#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) - -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; - -/* Exported common interfaces */ -extern void call_rcu_sched (struct rcu_head *head, -void (*func)(struct rcu_head *rcu)); -extern void synchronize_sched (void ); -extern void rcu_barrier_bh (void ); -extern void rcu_barrier_sched (void ); -extern int sched_expedited_torture_stats (char *page); +#include <linux/rcupdate_defs.h> static inline void __rcu_read_lock_bh (void ) {
@@ -84,7 +49,6 @@ static inline void __rcu_read_unlock_bh(void)extern void __rcu_read_lock (void );extern void __rcu_read_unlock (void ); -void synchronize_rcu (void );/* * Defined as a macro as it is a very low level header included from
@@ -106,11 +70,6 @@ static inline void __rcu_read_unlock(void)preempt_enable (); } -static inline void synchronize_rcu (void ) -{ -synchronize_sched (); -} -static inline int rcu_preempt_depth (void ) {return 0 ;
@@ -118,402 +77,6 @@ static inline int rcu_preempt_depth(void)#endif /* #else #ifdef CONFIG_PREEMPT_RCU */ -/* Internal to kernel */ -extern void rcu_sched_qs (int cpu); -extern void rcu_bh_qs (int cpu); -extern void rcu_check_callbacks (int cpu,int user); -struct notifier_block ; - -#ifdef CONFIG_NO_HZ - -extern void rcu_enter_nohz (void ); -extern void rcu_exit_nohz (void ); - -#else /* #ifdef CONFIG_NO_HZ */ - -static inline void rcu_enter_nohz (void ) -{ -} - -static inline void rcu_exit_nohz (void ) -{ -} - -#endif /* #else #ifdef CONFIG_NO_HZ */ - -#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) -#include <linux/rcutree.h> -#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) -#include <linux/rcutiny.h> -#else -#error "Unknown RCU implementation specified to kernel configuration" -#endif - -/* -* init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic -* initialization and destruction of rcu_head on the stack. rcu_head structures -* allocated dynamically in the heap or defined statically don't need any -* initialization. -*/ -#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD -extern void init_rcu_head_on_stack (struct rcu_head *head); -extern void destroy_rcu_head_on_stack (struct rcu_head *head); -#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ -static inline void init_rcu_head_on_stack (struct rcu_head *head) -{ -} - -static inline void destroy_rcu_head_on_stack (struct rcu_head *head) -{ -} -#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ - -#ifdef CONFIG_DEBUG_LOCK_ALLOC - -extern struct lockdep_map rcu_lock_map; -# define rcu_read_acquire () \ - lock_acquire(&rcu_lock_map, 0, 0, 2, 1, NULL, _THIS_IP_) -# define rcu_read_release () lock_release(&rcu_lock_map, 1, _THIS_IP_) - -extern struct lockdep_map rcu_bh_lock_map; -# define rcu_read_acquire_bh () \ - lock_acquire(&rcu_bh_lock_map, 0, 0, 2, 1, NULL, _THIS_IP_) -# define rcu_read_release_bh () lock_release(&rcu_bh_lock_map, 1, _THIS_IP_) - -extern struct lockdep_map rcu_sched_lock_map; -# define rcu_read_acquire_sched () \ - lock_acquire(&rcu_sched_lock_map, 0, 0, 2, 1, NULL, _THIS_IP_) -# define rcu_read_release_sched () \ - lock_release(&rcu_sched_lock_map, 1, _THIS_IP_) - -extern int debug_lockdep_rcu_enabled (void ); - -/** -* rcu_read_lock_held() - might we be in RCU read-side critical section? -* -* If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an RCU -* read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC, -* this assumes we are in an RCU read-side critical section unless it can -* prove otherwise. This is useful for debug checks in functions that -* require that they be called within an RCU read-side critical section. -* -* Checks debug_lockdep_rcu_enabled() to prevent false positives during boot -* and while lockdep is disabled. -*/ -static inline int rcu_read_lock_held (void ) -{ -if (!debug_lockdep_rcu_enabled ()) -return 1 ; -return lock_is_held (&rcu_lock_map); -} - -/* -* rcu_read_lock_bh_held() is defined out of line to avoid #include-file -* hell. -*/ -extern int rcu_read_lock_bh_held (void ); - -/** -* rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section? -* -* If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an -* RCU-sched read-side critical section. In absence of -* CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side -* critical section unless it can prove otherwise. Note that disabling -* of preemption (including disabling irqs) counts as an RCU-sched -* read-side critical section. This is useful for debug checks in functions -* that required that they be called within an RCU-sched read-side -* critical section. -* -* Check debug_lockdep_rcu_enabled() to prevent false positives during boot -* and while lockdep is disabled. -*/ -#ifdef CONFIG_PREEMPT -static inline int rcu_read_lock_sched_held (void ) -{ -int lockdep_opinion =0 ; - -if (!debug_lockdep_rcu_enabled ()) -return 1 ; -if (debug_locks) - lockdep_opinion =lock_is_held (&rcu_sched_lock_map); -return lockdep_opinion ||preempt_count () !=0 ||irqs_disabled (); -} -#else /* #ifdef CONFIG_PREEMPT */ -static inline int rcu_read_lock_sched_held (void ) -{ -return 1 ; -} -#endif /* #else #ifdef CONFIG_PREEMPT */ - -#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ - -# define rcu_read_acquire () do { } while (0) -# define rcu_read_release () do { } while (0) -# define rcu_read_acquire_bh () do { } while (0) -# define rcu_read_release_bh () do { } while (0) -# define rcu_read_acquire_sched () do { } while (0) -# define rcu_read_release_sched () do { } while (0) - -static inline int rcu_read_lock_held (void ) -{ -return 1 ; -} - -static inline int rcu_read_lock_bh_held (void ) -{ -return 1 ; -} - -#ifdef CONFIG_PREEMPT -static inline int rcu_read_lock_sched_held (void ) -{ -return preempt_count () !=0 ||irqs_disabled (); -} -#else /* #ifdef CONFIG_PREEMPT */ -static inline int rcu_read_lock_sched_held (void ) -{ -return 1 ; -} -#endif /* #else #ifdef CONFIG_PREEMPT */ - -#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ - -#ifdef CONFIG_PROVE_RCU - -extern int rcu_my_thread_group_empty (void ); - -/** -* rcu_lockdep_assert - emit lockdep splat if specified condition not met -* @c: condition to check -*/ -#define rcu_lockdep_assert (c) \ - do { \ - static bool __warned; \ - if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \ - __warned = true; \ - lockdep_rcu_dereference(__FILE__, __LINE__); \ - } \ - } while (0) - -#else /* #ifdef CONFIG_PROVE_RCU */ - -#define rcu_lockdep_assert (c) do { } while (0) - -#endif /* #else #ifdef CONFIG_PROVE_RCU */ - -/* -* Helper functions for rcu_dereference_check(), rcu_dereference_protected() -* and rcu_assign_pointer(). Some of these could be folded into their -* callers, but they are left separate in order to ease introduction of -* multiple flavors of pointers to match the multiple flavors of RCU -* (e.g., __rcu_bh, * __rcu_sched, and __srcu), should this make sense in -* the future. -*/ - -#ifdef __CHECKER__ -#define rcu_dereference_sparse (p, space) \ - ((void)(((typeof(*p) space *)p) == p)) -#else /* #ifdef __CHECKER__ */ -#define rcu_dereference_sparse (p, space) -#endif /* #else #ifdef __CHECKER__ */ - -#define __rcu_access_pointer (p, space) \ - ({ \ - typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ - rcu_dereference_sparse(p, space); \ - ((typeof(*p) __force __kernel *)(_________p1)); \ - }) -#define __rcu_dereference_check (p, c, space) \ - ({ \ - typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ - rcu_lockdep_assert(c); \ - rcu_dereference_sparse(p, space); \ - smp_read_barrier_depends(); \ - ((typeof(*p) __force __kernel *)(_________p1)); \ - }) -#define __rcu_dereference_protected (p, c, space) \ - ({ \ - rcu_lockdep_assert(c); \ - rcu_dereference_sparse(p, space); \ - ((typeof(*p) __force __kernel *)(p)); \ - }) - -#define __rcu_dereference_index_check (p, c) \ - ({ \ - typeof(p) _________p1 = ACCESS_ONCE(p); \ - rcu_lockdep_assert(c); \ - smp_read_barrier_depends(); \ - (_________p1); \ - }) -#define __rcu_assign_pointer (p, v, space) \ - ({ \ - if (!__builtin_constant_p(v) || \ - ((v) != NULL)) \ - smp_wmb(); \ - (p) = (typeof(*v) __force space *)(v); \ - }) - - -/** -* rcu_access_pointer() - fetch RCU pointer with no dereferencing -* @p: The pointer to read -* -* Return the value of the specified RCU-protected pointer, but omit the -* smp_read_barrier_depends() and keep the ACCESS_ONCE(). This is useful -* when the value of this pointer is accessed, but the pointer is not -* dereferenced, for example, when testing an RCU-protected pointer against -* NULL. Although rcu_access_pointer() may also be used in cases where -* update-side locks prevent the value of the pointer from changing, you -* should instead use rcu_dereference_protected() for this use case. -*/ -#define rcu_access_pointer (p) __rcu_access_pointer((p), __rcu) - -/** -* rcu_dereference_check() - rcu_dereference with debug checking -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* Do an rcu_dereference(), but check that the conditions under which the -* dereference will take place are correct. Typically the conditions -* indicate the various locking conditions that should be held at that -* point. The check should return true if the conditions are satisfied. -* An implicit check for being in an RCU read-side critical section -* (rcu_read_lock()) is included. -* -* For example: -* -* bar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock)); -* -* could be used to indicate to lockdep that foo->bar may only be dereferenced -* if either rcu_read_lock() is held, or that the lock required to replace -* the bar struct at foo->bar is held. -* -* Note that the list of conditions may also include indications of when a lock -* need not be held, for example during initialisation or destruction of the -* target struct: -* -* bar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock) || -* atomic_read(&foo->usage) == 0); -* -* Inserts memory barriers on architectures that require them -* (currently only the Alpha), prevents the compiler from refetching -* (and from merging fetches), and, more importantly, documents exactly -* which pointers are protected by RCU and checks that the pointer is -* annotated as __rcu. -*/ -#define rcu_dereference_check (p, c) \ - __rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu) - -/** -* rcu_dereference_bh_check() - rcu_dereference_bh with debug checking -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* This is the RCU-bh counterpart to rcu_dereference_check(). -*/ -#define rcu_dereference_bh_check (p, c) \ - __rcu_dereference_check((p), rcu_read_lock_bh_held() || (c), __rcu) - -/** -* rcu_dereference_sched_check() - rcu_dereference_sched with debug checking -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* This is the RCU-sched counterpart to rcu_dereference_check(). -*/ -#define rcu_dereference_sched_check (p, c) \ - __rcu_dereference_check((p), rcu_read_lock_sched_held() || (c), \ - __rcu) - -#define rcu_dereference_raw (p) rcu_dereference_check(p, 1)/*@@@ needed? @@@*/ - -/** -* rcu_dereference_index_check() - rcu_dereference for indices with debug checking -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* Similar to rcu_dereference_check(), but omits the sparse checking. -* This allows rcu_dereference_index_check() to be used on integers, -* which can then be used as array indices. Attempting to use -* rcu_dereference_check() on an integer will give compiler warnings -* because the sparse address-space mechanism relies on dereferencing -* the RCU-protected pointer. Dereferencing integers is not something -* that even gcc will put up with. -* -* Note that this function does not implicitly check for RCU read-side -* critical sections. If this function gains lots of uses, it might -* make sense to provide versions for each flavor of RCU, but it does -* not make sense as of early 2010. -*/ -#define rcu_dereference_index_check (p, c) \ - __rcu_dereference_index_check((p), (c)) - -/** -* rcu_dereference_protected() - fetch RCU pointer when updates prevented -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* Return the value of the specified RCU-protected pointer, but omit -* both the smp_read_barrier_depends() and the ACCESS_ONCE(). This -* is useful in cases where update-side locks prevent the value of the -* pointer from changing. Please note that this primitive does -not- -* prevent the compiler from repeating this reference or combining it -* with other references, so it should not be used without protection -* of appropriate locks. -* -* This function is only for update-side use. Using this function -* when protected only by rcu_read_lock() will result in infrequent -* but very ugly failures. -*/ -#define rcu_dereference_protected (p, c) \ - __rcu_dereference_protected((p), (c), __rcu) - -/** -* rcu_dereference_bh_protected() - fetch RCU-bh pointer when updates prevented -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* This is the RCU-bh counterpart to rcu_dereference_protected(). -*/ -#define rcu_dereference_bh_protected (p, c) \ - __rcu_dereference_protected((p), (c), __rcu) - -/** -* rcu_dereference_sched_protected() - fetch RCU-sched pointer when updates prevented -* @p: The pointer to read, prior to dereferencing -* @c: The conditions under which the dereference will take place -* -* This is the RCU-sched counterpart to rcu_dereference_protected(). -*/ -#define rcu_dereference_sched_protected (p, c) \ - __rcu_dereference_protected((p), (c), __rcu) - - -/** -* rcu_dereference() - fetch RCU-protected pointer for dereferencing -* @p: The pointer to read, prior to dereferencing -* -* This is a simple wrapper around rcu_dereference_check(). -*/ -#define rcu_dereference (p) rcu_dereference_check(p, 0) - -/** -* rcu_dereference_bh() - fetch an RCU-bh-protected pointer for dereferencing -* @p: The pointer to read, prior to dereferencing -* -* Makes rcu_dereference_check() do the dirty work. -*/ -#define rcu_dereference_bh (p) rcu_dereference_bh_check(p, 0) - -/** -* rcu_dereference_sched() - fetch RCU-sched-protected pointer for dereferencing -* @p: The pointer to read, prior to dereferencing -* -* Makes rcu_dereference_check() do the dirty work. -*/ -#define rcu_dereference_sched (p) rcu_dereference_sched_check(p, 0) -/** * rcu_read_lock() - mark the beginning of an RCU read-side critical section *
@@ -657,181 +220,4 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) 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. Returns the value assigned. -* -* Inserts memory barriers on architectures that require them -* (pretty much all of them other than x86), 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. -*/ -#define rcu_assign_pointer (p, v) \ - __rcu_assign_pointer((p), (v), __rcu) - -/** -* RCU_INIT_POINTER() - initialize an RCU protected pointer -* -* Initialize an RCU-protected pointer in such a way to avoid RCU-lockdep -* splats. -*/ -#define RCU_INIT_POINTER (p, v) \ - p = (typeof(*v) __force __rcu *)(v) - -/* Infrastructure to implement the synchronize_() primitives. */ - -struct rcu_synchronize { -struct rcu_head head; -struct completion completion; -}; - -extern void wakeme_after_rcu (struct rcu_head *head); - -#ifdef CONFIG_PREEMPT_RCU - -/** -* call_rcu() - Queue an RCU callback for invocation after a grace period. -* @head: structure to be used for queueing the RCU updates. -* @func: actual callback function to be invoked after the grace period -* -* The callback function will be invoked some time after a full grace -* period elapses, in other words after all pre-existing RCU read-side -* critical sections have completed. However, the callback function -* might well execute concurrently with RCU read-side critical sections -* that started after call_rcu() was invoked. RCU read-side critical -* sections are delimited by rcu_read_lock() and rcu_read_unlock(), -* and may be nested. -*/ -extern void call_rcu (struct rcu_head *head, -void (*func)(struct rcu_head *head)); - -#else /* #ifdef CONFIG_PREEMPT_RCU */ - -/* In classic RCU, call_rcu() is just call_rcu_sched(). */ -#define call_rcu call_rcu_sched - -#endif /* #else #ifdef CONFIG_PREEMPT_RCU */ - -/** -* call_rcu_bh() - Queue an RCU for invocation after a quicker grace period. -* @head: structure to be used for queueing the RCU updates. -* @func: actual callback function to be invoked after the grace period -* -* The callback function will be invoked some time after a full grace -* period elapses, in other words after all currently executing RCU -* read-side critical sections have completed. call_rcu_bh() assumes -* that the read-side critical sections end on completion of a softirq -* handler. This means that read-side critical sections in process -* context must not be interrupted by softirqs. This interface is to be -* used when most of the read-side critical sections are in softirq context. -* RCU read-side critical sections are delimited by : -* - rcu_read_lock() and rcu_read_unlock(), if in interrupt context. -* OR -* - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context. -* These may be nested. -*/ -extern void call_rcu_bh (struct rcu_head *head, -void (*func)(struct rcu_head *head)); - -/* -* debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally -* by call_rcu() and rcu callback execution, and are therefore not part of the -* RCU API. Leaving in rcupdate.h because they are used by all RCU flavors. -*/ - -#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD -# define STATE_RCU_HEAD_READY 0 -# define STATE_RCU_HEAD_QUEUED 1 - -extern struct debug_obj_descr rcuhead_debug_descr; - -static inline void debug_rcu_head_queue (struct rcu_head *head) -{ -WARN_ON_ONCE ((unsigned long )head &0x3 ); -debug_object_activate (head, &rcuhead_debug_descr); -debug_object_active_state (head, &rcuhead_debug_descr, -STATE_RCU_HEAD_READY , -STATE_RCU_HEAD_QUEUED ); -} - -static inline void debug_rcu_head_unqueue (struct rcu_head *head) -{ -debug_object_active_state (head, &rcuhead_debug_descr, -STATE_RCU_HEAD_QUEUED , -STATE_RCU_HEAD_READY ); -debug_object_deactivate (head, &rcuhead_debug_descr); -} -#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ -static inline void debug_rcu_head_queue (struct rcu_head *head) -{ -} - -static inline void debug_rcu_head_unqueue (struct rcu_head *head) -{ -} -#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ - -static __always_inline bool __is_kfree_rcu_offset(unsigned long offset) -{ -return offset <4096 ; -} - -static __always_inline -void __kfree_rcu(struct rcu_head *head, unsigned long offset) -{ -typedef void (*rcu_callback )(struct rcu_head *); - -BUILD_BUG_ON (!__builtin_constant_p (offset)); - -/* See the kfree_rcu() header comment. */ -BUILD_BUG_ON (!__is_kfree_rcu_offset (offset)); - -call_rcu (head, (rcu_callback )offset); -} - -extern void kfree (const void *); - -static inline void __rcu_reclaim (struct rcu_head *head) -{ -unsigned long offset = (unsigned long )head->func; - -if (__is_kfree_rcu_offset (offset)) -kfree ((void *)head - offset); -else - head->func (head); -} - -/** -* kfree_rcu() - kfree an object after a grace period. -* @ptr: pointer to kfree -* @rcu_head: the name of the struct rcu_head within the type of @ptr. -* -* Many rcu callbacks functions just call kfree() on the base structure. -* These functions are trivial, but their size adds up, and furthermore -* when they are used in a kernel module, that module must invoke the -* high-latency rcu_barrier() function at module-unload time. -* -* The kfree_rcu() function handles this issue. Rather than encoding a -* function address in the embedded rcu_head structure, kfree_rcu() instead -* encodes the offset of the rcu_head structure within the base structure. -* Because the functions are not allowed in the low-order 4096 bytes of -* kernel virtual memory, offsets up to 4095 bytes can be accommodated. -* If the offset is larger than 4095 bytes, a compile-time error will -* be generated in __kfree_rcu(). If this error is triggered, you can -* either fall back to use of call_rcu() or rearrange the structure to -* position the rcu_head structure into the first 4096 bytes. -* -* Note that the allowable offset might decrease in the future, for example, -* to allow something like kmem_cache_free_rcu(). -*/ -#define kfree_rcu (ptr, rcu_head) \ - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) -#endif /* __LINUX_RCUPDATE_H */
include/linux/rcupdate_defs.h new file +653 -0
653 lines not on this page · raw message
Signature · 1 line
1.7.4
PATCH 2/4 rcu: make rcudpate.h can use struct task_struct.
In reply to Paul E. McKenneyStep1: Ensure sched.h that it does not include rcudpate.h.
rcupdate.h is so generic that it is included in many headers. sched.h is so complex that it includes many headers. So we have to find out all header files which directly include rcupdate.h and are directly/indirectly included by sched.h.
I found out these files by a script(No False Positive, No False Negetive):
2 include/linux/aio.h ---> include/linux/rcupdate.h
2 include/linux/key.h ---> include/linux/rcupdate.h
2 include/linux/pid.h ---> include/linux/rcupdate.h
2 include/linux/rculist.h ---> include/linux/rcupdate.h
2 include/linux/sched.h ---> include/linux/rcupdate.h
2 include/linux/sem.h ---> include/linux/rcupdate.h
2 include/linux/sysctl.h ---> include/linux/rcupdate.h
So the step 1 changes these files just includes rcupdate_defs.h
Step2: Ensure rcupdate.h included in the files which use rcu_read_lock*()
When the step 1 is done, the kernel build will fail, because some files just include the above files and use rcu_read_lock*() without rcupdate.h included.
# vi ~/is_include.py ########### command1
import re
import sys
include_re = re.compile(r'#\s*include\s*<([_\-\w]*/)([/\._\-\w]*)>') searched = {}
def is_include(f, depth):
if f == ('include/linux/', 'rcupdate.h'):
sys.exit(0)
if depth <= 0:
return
if searched.has_key(f):
if searched[f] > depth:
return
searched[f] = depth
try:
ff = file(f[0]+f[1])
except:
return ()
for ch in include_re.findall(ff.read()):
if ch[0] != 'asm/':
is_include(('include/' + ch[0], ch[1]), depth - 1)"""usage: is_include.py file_name depth """is_include(('', sys.argv[1]), int(sys.argv[2]))sys.exit(1)
# vi ~/is_include.sh ############## command2 #!/bin/bash
depth="$1"
find -name "*.c" | xargs grep -l rcu_read_lock | while read file do
python ~/is_include.py "$file" "$depth" || echo "$file"
done
# ~/is_include.sh 3 ################# command3(after step1 is done)./drivers/base/power/wakeup.c./drivers/misc/sgi-gru/grutlbpurge.c./drivers/char/tpm/tpm.c./drivers/net/wireless/iwlwifi/iwl-agn-rxon.c./drivers/net/wireless/ath/ath9k/xmit.c./drivers/net/wireless/ath/ath9k/htc_drv_main.c./drivers/net/wireless/ath/ath9k/htc_drv_txrx.c./drivers/net/wireless/ath/carl9170/mac.c./drivers/net/wireless/ath/ar9170/mac.c./drivers/staging/tidspbridge/pmgr/dspapi.c./drivers/s390/cio/qdio_thinint.c./lib/is_single_threaded.c./fs/autofs4/waitq.c./fs/ecryptfs/messaging.c./fs/xfs/xfs_mount.c./fs/xfs/linux-2.6/xfs_sync.c./fs/xfs/xfs_iget.c./fs/xfs/xfs_inode.c./arch/ia64/sn/kernel/irq.c./security/tomoyo/common.c./security/apparmor/audit.c./kernel/sched_fair.c./kernel/tsacct.c./kernel/sched_debug.c./kernel/pid_namespace.c./kernel/futex_compat.c./kernel/sched_rt.c./net/rds/ib_rdma.c./net/rds/connection.c./net/mac80211/debugfs_sta.c./net/mac80211/mesh.c./net/mac80211/mesh_hwmp.c./net/mac80211/debugfs_key.c./net/mac80211/mesh_plink.c./net/batman-adv/send.c./net/batman-adv/routing.c./net/batman-adv/main.c./net/batman-adv/originator.c
(The simple scripts allow False Positive, disallow False Negetive) After manual check, only
drivers/staging/tidspbridge/pmgr/dspapi.c kernel/futex_compat.c
kernel/tsacct.c
lib/is_single_threaded.c
are required to add "#include <linux/rcupdate.h>"
--- drivers/staging/tidspbridge/pmgr/dspapi.c | 1 + include/linux/aio.h | 2 +- include/linux/key.h | 2 +- include/linux/pid.h | 2 +- include/linux/rculist.h | 2 +- include/linux/sched.h | 2 +- include/linux/sem.h | 2 +- include/linux/sysctl.h | 2 +- kernel/futex_compat.c | 1 + kernel/tsacct.c | 1 + lib/is_single_threaded.c | 1 + 11 files changed, 11 insertions(+), 7 deletions(-)
drivers/staging/tidspbridge/pmgr/dspapi.c +1 -0
@@ -17,6 +17,7 @@* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include <linux/types.h> +#include <linux/rcupdate.h> /* ----------------------------------- Host OS */ #include <dspbridge/host_os.h>
include/linux/aio.h +1 -1
@@ -5,7 +5,7 @@#include <linux/workqueue.h> #include <linux/aio_abi.h> #include <linux/uio.h> -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> #include <asm/atomic.h>
include/linux/key.h +1 -1
@@ -18,7 +18,7 @@#include <linux/types.h> #include <linux/list.h> #include <linux/rbtree.h> -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> #include <linux/sysctl.h> #include <linux/rwsem.h> #include <asm/atomic.h>
include/linux/pid.h +1 -1
@@ -1,7 +1,7 @@#ifndef _LINUX_PID_H#define _LINUX_PID_H -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> enum pid_type {
include/linux/rculist.h +1 -1
@@ -7,7 +7,7 @@* RCU-protected list version */ #include <linux/list.h> -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> /* * Why is there no list_empty_rcu()? Because list_empty() serves this
include/linux/sched.h +1 -1
@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> #include <linux/rculist.h> #include <linux/rtmutex.h>
include/linux/sem.h +1 -1
@@ -78,7 +78,7 @@ struct seminfo {#ifdef __KERNEL__#include <asm/atomic.h> -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> #include <linux/cache.h> struct task_struct ;
include/linux/sysctl.h +1 -1
@@ -930,7 +930,7 @@ enum#ifdef __KERNEL__#include <linux/list.h> -#include <linux/rcupdate.h> +#include <linux/rcupdate_defs.h> /* For the /proc/sys support */ struct ctl_table ;
kernel/futex_compat.c +1 -0
@@ -10,6 +10,7 @@#include <linux/compat.h> #include <linux/nsproxy.h> #include <linux/futex.h> +#include <linux/rcupdate.h> #include <asm/uaccess.h>
kernel/tsacct.c +1 -0
@@ -21,6 +21,7 @@#include <linux/tsacct_kern.h> #include <linux/acct.h> #include <linux/jiffies.h> +#include <linux/rcupdate.h> #include <linux/mm.h> /*
lib/is_single_threaded.c +1 -0
@@ -11,6 +11,7 @@*/ #include <linux/sched.h> +#include <linux/rcupdate.h> /* * Returns true if the task does not share ->mm with another thread/process.
Signature · 1 line
1.7.4
PATCH 3/4 rcu: introduce task_rcu_struct and move task's RCU code to rcupdate_defs.h
In reply to Paul E. McKenneyAdd struct task_rcu_struct to make code clearer and move them to rcupdate_defs.h which help us for code maitainment.
--- include/linux/init_task.h | 25 +---------------- include/linux/rcupdate.h | 34 ++++++++++++++++++----- include/linux/rcupdate_defs.h | 60 +++++++++++++++++++++++++++++++++++++++++ include/linux/sched.h | 39 +-------------------------- kernel/rcutiny_plugin.h | 26 +++++++++-------- kernel/rcutree_plugin.h | 37 +++++++++++++------------ 6 files changed, 122 insertions(+), 99 deletions(-)
include/linux/init_task.h +1 -24
@@ -90,29 +90,6 @@ extern struct group_info init_groups;*/ # define CAP_INIT_BSET CAP_FULL_SET -#ifdef CONFIG_RCU_BOOST -#define INIT_TASK_RCU_BOOST () \ - .rcu_boost_mutex = NULL, -#else -#define INIT_TASK_RCU_BOOST () -#endif -#ifdef CONFIG_TREE_PREEMPT_RCU -#define INIT_TASK_RCU_TREE_PREEMPT () \ - .rcu_blocked_node = NULL, -#else -#define INIT_TASK_RCU_TREE_PREEMPT (tsk) -#endif -#ifdef CONFIG_PREEMPT_RCU -#define INIT_TASK_RCU_PREEMPT (tsk) \ - .rcu_read_lock_nesting = 0, \ - .rcu_read_unlock_special = 0, \ - .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry), \ - INIT_TASK_RCU_TREE_PREEMPT() \ - INIT_TASK_RCU_BOOST() -#else -#define INIT_TASK_RCU_PREEMPT (tsk) -#endif -extern struct cred init_cred;#ifdef CONFIG_PERF_EVENTS
@@ -191,7 +168,7 @@ extern struct cred init_cred;INIT_LOCKDEP \ INIT_FTRACE_GRAPH \ INIT_TRACE_RECURSION \ - INIT_TASK_RCU_PREEMPT(tsk) \ + .task_rcu_struct = INIT_TASK_RCU_STRUCT(tsk.task_rcu_struct), \ }
include/linux/rcupdate.h +27 -7
@@ -34,6 +34,29 @@#define __LINUX_RCUPDATE_H#include <linux/rcupdate_defs.h> +#include <linux/sched.h> + +static inline +struct task_rcu_struct *task_rcu_struct (struct task_struct *t) +{ +return &t->task_rcu_struct; +} + +static inline +struct task_struct *task_of_task_rcu (struct task_rcu_struct *task_rcu) +{ + return container_of(task_rcu, struct task_struct, task_rcu_struct); +} + +static inline struct task_rcu_struct *current_task_rcu_struct (void ) +{ +return task_rcu_struct (current); +} + +static inline void rcu_copy_process (struct task_struct *tsk) +{ +init_task_rcu_struct (task_rcu_struct (tsk)); +}static inline void __rcu_read_lock_bh (void ) {
@@ -50,13 +73,10 @@ static inline void __rcu_read_unlock_bh(void)extern void __rcu_read_lock (void );extern void __rcu_read_unlock (void ); -/* -* Defined as a macro as it is a very low level header included from -* areas that don't even know about current. This gives the rcu_read_lock() -* nesting depth, but makes sense only if CONFIG_PREEMPT_RCU -- in other -* types of kernel builds, the rcu_read_lock() nesting depth is unknowable. -*/ -#define rcu_preempt_depth () (current->rcu_read_lock_nesting) +static inline int rcu_preempt_depth (void ) +{ +return current_task_rcu_struct ()->rcu_read_lock_nesting; +}#else /* #ifdef CONFIG_PREEMPT_RCU */
include/linux/rcupdate_defs.h +60 -0
66 lines not on this page · raw message
include/linux/sched.h +1 -38
@@ -1232,17 +1232,7 @@ struct task_struct {unsigned int policy;cpumask_t cpus_allowed; -#ifdef CONFIG_PREEMPT_RCU -int rcu_read_lock_nesting; -char rcu_read_unlock_special; -struct list_head rcu_node_entry; -#endif /* #ifdef CONFIG_PREEMPT_RCU */ -#ifdef CONFIG_TREE_PREEMPT_RCU -struct rcu_node *rcu_blocked_node; -#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -#ifdef CONFIG_RCU_BOOST -struct rt_mutex *rcu_boost_mutex; -#endif /* #ifdef CONFIG_RCU_BOOST */ +struct task_rcu_struct task_rcu_struct;#if defined(CONFIG_SCHEDSTATS ) || defined(CONFIG_TASK_DELAY_ACCT )struct sched_info sched_info;
@@ -1772,33 +1762,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *#define tsk_used_math (p) ((p)->flags & PF_USED_MATH)#define used_math () tsk_used_math(current) -#ifdef CONFIG_PREEMPT_RCU - -#define RCU_READ_UNLOCK_BLOCKED (1 << 0)/* blocked while in RCU read-side. */ -#define RCU_READ_UNLOCK_BOOSTED (1 << 1)/* boosted while in RCU read-side. */ -#define RCU_READ_UNLOCK_NEED_QS (1 << 2)/* RCU core needs CPU response. */ - -static inline void rcu_copy_process (struct task_struct *p) -{ - p->rcu_read_lock_nesting =0 ; - p->rcu_read_unlock_special =0 ; -#ifdef CONFIG_TREE_PREEMPT_RCU - p->rcu_blocked_node =NULL ; -#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -#ifdef CONFIG_RCU_BOOST - p->rcu_boost_mutex =NULL ; -#endif /* #ifdef CONFIG_RCU_BOOST */ -INIT_LIST_HEAD (&p->rcu_node_entry); -} - -#else - -static inline void rcu_copy_process (struct task_struct *p) -{ -} - -#endif -#ifdef CONFIG_SMP extern int set_cpus_allowed_ptr (struct task_struct *p,const struct cpumask *new_mask);
kernel/rcutiny_plugin.h +14 -12
@@ -150,7 +150,7 @@ static int rcu_cpu_blocking_cur_gp(void)*/ static int rcu_preempt_running_reader (void ) { -return current->rcu_read_lock_nesting; +return current_task_rcu_struct ()->rcu_read_lock_nesting; }/*
@@ -192,7 +192,7 @@ static int rcu_preempt_gp_in_progress(void)* Advance a ->blkd_tasks-list pointer to the next entry, instead * returning NULL if at the end of the list. */ -static struct list_head *rcu_next_node_entry (struct task_struct *t) +static struct list_head *rcu_next_node_entry (struct task_rcu_struct *t) {struct list_head *np;
@@ -255,7 +255,7 @@ static int rcu_boost(void) {unsigned long flags;struct rt_mutex mtx; -struct task_struct *t; +struct task_rcu_struct *t;struct list_head *tb; if (rcu_preempt_ctrlblk.boost_tasks == NULL &&
@@ -298,8 +298,8 @@ static int rcu_boost(void)* simply acquiring this artificial rt_mutex will boost task * t's priority. (Thanks to tglx for suggesting this approach!) */ - t = container_of(tb, struct task_struct, rcu_node_entry); -rt_mutex_init_proxy_locked (&mtx, t); + t = container_of(tb, struct task_rcu_struct, rcu_node_entry); +rt_mutex_init_proxy_locked (&mtx,task_of_task_rcu (t)); t->rcu_boost_mutex = &mtx; t->rcu_read_unlock_special |=RCU_READ_UNLOCK_BOOSTED ;raw_local_irq_restore (flags);
@@ -402,9 +402,11 @@ static void rcu_preempt_boost_start_gp(void)*/ static void rcu_preempt_cpu_qs (void ) { +struct task_rcu_struct *t =current_task_rcu_struct (); +/* Record both CPU and task as having responded to current GP. */ rcu_preempt_ctrlblk.gpcpu = rcu_preempt_ctrlblk.gpnum; - current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; + t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ;/* If there is no GP then there is nothing more to do. */ if (!rcu_preempt_gp_in_progress ())
@@ -473,7 +475,7 @@ static void rcu_preempt_start_gp(void)*/ void rcu_preempt_note_context_switch (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();unsigned long flags;local_irq_save (flags);/* must exclude scheduler_tick(). */
@@ -518,7 +520,7 @@ void rcu_preempt_note_context_switch(void)*/ void __rcu_read_lock (void ) { - current->rcu_read_lock_nesting++; +current_task_rcu_struct ()->rcu_read_lock_nesting++;barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ }EXPORT_SYMBOL_GPL (__rcu_read_lock);
@@ -528,7 +530,7 @@ EXPORT_SYMBOL_GPL(__rcu_read_lock);* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +static void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -617,7 +619,7 @@ static void rcu_read_unlock_special(struct task_struct *t)*/ void __rcu_read_unlock (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ --t->rcu_read_lock_nesting;
@@ -640,7 +642,7 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);*/ static void rcu_preempt_check_callbacks (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct (); if (rcu_preempt_gp_in_progress() && (!rcu_preempt_running_reader() ||
@@ -841,7 +843,7 @@ int rcu_preempt_needs_cpu(void)*/ void exit_rcu (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();if (t->rcu_read_lock_nesting ==0 )return ;
kernel/rcutree_plugin.h +19 -18
@@ -120,11 +120,12 @@ EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);static void rcu_preempt_qs (int cpu) {struct rcu_data *rdp = &per_cpu (rcu_preempt_data, cpu); +struct task_rcu_struct *t =current_task_rcu_struct (); rdp->passed_quiesc_completed = rdp->gpnum -1 ;barrier (); rdp->passed_quiesc =1 ; - current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; + t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; }/*
@@ -142,7 +143,7 @@ static void rcu_preempt_qs(int cpu)*/ static void rcu_preempt_note_context_switch (int cpu) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();unsigned long flags;struct rcu_data *rdp;struct rcu_node *rnp;
@@ -213,7 +214,7 @@ static void rcu_preempt_note_context_switch(int cpu)*/ void __rcu_read_lock (void ) { - current->rcu_read_lock_nesting++; +current_task_rcu_struct ()->rcu_read_lock_nesting++;barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ }EXPORT_SYMBOL_GPL (__rcu_read_lock);
@@ -268,7 +269,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)* Advance a ->blkd_tasks-list pointer to the next entry, instead * returning NULL if at the end of the list. */ -static struct list_head *rcu_next_node_entry (struct task_struct *t, +static struct list_head *rcu_next_node_entry (struct task_rcu_struct *t,struct rcu_node *rnp) {struct list_head *np;
@@ -284,7 +285,7 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_struct *t) +static void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -384,7 +385,7 @@ static void rcu_read_unlock_special(struct task_struct *t)*/ void __rcu_read_unlock (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ --t->rcu_read_lock_nesting;
@@ -407,15 +408,15 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);static void rcu_print_detail_task_stall_rnp (struct rcu_node *rnp) {unsigned long flags; -struct task_struct *t; +struct task_rcu_struct *t;if (!rcu_preempt_blocked_readers_cgp (rnp))return ;raw_spin_lock_irqsave (&rnp->lock, flags); t =list_entry (rnp->gp_tasks, - struct task_struct, rcu_node_entry); + struct task_rcu_struct, rcu_node_entry);list_for_each_entry_continue (t, &rnp->blkd_tasks, rcu_node_entry) -sched_show_task (t); +sched_show_task (task_of_task_rcu (t));raw_spin_unlock_irqrestore (&rnp->lock, flags); }
@@ -446,14 +447,14 @@ static void rcu_print_detail_task_stall(struct rcu_state *rsp)*/ static void rcu_print_task_stall (struct rcu_node *rnp) { -struct task_struct *t; +struct task_rcu_struct *t;if (!rcu_preempt_blocked_readers_cgp (rnp))return ; t =list_entry (rnp->gp_tasks, - struct task_struct, rcu_node_entry); + struct task_rcu_struct, rcu_node_entry);list_for_each_entry_continue (t, &rnp->blkd_tasks, rcu_node_entry) -printk (" P%d" , t->pid); +printk (" P%d" ,task_of_task_rcu (t)->pid); }/*
@@ -508,7 +509,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,struct list_head *lp_root;int retval =0 ;struct rcu_node *rnp_root =rcu_get_root (rsp); -struct task_struct *t; +struct task_rcu_struct *t;if (rnp == rnp_root) {WARN_ONCE (1 ,"Last CPU thought to be offlined?" );
@@ -581,7 +582,7 @@ static void rcu_preempt_offline_cpu(int cpu)*/ static void rcu_preempt_check_callbacks (int cpu) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();if (t->rcu_read_lock_nesting ==0 ) {rcu_preempt_qs (cpu);
@@ -851,7 +852,7 @@ static void __init __rcu_init_preempt(void)*/ void exit_rcu (void ) { -struct task_struct *t = current; +struct task_rcu_struct *t =current_task_rcu_struct ();if (t->rcu_read_lock_nesting ==0 )return ;
@@ -1110,7 +1111,7 @@ static int rcu_boost(struct rcu_node *rnp) {unsigned long flags;struct rt_mutex mtx; -struct task_struct *t; +struct task_rcu_struct *t;struct list_head *tb;if (rnp->exp_tasks ==NULL && rnp->boost_tasks ==NULL )
@@ -1158,8 +1159,8 @@ static int rcu_boost(struct rcu_node *rnp)* and task t's exiting its outermost RCU read-side critical * section. */ - t = container_of(tb, struct task_struct, rcu_node_entry); -rt_mutex_init_proxy_locked (&mtx, t); + t = container_of(tb, struct task_rcu_struct, rcu_node_entry); +rt_mutex_init_proxy_locked (&mtx,task_of_task_rcu (t)); t->rcu_boost_mutex = &mtx; t->rcu_read_unlock_special |=RCU_READ_UNLOCK_BOOSTED ;raw_spin_unlock_irqrestore (&rnp->lock, flags);
Signature · 1 line
1.7.4
Re: [PATCH 3/4] rcu: introduce task_rcu_struct and move task's RCU code to rcupdate_defs.h
Quoted 11 lines · Lai Jiangshan
Add struct
task_rcu_structto make code clearer and move them torcupdate_defs.hwhich help us for code maitainment.include/linux/sched.h +0
-2@@ -1232,17 +1232,7 @@ struct task_struct { unsigned int policy; cpumask_t cpus_allowed; -#ifdef CONFIG_PREEMPT_RCU - int rcu_read_lock_nesting;
include/linux/sched.h struct task_struct { · line 1235
Quoted 10 lines
include/linux/sched.h +1
-9- char rcu_read_unlock_special; - struct list_head rcu_node_entry; -#endif /* #ifdef CONFIG_PREEMPT_RCU */ -#ifdef CONFIG_TREE_PREEMPT_RCU - struct rcu_node *rcu_blocked_node; -#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -#ifdef CONFIG_RCU_BOOST - struct rt_mutex *rcu_boost_mutex; -#endif /* #ifdef CONFIG_RCU_BOOST */ + struct task_rcu_struct task_rcu_struct;
Oh, wow, all these movements are for this.
You could do
struct task_rcu {
...
} rcu;inside sched.h, drop pointless 1:1 current_() et al wrappers and avoid all this mess.
PATCH 4/4 rcu: declare preemptible __rcu_read_[un]lock() as inline function
In reply to Paul E. McKenney__rcu_read_[un]lock() are so simple functions, make them inlined. Also rmove dumplicated code.
--- include/linux/rcupdate.h | 36 ++++++++++++++++++++++++++++++++++-- kernel/rcutiny_plugin.h | 38 ++------------------------------------ kernel/rcutree_plugin.h | 38 ++------------------------------------ 3 files changed, 38 insertions(+), 74 deletions(-)
include/linux/rcupdate.h +34 -2
@@ -70,8 +70,40 @@ static inline void __rcu_read_unlock_bh(void)#ifdef CONFIG_PREEMPT_RCU -extern void __rcu_read_lock (void ); -extern void __rcu_read_unlock (void ); +void rcu_read_unlock_special (struct task_rcu_struct *t); + +/* +* Preemptible RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ +current_task_rcu_struct ()->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Preemptible RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_rcu_struct *t =current_task_rcu_struct (); + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +}static inline int rcu_preempt_depth (void ) {
kernel/rcutiny_plugin.h +2 -36
@@ -514,23 +514,11 @@ void rcu_preempt_note_context_switch(void) }/* -* Tiny-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ -current_task_rcu_struct ()->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Handle special cases during rcu_read_unlock(), such as needing to * notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_rcu_struct *t) +void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -609,29 +597,7 @@ static void rcu_read_unlock_special(struct task_rcu_struct *t)#endif /* #ifdef CONFIG_RCU_BOOST */ local_irq_restore (flags); } - -/* -* Tiny-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_rcu_struct *t =current_task_rcu_struct (); - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);/* * Check for a quiescent state from the current CPU. When a task blocks,
kernel/rcutree_plugin.h +2 -36
@@ -208,18 +208,6 @@ static void rcu_preempt_note_context_switch(int cpu) }/* -* Tree-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ -current_task_rcu_struct ()->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Check for preempted RCU readers blocking the current grace period * for the specified rcu_node structure. If the caller needs a reliable * answer, it must hold the rcu_node's ->lock.
@@ -285,7 +273,7 @@ static struct list_head *rcu_next_node_entry(struct task_rcu_struct *t,* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_rcu_struct *t) +void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -375,29 +363,7 @@ static void rcu_read_unlock_special(struct task_rcu_struct *t)local_irq_restore (flags); } } - -/* -* Tree-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_rcu_struct *t =current_task_rcu_struct (); - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);#ifdef CONFIG_RCU_CPU_STALL_VERBOSE
Signature · 1 line
1.7.4
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Paul E. McKenneyQuoted 2 lines · Paul E. McKenney
Quoted 1 line · Paul E. McKenney
On Fri, Apr 01, 2011 at 01:35:49PM +0200, Peter Zijlstra wrote:
[ . . . ]
Quoted 16 lines
Quoted 16 lines
Quoted 4 lines
There isn't a single
rcu_read_lock()user in the include chain ofsched.h, therefore its possible to splitrcupdate.hsuch that one part includes the bits needed forsched.hand another part that includessched.hand providesrcu_read_lock().Yep, you can easily split struct
rcu_headout into its own header file, and then include that intosched.hin place ofrcupdate.hwithout trouble (at least in the few builds I tried).The trouble comes when you take the next step and include
sched.hintoinclude/linux/rcutree.h, which would be needed to allow TREE_PREEMPT_RCU'srcu_read_lock()andrcu_read_unlock()to be inlined. This pullssched.hinto files that it was not already included into, and we do get build failures (the first of which requires changes local to RCU, FWIW).
Quoted 8 lines
Quoted 1 line
Of course, it would be good to straighten this out.
And here is a start -- the build is -much- quieter with this patch.
The next layer on this onion is the use of the
ctl_tabletypedef ininclude/linux/key.h-- which is defined to be structctl_table. Anyone know where structctl_tableis defined? Color me blind, but I am not seeing it...
Sigh... In include/linux/sysctl.h, but with the opening brace on the next line. Anyway, the problem is that include/linux/sysctl.h and include/linux/key.h indirectly include each other in a mutually recursive fashion.
So easy to fix -- just include include/linux/key.h prior to the include of include/linux/sysctl.h in kernel/sysctl_binary.c.
Thanx, Paul
Quoted 144 lines
------------------------------------------------------------------------
include/linux/rcu_head.h new file +46
-0@@ -0,0 +1,46 @@ +/* +* Read-Copy Update mechanism for mutual exclusion: base structures +* +* 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, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Copyright IBM Corporation, 2001 +* +* Author: Dipankar Sarma <[email protected]> +* +* Based on the original work by Paul McKenney <[email protected]> +* and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. +* Papers: +* http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf +* http://lse.sourceforge.net/locking/rclock_OLS.2001.05.01c.sc.pdf (OLS2001) +* +* For detailed explanation of Read-Copy Update mechanism see - +* http://lse.sourceforge.net/locking/rcupdate.html +* +*/ + +#ifndef __LINUX_RCU_HEAD_H +#define __LINUX_RCU_HEAD_H + +/** +* struct rcu_head - callback structure for use with RCU +* @next: next update requests in a list +* @func: actual update function to call after the grace period. +*/ +struct rcu_head { +struct rcu_head *next; +void (*func)(struct rcu_head *head); +}; + +#endif /* __LINUX_RCU_HEAD_H */ include/linux/rcupdate.h +9
-17@@ -52,15 +52,7 @@ extern int rcutorture_runnable; /* for sysctl */#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))#define ULONG_CMP_LT (a, b) (ULONG_MAX / 2 < (a) - (b)) -/** -* struct rcu_head - callback structure for use with RCU -* @next: next update requests in a list -* @func: actual update function to call after the grace period. -*/ -struct rcu_head { -struct rcu_head *next; -void (*func)(struct rcu_head *head); -}; +#include <linux/rcu_head.h> /* Exported common interfaces */ extern void call_rcu_sched(struct rcu_head *head,@@ -141,14 +133,6 @@ static inline void rcu_exit_nohz(void)#endif /* #else #ifdef CONFIG_NO_HZ */ -#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) -#include <linux/rcutree.h> -#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) -#include <linux/rcutiny.h> -#else -#error "Unknown RCU implementation specified to kernel configuration" -#endif -/* * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic * initialization and destruction of rcu_head on the stack. rcu_head structures @@ -797,4 +781,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) +#include <linux/rcutree.h> +#elif defined(CONFIG_TINY_RCU ) || defined(CONFIG_TINY_PREEMPT_RCU ) +#include <linux/rcutiny.h> +#else +#error "Unknown RCU implementation specified to kernel configuration" +#endif +#endif /* __LINUX_RCUPDATE_H */ include/linux/rcutree.h +2
-0@@ -30,6 +30,8 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +#include <linux/sched.h> +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);include/linux/sched.h +4
-6@@ -78,7 +78,7 @@ struct sched_param {#include <linux/topology.h> #include <linux/proportions.h> #include <linux/seccomp.h> -#include <linux/rcupdate.h> +#include <linux/rcu_head.h> #include <linux/rculist.h> #include <linux/rtmutex.h> @@ -2241,11 +2241,9 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)return p1->tgid == p2->tgid; } -static inline struct task_struct *next_thread (const struct task_struct *p) -{ -return list_entry_rcu (p->thread_group.next, - struct task_struct, thread_group); -} +/* Avoid #include hell for inlining rcu_read_lock(). */ +#define next_thread (p) \ + list_entry_rcu((p)->thread_group.next, struct task_struct, thread_group)static inline int thread_group_empty (struct task_struct *p) {
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Lai JiangshanQuoted 4 lines · Lai Jiangshan
But how about my
kernel-offset.cpatch? It is clean & simple, it just seems not so normal.
It is neither clear nor simple, sorry. It is quite the opposite.
I think Michal is on the right track, but yes, much work remains to be done.
-hpa
Re: [RFC PATCH 4/5] RCU: Add TASK_RCU_OFFSET
In reply to Lai JiangshanQuoted 4 lines · Lai Jiangshan
RCU is one of the most import subsystem,
I think it is worth to do such "wrong" way.
No, that's the wrong way to look at it.
RCU is important enough that it's worth creating disruption over doing it correctly.
-hpa
RFC PATCH 5/5 RCU: declare preemptible __rcu_read_[un]lock() as inline function
In reply to Lai Jiangshan__rcu_read_[un]lock() are so simple functions, make them inlined. Also rmove dumplicated code.
--- include/linux/rcupdate.h | 37 +++++++++++++++++++++++++++++++++++-- kernel/rcutiny_plugin.h | 38 ++------------------------------------ kernel/rcutree_plugin.h | 38 ++------------------------------------ 3 files changed, 39 insertions(+), 74 deletions(-)
include/linux/rcupdate.h +35 -2
@@ -187,8 +187,41 @@ static inline void rcu_copy_process(struct task_struct *tsk)#ifdef CONFIG_PREEMPT_RCU -extern void __rcu_read_lock (void ); -extern void __rcu_read_unlock (void ); +void rcu_read_unlock_special (struct task_rcu_struct *t); + +/* +* Preemptible RCU implementation for rcu_read_lock(). +* Just increment ->rcu_read_lock_nesting, shared state will be updated +* if we block. +*/ +static inline void __rcu_read_lock (void ) +{ +current_task_rcu_struct ()->rcu_read_lock_nesting++; +barrier (); +} + +/* +* Preemptible RCU implementation for rcu_read_unlock(). +* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost +* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then +* invoke rcu_read_unlock_special() to clean up after a context switch +* in an RCU read-side critical section and other special cases. +*/ +static inline void __rcu_read_unlock (void ) +{ +struct task_rcu_struct *t =current_task_rcu_struct (); + +barrier (); + --t->rcu_read_lock_nesting; +barrier ();/* decrement before load of ->rcu_read_unlock_special */ +if (t->rcu_read_lock_nesting ==0 && +unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) +rcu_read_unlock_special (t); +#ifdef CONFIG_PROVE_LOCKING +WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); +#endif /* #ifdef CONFIG_PROVE_LOCKING */ +} +void synchronize_rcu (void );/*
kernel/rcutiny_plugin.h +2 -36
@@ -514,23 +514,11 @@ void rcu_preempt_note_context_switch(void) }/* -* Tiny-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ -current_task_rcu_struct ()->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutiny.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Handle special cases during rcu_read_unlock(), such as needing to * notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_rcu_struct *t) +void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -609,29 +597,7 @@ static void rcu_read_unlock_special(struct task_rcu_struct *t)#endif /* #ifdef CONFIG_RCU_BOOST */ local_irq_restore (flags); } - -/* -* Tiny-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_rcu_struct *t =current_task_rcu_struct (); - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutiny.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (t->rcu_read_lock_nesting <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);/* * Check for a quiescent state from the current CPU. When a task blocks,
kernel/rcutree_plugin.h +2 -36
@@ -208,18 +208,6 @@ static void rcu_preempt_note_context_switch(int cpu) }/* -* Tree-preemptible RCU implementation for rcu_read_lock(). -* Just increment ->rcu_read_lock_nesting, shared state will be updated -* if we block. -*/ -void __rcu_read_lock (void ) -{ -current_task_rcu_struct ()->rcu_read_lock_nesting++; -barrier ();/* needed if we ever invoke rcu_read_lock in rcutree.c */ -} -EXPORT_SYMBOL_GPL (__rcu_read_lock); - -/* * Check for preempted RCU readers blocking the current grace period * for the specified rcu_node structure. If the caller needs a reliable * answer, it must hold the rcu_node's ->lock.
@@ -285,7 +273,7 @@ static struct list_head *rcu_next_node_entry(struct task_rcu_struct *t,* notify RCU core processing or task having blocked during the RCU * read-side critical section. */ -static void rcu_read_unlock_special (struct task_rcu_struct *t) +void rcu_read_unlock_special (struct task_rcu_struct *t) {int empty;int empty_exp;
@@ -375,29 +363,7 @@ static void rcu_read_unlock_special(struct task_rcu_struct *t)local_irq_restore (flags); } } - -/* -* Tree-preemptible RCU implementation for rcu_read_unlock(). -* Decrement ->rcu_read_lock_nesting. If the result is zero (outermost -* rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then -* invoke rcu_read_unlock_special() to clean up after a context switch -* in an RCU read-side critical section and other special cases. -*/ -void __rcu_read_unlock (void ) -{ -struct task_rcu_struct *t =current_task_rcu_struct (); - -barrier ();/* needed if we ever invoke rcu_read_unlock in rcutree.c */ - --t->rcu_read_lock_nesting; -barrier ();/* decrement before load of ->rcu_read_unlock_special */ -if (t->rcu_read_lock_nesting ==0 && -unlikely (ACCESS_ONCE (t->rcu_read_unlock_special))) -rcu_read_unlock_special (t); -#ifdef CONFIG_PROVE_LOCKING -WARN_ON_ONCE (ACCESS_ONCE (t->rcu_read_lock_nesting) <0 ); -#endif /* #ifdef CONFIG_PROVE_LOCKING */ -} -EXPORT_SYMBOL_GPL (__rcu_read_unlock); +EXPORT_SYMBOL_GPL (rcu_read_unlock_special);#ifdef CONFIG_RCU_CPU_STALL_VERBOSE
Signature · 1 line
1.7.4
Quoted 7 lines · Lai Jiangshan
__rcu_read_[un]lock() are so simple functions and called so frequent, it is not good that a function call overhead is required when use them. It would be better if we declare them inline and let the compiler do the choice.
Quoted 5 lines
We add
kernel-offset.cforTASK_RCU_OFFSET, which enable we declare rcu_read_[un]lock() as inline function.Adding
kernel-offset.cdoes not have any effect for the result compiled kernel, it just adds a small and fast step in the kbuid stage.
Good stuff, thank you! It will be really cool to have inlined rcu_read_lock() and rcu_read_unlock() for TREE_PREEMPT_RCU!
I will queue this up in a few days, currently chasing down a problem located in the upcoming TREE_RCU softirq-to-kthread commit.
Thanx, Paul
Quoted 19 lines
Lai Jiangshan (5):
task_rcu_struct
kbuild_dedumplicated
add_kernel_offset
access task'stask_rcu_structwithout includesched.hrcu inlineKbuild | 99 ++++++++++++++++--------------- include/linux/init_task.h | 25 +-------- include/linux/rcupdate.h | 144 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/sched.h | 39 +------------ kernel/kernel-offsets.c | 17 +++++ kernel/rcutiny_plugin.h | 58 ++++-------------- kernel/rcutree_plugin.h | 69 ++++++---------------- 7 files changed, 243 insertions(+), 208 deletions(-) create mode 100644 kernel/kernel-offsets.cSignature · 1 line
1.7.4