scheduler hang on cpu re-hotplug with 2.6.27rc8
Subsystems (2)
[Rafael, something for the regression list]
While testing cpu hotunplug/hotreplug (first
setting two CPUs to offline and then to online again) on a 16 thread machine with 2.6.27rc8 the first
# echo 1 > ./devices/system/cpu/cpu14/online
after hotunplug deadlocked somewhere in the scheduler:
bash D 00000000ffffcb5b 0 4683 4671
ffff8804bc583c68 0000000000000086 ffff8804bc9d8640 0000000000000296 ffff8804bdd34730 ffff8804be6fc090 ffff8804bdd34978 0000000c805a1e2a ffff8804be4fd780 ffffffff802298b4 ffffffff808acd98 ffff88027d0b1168
Call Trace: [<ffffffff802298b4>] __dequeue_entity+0x25/0x68 [<ffffffff805a1b4b>] schedule_timeout+0x1e/0xad [<ffffffff8022a11f>] __disable_runtime+0x57/0x155 [<ffffffff8025cc47>] cpupri_set+0xbe/0xcd [<ffffffff805a19b3>] wait_for_common+0xcd/0x131 [<ffffffff8022c918>] default_wake_function+0x0/0xe [<ffffffff80241f3a>] synchronize_rcu+0x30/0x36 [<ffffffff80241fac>] wakeme_after_rcu+0x0/0xc [<ffffffff8022dab6>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022dc26>] update_sched_domains+0x2e/0x35 [<ffffffff805a5297>] notifier_call_chain+0x29/0x4c [<ffffffff8059ef76>] _cpu_up+0xd0/0x10a [<ffffffff8059f004>] cpu_up+0x54/0x61 [<ffffffff805837d5>] store_online+0x43/0x67 [<ffffffff802c51e9>] sysfs_write_file+0xd2/0x110 [<ffffffff8028656b>] vfs_write+0xad/0x136 [<ffffffff802869f3>] sys_write+0x45/0x6e [<ffffffff8020b22b>] system_call_fastpath+0x16/0x1b
It just hung forever, but the machine was otherwise fully functional.
This was without frame pointers so the backtrace presumably has some garbage. Haven't looked too closely.
-Andi
Signature · 1 line
[email protected]
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
[modifying subject]
Quoted 9 lines · Andi Kleen
[Rafael, something for the regression list]
While testing cpu hotunplug/hotreplug (first
setting two CPUs to offline and then to online again) on a 16 thread machine with 2.6.27rc8 the first# echo 1 > ./devices/system/cpu/cpu14/onlineafter hotunplug deadlocked somewhere in the scheduler:
I let it run for longer and I ended up with more and more processes stuck in synchronize_rcu(). No more backtraces because the system has no console and is now not able to write to disk anymore.
So it seems like there's something broken with RCU & cpu hotplug in 2.6.28rc8. cc Paul.
It's probably not the scheduler, sorry for blaming it earlier.
-Andi
Quoted 33 lines
bash D
00000000ffffcb5b0 4683 4671
ffff8804bc583c680000000000000086ffff8804bc9d86400000000000000296ffff8804bdd34730ffff8804be6fc090ffff8804bdd349780000000c805a1e2affff8804be4fd780ffffffff802298b4ffffffff808acd98ffff88027d0b1168Call Trace: [<ffffffff802298b4>] __dequeue_entity+0x25/0x68 [<ffffffff805a1b4b>] schedule_timeout+0x1e/0xad [<ffffffff8022a11f>] __disable_runtime+0x57/0x155 [<ffffffff8025cc47>] cpupri_set+0xbe/0xcd [<ffffffff805a19b3>] wait_for_common+0xcd/0x131 [<ffffffff8022c918>] default_wake_function+0x0/0xe [<ffffffff80241f3a>] synchronize_rcu+0x30/0x36 [<ffffffff80241fac>] wakeme_after_rcu+0x0/0xc [<ffffffff8022dab6>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022dc26>] update_sched_domains+0x2e/0x35 [<ffffffff805a5297>] notifier_call_chain+0x29/0x4c [<ffffffff8059ef76>] _cpu_up+0xd0/0x10a [<ffffffff8059f004>] cpu_up+0x54/0x61 [<ffffffff805837d5>] store_online+0x43/0x67 [<ffffffff802c51e9>] sysfs_write_file+0xd2/0x110 [<ffffffff8028656b>] vfs_write+0xad/0x136 [<ffffffff802869f3>] sys_write+0x45/0x6e [<ffffffff8020b22b>] system_call_fastpath+0x16/0x1bIt just hung forever, but the machine was otherwise fully functional.
This was without frame pointers so the backtrace presumably has some garbage. Haven't looked too closely.
-Andi
Signature · 1 line
[email protected]
Signature · 1 line
[email protected]
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 13 lines · Andi Kleen
[modifying subject]
Quoted 9 lines · Andi Kleen
[Rafael, something for the regression list]
While testing cpu hotunplug/hotreplug (first
setting two CPUs to offline and then to online again) on a 16 thread machine with 2.6.27rc8 the first# echo 1 > ./devices/system/cpu/cpu14/onlineafter hotunplug deadlocked somewhere in the scheduler:
Quoted 8 lines
I let it run for longer and I ended up with more and more processes stuck in
synchronize_rcu(). No more backtraces because the system has no console and is now not able to write to disk anymore.So it seems like there's something broken with RCU & cpu hotplug in 2.6.28rc8. cc Paul.
It's probably not the scheduler, sorry for blaming it earlier.
Could you please try the patch at the following URL (from Thomas Gleixner)?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
This fixed some CPU hotplug hangs that I was seeing in 2.6.27-rc7 and -rc8. Alternatively, try 2.6.27-rc9, which seems to include Thomas's patch.
Thanx, Paul
Quoted 38 lines
-Andi
Quoted 33 lines
bash D
00000000ffffcb5b0 4683 4671
ffff8804bc583c680000000000000086ffff8804bc9d86400000000000000296ffff8804bdd34730ffff8804be6fc090ffff8804bdd349780000000c805a1e2affff8804be4fd780ffffffff802298b4ffffffff808acd98ffff88027d0b1168Call Trace: [<ffffffff802298b4>] __dequeue_entity+0x25/0x68 [<ffffffff805a1b4b>] schedule_timeout+0x1e/0xad [<ffffffff8022a11f>] __disable_runtime+0x57/0x155 [<ffffffff8025cc47>] cpupri_set+0xbe/0xcd [<ffffffff805a19b3>] wait_for_common+0xcd/0x131 [<ffffffff8022c918>] default_wake_function+0x0/0xe [<ffffffff80241f3a>] synchronize_rcu+0x30/0x36 [<ffffffff80241fac>] wakeme_after_rcu+0x0/0xc [<ffffffff8022dab6>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022dc26>] update_sched_domains+0x2e/0x35 [<ffffffff805a5297>] notifier_call_chain+0x29/0x4c [<ffffffff8059ef76>] _cpu_up+0xd0/0x10a [<ffffffff8059f004>] cpu_up+0x54/0x61 [<ffffffff805837d5>] store_online+0x43/0x67 [<ffffffff802c51e9>] sysfs_write_file+0xd2/0x110 [<ffffffff8028656b>] vfs_write+0xad/0x136 [<ffffffff802869f3>] sys_write+0x45/0x6e [<ffffffff8020b22b>] system_call_fastpath+0x16/0x1bIt just hung forever, but the machine was otherwise fully functional.
This was without frame pointers so the backtrace presumably has some garbage. Haven't looked too closely.
-Andi
Signature · 1 line
[email protected]Signature · 1 line
[email protected]
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 8 lines
Could you please try the patch at the following URL (from Thomas Gleixner)?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
This fixed some CPU hotplug hangs that I was seeing in 2.6.27-rc7 and -rc8. Alternatively, try 2.6.27-rc9, which seems to include Thomas's patch.
Still happens with rc9. This time with frame pointers:
bash D 00000000ffff975e 0 4770 4757
ffff8804bcda3bf8 0000000000000082 ffff8804bcda3c18 0000000000000296 ffff8804bde4e6b0 ffff8804be6fc630 ffff8804bde4e8f8 0000000e00000296 ffff8804bcda3c18 ffffffff808cfd98 ffff880288064780 ffff88027d18ec98
Call Trace: [<ffffffff805c4915>] schedule_timeout+0x22/0xb4 [<ffffffff8020a009>] ? __switch_to+0x320/0x330 [<ffffffff802602ed>] ? cpupri_set+0xc5/0xd8 [<ffffffff805c476f>] wait_for_common+0xcd/0x131 [<ffffffff8022db87>] ? default_wake_function+0x0/0xf [<ffffffff805c485d>] wait_for_completion+0x18/0x1a [<ffffffff80243fbf>] synchronize_rcu+0x35/0x3c [<ffffffff8024403e>] ? wakeme_after_rcu+0x0/0x12 [<ffffffff8022ed25>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022dbb3>] ? wake_up_process+0x10/0x12 [<ffffffff8022ee95>] update_sched_domains+0x2e/0x35 [<ffffffff805c8342>] notifier_call_chain+0x33/0x5b [<ffffffff80249291>] __raw_notifier_call_chain+0x9/0xb [<ffffffff802492a2>] raw_notifier_call_chain+0xf/0x11 [<ffffffff805c1c3a>] _cpu_up+0xd3/0x10c [<ffffffff805c1cca>] cpu_up+0x57/0x67 [<ffffffff805a5787>] store_online+0x4d/0x75 [<ffffffff803e67bb>] sysdev_store+0x1b/0x1d [<ffffffff802cce10>] sysfs_write_file+0xe0/0x11c [<ffffffff8028b661>] vfs_write+0xae/0x137 [<ffffffff8028bb0a>] sys_write+0x47/0x6f [<ffffffff8020b34b>] system_call_fastpath+0x16/0x1b
BTW it also happens reliably every time. Reproduced it three times now. I just do
laut:~ # echo 0 > /sys/devices/system/cpu/cpu15/online laut:~ # echo 0 > /sys/devices/system/cpu/cpu14/online laut:~ # echo 1 > /sys/devices/system/cpu/cpu14/online laut:~ # echo 1 > /sys/devices/system/cpu/cpu15/online <hang>
-Andi
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 10 lines · Andi Kleen
Quoted 8 lines
Could you please try the patch at the following URL (from Thomas Gleixner)?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
This fixed some CPU hotplug hangs that I was seeing in 2.6.27-rc7 and -rc8. Alternatively, try 2.6.27-rc9, which seems to include Thomas's patch.
Still happens with rc9. This time with frame pointers:
Hmmm... I chased out a number of these when doing rcutree.
This with classic RCU or preemptable RCU?
Quoted 28 lines
bash D
00000000ffff975e0 4770 4757
ffff8804bcda3bf80000000000000082ffff8804bcda3c180000000000000296ffff8804bde4e6b0ffff8804be6fc630ffff8804bde4e8f80000000e00000296ffff8804bcda3c18ffffffff808cfd98ffff880288064780ffff88027d18ec98Call Trace: [<ffffffff805c4915>] schedule_timeout+0x22/0xb4 [<ffffffff8020a009>] ? __switch_to+0x320/0x330 [<ffffffff802602ed>] ? cpupri_set+0xc5/0xd8 [<ffffffff805c476f>] wait_for_common+0xcd/0x131 [<ffffffff8022db87>] ? default_wake_function+0x0/0xf [<ffffffff805c485d>] wait_for_completion+0x18/0x1a [<ffffffff80243fbf>] synchronize_rcu+0x35/0x3c [<ffffffff8024403e>] ? wakeme_after_rcu+0x0/0x12 [<ffffffff8022ed25>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022dbb3>] ? wake_up_process+0x10/0x12 [<ffffffff8022ee95>] update_sched_domains+0x2e/0x35 [<ffffffff805c8342>] notifier_call_chain+0x33/0x5b [<ffffffff80249291>] __raw_notifier_call_chain+0x9/0xb [<ffffffff802492a2>] raw_notifier_call_chain+0xf/0x11 [<ffffffff805c1c3a>] _cpu_up+0xd3/0x10c [<ffffffff805c1cca>] cpu_up+0x57/0x67 [<ffffffff805a5787>] store_online+0x4d/0x75 [<ffffffff803e67bb>] sysdev_store+0x1b/0x1d [<ffffffff802cce10>] sysfs_write_file+0xe0/0x11c [<ffffffff8028b661>] vfs_write+0xae/0x137 [<ffffffff8028bb0a>] sys_write+0x47/0x6f [<ffffffff8020b34b>] system_call_fastpath+0x16/0x1b
Quoted 8 lines
BTW it also happens reliably every time. Reproduced it three times now. I just do
laut:~ # echo 0 >
/sys/devices/system/cpu/cpu15/onlinelaut:~ # echo 0 >/sys/devices/system/cpu/cpu14/onlinelaut:~ # echo 1 >/sys/devices/system/cpu/cpu14/onlinelaut:~ # echo 1 >/sys/devices/system/cpu/cpu15/online<hang>
Could you please send me your .config file?
Thanx, Paul
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 3 lines
Hmmm... I chased out a number of these when doing rcutree.
This with classic RCU or preemptable RCU?
classic.
Quoted 1 line
Could you please send me your .config file?
http://halobates.de/defconfig64
-Andi
Signature · 1 line
[email protected]
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 9 lines · Andi Kleen
Quoted 3 lines
Hmmm... I chased out a number of these when doing rcutree.
This with classic RCU or preemptable RCU?
classic.
Quoted 1 line
Could you please send me your .config file?
Thank you! Hmmm, classic RCU, worked just fine in 2.6.27-rc7 with Thomas's patch. I was doing random onlines and offlines in a loop, with about 3 seconds between each operation continuously for more than ten hours, both x86 and Power. So could you please try 2.6.27-rc7 with Thomas's patch as follows?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
Failing that, I guess my next step would be to create tracing for classic RCU to help figure out what RCU believes is preventing the grace period from ending.
Thanx, Paul
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 7 lines · Paul E. McKenney
Thank you! Hmmm, classic RCU, worked just fine in 2.6.27-rc7 with Thomas's patch. I was doing random onlines and offlines in a loop, with about 3 seconds between each operation continuously for more than ten hours, both x86 and Power. So could you please try 2.6.27-rc7 with Thomas's patch as follows?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
Same effect. Hung on the first try
bash D 00000000ffff25c1 0 4755 4742
ffff88027b127bf8 0000000000000086 ffff88027b127c18 0000000000000296 ffff88027c80b330 ffff8804be488b90 ffff88027c80b578 0000000300000296 ffff88027b127c18 ffffffff808cbd18 ffff88002805d600 ffff88027d182098
Call Trace: [<ffffffff805c318d>] schedule_timeout+0x22/0xb4 [<ffffffff8020a029>] ? __switch_to+0x320/0x330 [<ffffffff8025fa65>] ? cpupri_set+0xc5/0xd8 [<ffffffff805c2fe7>] wait_for_common+0xcd/0x131 [<ffffffff8022d297>] ? default_wake_function+0x0/0xf [<ffffffff805c30d5>] wait_for_completion+0x18/0x1a [<ffffffff8024374b>] synchronize_rcu+0x35/0x3c [<ffffffff802437ca>] ? wakeme_after_rcu+0x0/0x12 [<ffffffff8022e435>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022d2c3>] ? wake_up_process+0x10/0x12 [<ffffffff8022e5a5>] update_sched_domains+0x2e/0x35 [<ffffffff805c6bb2>] notifier_call_chain+0x33/0x5b [<ffffffff80248a29>] __raw_notifier_call_chain+0x9/0xb [<ffffffff80248a3a>] raw_notifier_call_chain+0xf/0x11 [<ffffffff805c06e6>] _cpu_up+0xd3/0x10c [<ffffffff805c0776>] cpu_up+0x57/0x67 [<ffffffff805a4ab7>] store_online+0x4d/0x75 [<ffffffff803e5d0b>] sysdev_store+0x1b/0x1d [<ffffffff802cc49c>] sysfs_write_file+0xe0/0x11c [<ffffffff8028ad1d>] vfs_write+0xae/0x137 [<ffffffff8028b1c6>] sys_write+0x47/0x6f [<ffffffff8020b36b>] system_call_fastpath+0x16/0x1b
-Andi
Signature · 1 line
[email protected]
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 30 lines · Andi Kleen
Quoted 7 lines · Paul E. McKenney
Thank you! Hmmm, classic RCU, worked just fine in 2.6.27-rc7 with Thomas's patch. I was doing random onlines and offlines in a loop, with about 3 seconds between each operation continuously for more than ten hours, both x86 and Power. So could you please try 2.6.27-rc7 with Thomas's patch as follows?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
Same effect. Hung on the first try
bash D
00000000ffff25c10 4755 4742
ffff88027b127bf80000000000000086ffff88027b127c180000000000000296ffff88027c80b330ffff8804be488b90ffff88027c80b5780000000300000296ffff88027b127c18ffffffff808cbd18ffff88002805d600ffff88027d182098Call Trace: [<ffffffff805c318d>] schedule_timeout+0x22/0xb4 [<ffffffff8020a029>] ? __switch_to+0x320/0x330 [<ffffffff8025fa65>] ? cpupri_set+0xc5/0xd8 [<ffffffff805c2fe7>] wait_for_common+0xcd/0x131 [<ffffffff8022d297>] ? default_wake_function+0x0/0xf [<ffffffff805c30d5>] wait_for_completion+0x18/0x1a [<ffffffff8024374b>] synchronize_rcu+0x35/0x3c [<ffffffff802437ca>] ? wakeme_after_rcu+0x0/0x12 [<ffffffff8022e435>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022d2c3>] ? wake_up_process+0x10/0x12 [<ffffffff8022e5a5>] update_sched_domains+0x2e/0x35 [<ffffffff805c6bb2>] notifier_call_chain+0x33/0x5b [<ffffffff80248a29>] __raw_notifier_call_chain+0x9/0xb [<ffffffff80248a3a>] raw_notifier_call_chain+0xf/0x11
Quoted 8 lines
[<ffffffff805c06e6>] _cpu_up+0xd3/0x10c [<ffffffff805c0776>] cpu_up+0x57/0x67 [<ffffffff805a4ab7>] store_online+0x4d/0x75 [<ffffffff803e5d0b>] sysdev_store+0x1b/0x1d [<ffffffff802cc49c>] sysfs_write_file+0xe0/0x11c [<ffffffff8028ad1d>] vfs_write+0xae/0x137 [<ffffffff8028b1c6>] sys_write+0x47/0x6f [<ffffffff8020b36b>] system_call_fastpath+0x16/0x1b
Thus far, as usual, I cannot reproduce, either on x86 or Power. You are running on hyperthreaded machines? If so, what happens if you disable CONFIG_SCHED_SMT and CONFIG_SCHED_MC?
You are running on a 16-CPU x86-64 box?
Thanx, Paul
PATCH 1/1 rudimentary tracing for Classic RCU
Hello!
This is a tracing patch for Classic RCU, which creates an "rcu/rcucb" file in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Reading from the file results in something like the following:
rcu: cur=1129 completed=1128 np=0 s=0 0,3,7 rcu_bh: cur=-287 completed=-287 np=0 s=0 online: 0-7
The first two lines are for rcu, the second two for rcu_bh. The cur= is the current grace-period number, and the completed= is the number of the last completed grace period. If these two numbers are equal, the corresponding flavor of RCU is idle. The np= is a flag indicating that an additional RCU grace period beyond the current one will be required. The s=, if non-zero, indicates that a round of reschedule IPIs has been send to attempt to expedite the current grace period.
The second and fourth lines are a comma/dash-separated list of the CPUs that have not yet reported a quiescent state for the current grace period (CPUs 0, 3, and 7 for "rcu" above).
The last line lists the online CPUs.
Tested on x86 and Power.
---
include/linux/rcuclassic.h | 3 + kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 4 - kernel/rcuclassic_trace.c | 126 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 3 deletions(-)
include/linux/rcuclassic.h +3 -0
@@ -54,6 +54,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {
kernel/Kconfig.preempt +0 -1
@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y help
kernel/Makefile +2 -0
@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
kernel/rcuclassic.c +2 -2
@@ -57,13 +57,13 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_bh_ctrlblk.lock),
kernel/rcuclassic_trace.c new file +126 -0
126 lines not on this page · raw message
Re: [PATCH] rudimentary tracing for Classic RCU
Quoted 60 lines · Paul E. McKenney
Hello!
This is a tracing patch for Classic RCU, which creates an "rcu/rcucb" file in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Reading from the file results in something like the following:
rcu: cur=1129 completed=1128 np=0 s=0 0,3,7 rcu_bh: cur=-287 completed=-287 np=0 s=0 online: 0-7The first two lines are for rcu, the second two for
rcu_bh. The cur= is the current grace-period number, and the completed= is the number of the last completed grace period. If these two numbers are equal, the corresponding flavor of RCU is idle. The np= is a flag indicating that an additional RCU grace period beyond the current one will be required. The s=, if non-zero, indicates that a round of reschedule IPIs has been send to attempt to expedite the current grace period.The second and fourth lines are a comma/dash-separated list of the CPUs that have not yet reported a quiescent state for the current grace period (CPUs 0, 3, and 7 for "rcu" above).
The last line lists the online CPUs.
Tested on x86 and Power.
Signed-off-by Paul E. McKenney <[email protected]>---
include/linux/rcuclassic.h | 3 + kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 4 - kernel/rcuclassic_trace.c | 126 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 3 deletions(-)include/linux/rcuclassic.h +3
-0@@ -54,6 +54,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {kernel/Kconfig.preempt +0
-0
kernel/Kconfig.preempt config PREEMPT_RCU · line 73
Quoted 7 lines
kernel/Kconfig.preempt +0
-1@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y help
I think that we can move it to lib/Kconfig.debug.
Quoted 118 lines
kernel/Makefile +2
-0@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.okernel/rcuclassic.c +2
-2@@ -57,13 +57,13 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_bh_ctrlblk.lock),kernel/rcuclassic_trace.c new file +79
-0@@ -0,0 +1,126 @@ +/* +* Read-Copy Update tracing for classic implementation +* +* 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, 2008 +* +* Papers: http://www.rdrop.com/users/paulmck/RCU +* +* For detailed explanation of Read-Copy Update mechanism see - +* Documentation/RCU +* +*/ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/rcupdate.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <asm/atomic.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/completion.h> +#include <linux/moduleparam.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/cpu.h> +#include <linux/mutex.h> +#include <linux/debugfs.h> + +static DEFINE_MUTEX (rcuclassic_trace_mutex); +static char *rcuclassic_trace_buf; +#define RCUCLASSIC_TRACE_BUF_SIZE (20*NR_CPUS + 100) + +static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +{ +int cnt =0 ; + + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " +"np=%d s=%d\n\t" , + rcp->cur, rcp->completed, + rcp->next_pending, rcp->signaled); + cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); +return cnt; +} + +static ssize_t rcucb_read (struct file *filp,char __user *buffer, +size_t count,loff_t *ppos) +{ +ssize_t bcount; +char *buf = rcuclassic_trace_buf; +char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; + +mutex_lock (&rcuclassic_trace_mutex); + buf +=snprintf (buf, ebuf - buf,"rcu: " ); + buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); + buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"online: " ); + buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); + buf +=snprintf (buf, ebuf - buf,"\n" ); + bcount =simple_read_from_buffer (buffer, count, ppos, + rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); +mutex_unlock (&rcuclassic_trace_mutex);
kernel/rcuclassic_trace.c line 89
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+return bcount; +} + +static struct file_operations rcucb_fops = { + .owner =THIS_MODULE , + .read = rcucb_read, +}; + +static struct dentry *rcudir, *cbdir; +static int rcuclassic_debugfs_init (void )
add __init:
static int __init rcuclassic_debugfs_init(void)
Quoted 9 lines
kernel/rcuclassic_trace.c new file +9
-0+{ + rcudir =debugfs_create_dir ("rcu" ,NULL ); +if (!rcudir) + goto out; + cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); +if (!cbdir) + goto free_out; +return 0 ; +free_out:
kernel/rcuclassic_trace.c line 108
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+debugfs_remove (rcudir); +out: +return 1 ; +} + +static int __init rcuclassic_trace_init (void ) +{ +int ret; + + rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL );
I'm wondering about this. rcuclassic_trace_buf is kmalloc-ed when init module.
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];
and use it like:
pos += snprintf(buf + cnt, sizeof(buf) - cnt, ...);
Quoted 8 lines
kernel/rcuclassic_trace.c new file +8
-0+if (!rcuclassic_trace_buf) +return 1 ; + ret =rcuclassic_debugfs_init (); +if (ret) +kfree (rcuclassic_trace_buf); +return ret; +} +
kernel/rcuclassic_trace.c line 126
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+static void __exit rcuclassic_trace_cleanup(void) +{ +debugfs_remove (cbdir); +debugfs_remove (rcudir); +kfree (rcuclassic_trace_buf); +} + + +module_init (rcuclassic_trace_init); +module_exit (rcuclassic_trace_cleanup);
I think this trace file shows too little vars for classic rcu.
It is better that this trace file shows more data.
such as some data in struct rcu_data(quiescent state handling fields, batch, qlen).
or add new files: rcu/rcu_data<cpu#>
Thanks, Lai
Re: [PATCH] rudimentary tracing for Classic RCU
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];
Actually you should near never use NR_CPUS now but always num_possible_cpus() (or even num_online_cpus()) Using NR_CPUS can lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.
And with num_possible_cpus() kmalloc is needed.
-Andi
Re: [PATCH] rudimentary tracing for Classic RCU
Quoted 13 lines · Andi Kleen
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];Actually you should near never use
NR_CPUSnow but alwaysnum_possible_cpus()(or evennum_online_cpus()) UsingNR_CPUScan lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.And with
num_possible_cpus()kmalloc is needed.-Andi
I thought the default value of NR_CPUS is 32.
if NR_CPUS is too large, I think using seq_file is good idea, and rcuclassic_trace_mutex is not need too.
Lai
Re: [PATCH] rudimentary tracing for Classic RCU
Hi Lai-san,
Quoted 10 lines
Quoted 8 lines
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];Actually you should near never use
NR_CPUSnow but alwaysnum_possible_cpus()(or evennum_online_cpus()) UsingNR_CPUScan lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.And with
num_possible_cpus()kmalloc is needed.I thought the default value of
NR_CPUSis 32.
it's pointless.
Almost distribution use _very_ large NR_CPUS (likes 4096). So, We should concern large NR_CPUS.
Quoted 3 lines
if
NR_CPUSis too large, I think usingseq_fileis good idea, andrcuclassic_trace_mutexis not need too.
Re: [PATCH] rudimentary tracing for Classic RCU
Quoted 8 lines · KOSAKI Motohiro
Hi Lai-san,
Quoted 6 lines
Quoted 6 lines
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];Actually you should near never use
NR_CPUSnow but alwaysnum_possible_cpus()(or evennum_online_cpus()) UsingNR_CPUScan lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.
Quoted 6 lines
Quoted 2 lines
Quoted 1 line
And with
num_possible_cpus()kmalloc is needed.I thought the default value of
NR_CPUSis 32.it's pointless.
Almost distribution use _very_ largeNR_CPUS(likes 4096). So, We should concern largeNR_CPUS.
Thanks.
So my advice is to use seq_file.
Quoted 9 lines
Quoted 4 lines
if
NR_CPUSis too large, I think usingseq_fileis good idea, andrcuclassic_trace_mutexis not need too.
Re: [PATCH] rudimentary tracing for Classic RCU
In reply to KOSAKI MotohiroQuoted 9 lines · KOSAKI Motohiro
Hi Lai-san,
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];Actually you should near never use
NR_CPUSnow but alwaysnum_possible_cpus()(or evennum_online_cpus()) UsingNR_CPUScan lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
And with
num_possible_cpus()kmalloc is needed.I thought the default value of
NR_CPUSis 32.it's pointless.
Almost distribution use _very_ largeNR_CPUS(likes 4096).
Right now it's more like 8-128, but at least there is some effort to make a 4096 CPU distribution possible and Mike Travis has been
tirelessly working on eradicating all the rogue NR_CPUs all over
the tree. So it's better to not add more.
Quoted 1 line
So, We should concern large
NR_CPUS.
Agreed.
-Andi
Signature · 1 line
[email protected]
Re: [PATCH] rudimentary tracing for Classic RCU
In reply to Lai JiangshanQuoted 8 lines · Lai Jiangshan
Quoted 7 lines · Andi Kleen
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];Actually you should near never use
NR_CPUSnow but alwaysnum_possible_cpus()(or evennum_online_cpus()) UsingNR_CPUScan lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.
Quoted 8 lines
Quoted 3 lines
And with
num_possible_cpus()kmalloc is needed.-Andi
I thought the default value of
NR_CPUSis 32.if
NR_CPUSis too large, I think usingseq_fileis good idea, andrcuclassic_trace_mutexis not need too.
I never have used seq_file, to be honest. I would welcome a patch from you applying it to my rcucb and rcudata patch set.
Thanx, Paul
Re: [PATCH] rudimentary tracing for Classic RCU
In reply to Andi KleenQuoted 8 lines · Andi Kleen
Quoted 2 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];Actually you should near never use
NR_CPUSnow but alwaysnum_possible_cpus()(or evennum_online_cpus()) UsingNR_CPUScan lead to extreme waste of memory on kernels which are compiled for 4096 CPUs for example.And with
num_possible_cpus()kmalloc is needed.
OK, new one on me! Thank you for the pointer!
Thanx, Paul
Re: [PATCH] rudimentary tracing for Classic RCU
In reply to Lai JiangshanOn Thu, Oct 09, 2008 at 02:20:22PM +0800, Lai Jiangshan wrote:
Thank you for looking this over!
Quoted 1 line
Paul E. McKenney wrote:
[ . . . ]
Quoted 6 lines
Quoted 6 lines
kernel/Kconfig.preempt +0
-0@@ -68,7 +68,6 @@ config PREEMPT_RCU
Quoted 8 lines
kernel/Kconfig.preempt config PREEMPT_RCU · line 73
Quoted 6 lines
kernel/Kconfig.preempt +0
-1config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y helpI think that we can move it to
lib/Kconfig.debug.
Makes sense!
[ . . . ]
Quoted 9 lines
kernel/Kconfig.preempt
Quoted 5 lines
kernel/Kconfig.preempt +5
-0+static int __init rcuclassic_trace_init(void) +{ + int ret; + + rcuclassic_trace_buf = kmalloc(RCUCLASSIC_TRACE_BUF_SIZE, GFP_KERNEL);I'm wondering about this.
rcuclassic_trace_bufis kmalloc-ed when init module.
Quoted 5 lines
In this case, why not define it as:
static char buf[20*NR_CPUS + 100];and use it like:
pos +=snprintf(buf + cnt, sizeof(buf) - cnt, ...);
I will make Andi's suggested change, both here and in other previously submitted code.
[ . . . ]
Quoted 22 lines
Quoted 8 lines
kernel/Kconfig.preempt +8
-0+ if (!rcuclassic_trace_buf) + return 1; + ret = rcuclassic_debugfs_init(); + if (ret) + kfree(rcuclassic_trace_buf); + return ret; +} +kernel/Kconfig.preempt
Quoted 10 lines
kernel/Kconfig.preempt +10
-0+static void __exit rcuclassic_trace_cleanup(void) +{ + debugfs_remove(cbdir); + debugfs_remove(rcudir); + kfree(rcuclassic_trace_buf); +} + + +module_init(rcuclassic_trace_init); +module_exit(rcuclassic_trace_cleanup);I think this trace file shows too little vars for classic rcu.
Quoted 4 lines
It is better that this trace file shows more data.
such as some data in structrcu_data(quiescent state handling fields, batch, qlen).or add new files: rcu/rcu_data<cpu#>
Indeed! I will add the ability to dump the rcu_data structures, though I was planning to just dump all of them rather than CPU-by-CPU. (Same approach as in rcutree_trace.c patches.)
Thanx, Paul
Re: [PATCH] rudimentary tracing for Classic RCU
In reply to Paul E. McKenney2008/10/9 Paul E. McKenney <[email protected]>:
Quoted 6 lines
Hello!
This is a tracing patch for Classic RCU, which creates an "rcu/rcucb" file in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Quoted 7 lines
Reading from the file results in something like the following:
rcu: cur=1129 completed=1128 np=0 s=0 0,3,7 rcu_bh: cur=-287 completed=-287 np=0 s=0 online: 0-7
Hi Paul,
Why don't you use the ring-buffer tracing engine?
You will really make your life better by putting it as a tracer in kernel/trace and by using the relevant API.
That will avoid you to manage the debugfs things, the memory allocation, the buffer managment.....
Re: [PATCH] rudimentary tracing for Classic RCU
Quoted 1 line
Why don't you use the ring-buffer tracing engine?
Because he doesn't actually need a ring buffer, it's a snapshot in time.
Quoted 4 lines
You will really make your life better by putting it as a tracer in kernel/trace and by using the relevant API.
That will avoid you to manage the debugfs things, the memory allocation, the buffer managment.....
ftrace-of-bork wants to assimilate everything?
-Andi
Signature · 1 line
[email protected]
Re: [PATCH] rudimentary tracing for Classic RCU
2008/10/9 Andi Kleen <[email protected]>:
Quoted 4 lines
Quoted 1 line
Why don't you use the ring-buffer tracing engine?
Because he doesn't actually need a ring buffer, it's a snapshot in time.
You have the possibility to implement a read callback to not use the ring buffer.
Quoted 1 line
ftrace-of-bork wants to assimilate everything?
I just proposed that to unify the tracers.
Re: [PATCH] rudimentary tracing for Classic RCU
In reply to Frédéric WeisbeckerQuoted 16 lines · Frédéric Weisbecker
2008/10/9 Paul E. McKenney <[email protected]>:
Quoted 6 lines
Hello!
This is a tracing patch for Classic RCU, which creates an "rcu/rcucb" file in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Quoted 7 lines
Reading from the file results in something like the following:
rcu: cur=1129 completed=1128 np=0 s=0 0,3,7 rcu_bh: cur=-287 completed=-287 np=0 s=0 online: 0-7
Quoted 7 lines
Hi Paul,
Why don't you use the ring-buffer tracing engine?
You will really make your life better by putting it as a tracer in kernel/trace and by using the relevant API.
That will avoid you to manage the debugfs things, the memory allocation, the buffer managment.....
Hello, Frédéric,
Well, one reason is that I didn't know about it. ;-)
Does it allow the user to trigger a one-shot trace? Right now, what one does is:
cat /debug/rcu/rcucb
whenever one wants to see what RCU is up to. You really don't want to see every new value, as that would generate hundreds of trace records per second -- per CPU. What does the user do with the ring-buffer tracing enging?
Thanx, Paul
Re: [PATCH] rudimentary tracing for Classic RCU
2008/10/9 Paul E. McKenney <[email protected]>:
Quoted 5 lines
Well, one reason is that I didn't know about it. ;-)
Does it allow the user to trigger a one-shot trace? Right now, what one does is:
Quoted 8 lines
cat /debug/rcu/rcucb
whenever one wants to see what RCU is up to. You really don't want to see every new value, as that would generate hundreds of trace records per second -- per CPU. What does the user do with the ring-buffer tracing enging?
Thanx, Paul
With a tracer from the unified tracing buffer, you have often one function, used somewhere in the kernel, which will add periodically some specific entries. For example mmiotrace receives entries which contain IO access.
When the user tries to read the entries, he has to read the pipe /debug/tracing/trace_pipe. During this reading, the tracing engine calls a read callback given by the tracer. This read callback is nothing related to entries on the buffer: if the tracer has to print something special, this is the ususal function.
Than if the read gave some content, the pipe reading returns. Else, the tracing engine tells the tracer to format its entries from the ring buffer. If there is no entries, the pipe reading sleeps and waits for new entries.
So after some thought, I don't think the current tracing engine is really adapted for what you want. It is a pipe system and it's not adapted for your one-shot captures.
Sorry for the noise.
But it only requires few features to add for the unified tracing engine to support such one-shot tracer.
PATCH 1/1 v2 rudimentary tracing for Classic RCU
In reply to Paul E. McKenneyHello!
This is a tracing patch for Classic RCU, which creates an "rcu/rcucb" file in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Changes since v1: Adds (crude) tracing for rcu_data structures.
Additional work needed: Don't print rcu_data for offline CPUs.
Documentation update.
Reading from the file results in something like the following:
rcu: cur=1129 completed=1128 np=0 s=0 0,3,7 rcu_bh: cur=-287 completed=-287 np=0 s=0 online: 0-7
The first two lines are for rcu, the second two for rcu_bh. The cur= is the current grace-period number, and the completed= is the number of the last completed grace period. If these two numbers are equal, the corresponding flavor of RCU is idle. The np= is a flag indicating that an additional RCU grace period beyond the current one will be required. The s=, if non-zero, indicates that a round of reschedule IPIs has been send to attempt to expedite the current grace period.
The second and fourth lines are a comma/dash-separated list of the CPUs that have not yet reported a quiescent state for the current grace period (CPUs 0, 3, and 7 for "rcu" above).
The last line lists the online CPUs.
Tested on x86 and Power.
---
include/linux/rcuclassic.h | 3 kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 4 - kernel/rcuclassic_trace.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+), 3 deletions(-)
include/linux/rcuclassic.h +3 -0
@@ -54,6 +54,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {
kernel/Kconfig.preempt +0 -1
@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y help
kernel/Makefile +2 -0
@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
kernel/rcuclassic.c +2 -2
@@ -57,13 +57,13 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_bh_ctrlblk.lock),
kernel/rcuclassic_trace.c new file +179 -0
179 lines not on this page · raw message
PATCH 1/1 v3 rudimentary tracing for Classic RCU
Hello!
This is v3 of a tracing patch for Classic RCU, which creates "rcu/rcucb" and "rcu/rcudata" files in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Should be ready for inclusion in tip/core/rcu, Ingo, please apply.
Changes since v2: Add flag to rcu_data to avoid printing rcu_data for
CPUs that have never been online.
Add documentation (below).
Changes since v1: Adds (crude) tracing for rcu_data structures.
Reading from the "rcu/rcucb" file results in something like the following:
rcu: cur=1129 completed=1128 pending=0 s=0 0,3,7 rcu_bh: cur=-287 completed=-287 pending=0 s=0 online: 0-7
The first two lines are for rcu, the second two for rcu_bh. The cur= is the current grace-period number, and the completed= is the number of the last completed grace period. If these two numbers are equal, the corresponding flavor of RCU is idle. The pending= is the furthest future batch number that is required, if equal to cur=, no additional grace periods are required. The s=, if non-zero, indicates that a round of reschedule IPIs has been send to attempt to expedite the current grace period.
The second and fourth lines are a comma/dash-separated list of the CPUs that have not yet reported a quiescent state for the current grace period (CPUs 0, 3, and 7 for "rcu" above).
The last line lists the online CPUs.
Reading from the "rcu/rcudata" file results in the following:
rcu: 0 qb=885 b=884 pq=1 qsp=0 ql=0 bl=10 1 qb=885 b=882 pq=1 qsp=0 ql=2 bl=10 2 qb=885 b=854 pq=1 qsp=0 ql=0 bl=10 3 qb=885 b=885 pq=1 qsp=0 ql=0 bl=10 rcu_bh: 0 qb=-291 b=-291 pq=1 qsp=0 ql=0 bl=10 1 qb=-291 b=0 pq=1 qsp=0 ql=0 bl=10 2 qb=-291 b=0 pq=1 qsp=0 ql=0 bl=10 3 qb=-291 b=-298 pq=1 qsp=0 ql=0 bl=10
This output is again split into rcu and rcu_bh portions. Within each portion, there is one line per CPU, but only for those CPUs that have been online at least once since boot. The number at the beginning of each line is the CPU number, followed by an "!" if the corresponding CPU is currently offline. The qb= is the batch number for the RCU core, the b= is the batch number corresponding to the callbacks waiting for the current grace period for this CPU, the pq= is a flag indicating that this CPU has passed through a quiescent state for the current grace period, the qsp= is a flag indicating that the RCU core has been informed that this CPU has passed through a quiescent state for the current grace period, the ql= is the number of RCU callbacks currently enqueued on this CPU (regardless of their state), and the bl= is the current limit of the number of callbacks to be invoked at one shot.
Tested on x86 and Power, rebased to -tip.
---
include/linux/rcuclassic.h | 4 + kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 5 - kernel/rcuclassic_trace.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+), 3 deletions(-)
include/linux/rcuclassic.h +4 -0
@@ -63,6 +63,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {
@@ -81,6 +84,7 @@ struct rcu_data {long quiescbatch;/* Batch # for grace period */ int passed_quiesc;/* User-mode/idle loop etc. */ int qs_pending;/* core waits for quiesc state */ +bool beenonline;/* CPU online at least once */ /* 2) batch handling */ /*
kernel/Kconfig.preempt +0 -1
@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y help
kernel/Makefile +2 -0
@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
kernel/rcuclassic.c +3 -2
@@ -58,14 +58,14 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .pending =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .pending =-300 ,
@@ -725,6 +725,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->donetail = &rdp->donelist; rdp->quiescbatch = rcp->completed; rdp->qs_pending =0 ; + rdp->beenonline =1 ; rdp->cpu = cpu; rdp->blimit = blimit;spin_unlock_irqrestore (&rcp->lock, flags);
kernel/rcuclassic_trace.c new file +179 -0
179 lines not on this page · raw message
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 7 lines · Paul E. McKenney
Hello!
This is v3 of a tracing patch for Classic RCU, which creates "rcu/rcucb" and "rcu/rcudata" files in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Should be ready for inclusion in tip/core/rcu, Ingo, please apply.
Hi, Paul,
I'm sorry that I'm a little busy these days, so I have not ported it to seq_file, and you lost one choice.
I found that seq_cpumask_list() is needed when I tried to ported v2 to seq_file, so I introduced seq_cpumask_list() for seq_file, I'm waiting procfs hackers apply that patch too.
Lai.
Quoted 4 lines
Changes since v2: Add flag to
rcu_datato avoid printingrcu_datafor
CPUs that have never been online.
Quoted 8 lines
Add documentation (below).
Changes since v1: Adds (crude) tracing for
rcu_datastructures.Reading from the "rcu/rcucb" file results in something like the following:
rcu: cur=1129 completed=1128 pending=0 s=0 0,3,7
use "somename: 0,3,7" ? then when mask is empty, I think "somename:" is better than empty line.
Quoted 216 lines
rcu_bh: cur=-287 completed=-287 pending=0 s=0 online: 0-7The first two lines are for rcu, the second two for
rcu_bh. The cur= is the current grace-period number, and the completed= is the number of the last completed grace period. If these two numbers are equal, the corresponding flavor of RCU is idle. The pending= is the furthest future batch number that is required, if equal to cur=, no additional grace periods are required. The s=, if non-zero, indicates that a round of reschedule IPIs has been send to attempt to expedite the current grace period.The second and fourth lines are a comma/dash-separated list of the CPUs that have not yet reported a quiescent state for the current grace period (CPUs 0, 3, and 7 for "rcu" above).
The last line lists the online CPUs.
Reading from the "rcu/rcudata" file results in the following:
rcu: 0 qb=885 b=884 pq=1 qsp=0 ql=0 bl=10 1 qb=885 b=882 pq=1 qsp=0 ql=2 bl=10 2 qb=885 b=854 pq=1 qsp=0 ql=0 bl=10 3 qb=885 b=885 pq=1 qsp=0 ql=0 bl=10 rcu_bh: 0 qb=-291 b=-291 pq=1 qsp=0 ql=0 bl=10 1 qb=-291 b=0 pq=1 qsp=0 ql=0 bl=10 2 qb=-291 b=0 pq=1 qsp=0 ql=0 bl=10 3 qb=-291 b=-298 pq=1 qsp=0 ql=0 bl=10This output is again split into rcu and
rcu_bhportions. Within each portion, there is one line per CPU, but only for those CPUs that have been online at least once since boot. The number at the beginning of each line is the CPU number, followed by an "!" if the corresponding CPU is currently offline. The qb= is the batch number for the RCU core, the b= is the batch number corresponding to the callbacks waiting for the current grace period for this CPU, the pq= is a flag indicating that this CPU has passed through a quiescent state for the current grace period, the qsp= is a flag indicating that the RCU core has been informed that this CPU has passed through a quiescent state for the current grace period, the ql= is the number of RCU callbacks currently enqueued on this CPU (regardless of their state), and the bl= is the current limit of the number of callbacks to be invoked at one shot.Tested on x86 and Power, rebased to -tip.
Signed-off-by Paul E. McKenney <[email protected]>---
include/linux/rcuclassic.h | 4 + kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 5 - kernel/rcuclassic_trace.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+), 3 deletions(-)include/linux/rcuclassic.h +4
-0@@ -63,6 +63,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {@@ -81,6 +84,7 @@ struct rcu_data {long quiescbatch;/* Batch # for grace period */ int passed_quiesc;/* User-mode/idle loop etc. */ int qs_pending;/* core waits for quiesc state */ +bool beenonline;/* CPU online at least once */ /* 2) batch handling */ /* kernel/Kconfig.preempt +0
-1@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y helpkernel/Makefile +2
-0@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.okernel/rcuclassic.c +3
-2@@ -58,14 +58,14 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .pending =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .pending =-300 ,@@ -725,6 +725,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->donetail = &rdp->donelist; rdp->quiescbatch = rcp->completed; rdp->qs_pending =0 ; + rdp->beenonline =1 ; rdp->cpu = cpu; rdp->blimit = blimit;spin_unlock_irqrestore (&rcp->lock, flags);kernel/rcuclassic_trace.c new file +75
-0@@ -0,0 +1,179 @@ +/* +* Read-Copy Update tracing for classic implementation +* +* 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, 2008 +* +* Papers: http://www.rdrop.com/users/paulmck/RCU +* +* For detailed explanation of Read-Copy Update mechanism see - +* Documentation/RCU +* +*/ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/rcupdate.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <asm/atomic.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/completion.h> +#include <linux/moduleparam.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/cpu.h> +#include <linux/mutex.h> +#include <linux/debugfs.h> + +static DEFINE_MUTEX (rcuclassic_trace_mutex); +static char *rcuclassic_trace_buf; +#define RCUCLASSIC_TRACE_BUF_SIZE (128 * num_possible_cpus() + 100) + +static int print_one_rcu_data (struct rcu_data *rdp,char *buf,char *ebuf) +{ +int cnt =0 ; + +if (!rdp->beenonline) +return 0 ; + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt], +"%3d%cqb=%ld b=%ld pq=%d qsp=%d ql=%ld bl=%ld\n" , + rdp->cpu,cpu_is_offline (rdp->cpu) ?'!' :' ' , + rdp->quiescbatch, rdp->batch, rdp->passed_quiesc, + rdp->qs_pending, rdp->qlen, rdp->blimit); +return cnt; +} + +#define PRINT_RCU_DATA (name, buf, ebuf) \ + do { \ + int _p_r_d_i; \ + \ + for_each_possible_cpu(_p_r_d_i) \ + (buf) += print_one_rcu_data(&per_cpu(name, _p_r_d_i), \ + buf, ebuf); \ + } while (0) + +static ssize_t rcudata_read (struct file *filp,char __user *buffer, +size_t count,loff_t *ppos) +{ +ssize_t bcount;
kernel/rcuclassic_trace.c line 85
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+char *buf = rcuclassic_trace_buf; +char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; + +mutex_lock (&rcuclassic_trace_mutex); + buf +=snprintf (buf, ebuf - buf,"rcu:\n" ); +PRINT_RCU_DATA (rcu_data, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"rcu_bh:\n" ); +PRINT_RCU_DATA (rcu_bh_data, buf, ebuf); + bcount =simple_read_from_buffer (buffer, count, ppos, + rcuclassic_trace_buf,strlen (rcuclassic_trace_buf));
Is strlen(rcuclassic_trace_buf) == buf - rcuclassic_trace_buf ?
Quoted 84 lines
kernel/rcuclassic_trace.c new file +84
-0+mutex_unlock (&rcuclassic_trace_mutex); +return bcount; +} + +static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +{ +int cnt =0 ; + + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " +"pending=%ld s=%d\n\t" , + rcp->cur, rcp->completed, + rcp->pending, rcp->signaled); + cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); +return cnt; +} + +static ssize_t rcucb_read (struct file *filp,char __user *buffer, +size_t count,loff_t *ppos) +{ +ssize_t bcount; +char *buf = rcuclassic_trace_buf; +char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; + +mutex_lock (&rcuclassic_trace_mutex); + buf +=snprintf (buf, ebuf - buf,"rcu: " ); + buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); + buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"online: " ); + buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); + buf +=snprintf (buf, ebuf - buf,"\n" ); + bcount =simple_read_from_buffer (buffer, count, ppos, + rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); +mutex_unlock (&rcuclassic_trace_mutex); +return bcount; +} + +static struct file_operations rcudata_fops = { + .owner =THIS_MODULE , + .read = rcudata_read, +}; + +static struct file_operations rcucb_fops = { + .owner =THIS_MODULE , + .read = rcucb_read, +}; + +static struct dentry *rcudir, *datadir, *cbdir; +static int rcuclassic_debugfs_init (void ) +{ + rcudir =debugfs_create_dir ("rcu" ,NULL ); +if (!rcudir) + goto out; + datadir =debugfs_create_file ("rcudata" ,0444 , rcudir, +NULL , &rcudata_fops); +if (!datadir) + goto free_out; + cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); +if (!cbdir) + goto free_out; +return 0 ; +free_out: +if (datadir) +debugfs_remove (datadir); +debugfs_remove (rcudir); +out: +return 1 ; +} + +static int __init rcuclassic_trace_init (void ) +{ +int ret; + + rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL ); +if (!rcuclassic_trace_buf) +return 1 ; + ret =rcuclassic_debugfs_init (); +if (ret) +kfree (rcuclassic_trace_buf); +return ret; +} + +static void __exit rcuclassic_trace_cleanup(void)
kernel/rcuclassic_trace.c line 179
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+{ +debugfs_remove (datadir); +debugfs_remove (cbdir); +debugfs_remove (rcudir); +kfree (rcuclassic_trace_buf); +} + + +module_init (rcuclassic_trace_init); +module_exit (rcuclassic_trace_cleanup);
should have:MODULE_LICENSE("GPL");
optional but recommend:
MODULE_AUTHOR("Paul E. McKenney");MODULE_DESCRIPTION("DESCRIPTION");
Quoted 8 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/
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 9 lines · Lai Jiangshan
Quoted 7 lines · Paul E. McKenney
Hello!
This is v3 of a tracing patch for Classic RCU, which creates "rcu/rcucb" and "rcu/rcudata" files in debugfs. This patch can be handy when you need to work out why RCU is refusing to end the current grace period.
Should be ready for inclusion in tip/core/rcu, Ingo, please apply.
Quoted 8 lines
Hi, Paul,
I'm sorry that I'm a little busy these days, so I have not ported it to
seq_file, and you lost one choice.I found that
seq_cpumask_list()is needed when I tried to ported v2 toseq_file, so I introducedseq_cpumask_list()forseq_file, I'm waiting procfs hackers apply that patch too.
No problem, will be happy to see your patch whenever it is available.
Thanx, Paul
Quoted 360 lines
Lai.
Quoted 4 lines
Changes since v2: Add flag to
rcu_datato avoid printingrcu_datafor
CPUs that have never been online.Quoted 8 lines
Add documentation (below).
Changes since v1: Adds (crude) tracing for
rcu_datastructures.Reading from the "rcu/rcucb" file results in something like the following:
rcu: cur=1129 completed=1128 pending=0 s=0 0,3,7use "somename: 0,3,7" ? then when mask is empty, I think "somename:" is better than empty line.
Quoted 216 lines
rcu_bh: cur=-287 completed=-287 pending=0 s=0 online: 0-7The first two lines are for rcu, the second two for
rcu_bh. The cur= is the current grace-period number, and the completed= is the number of the last completed grace period. If these two numbers are equal, the corresponding flavor of RCU is idle. The pending= is the furthest future batch number that is required, if equal to cur=, no additional grace periods are required. The s=, if non-zero, indicates that a round of reschedule IPIs has been send to attempt to expedite the current grace period.The second and fourth lines are a comma/dash-separated list of the CPUs that have not yet reported a quiescent state for the current grace period (CPUs 0, 3, and 7 for "rcu" above).
The last line lists the online CPUs.
Reading from the "rcu/rcudata" file results in the following:
rcu: 0 qb=885 b=884 pq=1 qsp=0 ql=0 bl=10 1 qb=885 b=882 pq=1 qsp=0 ql=2 bl=10 2 qb=885 b=854 pq=1 qsp=0 ql=0 bl=10 3 qb=885 b=885 pq=1 qsp=0 ql=0 bl=10 rcu_bh: 0 qb=-291 b=-291 pq=1 qsp=0 ql=0 bl=10 1 qb=-291 b=0 pq=1 qsp=0 ql=0 bl=10 2 qb=-291 b=0 pq=1 qsp=0 ql=0 bl=10 3 qb=-291 b=-298 pq=1 qsp=0 ql=0 bl=10This output is again split into rcu and
rcu_bhportions. Within each portion, there is one line per CPU, but only for those CPUs that have been online at least once since boot. The number at the beginning of each line is the CPU number, followed by an "!" if the corresponding CPU is currently offline. The qb= is the batch number for the RCU core, the b= is the batch number corresponding to the callbacks waiting for the current grace period for this CPU, the pq= is a flag indicating that this CPU has passed through a quiescent state for the current grace period, the qsp= is a flag indicating that the RCU core has been informed that this CPU has passed through a quiescent state for the current grace period, the ql= is the number of RCU callbacks currently enqueued on this CPU (regardless of their state), and the bl= is the current limit of the number of callbacks to be invoked at one shot.Tested on x86 and Power, rebased to -tip.
Signed-off-by Paul E. McKenney <[email protected]>---
include/linux/rcuclassic.h | 4 + kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 5 - kernel/rcuclassic_trace.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+), 3 deletions(-)include/linux/rcuclassic.h +4
-0@@ -63,6 +63,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {@@ -81,6 +84,7 @@ struct rcu_data {long quiescbatch;/* Batch # for grace period */ int passed_quiesc;/* User-mode/idle loop etc. */ int qs_pending;/* core waits for quiesc state */ +bool beenonline;/* CPU online at least once */ /* 2) batch handling */ /* kernel/Kconfig.preempt +0
-1@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y helpkernel/Makefile +2
-0@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.okernel/rcuclassic.c +3
-2@@ -58,14 +58,14 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .pending =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .pending =-300 ,@@ -725,6 +725,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->donetail = &rdp->donelist; rdp->quiescbatch = rcp->completed; rdp->qs_pending =0 ; + rdp->beenonline =1 ; rdp->cpu = cpu; rdp->blimit = blimit;spin_unlock_irqrestore (&rcp->lock, flags);kernel/rcuclassic_trace.c new file +75
-0@@ -0,0 +1,179 @@ +/* +* Read-Copy Update tracing for classic implementation +* +* 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, 2008 +* +* Papers: http://www.rdrop.com/users/paulmck/RCU +* +* For detailed explanation of Read-Copy Update mechanism see - +* Documentation/RCU +* +*/ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/rcupdate.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <asm/atomic.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/completion.h> +#include <linux/moduleparam.h> +#include <linux/percpu.h> +#include <linux/notifier.h> +#include <linux/cpu.h> +#include <linux/mutex.h> +#include <linux/debugfs.h> + +static DEFINE_MUTEX (rcuclassic_trace_mutex); +static char *rcuclassic_trace_buf; +#define RCUCLASSIC_TRACE_BUF_SIZE (128 * num_possible_cpus() + 100) + +static int print_one_rcu_data (struct rcu_data *rdp,char *buf,char *ebuf) +{ +int cnt =0 ; + +if (!rdp->beenonline) +return 0 ; + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt], +"%3d%cqb=%ld b=%ld pq=%d qsp=%d ql=%ld bl=%ld\n" , + rdp->cpu,cpu_is_offline (rdp->cpu) ?'!' :' ' , + rdp->quiescbatch, rdp->batch, rdp->passed_quiesc, + rdp->qs_pending, rdp->qlen, rdp->blimit); +return cnt; +} + +#define PRINT_RCU_DATA (name, buf, ebuf) \ + do { \ + int _p_r_d_i; \ + \ + for_each_possible_cpu(_p_r_d_i) \ + (buf) += print_one_rcu_data(&per_cpu(name, _p_r_d_i), \ + buf, ebuf); \ + } while (0) + +static ssize_t rcudata_read (struct file *filp,char __user *buffer, +size_t count,loff_t *ppos) +{ +ssize_t bcount;kernel/rcuclassic_trace.c line 85
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+char *buf = rcuclassic_trace_buf; +char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; + +mutex_lock (&rcuclassic_trace_mutex); + buf +=snprintf (buf, ebuf - buf,"rcu:\n" ); +PRINT_RCU_DATA (rcu_data, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"rcu_bh:\n" ); +PRINT_RCU_DATA (rcu_bh_data, buf, ebuf); + bcount =simple_read_from_buffer (buffer, count, ppos, + rcuclassic_trace_buf,strlen (rcuclassic_trace_buf));Is
strlen(rcuclassic_trace_buf)== buf -rcuclassic_trace_buf?Quoted 84 lines
kernel/rcuclassic_trace.c new file +84
-0+mutex_unlock (&rcuclassic_trace_mutex); +return bcount; +} + +static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +{ +int cnt =0 ; + + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " +"pending=%ld s=%d\n\t" , + rcp->cur, rcp->completed, + rcp->pending, rcp->signaled); + cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); + cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); +return cnt; +} + +static ssize_t rcucb_read (struct file *filp,char __user *buffer, +size_t count,loff_t *ppos) +{ +ssize_t bcount; +char *buf = rcuclassic_trace_buf; +char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; + +mutex_lock (&rcuclassic_trace_mutex); + buf +=snprintf (buf, ebuf - buf,"rcu: " ); + buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); + buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); + buf +=snprintf (buf, ebuf - buf,"online: " ); + buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); + buf +=snprintf (buf, ebuf - buf,"\n" ); + bcount =simple_read_from_buffer (buffer, count, ppos, + rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); +mutex_unlock (&rcuclassic_trace_mutex); +return bcount; +} + +static struct file_operations rcudata_fops = { + .owner =THIS_MODULE , + .read = rcudata_read, +}; + +static struct file_operations rcucb_fops = { + .owner =THIS_MODULE , + .read = rcucb_read, +}; + +static struct dentry *rcudir, *datadir, *cbdir; +static int rcuclassic_debugfs_init (void ) +{ + rcudir =debugfs_create_dir ("rcu" ,NULL ); +if (!rcudir) + goto out; + datadir =debugfs_create_file ("rcudata" ,0444 , rcudir, +NULL , &rcudata_fops); +if (!datadir) + goto free_out; + cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); +if (!cbdir) + goto free_out; +return 0 ; +free_out: +if (datadir) +debugfs_remove (datadir); +debugfs_remove (rcudir); +out: +return 1 ; +} + +static int __init rcuclassic_trace_init (void ) +{ +int ret; + + rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL ); +if (!rcuclassic_trace_buf) +return 1 ; + ret =rcuclassic_debugfs_init (); +if (ret) +kfree (rcuclassic_trace_buf); +return ret; +} + +static void __exit rcuclassic_trace_cleanup(void)kernel/rcuclassic_trace.c line 179
Quoted 10 lines
kernel/rcuclassic_trace.c new file +10
-0+{ +debugfs_remove (datadir); +debugfs_remove (cbdir); +debugfs_remove (rcudir); +kfree (rcuclassic_trace_buf); +} + + +module_init (rcuclassic_trace_init); +module_exit (rcuclassic_trace_cleanup);should have:
MODULE_LICENSE("GPL");optional but recommend:
MODULE_AUTHOR("Paul E. McKenney");MODULE_DESCRIPTION("DESCRIPTION");Quoted 8 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/
Re: [PATCH] v3 rudimentary tracing for Classic RCU
In reply to Paul E. McKenneytrivial ported it to seq_file.seq_file are very good for the output buffer.
---
kernel/rcuclassic_trace.c +122 -112
@@ -23,157 +23,167 @@* Documentation/RCU * */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/smp.h> #include <linux/rcupdate.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <asm/atomic.h> -#include <linux/bitops.h> #include <linux/module.h> -#include <linux/completion.h> -#include <linux/moduleparam.h> -#include <linux/percpu.h> -#include <linux/notifier.h> -#include <linux/cpu.h> -#include <linux/mutex.h> #include <linux/debugfs.h> +#include <linux/seq_file.h> -static DEFINE_MUTEX (rcuclassic_trace_mutex); -static char *rcuclassic_trace_buf; -#define RCUCLASSIC_TRACE_BUF_SIZE (128 * num_possible_cpus() + 100) +static struct rcu_data *get_rcu_data_bh (int cpu) +{ +return &per_cpu (rcu_bh_data, cpu); +} -static int print_one_rcu_data (struct rcu_data *rdp,char *buf,char *ebuf) +static struct rcu_data *get_rcu_data (int cpu) { -int cnt =0 ; +return &per_cpu (rcu_data, cpu); +} +static int show_rcu_data (struct seq_file *m,void *v) +{ +struct rcu_data *rdp = v;if (!rdp->beenonline)return 0 ; - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt], -"%3d%cqb=%ld b=%ld pq=%d qsp=%d ql=%ld bl=%ld\n" , - rdp->cpu,cpu_is_offline (rdp->cpu) ?'!' :' ' , - rdp->quiescbatch, rdp->batch, rdp->passed_quiesc, - rdp->qs_pending, rdp->qlen, rdp->blimit); -return cnt; + +seq_printf (m,"processor\t: %d" , rdp->cpu); +if (cpu_is_offline (rdp->cpu)) +seq_puts (m,"!\n" ); +else +seq_puts (m,"\n" ); +seq_printf (m,"quiescbatch\t: %ld\n" , rdp->quiescbatch); +seq_printf (m,"batch\t: %ld\n" , rdp->batch); +seq_printf (m,"passed_quiesc\t: %d\n" , rdp->passed_quiesc); +seq_printf (m,"qs_pending\t: %d\n" , rdp->qs_pending); +seq_printf (m,"qlen\t: %ld\n" , rdp->qlen); +seq_printf (m,"blimit\t: %ld\n" , rdp->blimit); +seq_puts (m,"\n\n" ); +return 0 ; } -#define PRINT_RCU_DATA (name, buf, ebuf) \ - do { \ - int _p_r_d_i; \ - \ - for_each_possible_cpu(_p_r_d_i) \ - (buf) += print_one_rcu_data(&per_cpu(name, _p_r_d_i), \ - buf, ebuf); \ - } while (0) - -static ssize_t rcudata_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void *c_start (struct seq_file *m,loff_t *pos) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu:\n" ); -PRINT_RCU_DATA (rcu_data, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh:\n" ); -PRINT_RCU_DATA (rcu_bh_data, buf, ebuf); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; +typedef struct rcu_data *(*get_data_func )(int ); + +if (*pos ==0 )/* just in case, cpu 0 is not the first */ + *pos =first_cpu (cpu_possible_map); +else + *pos =next_cpu_nr (*pos -1 , cpu_possible_map); +if ((*pos) < nr_cpu_ids) +return ((get_data_func )m->private)(*pos); +return NULL ; } -static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +static void *c_next (struct seq_file *m,void *v,loff_t *pos) { -int cnt =0 ; - - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " -"pending=%ld s=%d\n\t" , - rcp->cur, rcp->completed, - rcp->pending, rcp->signaled); - cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); -return cnt; + (*pos)++; +return c_start (m, pos); } -static ssize_t rcucb_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void c_stop (struct seq_file *m,void *v) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu: " ); - buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); - buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"online: " ); - buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); - buf +=snprintf (buf, ebuf - buf,"\n" ); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; } -static struct file_operations rcudata_fops = { - .owner =THIS_MODULE , - .read = rcudata_read, +const struct seq_operations rcu_data_seq_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_rcu_data, }; +static int rcu_data_open (struct inode *inode,struct file *file) +{ +int ret =seq_open (file, &rcu_data_seq_op); +if (ret) +return ret; + ((struct seq_file *)file->private_data)->private = inode->i_private; +return 0 ; +} + +static const struct file_operations rcu_data_fops = { + .owner =THIS_MODULE , + .open = rcu_data_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void print_one_rcu_ctrlblk (struct seq_file *m,struct rcu_ctrlblk *rcp) +{ +seq_printf (m,"cur=%ld completed=%ld pending=%ld s=%d\n\t" , + rcp->cur, rcp->completed, rcp->pending, rcp->signaled); +seq_cpumask (m, &rcp->cpumask); +seq_puts (m,"\n" ); +} + +static int show_rcucb (struct seq_file *m,void *unused) +{ +seq_puts (m,"rcu: " ); +print_one_rcu_ctrlblk (m, &rcu_ctrlblk); +seq_puts (m,"rcu_bh: " ); +print_one_rcu_ctrlblk (m, &rcu_bh_ctrlblk); +seq_puts (m,"online: " ); +seq_cpumask (m, &cpu_online_map); +seq_puts (m,"\n" ); +return 0 ; +} + +static int rcucb_open (struct inode *inode,struct file *file) +{ +return single_open (file, show_rcucb,NULL ); +} +static struct file_operations rcucb_fops = { - .owner =THIS_MODULE , - .read = rcucb_read, + .owner =THIS_MODULE , + .open = rcucb_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; -static struct dentry *rcudir, *datadir, *cbdir; -static int rcuclassic_debugfs_init (void ) +static struct dentry *rcudir, *rcu_bh_data_file, *rcu_data_file, *rcucb_file; + +static int __init rcuclassic_trace_init (void ) { rcudir =debugfs_create_dir ("rcu" ,NULL );if (!rcudir) goto out; - datadir =debugfs_create_file ("rcudata" ,0444 , rcudir, -NULL , &rcudata_fops); -if (!datadir) - goto free_out; - cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); -if (!cbdir) - goto free_out; + + rcu_bh_data_file =debugfs_create_file ("rcu_bh_data" ,0444 , rcudir, + get_rcu_data_bh, &rcu_data_fops); +if (!rcu_bh_data_file) + goto out_rcudir; + + rcu_data_file =debugfs_create_file ("rcu_data" ,0444 , rcudir, + get_rcu_data, &rcu_data_fops); +if (!rcu_data_file) + goto out_rcudata_bh_file; + + rcucb_file =debugfs_create_file ("rcucb" ,0444 , rcudir, +NULL , &rcucb_fops); +if (!rcucb_file) + goto out_rcudata_file;return 0 ; -free_out: -if (datadir) -debugfs_remove (datadir); + +out_rcudata_file: +debugfs_remove (rcu_data_file); +out_rcudata_bh_file: +debugfs_remove (rcu_bh_data_file); +out_rcudir:debugfs_remove (rcudir); out:return 1 ; } -static int __init rcuclassic_trace_init (void ) -{ -int ret; - - rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL ); -if (!rcuclassic_trace_buf) -return 1 ; - ret =rcuclassic_debugfs_init (); -if (ret) -kfree (rcuclassic_trace_buf); -return ret; -} - static void __exit rcuclassic_trace_cleanup(void) { -debugfs_remove (datadir); -debugfs_remove (cbdir); +debugfs_remove (rcucb_file); +debugfs_remove (rcu_data_file); +debugfs_remove (rcu_bh_data_file);debugfs_remove (rcudir); -kfree (rcuclassic_trace_buf); } -module_init (rcuclassic_trace_init);module_exit (rcuclassic_trace_cleanup); + +MODULE_AUTHOR ("Paul E. McKenney" ); +MODULE_DESCRIPTION ("Read-Copy Update tracing for classic implementation" ); +MODULE_LICENSE ("GPL" );
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 3 lines · Lai Jiangshan
trivial ported it to
seq_file.seq_fileare very good for the output buffer.
Thank you for putting this together!!! Looks good at first glance -- I will test it out.
Thanx, Paul
Quoted 287 lines
Signed-off-by Lai Jiangshan <[email protected]>---
kernel/rcuclassic_trace.c +122
-112@@ -23,157 +23,167 @@* Documentation/RCU * */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/smp.h> #include <linux/rcupdate.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <asm/atomic.h> -#include <linux/bitops.h> #include <linux/module.h> -#include <linux/completion.h> -#include <linux/moduleparam.h> -#include <linux/percpu.h> -#include <linux/notifier.h> -#include <linux/cpu.h> -#include <linux/mutex.h> #include <linux/debugfs.h> +#include <linux/seq_file.h> -static DEFINE_MUTEX (rcuclassic_trace_mutex); -static char *rcuclassic_trace_buf; -#define RCUCLASSIC_TRACE_BUF_SIZE (128 * num_possible_cpus() + 100) +static struct rcu_data *get_rcu_data_bh (int cpu) +{ +return &per_cpu (rcu_bh_data, cpu); +} -static int print_one_rcu_data (struct rcu_data *rdp,char *buf,char *ebuf) +static struct rcu_data *get_rcu_data (int cpu) { -int cnt =0 ; +return &per_cpu (rcu_data, cpu); +} +static int show_rcu_data (struct seq_file *m,void *v) +{ +struct rcu_data *rdp = v;if (!rdp->beenonline)return 0 ; - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt], -"%3d%cqb=%ld b=%ld pq=%d qsp=%d ql=%ld bl=%ld\n" , - rdp->cpu,cpu_is_offline (rdp->cpu) ?'!' :' ' , - rdp->quiescbatch, rdp->batch, rdp->passed_quiesc, - rdp->qs_pending, rdp->qlen, rdp->blimit); -return cnt; + +seq_printf (m,"processor\t: %d" , rdp->cpu); +if (cpu_is_offline (rdp->cpu)) +seq_puts (m,"!\n" ); +else +seq_puts (m,"\n" ); +seq_printf (m,"quiescbatch\t: %ld\n" , rdp->quiescbatch); +seq_printf (m,"batch\t: %ld\n" , rdp->batch); +seq_printf (m,"passed_quiesc\t: %d\n" , rdp->passed_quiesc); +seq_printf (m,"qs_pending\t: %d\n" , rdp->qs_pending); +seq_printf (m,"qlen\t: %ld\n" , rdp->qlen); +seq_printf (m,"blimit\t: %ld\n" , rdp->blimit); +seq_puts (m,"\n\n" ); +return 0 ; } -#define PRINT_RCU_DATA (name, buf, ebuf) \ - do { \ - int _p_r_d_i; \ - \ - for_each_possible_cpu(_p_r_d_i) \ - (buf) += print_one_rcu_data(&per_cpu(name, _p_r_d_i), \ - buf, ebuf); \ - } while (0) - -static ssize_t rcudata_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void *c_start (struct seq_file *m,loff_t *pos) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu:\n" ); -PRINT_RCU_DATA (rcu_data, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh:\n" ); -PRINT_RCU_DATA (rcu_bh_data, buf, ebuf); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; +typedef struct rcu_data *(*get_data_func )(int ); + +if (*pos ==0 )/* just in case, cpu 0 is not the first */ + *pos =first_cpu (cpu_possible_map); +else + *pos =next_cpu_nr (*pos -1 , cpu_possible_map); +if ((*pos) < nr_cpu_ids) +return ((get_data_func )m->private)(*pos); +return NULL ; } -static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +static void *c_next (struct seq_file *m,void *v,loff_t *pos) { -int cnt =0 ; - - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " -"pending=%ld s=%d\n\t" , - rcp->cur, rcp->completed, - rcp->pending, rcp->signaled); - cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); -return cnt; + (*pos)++; +return c_start (m, pos); } -static ssize_t rcucb_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void c_stop (struct seq_file *m,void *v) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu: " ); - buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); - buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"online: " ); - buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); - buf +=snprintf (buf, ebuf - buf,"\n" ); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; } -static struct file_operations rcudata_fops = { - .owner =THIS_MODULE , - .read = rcudata_read, +const struct seq_operations rcu_data_seq_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_rcu_data, }; +static int rcu_data_open (struct inode *inode,struct file *file) +{ +int ret =seq_open (file, &rcu_data_seq_op); +if (ret) +return ret; + ((struct seq_file *)file->private_data)->private = inode->i_private; +return 0 ; +} + +static const struct file_operations rcu_data_fops = { + .owner =THIS_MODULE , + .open = rcu_data_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void print_one_rcu_ctrlblk (struct seq_file *m,struct rcu_ctrlblk *rcp) +{ +seq_printf (m,"cur=%ld completed=%ld pending=%ld s=%d\n\t" , + rcp->cur, rcp->completed, rcp->pending, rcp->signaled); +seq_cpumask (m, &rcp->cpumask); +seq_puts (m,"\n" ); +} + +static int show_rcucb (struct seq_file *m,void *unused) +{ +seq_puts (m,"rcu: " ); +print_one_rcu_ctrlblk (m, &rcu_ctrlblk); +seq_puts (m,"rcu_bh: " ); +print_one_rcu_ctrlblk (m, &rcu_bh_ctrlblk); +seq_puts (m,"online: " ); +seq_cpumask (m, &cpu_online_map); +seq_puts (m,"\n" ); +return 0 ; +} + +static int rcucb_open (struct inode *inode,struct file *file) +{ +return single_open (file, show_rcucb,NULL ); +} +static struct file_operations rcucb_fops = { - .owner =THIS_MODULE , - .read = rcucb_read, + .owner =THIS_MODULE , + .open = rcucb_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; -static struct dentry *rcudir, *datadir, *cbdir; -static int rcuclassic_debugfs_init (void ) +static struct dentry *rcudir, *rcu_bh_data_file, *rcu_data_file, *rcucb_file; + +static int __init rcuclassic_trace_init (void ) { rcudir =debugfs_create_dir ("rcu" ,NULL );if (!rcudir) goto out; - datadir =debugfs_create_file ("rcudata" ,0444 , rcudir, -NULL , &rcudata_fops); -if (!datadir) - goto free_out; - cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); -if (!cbdir) - goto free_out; + + rcu_bh_data_file =debugfs_create_file ("rcu_bh_data" ,0444 , rcudir, + get_rcu_data_bh, &rcu_data_fops); +if (!rcu_bh_data_file) + goto out_rcudir; + + rcu_data_file =debugfs_create_file ("rcu_data" ,0444 , rcudir, + get_rcu_data, &rcu_data_fops); +if (!rcu_data_file) + goto out_rcudata_bh_file; + + rcucb_file =debugfs_create_file ("rcucb" ,0444 , rcudir, +NULL , &rcucb_fops); +if (!rcucb_file) + goto out_rcudata_file;return 0 ; -free_out: -if (datadir) -debugfs_remove (datadir); + +out_rcudata_file: +debugfs_remove (rcu_data_file); +out_rcudata_bh_file: +debugfs_remove (rcu_bh_data_file); +out_rcudir:debugfs_remove (rcudir); out:return 1 ; } -static int __init rcuclassic_trace_init (void ) -{ -int ret; - - rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL ); -if (!rcuclassic_trace_buf) -return 1 ; - ret =rcuclassic_debugfs_init (); -if (ret) -kfree (rcuclassic_trace_buf); -return ret; -} - static void __exit rcuclassic_trace_cleanup(void) { -debugfs_remove (datadir); -debugfs_remove (cbdir); +debugfs_remove (rcucb_file); +debugfs_remove (rcu_data_file); +debugfs_remove (rcu_bh_data_file);debugfs_remove (rcudir); -kfree (rcuclassic_trace_buf); } -module_init (rcuclassic_trace_init);module_exit (rcuclassic_trace_cleanup); + +MODULE_AUTHOR ("Paul E. McKenney" ); +MODULE_DESCRIPTION ("Read-Copy Update tracing for classic implementation" ); +MODULE_LICENSE ("GPL" );
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 7 lines · Paul E. McKenney
Quoted 3 lines · Lai Jiangshan
trivial ported it to
seq_file.seq_fileare very good for the output buffer.Thank you for putting this together!!! Looks good at first glance -- I will test it out.
So it does seem to operate correctly. I combined it with my patch and applied against 2.6.27 for ease of testing.
One question -- why the multi-line format? This would be a bit awkward on a 128-CPU system, let alone on a 4,096-CPU system. Or am I missing some trick here?
Quoted 289 lines
Thanx, Paul
Quoted 287 lines
Signed-off-by Lai Jiangshan <[email protected]>---
kernel/rcuclassic_trace.c +122
-112@@ -23,157 +23,167 @@* Documentation/RCU * */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/smp.h> #include <linux/rcupdate.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <asm/atomic.h> -#include <linux/bitops.h> #include <linux/module.h> -#include <linux/completion.h> -#include <linux/moduleparam.h> -#include <linux/percpu.h> -#include <linux/notifier.h> -#include <linux/cpu.h> -#include <linux/mutex.h> #include <linux/debugfs.h> +#include <linux/seq_file.h> -static DEFINE_MUTEX (rcuclassic_trace_mutex); -static char *rcuclassic_trace_buf; -#define RCUCLASSIC_TRACE_BUF_SIZE (128 * num_possible_cpus() + 100) +static struct rcu_data *get_rcu_data_bh (int cpu) +{ +return &per_cpu (rcu_bh_data, cpu); +} -static int print_one_rcu_data (struct rcu_data *rdp,char *buf,char *ebuf) +static struct rcu_data *get_rcu_data (int cpu) { -int cnt =0 ; +return &per_cpu (rcu_data, cpu); +} +static int show_rcu_data (struct seq_file *m,void *v) +{ +struct rcu_data *rdp = v;if (!rdp->beenonline)return 0 ; - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt], -"%3d%cqb=%ld b=%ld pq=%d qsp=%d ql=%ld bl=%ld\n" , - rdp->cpu,cpu_is_offline (rdp->cpu) ?'!' :' ' , - rdp->quiescbatch, rdp->batch, rdp->passed_quiesc, - rdp->qs_pending, rdp->qlen, rdp->blimit); -return cnt; + +seq_printf (m,"processor\t: %d" , rdp->cpu); +if (cpu_is_offline (rdp->cpu)) +seq_puts (m,"!\n" ); +else +seq_puts (m,"\n" ); +seq_printf (m,"quiescbatch\t: %ld\n" , rdp->quiescbatch); +seq_printf (m,"batch\t: %ld\n" , rdp->batch); +seq_printf (m,"passed_quiesc\t: %d\n" , rdp->passed_quiesc); +seq_printf (m,"qs_pending\t: %d\n" , rdp->qs_pending); +seq_printf (m,"qlen\t: %ld\n" , rdp->qlen); +seq_printf (m,"blimit\t: %ld\n" , rdp->blimit); +seq_puts (m,"\n\n" ); +return 0 ; } -#define PRINT_RCU_DATA (name, buf, ebuf) \ - do { \ - int _p_r_d_i; \ - \ - for_each_possible_cpu(_p_r_d_i) \ - (buf) += print_one_rcu_data(&per_cpu(name, _p_r_d_i), \ - buf, ebuf); \ - } while (0) - -static ssize_t rcudata_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void *c_start (struct seq_file *m,loff_t *pos) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu:\n" ); -PRINT_RCU_DATA (rcu_data, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh:\n" ); -PRINT_RCU_DATA (rcu_bh_data, buf, ebuf); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; +typedef struct rcu_data *(*get_data_func )(int ); + +if (*pos ==0 )/* just in case, cpu 0 is not the first */ + *pos =first_cpu (cpu_possible_map); +else + *pos =next_cpu_nr (*pos -1 , cpu_possible_map); +if ((*pos) < nr_cpu_ids) +return ((get_data_func )m->private)(*pos); +return NULL ; } -static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +static void *c_next (struct seq_file *m,void *v,loff_t *pos) { -int cnt =0 ; - - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " -"pending=%ld s=%d\n\t" , - rcp->cur, rcp->completed, - rcp->pending, rcp->signaled); - cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); -return cnt; + (*pos)++; +return c_start (m, pos); } -static ssize_t rcucb_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void c_stop (struct seq_file *m,void *v) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu: " ); - buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); - buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"online: " ); - buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); - buf +=snprintf (buf, ebuf - buf,"\n" ); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; } -static struct file_operations rcudata_fops = { - .owner =THIS_MODULE , - .read = rcudata_read, +const struct seq_operations rcu_data_seq_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_rcu_data, }; +static int rcu_data_open (struct inode *inode,struct file *file) +{ +int ret =seq_open (file, &rcu_data_seq_op); +if (ret) +return ret; + ((struct seq_file *)file->private_data)->private = inode->i_private; +return 0 ; +} + +static const struct file_operations rcu_data_fops = { + .owner =THIS_MODULE , + .open = rcu_data_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void print_one_rcu_ctrlblk (struct seq_file *m,struct rcu_ctrlblk *rcp) +{ +seq_printf (m,"cur=%ld completed=%ld pending=%ld s=%d\n\t" , + rcp->cur, rcp->completed, rcp->pending, rcp->signaled); +seq_cpumask (m, &rcp->cpumask); +seq_puts (m,"\n" ); +} + +static int show_rcucb (struct seq_file *m,void *unused) +{ +seq_puts (m,"rcu: " ); +print_one_rcu_ctrlblk (m, &rcu_ctrlblk); +seq_puts (m,"rcu_bh: " ); +print_one_rcu_ctrlblk (m, &rcu_bh_ctrlblk); +seq_puts (m,"online: " ); +seq_cpumask (m, &cpu_online_map); +seq_puts (m,"\n" ); +return 0 ; +} + +static int rcucb_open (struct inode *inode,struct file *file) +{ +return single_open (file, show_rcucb,NULL ); +} +static struct file_operations rcucb_fops = { - .owner =THIS_MODULE , - .read = rcucb_read, + .owner =THIS_MODULE , + .open = rcucb_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; -static struct dentry *rcudir, *datadir, *cbdir; -static int rcuclassic_debugfs_init (void ) +static struct dentry *rcudir, *rcu_bh_data_file, *rcu_data_file, *rcucb_file; + +static int __init rcuclassic_trace_init (void ) { rcudir =debugfs_create_dir ("rcu" ,NULL );if (!rcudir) goto out; - datadir =debugfs_create_file ("rcudata" ,0444 , rcudir, -NULL , &rcudata_fops); -if (!datadir) - goto free_out; - cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); -if (!cbdir) - goto free_out; + + rcu_bh_data_file =debugfs_create_file ("rcu_bh_data" ,0444 , rcudir, + get_rcu_data_bh, &rcu_data_fops); +if (!rcu_bh_data_file) + goto out_rcudir; + + rcu_data_file =debugfs_create_file ("rcu_data" ,0444 , rcudir, + get_rcu_data, &rcu_data_fops); +if (!rcu_data_file) + goto out_rcudata_bh_file; + + rcucb_file =debugfs_create_file ("rcucb" ,0444 , rcudir, +NULL , &rcucb_fops); +if (!rcucb_file) + goto out_rcudata_file;return 0 ; -free_out: -if (datadir) -debugfs_remove (datadir); + +out_rcudata_file: +debugfs_remove (rcu_data_file); +out_rcudata_bh_file: +debugfs_remove (rcu_bh_data_file); +out_rcudir:debugfs_remove (rcudir); out:return 1 ; } -static int __init rcuclassic_trace_init (void ) -{ -int ret; - - rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL ); -if (!rcuclassic_trace_buf) -return 1 ; - ret =rcuclassic_debugfs_init (); -if (ret) -kfree (rcuclassic_trace_buf); -return ret; -} - static void __exit rcuclassic_trace_cleanup(void) { -debugfs_remove (datadir); -debugfs_remove (cbdir); +debugfs_remove (rcucb_file); +debugfs_remove (rcu_data_file); +debugfs_remove (rcu_bh_data_file);debugfs_remove (rcudir); -kfree (rcuclassic_trace_buf); } -module_init (rcuclassic_trace_init);module_exit (rcuclassic_trace_cleanup); + +MODULE_AUTHOR ("Paul E. McKenney" ); +MODULE_DESCRIPTION ("Read-Copy Update tracing for classic implementation" ); +MODULE_LICENSE ("GPL" );
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 9 lines · Paul E. McKenney
Quoted 7 lines · Paul E. McKenney
Quoted 3 lines · Lai Jiangshan
trivial ported it to
seq_file.seq_fileare very good for the output buffer.Thank you for putting this together!!! Looks good at first glance -- I will test it out.
Quoted 6 lines
So it does seem to operate correctly. I combined it with my patch and applied against 2.6.27 for ease of testing.
One question -- why the multi-line format? This would be a bit awkward on a 128-CPU system, let alone on a 4,096-CPU system. Or am I missing some trick here?
To clarify, by "missing some trick", I am wondering if there is some command that works in blocks of lines. After all, /proc/cpuinfo produces the same sort of output that your patch does. ;-)
Thanx, Paul
Quoted 287 lines
Quoted 287 lines
Quoted 287 lines
Signed-off-by Lai Jiangshan <[email protected]>---
kernel/rcuclassic_trace.c +122
-112@@ -23,157 +23,167 @@* Documentation/RCU * */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/smp.h> #include <linux/rcupdate.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <asm/atomic.h> -#include <linux/bitops.h> #include <linux/module.h> -#include <linux/completion.h> -#include <linux/moduleparam.h> -#include <linux/percpu.h> -#include <linux/notifier.h> -#include <linux/cpu.h> -#include <linux/mutex.h> #include <linux/debugfs.h> +#include <linux/seq_file.h> -static DEFINE_MUTEX (rcuclassic_trace_mutex); -static char *rcuclassic_trace_buf; -#define RCUCLASSIC_TRACE_BUF_SIZE (128 * num_possible_cpus() + 100) +static struct rcu_data *get_rcu_data_bh (int cpu) +{ +return &per_cpu (rcu_bh_data, cpu); +} -static int print_one_rcu_data (struct rcu_data *rdp,char *buf,char *ebuf) +static struct rcu_data *get_rcu_data (int cpu) { -int cnt =0 ; +return &per_cpu (rcu_data, cpu); +} +static int show_rcu_data (struct seq_file *m,void *v) +{ +struct rcu_data *rdp = v;if (!rdp->beenonline)return 0 ; - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt], -"%3d%cqb=%ld b=%ld pq=%d qsp=%d ql=%ld bl=%ld\n" , - rdp->cpu,cpu_is_offline (rdp->cpu) ?'!' :' ' , - rdp->quiescbatch, rdp->batch, rdp->passed_quiesc, - rdp->qs_pending, rdp->qlen, rdp->blimit); -return cnt; + +seq_printf (m,"processor\t: %d" , rdp->cpu); +if (cpu_is_offline (rdp->cpu)) +seq_puts (m,"!\n" ); +else +seq_puts (m,"\n" ); +seq_printf (m,"quiescbatch\t: %ld\n" , rdp->quiescbatch); +seq_printf (m,"batch\t: %ld\n" , rdp->batch); +seq_printf (m,"passed_quiesc\t: %d\n" , rdp->passed_quiesc); +seq_printf (m,"qs_pending\t: %d\n" , rdp->qs_pending); +seq_printf (m,"qlen\t: %ld\n" , rdp->qlen); +seq_printf (m,"blimit\t: %ld\n" , rdp->blimit); +seq_puts (m,"\n\n" ); +return 0 ; } -#define PRINT_RCU_DATA (name, buf, ebuf) \ - do { \ - int _p_r_d_i; \ - \ - for_each_possible_cpu(_p_r_d_i) \ - (buf) += print_one_rcu_data(&per_cpu(name, _p_r_d_i), \ - buf, ebuf); \ - } while (0) - -static ssize_t rcudata_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void *c_start (struct seq_file *m,loff_t *pos) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu:\n" ); -PRINT_RCU_DATA (rcu_data, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh:\n" ); -PRINT_RCU_DATA (rcu_bh_data, buf, ebuf); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; +typedef struct rcu_data *(*get_data_func )(int ); + +if (*pos ==0 )/* just in case, cpu 0 is not the first */ + *pos =first_cpu (cpu_possible_map); +else + *pos =next_cpu_nr (*pos -1 , cpu_possible_map); +if ((*pos) < nr_cpu_ids) +return ((get_data_func )m->private)(*pos); +return NULL ; } -static int print_one_rcu_ctrlblk (struct rcu_ctrlblk *rcp,char *buf,char *ebuf) +static void *c_next (struct seq_file *m,void *v,loff_t *pos) { -int cnt =0 ; - - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"cur=%ld completed=%ld " -"pending=%ld s=%d\n\t" , - rcp->cur, rcp->completed, - rcp->pending, rcp->signaled); - cnt +=cpulist_scnprintf (&buf[cnt], ebuf - &buf[cnt], rcp->cpumask); - cnt +=snprintf (&buf[cnt], ebuf - &buf[cnt],"\n" ); -return cnt; + (*pos)++; +return c_start (m, pos); } -static ssize_t rcucb_read (struct file *filp,char __user *buffer, -size_t count,loff_t *ppos) +static void c_stop (struct seq_file *m,void *v) { -ssize_t bcount; -char *buf = rcuclassic_trace_buf; -char *ebuf = &rcuclassic_trace_buf[RCUCLASSIC_TRACE_BUF_SIZE ]; - -mutex_lock (&rcuclassic_trace_mutex); - buf +=snprintf (buf, ebuf - buf,"rcu: " ); - buf +=print_one_rcu_ctrlblk (&rcu_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"rcu_bh: " ); - buf +=print_one_rcu_ctrlblk (&rcu_bh_ctrlblk, buf, ebuf); - buf +=snprintf (buf, ebuf - buf,"online: " ); - buf +=cpulist_scnprintf (buf, ebuf - buf, cpu_online_map); - buf +=snprintf (buf, ebuf - buf,"\n" ); - bcount =simple_read_from_buffer (buffer, count, ppos, - rcuclassic_trace_buf,strlen (rcuclassic_trace_buf)); -mutex_unlock (&rcuclassic_trace_mutex); -return bcount; } -static struct file_operations rcudata_fops = { - .owner =THIS_MODULE , - .read = rcudata_read, +const struct seq_operations rcu_data_seq_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_rcu_data, }; +static int rcu_data_open (struct inode *inode,struct file *file) +{ +int ret =seq_open (file, &rcu_data_seq_op); +if (ret) +return ret; + ((struct seq_file *)file->private_data)->private = inode->i_private; +return 0 ; +} + +static const struct file_operations rcu_data_fops = { + .owner =THIS_MODULE , + .open = rcu_data_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void print_one_rcu_ctrlblk (struct seq_file *m,struct rcu_ctrlblk *rcp) +{ +seq_printf (m,"cur=%ld completed=%ld pending=%ld s=%d\n\t" , + rcp->cur, rcp->completed, rcp->pending, rcp->signaled); +seq_cpumask (m, &rcp->cpumask); +seq_puts (m,"\n" ); +} + +static int show_rcucb (struct seq_file *m,void *unused) +{ +seq_puts (m,"rcu: " ); +print_one_rcu_ctrlblk (m, &rcu_ctrlblk); +seq_puts (m,"rcu_bh: " ); +print_one_rcu_ctrlblk (m, &rcu_bh_ctrlblk); +seq_puts (m,"online: " ); +seq_cpumask (m, &cpu_online_map); +seq_puts (m,"\n" ); +return 0 ; +} + +static int rcucb_open (struct inode *inode,struct file *file) +{ +return single_open (file, show_rcucb,NULL ); +} +static struct file_operations rcucb_fops = { - .owner =THIS_MODULE , - .read = rcucb_read, + .owner =THIS_MODULE , + .open = rcucb_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; -static struct dentry *rcudir, *datadir, *cbdir; -static int rcuclassic_debugfs_init (void ) +static struct dentry *rcudir, *rcu_bh_data_file, *rcu_data_file, *rcucb_file; + +static int __init rcuclassic_trace_init (void ) { rcudir =debugfs_create_dir ("rcu" ,NULL );if (!rcudir) goto out; - datadir =debugfs_create_file ("rcudata" ,0444 , rcudir, -NULL , &rcudata_fops); -if (!datadir) - goto free_out; - cbdir =debugfs_create_file ("rcucb" ,0444 , rcudir,NULL , &rcucb_fops); -if (!cbdir) - goto free_out; + + rcu_bh_data_file =debugfs_create_file ("rcu_bh_data" ,0444 , rcudir, + get_rcu_data_bh, &rcu_data_fops); +if (!rcu_bh_data_file) + goto out_rcudir; + + rcu_data_file =debugfs_create_file ("rcu_data" ,0444 , rcudir, + get_rcu_data, &rcu_data_fops); +if (!rcu_data_file) + goto out_rcudata_bh_file; + + rcucb_file =debugfs_create_file ("rcucb" ,0444 , rcudir, +NULL , &rcucb_fops); +if (!rcucb_file) + goto out_rcudata_file;return 0 ; -free_out: -if (datadir) -debugfs_remove (datadir); + +out_rcudata_file: +debugfs_remove (rcu_data_file); +out_rcudata_bh_file: +debugfs_remove (rcu_bh_data_file); +out_rcudir:debugfs_remove (rcudir); out:return 1 ; } -static int __init rcuclassic_trace_init (void ) -{ -int ret; - - rcuclassic_trace_buf =kmalloc (RCUCLASSIC_TRACE_BUF_SIZE ,GFP_KERNEL ); -if (!rcuclassic_trace_buf) -return 1 ; - ret =rcuclassic_debugfs_init (); -if (ret) -kfree (rcuclassic_trace_buf); -return ret; -} - static void __exit rcuclassic_trace_cleanup(void) { -debugfs_remove (datadir); -debugfs_remove (cbdir); +debugfs_remove (rcucb_file); +debugfs_remove (rcu_data_file); +debugfs_remove (rcu_bh_data_file);debugfs_remove (rcudir); -kfree (rcuclassic_trace_buf); } -module_init (rcuclassic_trace_init);module_exit (rcuclassic_trace_cleanup); + +MODULE_AUTHOR ("Paul E. McKenney" ); +MODULE_DESCRIPTION ("Read-Copy Update tracing for classic implementation" ); +MODULE_LICENSE ("GPL" );
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 13 lines · Paul E. McKenney
Quoted 12 lines · Paul E. McKenney
Quoted 7 lines · Paul E. McKenney
Quoted 3 lines · Lai Jiangshan
trivial ported it to
seq_file.seq_fileare very good for the output buffer.Thank you for putting this together!!! Looks good at first glance -- I will test it out.
So it does seem to operate correctly. I combined it with my patch and applied against 2.6.27 for ease of testing.
Quoted 7 lines
Quoted 3 lines
One question -- why the multi-line format? This would be a bit awkward on a 128-CPU system, let alone on a 4,096-CPU system. Or am I missing some trick here?
To clarify, by "missing some trick", I am wondering if there is some command that works in blocks of lines. After all,
/proc/cpuinfoproduces the same sort of output that your patch does. ;-)
Ported to 2.6.27 to ease testing, and fixed up the formatting a bit. I remember quickly scanning through one-line-per-CPU data to find problems with rcutree.c, but the expanded names are quite nice -- I had to brutally abbreviate to fit each CPU on a single line. And I agree that seqfile does work nicely for this.
I am strongly tempted to suggest CSV format output with headers to allow the data to be pulled into gnumeric or oocalc -- this would make handling large numbers of CPUs much easier. (Quickly donning the asbestos suit with titanium pinstripes...)
Thanx, Paul
---
include/linux/rcuclassic.h | 4 kernel/Kconfig.preempt | 1 kernel/Makefile | 2 kernel/rcuclassic.c | 5 - kernel/rcuclassic_trace.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+), 3 deletions(-)
include/linux/rcuclassic.h +4 -0
@@ -54,6 +54,9 @@ struct rcu_ctrlblk {/* for current batch to proceed. */ }____cacheline_internodealigned_in_smp ; +extern struct rcu_ctrlblk rcu_ctrlblk; +extern struct rcu_ctrlblk rcu_bh_ctrlblk; +/* Is batch a before batch b ? */ static inline int rcu_batch_before (long a,long b) {
@@ -76,6 +79,7 @@ struct rcu_data {long quiescbatch;/* Batch # for grace period */ int passed_quiesc;/* User-mode/idle loop etc. */ int qs_pending;/* core waits for quiesc state */ +bool beenonline;/* CPU online at least once */ /* 2) batch handling */ long batch;/* Batch # for current RCU batch */
kernel/Kconfig.preempt +0 -1
@@ -68,7 +68,6 @@ config PREEMPT_RCU config RCU_TRACE bool "Enable tracing for RCU - currently stats in debugfs" - depends on PREEMPT_RCU select DEBUG_FS default y help
kernel/Makefile +2 -0
@@ -77,6 +77,8 @@ obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o ifeq ($(CONFIG_PREEMPT_RCU),y) obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o +else +obj-$(CONFIG_RCU_TRACE) += rcuclassic_trace.o endif obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
kernel/rcuclassic.c +3 -2
@@ -57,13 +57,13 @@ EXPORT_SYMBOL_GPL(rcu_lock_map);/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { +struct rcu_ctrlblk rcu_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_ctrlblk.lock), .cpumask =CPU_MASK_NONE , }; -static struct rcu_ctrlblk rcu_bh_ctrlblk = { +struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur =-300 , .completed =-300 , .lock =__SPIN_LOCK_UNLOCKED (&rcu_bh_ctrlblk.lock),
@@ -564,6 +564,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->donetail = &rdp->donelist; rdp->quiescbatch = rcp->completed; rdp->qs_pending =0 ; + rdp->beenonline =1 ; rdp->cpu = cpu; rdp->blimit = blimit; }
kernel/rcuclassic_trace.c new file +198 -0
198 lines not on this page · raw message
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 6 lines · Paul E. McKenney
Ported to 2.6.27 to ease testing, and fixed up the formatting a bit. I remember quickly scanning through one-line-per-CPU data to find problems with
rcutree.c, but the expanded names are quite nice -- I had to brutally abbreviate to fit each CPU on a single line. And I agree that seqfile does work nicely for this.
Quoted 8 lines
I am strongly tempted to suggest CSV format output with headers to allow the data to be pulled into gnumeric or oocalc -- this would make handling large numbers of CPUs much easier. (Quickly donning the asbestos suit with titanium pinstripes...)
Thanx, Paul
Hi, Paul,
My patch is like an example, you do not need keep the
codes that I have wrote. you can rewrite all of it. these files are only accessed by RCU guys, not users. and some file in /proc is very simple but easy to be read: /proc/stat, /proc/loadavg.
Thanx, Lai.
Re: [PATCH] v3 rudimentary tracing for Classic RCU
Quoted 13 lines · Lai Jiangshan
Quoted 10 lines · Paul E. McKenney
Ported to 2.6.27 to ease testing, and fixed up the formatting a bit. I remember quickly scanning through one-line-per-CPU data to find problems with
rcutree.c, but the expanded names are quite nice -- I had to brutally abbreviate to fit each CPU on a single line. And I agree that seqfile does work nicely for this.I am strongly tempted to suggest CSV format output with headers to allow the data to be pulled into gnumeric or oocalc -- this would make handling large numbers of CPUs much easier. (Quickly donning the asbestos suit with titanium pinstripes...)
Quoted 5 lines
Hi, Paul,
My patch is like an example, you do not need keep the
codes that I have wrote. you can rewrite all of it. these files are only accessed by RCU guys, not users. and some file in /proc is very simple but easy to be read:/proc/stat,/proc/loadavg.
Hello, Jiangshan,
Good point -- I do very much appreciate the seqfile tutorial!!!
Thanx, Paul
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
In reply to Paul E. McKenneyQuoted 40 lines · Paul E. McKenney
Quoted 30 lines · Andi Kleen
Quoted 7 lines · Paul E. McKenney
Thank you! Hmmm, classic RCU, worked just fine in 2.6.27-rc7 with Thomas's patch. I was doing random onlines and offlines in a loop, with about 3 seconds between each operation continuously for more than ten hours, both x86 and Power. So could you please try 2.6.27-rc7 with Thomas's patch as follows?
http://www.rdrop.com/users/paulmck/patches/2.6.27-rc7-tglx-timer-1.patch
Same effect. Hung on the first try
bash D
00000000ffff25c10 4755 4742
ffff88027b127bf80000000000000086ffff88027b127c180000000000000296ffff88027c80b330ffff8804be488b90ffff88027c80b5780000000300000296ffff88027b127c18ffffffff808cbd18ffff88002805d600ffff88027d182098Call Trace: [<ffffffff805c318d>] schedule_timeout+0x22/0xb4 [<ffffffff8020a029>] ? __switch_to+0x320/0x330 [<ffffffff8025fa65>] ? cpupri_set+0xc5/0xd8 [<ffffffff805c2fe7>] wait_for_common+0xcd/0x131 [<ffffffff8022d297>] ? default_wake_function+0x0/0xf [<ffffffff805c30d5>] wait_for_completion+0x18/0x1a [<ffffffff8024374b>] synchronize_rcu+0x35/0x3c [<ffffffff802437ca>] ? wakeme_after_rcu+0x0/0x12 [<ffffffff8022e435>] partition_sched_domains+0x9b/0x1dd [<ffffffff8022d2c3>] ? wake_up_process+0x10/0x12 [<ffffffff8022e5a5>] update_sched_domains+0x2e/0x35 [<ffffffff805c6bb2>] notifier_call_chain+0x33/0x5b [<ffffffff80248a29>] __raw_notifier_call_chain+0x9/0xb [<ffffffff80248a3a>] raw_notifier_call_chain+0xf/0x11Quoted 8 lines
[<ffffffff805c06e6>] _cpu_up+0xd3/0x10c [<ffffffff805c0776>] cpu_up+0x57/0x67 [<ffffffff805a4ab7>] store_online+0x4d/0x75 [<ffffffff803e5d0b>] sysdev_store+0x1b/0x1d [<ffffffff802cc49c>] sysfs_write_file+0xe0/0x11c [<ffffffff8028ad1d>] vfs_write+0xae/0x137 [<ffffffff8028b1c6>] sys_write+0x47/0x6f [<ffffffff8020b36b>] system_call_fastpath+0x16/0x1b
Quoted 5 lines
Thus far, as usual, I cannot reproduce, either on x86 or Power. You are running on hyperthreaded machines? If so, what happens if you disable
CONFIG_SCHED_SMTandCONFIG_SCHED_MC?You are running on a 16-CPU x86-64 box?
The attached patch (similar to one in -tip, but set up for mainline and tweaked to make stall-checking on by default) should get you a stack trace of any CPUs holding up RCU grace periods for more than about three seconds.
On the off-chance that this helps.
Thanx, Paul
---
include/linux/rcuclassic.h +9 -0
@@ -40,6 +40,10 @@#include <linux/cpumask.h> #include <linux/seqlock.h> +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR +#define RCU_SECONDS_TILL_STALL_CHECK 3 * HZ/* for rcp->jiffies_stall */ +#define RCU_SECONDS_TILL_STALL_RECHECK 30 * HZ/* for rcp->jiffies_stall */ +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ /* Global control variables for rcupdate callback mechanism. */ struct rcu_ctrlblk {
@@ -52,6 +56,11 @@ struct rcu_ctrlblk {spinlock_t lock____cacheline_internodealigned_in_smp ;cpumask_t cpumask;/* CPUs that need to switch in order */ /* for current batch to proceed. */ +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR +unsigned long gp_start;/* Time at which GP started in jiffies. */ +unsigned long jiffies_stall; +/* Time at which to check for CPU stalls. */ +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ }____cacheline_internodealigned_in_smp ;/* Is batch a before batch b ? */
kernel/rcuclassic.c +88 -0
112 lines not on this page · raw message
lib/Kconfig.debug +13 -0
@@ -597,6 +597,19 @@ config RCU_TORTURE_TEST_RUNNABLE Say N here if you want the RCU torture tests to start only after being manually enabled via /proc. +config RCU_CPU_STALL_DETECTOR + bool "Check for stalled CPUs delaying RCU grace periods" + depends on CLASSIC_RCU + default y + help + This option causes RCU to printk information on which + CPUs are delaying the current grace period, but only when + the grace period extends for excessive time periods. + + Say Y if you want RCU to perform such checks. + + Say N if you are unsure. + config KPROBES_SANITY_TEST bool "Kprobes sanity tests" depends on DEBUG_KERNEL
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
[fix up Thomas' address to not bounce]
Quoted 6 lines · Paul E. McKenney
The attached patch (similar to one in -tip, but set up for mainline and tweaked to make stall-checking on by default) should get you a stack trace of any CPUs holding up RCU grace periods for more than about three seconds.
On the off-chance that this helps.
It actually does. The stall detector makes the online echo return after three seconds, although it's not 100% clear to me why.
here's the backtrace
RCU detected CPU 14 stall (t=4295149800/5928 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #5
Call Trace: <IRQ> [<ffffffff8025d188>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025d329>] rcu_pending+0x36/0x6e [<ffffffff8023b480>] update_process_times+0x37/0x5b [<ffffffff8024be72>] tick_periodic+0x68/0x74 [<ffffffff8024be9f>] tick_handle_periodic+0x21/0x66 [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bfe6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803adb39>] ? acpi_safe_halt+0x2b/0x3e [<ffffffff803adbfa>] ? acpi_idle_enter_c1+0xae/0x102 [<ffffffff804ffdd6>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a097>] ? cpu_idle+0x7e/0x9c [<ffffffff805bef4a>] ? start_secondary+0x157/0x15c
Timer issue?
-Andi
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 22 lines · Andi Kleen
It actually does. The stall detector makes the online echo return after three seconds, although it's not 100% clear to me why.
here's the backtrace
RCU detected CPU 14 stall (t=4295149800/5928 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #5Call Trace: <IRQ> [<ffffffff8025d188>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025d329>] rcu_pending+0x36/0x6e [<ffffffff8023b480>] update_process_times+0x37/0x5b [<ffffffff8024be72>] tick_periodic+0x68/0x74 [<ffffffff8024be9f>] tick_handle_periodic+0x21/0x66 [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bfe6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803adb39>] ? acpi_safe_halt+0x2b/0x3e [<ffffffff803adbfa>] ? acpi_idle_enter_c1+0xae/0x102 [<ffffffff804ffdd6>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a097>] ? cpu_idle+0x7e/0x9c [<ffffffff805bef4a>] ? start_secondary+0x157/0x15c
Quoted 1 line
Timer issue?
Hmm, this is periodic mode so rather unlikely, but who knows. Does this happen with nohz and/or highres as well ?
Thanks,
tglx
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
Quoted 23 lines · Thomas Gleixner
Quoted 22 lines · Andi Kleen
It actually does. The stall detector makes the online echo return after three seconds, although it's not 100% clear to me why.
here's the backtrace
RCU detected CPU 14 stall (t=4295149800/5928 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #5Call Trace: <IRQ> [<ffffffff8025d188>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025d329>] rcu_pending+0x36/0x6e [<ffffffff8023b480>] update_process_times+0x37/0x5b [<ffffffff8024be72>] tick_periodic+0x68/0x74 [<ffffffff8024be9f>] tick_handle_periodic+0x21/0x66 [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bfe6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803adb39>] ? acpi_safe_halt+0x2b/0x3e [<ffffffff803adbfa>] ? acpi_idle_enter_c1+0xae/0x102 [<ffffffff804ffdd6>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a097>] ? cpu_idle+0x7e/0x9c [<ffffffff805bef4a>] ? start_secondary+0x157/0x15c
Quoted 4 lines
Quoted 1 line
Timer issue?
Hmm, this is periodic mode so rather unlikely, but who knows. Does this happen with nohz and/or highres as well ?
With nohz/highres enabled it takes much longer to trigger. Normally it happened near always on the first try, now I had to let a loop run for several minutes to trigger it.
But the strange thing is that the stall detector doesn't detect the hotplugged CPUs stalling now, but other unrelated ones. I only hotplug 14/15, but it reports 3 and 4. In periodic mode the correct CPUs were reported.
-Andi
Here are the backtraces
Switched to high resolution mode on CPU 14 CPU 15 is now offline
RCU detected CPU 3 stall (t=4294999688/3809 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025f615>] rcu_pending+0x36/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803b0254>] ? acpi_idle_enter_bm+0x2a2/0x312 [<ffffffff803b024a>] ? acpi_idle_enter_bm+0x298/0x312 [<ffffffff805020c2>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a0a1>] ? cpu_idle+0x88/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c
RCU detected CPU 3 stall (t=4295007688/1250 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025f615>] rcu_pending+0x36/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803b0254>] ? acpi_idle_enter_bm+0x2a2/0x312 [<ffffffff803b024a>] ? acpi_idle_enter_bm+0x298/0x312 [<ffffffff805020c2>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a0a1>] ? cpu_idle+0x88/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c
RCU detected CPU 3 stall (t=4295012121/2548 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025f640>] rcu_pending+0x61/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803b0254>] ? acpi_idle_enter_bm+0x2a2/0x312 [<ffffffff803b024a>] ? acpi_idle_enter_bm+0x298/0x312 [<ffffffff805020c2>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a0a1>] ? cpu_idle+0x88/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c
RCU detected CPU 2 stall (t=4295014976/874 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> <3>RCU detected CPU 3 stall (t=4295014976/874 jiffies) [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025f615>] rcu_pending+0x36/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff8024e1b0>] ? tick_nohz_restart_sched_tick+0x15e/0x165 [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025f615>] rcu_pending+0x36/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020a0bd>] ? cpu_idle+0xa4/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70
<EOI> [<ffffffff803b0254>] ? acpi_idle_enter_bm+0x2a2/0x312 [<ffffffff803b024a>] ? acpi_idle_enter_bm+0x298/0x312 [<ffffffff805020c2>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a0a1>] ? cpu_idle+0x88/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c
RCU detected CPU 4 stall (t=4295019871/4894 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025f615>] rcu_pending+0x36/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96
RCU detected CPU 6 stall (t=4295019871/4894 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #6
Call Trace: <IRQ> [<ffffffff8025f474>] __rcu_pending+0x6e/0x1d9 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803b0254>] ? acpi_idle_enter_bm+0x2a2/0x312 [<ffffffff8025f615>] rcu_pending+0x36/0x6e [<ffffffff8023bc5d>] update_process_times+0x37/0x5b [<ffffffff8024de88>] tick_sched_timer+0x81/0xb5 [<ffffffff80247538>] __run_hrtimer+0x56/0x96 [<ffffffff80248002>] hrtimer_interrupt+0xe6/0x14d [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bff6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff8024e1b0>] ? tick_nohz_restart_sched_tick+0x15e/0x165 [<ffffffff803b024a>] ? acpi_idle_enter_bm+0x298/0x312 [<ffffffff805020c2>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a0a1>] ? cpu_idle+0x88/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c
[<ffffffff8020a0bd>] ? cpu_idle+0xa4/0xae [<ffffffff805c137a>] ? start_secondary+0x157/0x15c
Signature · 1 line
[email protected]
Re: RCU hang on cpu re-hotplug with 2.6.27rc8
In reply to Andi KleenQuoted 8 lines · Andi Kleen
[fix up Thomas' address to not bounce]
Quoted 5 lines · Paul E. McKenney
The attached patch (similar to one in -tip, but set up for mainline and tweaked to make stall-checking on by default) should get you a stack trace of any CPUs holding up RCU grace periods for more than about three seconds.
Quoted 4 lines
Quoted 1 line
On the off-chance that this helps.
It actually does. The stall detector makes the online echo return after three seconds, although it's not 100% clear to me why.
Interesting. This behavior would be consistent with the CPU entering dyntick-idle mode without RCU's being aware of this. Except that your earlier .config file says "# CONFIG_NO_HZ is not set". And that would mean that the CPU really should be invoking RCU's state machine every scheduling tick.
I confess confusion.
Thanx, Paul
Quoted 23 lines
here's the backtrace
RCU detected CPU 14 stall (t=4295149800/5928 jiffies)
Pid: 0, comm: swapper Not tainted 2.6.27-rc9 #5Call Trace: <IRQ> [<ffffffff8025d188>] __rcu_pending+0x6e/0x1d9 [<ffffffff8025d329>] rcu_pending+0x36/0x6e [<ffffffff8023b480>] update_process_times+0x37/0x5b [<ffffffff8024be72>] tick_periodic+0x68/0x74 [<ffffffff8024be9f>] tick_handle_periodic+0x21/0x66 [<ffffffff8021bcd2>] smp_apic_timer_interrupt+0x8a/0xa8 [<ffffffff8020bfe6>] apic_timer_interrupt+0x66/0x70 <EOI> [<ffffffff803adb39>] ? acpi_safe_halt+0x2b/0x3e [<ffffffff803adbfa>] ? acpi_idle_enter_c1+0xae/0x102 [<ffffffff804ffdd6>] ? cpuidle_idle_call+0x70/0xa2 [<ffffffff8020a097>] ? cpu_idle+0x7e/0x9c [<ffffffff805bef4a>] ? start_secondary+0x157/0x15cTimer issue?
-Andi