调度器37—关中断/关抢占Debug-2-CONFIG_TRACE_IRQFLAGS 的作用
一、梳理
基于 msm-4.4
注: 本文主要用于求证使能 CONFIG_TRACE_IRQFLAGS 与否的区别。
若使能后会多出下面定义:
//kernel/msm-4.4/include/linux/irqflags.h #ifdef CONFIG_TRACE_IRQFLAGS extern void trace_softirqs_on(unsigned long ip); extern void trace_softirqs_off(unsigned long ip); extern void trace_hardirqs_on(void); extern void trace_hardirqs_off(void); #define trace_hardirq_context(p) ((p)->hardirq_context) #define trace_softirq_context(p) ((p)->softirq_context) #define trace_hardirqs_enabled(p) ((p)->hardirqs_enabled) #define trace_softirqs_enabled(p) ((p)->softirqs_enabled) #define trace_hardirq_enter() do { current->hardirq_context++; } while (0) #define trace_hardirq_exit() do { current->hardirq_context--; } while (0) #define lockdep_softirq_enter() do { current->softirq_context++; } while (0) #define lockdep_softirq_exit() do { current->softirq_context--; } while (0) #define INIT_TRACE_IRQFLAGS .softirqs_enabled = 1,
1. trace_softirqs_on
若不包括 trace_irqsoff.c 和 lockdep.c(它里面自己实现的) 的话,只有一处使用:
__do_softirq //softirq.c _local_bh_enable //softirq.c __local_bh_enable //softirq.c if (softirq_count() == (cnt & SOFTIRQ_MASK)) //软中断部分计数要减为0时调用 trace_softirqs_on(_RET_IP_);
软中断不可以嵌套执行。
==> 小结: 软中断部分计数要减为0时调用 trace_softirqs_on()
2. trace_softirqs_off
若不包括 trace_irqsoff.c 和 lockdep.c(它里面自己实现的) 的话,只有一处使用:
_raw_spin_lock_bh_nested //spinlock.c 若使能 CONFIG_DEBUG_LOCK_ALLOC 才调用 __do_softirq //softirq.c 传参(_RET_IP_, SOFTIRQ_OFFSET) 置位bit8表示正在执行软中断 __raw_read_lock_bh //rwlock_api_smp.h 传参 (_RET_IP_, SOFTIRQ_LOCK_OFFSET)同时置位bit9和bit0 __raw_write_lock_bh //rwlock_api_smp.h 传参(_RET_IP_, SOFTIRQ_LOCK_OFFSET) __raw_spin_lock_bh //spinlock_api_smp.h 传参(_RET_IP_, SOFTIRQ_LOCK_OFFSET) __raw_spin_trylock_bh //spinlock_api_smp.h 传参(_RET_IP_, SOFTIRQ_LOCK_OFFSET) local_bh_disable //bottom_half.h 传参 (_THIS_IP_, SOFTIRQ_DISABLE_OFFSET) __local_bh_disable_ip(ip, cnt) //softirq.c __preempt_count_add(cnt); if (softirq_count() == (cnt & SOFTIRQ_MASK)) trace_softirqs_off(ip);
==>小结: 当抢占计数部分由0变为非0的时候执行。
总结:由这两个trace可知,若是想监控关软中断临界区(包括正在执行软中断),可以使用 trace_softirqs_on()/trace_softirqs_off().
3. trace_hardirqs_on
若不包括 trace_irqsoff.c 的话,只有一处使用:
local_irq_enable() //irqflags.h do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) local_irq_restore(flags) //irqflags.h trace_hardirqs_on() safe_halt() //irqflags.h do { trace_hardirqs_on(); raw_safe_halt(); } while (0) do_debug_exception //fault.c if (interrupts_enabled(regs)) trace_hardirqs_on(); el1_irq: //entry.S 的退出 trace_hardirqs_on(); el0_irq: //entry.S 的退出 el0_irq_naked: //entry.S 的退出 bl trace_hardirqs_on
这是监控长时间关中断所需要的。
4. trace_hardirqs_off
若不包括 trace_irqsoff.c 和 lockdep.c(它里面自己实现的) 的话:
local_irq_disable() do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) local_irq_save(flags) do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) local_irq_restore(flags) trace_hardirqs_off(); secondary_start_kernel //smp.c idle进程上下文 trace_hardirqs_off() do_debug_exception //fault.c 这就要求在函数内判断中断是关闭的 if (interrupts_enabled(regs)) trace_hardirqs_off(); el1_irq: //entry.S 的入口 bl trace_hardirqs_off el0_ia: //entry.S 的入口 bl trace_hardirqs_off el0_irq: //entry.S 的入口 el0_irq_naked: //entry.S 的入口 bl trace_hardirqs_off work_resched: //entry.S 的入口 bl trace_hardirqs_off
小结: 若是想监控关中断持续时长,可以使用 trace_hardirqs_off()/trace_hardirqs_on() 这两个回调。
5. trace_hardirq_context
__do_softirq //softirq.c lockdep_softirq_start //softirq.c 下面不为0返回true trace_hardirq_context(current) print_usage_bug //lockdep.c 在打印中获取这些信息 //默认不使能 printk(trace_hardirq_context(curr))
===> 小结: 这个若使能了 lockdep 有用,否则上什么作用也没起到。
6. trace_softirq_context
print_usage_bug //lockdep.c printk(trace_softirq_context(curr))
===> 小结: 这个只有 lockdep 中使用。
7. trace_hardirqs_enabled
print_usage_bug
printk(trace_hardirqs_enabled(curr))
===> 小结: 这个只有 lockdep 中使用。
8. trace_softirqs_enabled
print_usage_bug
printk(trace_softirqs_enabled(curr))
===> 小结: 这个只有 lockdep 中使用。
9. trace_hardirq_enter
__do_softirq //softirq.c lockdep_softirq_end(in_hardirq) //softirq.c if (in_hardirq) trace_hardirq_enter(); __irq_enter() //hardirq.h 表示正在执行硬中断回调时执行 trace_hardirq_enter(); nmi_enter() //hardirq.h trace_hardirq_enter();
10. trace_hardirq_exit
__do_softirq //softirq.c irq_exit //softirq.c 表示硬中断退出 lockdep_softirq_start() //softirq.c if (trace_hardirq_context(current)) { in_hardirq = true; trace_hardirq_exit(); } __irq_exit //hardirq.h trace_hardirq_exit(); nmi_exit //hardirq.h trace_hardirq_exit()
==> 小结: trace_hardirq_enter()/trace_hardirq_exit() 可用来检查硬中断回调执行时长,它只对 current->hardirq_context 进行加加/减减操作,trace_hardirq_context() 返回 current->hardirq_context 的值。
11. lockdep_softirq_enter
__do_softirq //softirq.c lockdep_softirq_start //softirq.c lockdep_softirq_enter()
12. lockdep_softirq_exit
__do_softirq //softirq.c 临近退出时执行 lockdep_softirq_end(in_hardirq) lockdep_softirq_exit(); //current->softirq_context--; if (in_hardirq) trace_hardirq_enter(); //current->hardirq_context++;
在硬中断上下文之间划出一小块软中断上下文。
要注意使能 CONFIG_TRACE_IRQFLAGS 后与 lockdep 中的定义兼容,宏的依赖上要处理一下。
posted on 2025-07-24 21:59 Hello-World3 阅读(14) 评论(0) 收藏 举报