nmi 内核在紧密循环中调用
nmi kernel calls in a tight loop
我有一个测试程序
void task()
{
long sum=0;
while(true) {
for(int i=0; i<100000;++i)
for(int j=0; j < 10000; ++j)
sum += j
}
}
int main()
{
boost::thread t(task);
t.join();
return true;
}
并且我使用 perf record -t -e intel_pt// 来分析线程。我看到很多对 nmi 的调用,比如每隔几毫秒调用 2(?)。无论如何要摆脱这种类型的中断? Centos 7,内核 3.10.0,kernel.watchdog = 0.
根据@Zulan 的评论进行编辑:gcc 版本:4.8.5。
编译行:g++ -I//include/ -L//lib -lboost_system -lboost_thread test.cpp
处理器 Intel Platinum 8xxx/Gold 6xxx 系列。
性能脚本输出片段网:
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ac7f5 nmi ([kernel.kallsyms]) => ffffffff816ad500 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad54f do_nmi ([kernel.kallsyms]) => ffffffff816ad5f3 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad5fa do_nmi ([kernel.kallsyms]) => ffffffff8103dc10 is_debug_stack ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff8103dc62 is_debug_stack ([kernel.kallsyms]) => ffffffff816ad5ff do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad60e do_nmi ([kernel.kallsyms]) => ffffffff816ad558 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad573 do_nmi ([kernel.kallsyms]) => ffffffff8113a3f0 rcu_nmi_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff8113a41e rcu_nmi_enter ([kernel.kallsyms]) => ffffffff810ba170 __smp_mb__before_atomic ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff810ba17a __smp_mb__before_atomic ([kernel.kallsyms]) => ffffffff8113a423 rcu_nmi_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff8113a427 rcu_nmi_enter ([kernel.kallsyms]) => ffffffff810ba180 __smp_mb__after_atomic ([kernel.kallsyms])
...
a.out 25192 [009] 3976.829807: 1 branches: ffffffff8113a4aa rcu_nmi_exit ([kernel.kallsyms]) => ffffffff8113a48a rcu_nmi_exit ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff8113a48c rcu_nmi_exit ([kernel.kallsyms]) => ffffffff816ad592 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff816ad5ed do_nmi ([kernel.kallsyms]) => ffffffff816ad760 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff816ad76e do_nmi ([kernel.kallsyms]) => ffffffff816ac7fa nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff816ac804 nmi ([kernel.kallsyms]) => ffffffff816ac23c restore_args ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
另一个:
a.out 25192 [009] 3976.829808: 1 branches: ffffffff816b6718 irq_work_interrupt ([kernel.kallsyms]) => ffffffff8102f620 smp_irq_work_interrupt ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff8102f629 smp_irq_work_interrupt ([kernel.kallsyms]) => ffffffff81090d20 irq_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff81090d29 irq_enter ([kernel.kallsyms]) => ffffffff8113a360 rcu_irq_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff8113a3a0 rcu_irq_enter ([kernel.kallsyms]) => ffffffff8113a3b8 rcu_irq_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff8113a3c0 rcu_irq_enter ([kernel.kallsyms]) => ffffffff81137e10 rcu_eqs_exit_common.isra.31 ([kernel.kallsyms])
...
a.out 25192 [009] 3976.829809: 1 branches: ffffffff8113a27d rcu_irq_exit ([kernel.kallsyms]) => ffffffff8113a260 rcu_irq_exit ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff8113a26e rcu_irq_exit ([kernel.kallsyms]) => ffffffff81090e4e irq_exit ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff81090e50 irq_exit ([kernel.kallsyms]) => ffffffff8102f653 smp_irq_work_interrupt ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff8102f654 smp_irq_work_interrupt ([kernel.kallsyms]) => ffffffff816b671d irq_work_interrupt ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816b671d irq_work_interrupt ([kernel.kallsyms]) => ffffffff816ac1ed ret_from_intr ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816ac234 retint_swapgs ([kernel.kallsyms]) => ffffffff816ac23c restore_args ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
grep'g for irq_return() 从 perf 脚本输出显示每 20ms 3 irq。
a.out 25192 [009] 3976.809174: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.809178: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.829808: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.850317: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.850393: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.850395: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.870945: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.870984: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.870985: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.891571: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.891609: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.891611: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
在 grub、isolcpus 中,nohz_full、rcu_nocbs 设置在特定的 cpus 上,并且 nmi_watchdog=0。使用 taskset -c a.out.
测试程序 运行
首先,如果你想跟踪内核,你会在跟踪中得到很多内核函数调用,包括但不限于NMI相关的。
如果您想像上面发布的那样跟踪您的用户 space 程序,请使用
perf record -t -e intel_pt//u ...
最好参考文档https://elixir.bootlin.com/linux/latest/source/tools/perf/Documentation/intel-pt.txt
我有一个测试程序
void task()
{
long sum=0;
while(true) {
for(int i=0; i<100000;++i)
for(int j=0; j < 10000; ++j)
sum += j
}
}
int main()
{
boost::thread t(task);
t.join();
return true;
}
并且我使用 perf record -t -e intel_pt// 来分析线程。我看到很多对 nmi 的调用,比如每隔几毫秒调用 2(?)。无论如何要摆脱这种类型的中断? Centos 7,内核 3.10.0,kernel.watchdog = 0.
根据@Zulan 的评论进行编辑:gcc 版本:4.8.5。
编译行:g++ -I//include/ -L//lib -lboost_system -lboost_thread test.cpp
处理器 Intel Platinum 8xxx/Gold 6xxx 系列。
性能脚本输出片段网:
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ac7f5 nmi ([kernel.kallsyms]) => ffffffff816ad500 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad54f do_nmi ([kernel.kallsyms]) => ffffffff816ad5f3 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad5fa do_nmi ([kernel.kallsyms]) => ffffffff8103dc10 is_debug_stack ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff8103dc62 is_debug_stack ([kernel.kallsyms]) => ffffffff816ad5ff do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad60e do_nmi ([kernel.kallsyms]) => ffffffff816ad558 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff816ad573 do_nmi ([kernel.kallsyms]) => ffffffff8113a3f0 rcu_nmi_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff8113a41e rcu_nmi_enter ([kernel.kallsyms]) => ffffffff810ba170 __smp_mb__before_atomic ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff810ba17a __smp_mb__before_atomic ([kernel.kallsyms]) => ffffffff8113a423 rcu_nmi_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829805: 1 branches: ffffffff8113a427 rcu_nmi_enter ([kernel.kallsyms]) => ffffffff810ba180 __smp_mb__after_atomic ([kernel.kallsyms])
...
a.out 25192 [009] 3976.829807: 1 branches: ffffffff8113a4aa rcu_nmi_exit ([kernel.kallsyms]) => ffffffff8113a48a rcu_nmi_exit ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff8113a48c rcu_nmi_exit ([kernel.kallsyms]) => ffffffff816ad592 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff816ad5ed do_nmi ([kernel.kallsyms]) => ffffffff816ad760 do_nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff816ad76e do_nmi ([kernel.kallsyms]) => ffffffff816ac7fa nmi ([kernel.kallsyms])
a.out 25192 [009] 3976.829807: 1 branches: ffffffff816ac804 nmi ([kernel.kallsyms]) => ffffffff816ac23c restore_args ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
另一个:
a.out 25192 [009] 3976.829808: 1 branches: ffffffff816b6718 irq_work_interrupt ([kernel.kallsyms]) => ffffffff8102f620 smp_irq_work_interrupt ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff8102f629 smp_irq_work_interrupt ([kernel.kallsyms]) => ffffffff81090d20 irq_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff81090d29 irq_enter ([kernel.kallsyms]) => ffffffff8113a360 rcu_irq_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff8113a3a0 rcu_irq_enter ([kernel.kallsyms]) => ffffffff8113a3b8 rcu_irq_enter ([kernel.kallsyms])
a.out 25192 [009] 3976.829808: 1 branches: ffffffff8113a3c0 rcu_irq_enter ([kernel.kallsyms]) => ffffffff81137e10 rcu_eqs_exit_common.isra.31 ([kernel.kallsyms])
...
a.out 25192 [009] 3976.829809: 1 branches: ffffffff8113a27d rcu_irq_exit ([kernel.kallsyms]) => ffffffff8113a260 rcu_irq_exit ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff8113a26e rcu_irq_exit ([kernel.kallsyms]) => ffffffff81090e4e irq_exit ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff81090e50 irq_exit ([kernel.kallsyms]) => ffffffff8102f653 smp_irq_work_interrupt ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff8102f654 smp_irq_work_interrupt ([kernel.kallsyms]) => ffffffff816b671d irq_work_interrupt ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816b671d irq_work_interrupt ([kernel.kallsyms]) => ffffffff816ac1ed ret_from_intr ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816ac234 retint_swapgs ([kernel.kallsyms]) => ffffffff816ac23c restore_args ([kernel.kallsyms])
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
grep'g for irq_return() 从 perf 脚本输出显示每 20ms 3 irq。
a.out 25192 [009] 3976.809174: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.809178: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.829808: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.829809: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.850317: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.850393: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.850395: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.870945: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 405764 task (a.out)
a.out 25192 [009] 3976.870984: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.870985: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.891571: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.891609: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
a.out 25192 [009] 3976.891611: 1 branches: ffffffff816ac26c irq_return ([kernel.kallsyms]) => 40576f task (a.out)
在 grub、isolcpus 中,nohz_full、rcu_nocbs 设置在特定的 cpus 上,并且 nmi_watchdog=0。使用 taskset -c a.out.
测试程序 运行首先,如果你想跟踪内核,你会在跟踪中得到很多内核函数调用,包括但不限于NMI相关的。
如果您想像上面发布的那样跟踪您的用户 space 程序,请使用
perf record -t -e intel_pt//u ...
最好参考文档https://elixir.bootlin.com/linux/latest/source/tools/perf/Documentation/intel-pt.txt