Softlockup分析
来源:互联网 发布:瓦拉内fifa数据 编辑:程序博客网 时间:2024/04/30 12:53
在Linux环境机器上面进行测试的时候,经常会报softlockup的问题,而导致系统panic。Softlockup是内核中进行死锁检查的一种机制,在2.6.X内核中是在softlockup.c的文件中实现,在新的3.X内核中是在watchdog.c文件中实现的。
Softlockup是用来检测内核长时间不发生调度的情况,它的工作原理是在内核中启动一个优先级为MAX_RT_PRIO – 1的FIFO进程,在此进程里面会刷新时间戳。如果此时间戳超过设定的时间阈值没有更新,则会报softlockup错误。
下面结合代码来分析softlockup的实现。系统启动会调用
lockup_detector_init函数
àwatchdog_enable_all_cpus函数
watchdog_enable_all_cpus函数会在每个cpu上都创建一个watchdog_threads内核线程。
static struct smp_hotplug_threadwatchdog_threads ={
.store = &softlockup_watchdog,
.thread_should_run = watchdog_should_run,
.thread_fn = watchdog,
.thread_comm = "watchdog/%u",
.setup = watchdog_enable,
.cleanup = watchdog_cleanup,
.park = watchdog_disable,
.unpark = watchdog_enable,
};
此内核线程的名字为watchdog/%u,对应与每个CPU就是watchdog0、watchdog1等,线程函数为watchdog。在创建线程的时候会调用watchdog_enable函数:
static void watchdog_enable(unsigned intcpu)
{
struct hrtimer*hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
hrtimer_init(hrtimer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
hrtimer->function = watchdog_timer_fn;
hrtimer_start(hrtimer,ns_to_ktime(sample_period), HRTIMER_MODE_REL_PINNED);
watchdog_set_prio(SCHED_FIFO,MAX_RT_PRIO- 1);
__touch_watchdog();
}
首先获取当前CPU的per cpu变量watchdog_hrtimer,启动一个hrtimer,此hrtimer的处理函数为watchdog_timer_fn,并在随后启动此hrtimer。
然后调用函数设置进程的调度策略和优先级,此内核线程为实时的FIFO线程,优先级为MAX_RT_PRIO-1,优先级最高了,这样就能够在进程被唤醒的时候能够强制其它优先级低的线程\进程了。
最后在__touch_watchdog函数中刷新时间戳PER CPU变量watchdog_touch_ts。
watchdog/%u的线程函数watchdog主要工作就是调用__touch_watchdog函数来刷新时间戳。此线程函数是在watchdog_timer_fn中唤醒的。
下面分析下hrtimer的处理函数watchdog_timer_fn:
static enum hrtimer_restartwatchdog_timer_fn(struct hrtimer *hrtimer)
{
unsigned long touch_ts =__this_cpu_read(watchdog_touch_ts);
int softlockup_all_cpu_backtrace =sysctl_softlockup_all_cpu_backtrace;
wake_up_process(__this_cpu_read(softlockup_watchdog));
hrtimer_forward_now(hrtimer,ns_to_ktime(sample_period));
if (touch_ts==0) {
if (unlikely(__this_cpu_read(softlockup_touch_sync))) {
__this_cpu_write(softlockup_touch_sync, false);
sched_clock_tick();
}
__touch_watchdog();
return HRTIMER_RESTART;
}
下面分析下hrtimer的处理函数watchdog_timer_fn:
首先读取per CPU变量watchdog_touch_ts赋值给touch_ts,表示上一次刷新的时间戳。sysctl_softlockup_all_cpu_backtrace变量由用户通过sysctl命令改写或者接口/proc/sys/kernel/softlockup_all_cpu_backtrace来设置。
然后调用wake_up_process函数唤醒此cpu上的watchdog线程,如果watchdog线程被唤醒就会去刷新时间戳。如果系统关了抢占,此watchdog线程不会被唤醒,这样时间戳就不会更新。
hrtimer_forward_now函数会将此hrtimer的下次到期时间设置为从现在开始的sample_period纳秒之后。
如果touch_ts为0,表示第一次hrtimer到期,直接刷新时间戳,并重新启动此定时器。
duration =is_softlockup(touch_ts);
if (unlikely(duration)) {
if (__this_cpu_read(soft_watchdog_warn)==true)
return HRTIMER_RESTART;
if (softlockup_all_cpu_backtrace) {
if (test_and_set_bit(0,&soft_lockup_nmi_warn)) {
__this_cpu_write(soft_watchdog_warn, true);
return HRTIMER_RESTART;
}
}
is_softlockup函数会判断当前时间与上次刷新时间touch_ts的差值,如果差值大于设定的阈值,就返回差值即变量duration,否则返回0。
如果duration不为0,则表示内核有超过设定的阈值时间没有发生调度。
printk(KERN_EMERG"BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", smp_processor_id(),duration,
current->comm,task_pid_nr(current));
print_modules();
print_irqtrace_events(current);
if (regs)
show_regs(regs);
else
dump_stack();
if (softlockup_all_cpu_backtrace) {
trigger_allbutself_cpu_backtrace();
clear_bit(0,&soft_lockup_nmi_warn);
smp_mb__after_atomic();
}
if (softlockup_panic)
panic("softlockup: hung tasks");
__this_cpu_write(soft_watchdog_warn, true);
} else
__this_cpu_write(soft_watchdog_warn, false);
上面的代码打印出softlockup信息,包括模块信息、寄存器信息、堆栈信息等。如果变量softlockup_all_cpu_backtrace有设置,还会给其它的CPU发生IPI中断,触发softlockup信息。
变量softlockup_panic可以通过sysctl和proc接口设置,在使能的情况下,系统会panic。
- Softlockup分析
- softlockup检测(watchdog)原理
- Linux死锁调试之softlockup
- softlock---Kernel panic - not syncing: softlockup: hung tasks
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 分析
- 大家帮忙分析分析!
- FFMpeg分析详细分析
- FFMpeg分析详细分析
- core 分析的分析
- 写给自己,分析分析
- OpenGL ES开发绘制2D图形
- PATbasic1001害死人不偿命的(3n+1)猜想
- Android Service完全解析,关于服务你所需知道的一切
- 双重指针做参数传递
- linux系统上FTP使用
- Softlockup分析
- mysql查询注释信息
- python signal
- 判断字符串中是否有重复字母
- 深入理解React(二) —— 数据流和事件原理
- 超人学院大数据8期
- red5连接MySQL时找不到JDBC驱动
- Python实战小程序——简单的排序
- error: cannot run .git/hooks/pre-commit: No such file or directory解决方法