RCU changes for v2.6.38
Subsystems (3)
Linus,
Please pull the latest core-rcu-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git core-rcu-for-linus
Thanks,
Ingo
------------------>
Frederic Weisbecker (2):
rcu: Stop chasing QS if another CPU did it for us
rcu: Keep gpnum and completed fields synchronized
Lai Jiangshan (2):
rcu,cleanup: move synchronize_sched_expedited() out of sched.c rcu,cleanup: simplify the code when cpu is dying
Mariusz Kozlowski (1):
rculist: fix borked __list_for_each_rcu() macro
Paul E. McKenney (14):
rcu: add priority-inversion testing to rcutorture
rcu: move TINY_RCU from softirq to kthread
rcu: priority boosting for TINY_PREEMPT_RCU
rcu: add tracing for TINY_RCU and TINY_PREEMPT_RCU
rcu: document TINY_RCU and TINY_PREEMPT_RCU tracing.
rcu: Distinguish between boosting and boosted
rcu: get rid of obsolete "classic" names in TREE_RCU tracing
rcu: update documentation/comments for Lai's adoption patch
rcu: fix race condition in synchronize_sched_expedited()
rcu: Make synchronize_srcu_expedited() fast if running readers
rcu: fine-tune grace-period begin/end checks
rcu: limit rcu_node leaf-level fanout
rcu: reduce __call_rcu()-induced contention on rcu_node structures
rcu: remove unused __list_for_each_rcu() macro
Tejun Heo (1):
rcu: increase synchronize_sched_expedited() batching
Documentation/RCU/trace.txt | 144 +++++++++++++-- include/linux/init_task.h | 9 +- include/linux/rculist.h | 5 - include/linux/rcupdate.h | 4 +- include/linux/rcutiny.h | 13 +- include/linux/rcutree.h | 2 + include/linux/sched.h | 11 +- init/Kconfig | 55 ++++++- kernel/rcutiny.c | 105 +++++++---- kernel/rcutiny_plugin.h | 433 +++++++++++++++++++++++++++++++++++++++++-- kernel/rcutorture.c | 270 ++++++++++++++++++++++++++- kernel/rcutree.c | 156 ++++++++-------- kernel/rcutree.h | 61 +++---- kernel/rcutree_plugin.h | 135 +++++++++++++- kernel/rcutree_trace.c | 12 +- kernel/sched.c | 69 ------- kernel/srcu.c | 8 +- 17 files changed, 1207 insertions(+), 285 deletions(-)
Documentation/RCU/trace.txt +128 -16
@@ -1,18 +1,22 @@ CONFIG_RCU_TRACE debugfs Files and Formats -The rcutree implementation of RCU provides debugfs trace output that -summarizes counters and state. This information is useful for debugging -RCU itself, and can sometimes also help to debug abuses of RCU. -The following sections describe the debugfs files and formats. +The rcutree and rcutiny implementations of RCU provide debugfs trace +output that summarizes counters and state. This information is useful for +debugging RCU itself, and can sometimes also help to debug abuses of RCU. +The following sections describe the debugfs files and formats, first +for rcutree and next for rcutiny. -Hierarchical RCU debugfs Files and Formats +CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -This implementation of RCU provides three debugfs files under the +These implementations of RCU provides five debugfs files under the top-level directory RCU: rcu/rcudata (which displays fields in struct -rcu_data), rcu/rcugp (which displays grace-period counters), and -rcu/rcuhier (which displays the struct rcu_node hierarchy). +rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of +rcu/rcudata), rcu/rcugp (which displays grace-period counters), +rcu/rcuhier (which displays the struct rcu_node hierarchy), and +rcu/rcu_pending (which displays counts of the reasons that the +rcu_pending() function decided that there was core RCU work to do). The output of "cat rcu/rcudata" looks as follows:
@@ -130,7 +134,8 @@ o "ci" is the number of RCU callbacks that have been invoked for been registered in absence of CPU-hotplug activity. o "co" is the number of RCU callbacks that have been orphaned due to - this CPU going offline. + this CPU going offline. These orphaned callbacks have been moved + to an arbitrarily chosen online CPU. o "ca" is the number of RCU callbacks that have been adopted due to other CPUs going offline. Note that ci+co-ca+ql is the number of
@@ -168,12 +173,12 @@ o "gpnum" is the number of grace periods that have started. It is The output of "cat rcu/rcuhier" looks as follows, with very long lines: -c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 oqlen=0 +c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 1/1 .>. 0:127 ^0 3/3 .>. 0:35 ^0 0/0 .>. 36:71 ^1 0/0 .>. 72:107 ^2 0/0 .>. 108:127 ^3 3/3f .>. 0:5 ^0 2/3 .>. 6:11 ^1 0/0 .>. 12:17 ^2 0/0 .>. 18:23 ^3 0/0 .>. 24:29 ^4 0/0 .>. 30:35 ^5 0/0 .>. 36:41 ^0 0/0 .>. 42:47 ^1 0/0 .>. 48:53 ^2 0/0 .>. 54:59 ^3 0/0 .>. 60:65 ^4 0/0 .>. 66:71 ^5 0/0 .>. 72:77 ^0 0/0 .>. 78:83 ^1 0/0 .>. 84:89 ^2 0/0 .>. 90:95 ^3 0/0 .>. 96:101 ^4 0/0 .>. 102:107 ^5 0/0 .>. 108:113 ^0 0/0 .>. 114:119 ^1 0/0 .>. 120:125 ^2 0/0 .>. 126:127 ^3 rcu_bh: -c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 oqlen=0 +c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 0/1 .>. 0:127 ^0 0/3 .>. 0:35 ^0 0/0 .>. 36:71 ^1 0/0 .>. 72:107 ^2 0/0 .>. 108:127 ^3 0/3f .>. 0:5 ^0 0/3 .>. 6:11 ^1 0/0 .>. 12:17 ^2 0/0 .>. 18:23 ^3 0/0 .>. 24:29 ^4 0/0 .>. 30:35 ^5 0/0 .>. 36:41 ^0 0/0 .>. 42:47 ^1 0/0 .>. 48:53 ^2 0/0 .>. 54:59 ^3 0/0 .>. 60:65 ^4 0/0 .>. 66:71 ^5 0/0 .>. 72:77 ^0 0/0 .>. 78:83 ^1 0/0 .>. 84:89 ^2 0/0 .>. 90:95 ^3 0/0 .>. 96:101 ^4 0/0 .>. 102:107 ^5 0/0 .>. 108:113 ^0 0/0 .>. 114:119 ^1 0/0 .>. 120:125 ^2 0/0 .>. 126:127 ^3
@@ -212,11 +217,6 @@ o "fqlh" is the number of calls to force_quiescent_state() that exited immediately (without even being counted in nfqs above) due to contention on ->fqslock. -o "oqlen" is the number of callbacks on the "orphan" callback - list. RCU callbacks are placed on this list by CPUs going - offline, and are "adopted" either by the CPU helping the outgoing - CPU or by the next rcu_barrier*() call, whichever comes first. - o Each element of the form "1/1 0:127 ^0" represents one struct rcu_node. Each line represents one level of the hierarchy, from root to leaves. It is best to think of the rcu_data structures
@@ -326,3 +326,115 @@ o "nn" is the number of times that this CPU needed nothing. Alert readers will note that the rcu "nn" number for a given CPU very closely matches the rcu_bh "np" number for that same CPU. This is due to short-circuit evaluation in rcu_pending(). + + +CONFIG_TINY_RCU and CONFIG_TINY_PREEMPT_RCU debugfs Files and Formats + +These implementations of RCU provides a single debugfs file under the +top-level directory RCU, namely rcu/rcudata, which displays fields in +rcu_bh_ctrlblk, rcu_sched_ctrlblk and, for CONFIG_TINY_PREEMPT_RCU, +rcu_preempt_ctrlblk. + +The output of "cat rcu/rcudata" is as follows: + +rcu_preempt: qlen=24 gp=1097669 g197/p197/c197 tasks=... + ttb=. btg=no ntb=184 neb=0 nnb=183 j=01f7 bt=0274 + normal balk: nt=1097669 gt=0 bt=371 b=0 ny=25073378 nos=0 + exp balk: bt=0 nos=0 +rcu_sched: qlen: 0 +rcu_bh: qlen: 0 + +This is split into rcu_preempt, rcu_sched, and rcu_bh sections, with the +rcu_preempt section appearing only in CONFIG_TINY_PREEMPT_RCU builds. +The last three lines of the rcu_preempt section appear only in +CONFIG_RCU_BOOST kernel builds. The fields are as follows: + +o "qlen" is the number of RCU callbacks currently waiting either + for an RCU grace period or waiting to be invoked. This is the + only field present for rcu_sched and rcu_bh, due to the + short-circuiting of grace period in those two cases. + +o "gp" is the number of grace periods that have completed. + +o "g197/p197/c197" displays the grace-period state, with the + "g" number being the number of grace periods that have started + (mod 256), the "p" number being the number of grace periods + that the CPU has responded to (also mod 256), and the "c" + number being the number of grace periods that have completed + (once again mode 256). + + Why have both "gp" and "g"? Because the data flowing into + "gp" is only present in a CONFIG_RCU_TRACE kernel. + +o "tasks" is a set of bits. The first bit is "T" if there are + currently tasks that have recently blocked within an RCU + read-side critical section, the second bit is "N" if any of the + aforementioned tasks are blocking the current RCU grace period, + and the third bit is "E" if any of the aforementioned tasks are + blocking the current expedited grace period. Each bit is "." + if the corresponding condition does not hold. + +o "ttb" is a single bit. It is "B" if any of the blocked tasks + need to be priority boosted and "." otherwise. + +o "btg" indicates whether boosting has been carried out during + the current grace period, with "exp" indicating that boosting + is in progress for an expedited grace period, "no" indicating + that boosting has not yet started for a normal grace period, + "begun" indicating that boosting has bebug for a normal grace + period, and "done" indicating that boosting has completed for + a normal grace period. + +o "ntb" is the total number of tasks subjected to RCU priority boosting + periods since boot. + +o "neb" is the number of expedited grace periods that have had + to resort to RCU priority boosting since boot. + +o "nnb" is the number of normal grace periods that have had + to resort to RCU priority boosting since boot. + +o "j" is the low-order 12 bits of the jiffies counter in hexadecimal. + +o "bt" is the low-order 12 bits of the value that the jiffies counter + will have at the next time that boosting is scheduled to begin. + +o In the line beginning with "normal balk", the fields are as follows: + + o "nt" is the number of times that the system balked from + boosting because there were no blocked tasks to boost. + Note that the system will balk from boosting even if the + grace period is overdue when the currently running task + is looping within an RCU read-side critical section. + There is no point in boosting in this case, because + boosting a running task won't make it run any faster. + + o "gt" is the number of times that the system balked + from boosting because, although there were blocked tasks, + none of them were preventing the current grace period + from completing. + + o "bt" is the number of times that the system balked + from boosting because boosting was already in progress. + + o "b" is the number of times that the system balked from + boosting because boosting had already completed for + the grace period in question. + + o "ny" is the number of times that the system balked from + boosting because it was not yet time to start boosting + the grace period in question. + + o "nos" is the number of times that the system balked from + boosting for inexplicable ("not otherwise specified") + reasons. This can actually happen due to races involving + increments of the jiffies counter. + +o In the line beginning with "exp balk", the fields are as follows: + + o "bt" is the number of times that the system balked from + boosting because there were no blocked tasks to boost. + + o "nos" is the number of times that the system balked from + boosting for inexplicable ("not otherwise specified") + reasons.
include/linux/init_task.h +8 -1
@@ -83,6 +83,12 @@ 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,
@@ -94,7 +100,8 @@ extern struct group_info init_groups; .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_TREE_PREEMPT() \ + INIT_TASK_RCU_BOOST()#else #define INIT_TASK_RCU_PREEMPT (tsk)#endif
include/linux/rculist.h +0 -5
@@ -241,11 +241,6 @@ static inline void list_splice_init_rcu(struct list_head *list,#define list_first_entry_rcu (ptr, type, member) \ list_entry_rcu((ptr)->next, type, member) -#define __list_for_each_rcu (pos, head) \ - for (pos = rcu_dereference_raw(list_next_rcu(head)); \ - pos != (head); \ - pos = rcu_dereference_raw(list_next_rcu((pos))) -/** * list_for_each_entry_rcu - iterate over rcu list of given type * @pos: the type * to use as a loop cursor.
include/linux/rcupdate.h +2 -2
@@ -47,6 +47,8 @@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))
@@ -66,7 +68,6 @@ extern void call_rcu_sched(struct rcu_head *head,extern void synchronize_sched (void );extern void rcu_barrier_bh (void );extern void rcu_barrier_sched (void ); -extern void synchronize_sched_expedited (void );extern int sched_expedited_torture_stats (char *page);static inline void __rcu_read_lock_bh (void )
@@ -118,7 +119,6 @@ static inline int rcu_preempt_depth(void)#endif /* #else #ifdef CONFIG_PREEMPT_RCU */ /* Internal to kernel */ -extern void rcu_init (void );extern void rcu_sched_qs (int cpu);extern void rcu_bh_qs (int cpu);extern void rcu_check_callbacks (int cpu,int user);
include/linux/rcutiny.h +8 -5
@@ -27,7 +27,9 @@#include <linux/cache.h> -#define rcu_init_sched () do { } while (0) +static inline void rcu_init (void ) +{ +}#ifdef CONFIG_TINY_RCU
@@ -58,6 +60,11 @@ static inline void synchronize_rcu_bh_expedited(void)synchronize_sched (); } +static inline void synchronize_sched_expedited (void ) +{ +synchronize_sched (); +} +#ifdef CONFIG_TINY_RCU static inline void rcu_preempt_note_context_switch (void )
@@ -125,16 +132,12 @@ static inline void rcu_cpu_stall_reset(void) }#ifdef CONFIG_DEBUG_LOCK_ALLOC -extern int rcu_scheduler_active__read_mostly ;extern void rcu_scheduler_starting (void ); -#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ -static inline void rcu_scheduler_starting (void ) { } -#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ #endif /* __LINUX_RCUTINY_H */
include/linux/rcutree.h +2 -0
@@ -30,6 +30,7 @@#ifndef __LINUX_RCUTREE_H#define __LINUX_RCUTREE_H +extern void rcu_init (void );extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);extern void rcu_cpu_stall_reset (void );
@@ -47,6 +48,7 @@ static inline void exit_rcu(void)#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */ extern void synchronize_rcu_bh (void ); +extern void synchronize_sched_expedited (void );extern void synchronize_rcu_expedited (void );static inline void synchronize_rcu_bh_expedited (void )
include/linux/sched.h +9 -2
@@ -1229,6 +1229,9 @@ struct task_struct {#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 */ #if defined(CONFIG_SCHEDSTATS ) || defined(CONFIG_TASK_DELAY_ACCT )struct sched_info sched_info;
@@ -1759,7 +1762,8 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *#ifdef CONFIG_PREEMPT_RCU #define RCU_READ_UNLOCK_BLOCKED (1 << 0)/* blocked while in RCU read-side. */ -#define RCU_READ_UNLOCK_NEED_QS (1 << 1)/* RCU core needs CPU response. */ +#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) {
@@ -1767,7 +1771,10 @@ static inline void rcu_copy_process(struct task_struct *p) p->rcu_read_unlock_special =0 ;#ifdef CONFIG_TREE_PREEMPT_RCU p->rcu_blocked_node =NULL ; -#endif +#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); }
init/Kconfig +54 -1
67 lines not on this page · raw message
kernel/rcutiny.c +70 -35
160 lines not on this page · raw message
kernel/rcutiny_plugin.h +419 -14
556 lines not on this page · raw message
kernel/rcutorture.c +259 -11
404 lines not on this page · raw message
kernel/rcutree.c +75 -81
244 lines not on this page · raw message
kernel/rcutree.h +29 -32
105 lines not on this page · raw message
kernel/rcutree_plugin.h +131 -4
161 lines not on this page · raw message
kernel/rcutree_trace.c +6 -6
@@ -166,13 +166,13 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) gpnum = rsp->gpnum;seq_printf (m,"c=%lu g=%lu s=%d jfq=%ld j=%x " -"nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld\n" , +"nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n" , rsp->completed, gpnum, rsp->signaled, (long )(rsp->jiffies_force_qs - jiffies), (int )(jiffies &0xffff ), rsp->n_force_qs, rsp->n_force_qs_ngp, rsp->n_force_qs - rsp->n_force_qs_ngp, - rsp->n_force_qs_lh, rsp->orphan_qlen); + rsp->n_force_qs_lh);for (rnp = &rsp->node[0 ]; rnp - &rsp->node[0 ] <NUM_RCU_NODES ; rnp++) {if (rnp->level != level) {seq_puts (m,"\n" );
@@ -300,7 +300,7 @@ static const struct file_operations rcu_pending_fops = {static struct dentry *rcudir; -static int __init rcuclassic_trace_init (void ) +static int __init rcutree_trace_init (void ) {struct dentry *retval;
@@ -337,14 +337,14 @@ free_out:return 1 ; } -static void __exit rcuclassic_trace_cleanup(void) +static void __exit rcutree_trace_cleanup(void) {debugfs_remove_recursive (rcudir); } -module_init (rcuclassic_trace_init); -module_exit (rcuclassic_trace_cleanup); +module_init (rcutree_trace_init); +module_exit (rcutree_trace_cleanup);MODULE_AUTHOR ("Paul E. McKenney" );MODULE_DESCRIPTION ("Read-Copy Update tracing for hierarchical implementation" );
kernel/sched.c +0 -69
72 lines not on this page · raw message
kernel/srcu.c +7 -1
@@ -31,6 +31,7 @@#include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/smp.h> +#include <linux/delay.h> #include <linux/srcu.h> static int init_srcu_struct_fields (struct srcu_struct *sp)
@@ -203,9 +204,14 @@ static void __synchronize_srcu(struct srcu_struct *sp, void (*sync_func)(void))* all srcu_read_lock() calls using the old counters have completed. * Their corresponding critical sections might well be still * executing, but the srcu_read_lock() primitives themselves -* will have finished executing. +* will have finished executing. We initially give readers +* an arbitrarily chosen 10 microseconds to get out of their +* SRCU read-side critical sections, then loop waiting 1/HZ +* seconds per iteration. */ +if (srcu_readers_active_idx (sp, idx)) +udelay (CONFIG_SRCU_SYNCHRONIZE_DELAY );while (srcu_readers_active_idx (sp, idx))schedule_timeout_interruptible (1 );
Quoted 2 lines · Ingo Molnar
Please pull the latest core-rcu-for-linus git tree from:
So I pulled, but I'm not convinced about the crazy busy-looping SRCU_SYNCHRONIZE_DELAY thing.
Why does it do a silly udelay(), instead of just looping over the srcu_readers_active_idx() for a few times? You're wasting CPU time anyway, why ask the user how many usecs to waste?
IOW, why isn't that "wait for no active readers" a nice helper function, and why doesn't it do
for (i = 0; i < CONFIG_SRCU_SYNCHRONIZE_DELAY; i++) {
if (!srcu_readers_active_idx(sp, idx))
return;
udelay(1);
}
while (srcu_readers_active_idx(sp, idx))
schedule_timeout_interruptible(1);instead? And is it really sane to ask the kernel configurator to come up with a random value (ie that "CONFIG_SRCU_SYNCHRONIZE_DELAY" is just stupid and wrong)?
Please fix this. And don't make people answer unanswerable questions. If YOU and Paul don't know the answer, why the hell do you expect somebody who does a "make config" to know the answer?
Either pick a number, or pick an algorithm that self-tunes.
Don't use the Kconfig system as a way to tell people that it's their fault when you made a bad decision. Really.
Linus
Quoted 26 lines · Linus Torvalds
Quoted 2 lines · Ingo Molnar
Please pull the latest core-rcu-for-linus git tree from:
So I pulled, but I'm not convinced about the crazy busy-looping
SRCU_SYNCHRONIZE_DELAYthing.Why does it do a silly
udelay(), instead of just looping over thesrcu_readers_active_idx()for a few times? You're wasting CPU time anyway, why ask the user how many usecs to waste?IOW, why isn't that "wait for no active readers" a nice helper function, and why doesn't it do
for (i = 0; i < CONFIG_SRCU_SYNCHRONIZE_DELAY; i++) { if (!srcu_readers_active_idx(sp, idx)) return; udelay(1); } while (srcu_readers_active_idx(sp, idx)) schedule_timeout_interruptible(1);instead? And is it really sane to ask the kernel configurator to come up with a random value (ie that "
CONFIG_SRCU_SYNCHRONIZE_DELAY" is just stupid and wrong)?
Quoted 8 lines
Please fix this. And don't make people answer unanswerable questions. If YOU and Paul don't know the answer, why the hell do you expect somebody who does a "make config" to know the answer?
Either pick a number, or pick an algorithm that self-tunes.
Don't use the
Kconfigsystem as a way to tell people that it's their fault when you made a bad decision. Really.
Fully agreed - we'll fix this.
Thanks,
Ingo
Quoted 33 lines · Ingo Molnar
Quoted 30 lines · Linus Torvalds
Quoted 2 lines · Ingo Molnar
Please pull the latest core-rcu-for-linus git tree from:
So I pulled, but I'm not convinced about the crazy busy-looping
SRCU_SYNCHRONIZE_DELAYthing.Why does it do a silly
udelay(), instead of just looping over thesrcu_readers_active_idx()for a few times? You're wasting CPU time anyway, why ask the user how many usecs to waste?IOW, why isn't that "wait for no active readers" a nice helper function, and why doesn't it do
for (i = 0; i < CONFIG_SRCU_SYNCHRONIZE_DELAY; i++) { if (!srcu_readers_active_idx(sp, idx)) return; udelay(1); } while (srcu_readers_active_idx(sp, idx)) schedule_timeout_interruptible(1);instead? And is it really sane to ask the kernel configurator to come up with a random value (ie that "
CONFIG_SRCU_SYNCHRONIZE_DELAY" is just stupid and wrong)?Please fix this. And don't make people answer unanswerable questions. If YOU and Paul don't know the answer, why the hell do you expect somebody who does a "make config" to know the answer?
Quoted 6 lines
Quoted 4 lines
Either pick a number, or pick an algorithm that self-tunes.
Don't use the
Kconfigsystem as a way to tell people that it's their fault when you made a bad decision. Really.Fully agreed - we'll fix this.
I am on it!
Thanx, Paul