- 论坛徽章:
- 0
|
在FreeBSD 7.0上遇到一个kernel panic, 其中有打印一条这样的信息 ”Sleeping thread (tid 100133, pid 98686) owns a non-sleepable lock“ 。
根据堆栈内容找到发现是在一个系统调用里面需要获取一个non-spin mutex, 但是这个锁被另外一个内核线程占着,并且带着这个锁调用了tsleep跑去睡眠去了。
当前线程就要到一个等待队列上去等待锁被释放了, FreeBSD 在这里用到了一个turnstile的东东, 貌似是从solaris那里借鉴来的东西, 主要是用来解决优先级倒置的问题。里面有的个函数没有看太明白,
/*
* Walks the chain of turnstiles and their owners to propagate the priority
* of the thread being blocked to all the threads holding locks that have to
* release their locks before this thread can run again.
*/
static void
propagate_priority(struct thread *td)
{
。。。
for (; {
td = ts->ts_owner;
。。。
/*
* If the thread is asleep, then we are probably about
* to deadlock. To make debugging this easier, just
* panic and tell the user which thread misbehaved so
* they can hopefully get a stack trace from the truly
* misbehaving thread.
*/
if (TD_IS_SLEEPING(td)) {
printf(
"Sleeping thread (tid %d, pid %d) owns a non-sleepable lock\n",
td->td_tid, td->td_proc->p_pid);
#ifdef DDB
db_trace_thread(td, -1);
#endif
panic("sleeping thread" ;
}
。。。。。
。。。
}
如我上面贴出来的, 这个函数里面一个死锁检查if (TD_IS_SLEEPING(td)),也就是说当前线程等待在等待另个线程释放锁的时候, 另一个线程不能处于sleep状态, 否则按注释讲得既是发生了一个死锁。这里不明白为什么另一个线程不能sleep, 不是说只有spin-lock才不能sleep吗?难道mutex也不能sleep? |
|