我试图跟踪一段代码的流程,只是为了了解任务进入 D/S/R 状态(不可中断/可中断/运行)的点。我确实理解每个状态的含义,但是进行练习显示出令人困惑的结果,直到现在我才弄清楚原因。
我正在运行的代码片段:
void foo() {
pthread_setname_np(pthread_self(), "lock_func/1");
while(quit == false)
{
for(int64_t idx=0; idx<10000000;idx++)
(void)idx;
flag = true;
cv1.notify_all();
}
}
void bar() {
pthread_setname_np(pthread_self(), "lock_func/2");
std::mutex mutex1;
std::unique_lock<std::mutex> lock(mutex1);
while(!flag)
cv1.wait(lock);
flag = false;
}
int main(int argc, char *argv[]) {
...
std::thread t1 = std::thread(foo);
std::thread t2 = std::thread(bar);
...
if (mlockall( MCL_CURRENT | MCL_FUTURE ) < 0) {
perror("mlockall")
}
....
}
设置标志时我故意不使用互斥锁,因为我不希望 foo 线程被阻塞。所以我不在乎 bar 是否错过了一些唤醒,无论如何它都会由于循环而不时被唤醒富。这里的目标只是查看以下状态富和酒吧任务,现在更关注酒吧。如果我在 ftrace 中跟踪 sched_switch 事件,我会得到以下信息:
<idle>-0 [007] d... 335998: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [007] d... 335999: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
<idle>-0 [007] d... 336000: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [007] d... 336001: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
<idle>-0 [007] d... 336002: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [007] d... 336003: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
<idle>-0 [007] d... 336004: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [007] d... 336005: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
<idle>-0 [007] d... 336006: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [007] d... 336007: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
<idle>-0 [007] d... 336008: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [007] d... 336009: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
<idle>-0 [000] d... 336010: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
lock_func/1-30296 [000] d... 336011: sched_switch: prev_comm=lock_func/1 prev_pid=30296 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
<idle>-0 [000] d... 336012: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=S ==> next_comm=lock_func/1 next_pid=30296 next_prio=120
观察我的 lock_func1 (bar) 的 prev_state 始终如何D(不间断)。查看代码,上下文切换只能在条件变量 sleep 时发生,或者当时间片完成时(在 CFS 调度程序中运行)
cat /proc/30295/task/30296/wchan
futex_wait_queue_me
根据文档,这是一个可中断的函数。多次检查 proc 中的任务状态始终显示S:
cat /proc/30295/task/30296/stat
30295 (lock_func/1) S ...
所以统计显示S-可中断状态,futex_wait_queue_me是可中断的,但是 ftrace 总是在上下文切换时显示上一个状态=D。运行此代码并使用 ftrace 记录几秒钟仅显示上一个状态=D对于我的lock_func/1(条)。我从来没有得到过S-中断。
有人可以解释为什么吗?调度程序是否在两者之间进行一些状态更改?
谢谢。