免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1800 | 回复: 2
打印 上一主题 下一主题

[内核同步] 遇到一个FreeBSD turnstile的一个问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-23 13:29 |只看该作者 |倒序浏览
在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?

论坛徽章:
0
2 [报告]
发表于 2012-07-23 22:11 |只看该作者
本帖最后由 panda-man 于 2012-07-23 22:14 编辑

一个人都没有, 自己顶一下。
在manpage里找到了下面这一段,按这段文字的描述mutex确实是不能睡眠的。但是不知道这只是一种约定, 还是在实现上的原因, 如果让sleep会导致死锁???

The following table shows what you can and can not do while holding one
     of the synchronization primitives discussed:

           You have: You want: spin mtx  mutex         sx         rwlock  rmlock sleep
           spin mtx               ok-1         no         no         no         no        no-3
           mutex               ok         ok-1         no         ok         ok        no-3
           sx                       ok         ok         ok-2         ok         ok        ok-4
           rwlock               ok         ok         no         ok-2         ok        no-3
           rmlock               ok         ok         ok-5         ok         ok-2        ok-5

     *1 Recursion is defined per lock.        Lock order is important.

     *2 Readers can recurse though writers can not.  Lock order is important.

     *3 There are calls that atomically release this primitive when going to
     sleep and reacquire it on wakeup (e.g.  mtx_sleep(), rw_sleep() and
     msleep_spin() ).

     *4 Though one can sleep holding an sx lock, one can also use sx_sleep()
     which will atomically release this primitive when going to sleep and
     reacquire it on wakeup.

     *5 Read-mostly locks can be initialized to support sleeping while holding
     a write lock.  See rmlock(9) for details.

论坛徽章:
0
3 [报告]
发表于 2012-07-24 17:09 |只看该作者
本帖最后由 panda-man 于 2012-07-24 17:10 编辑

在freebsd的邮件列表里发现这么一段
you can't do an M_WAITOK malloc while holding a mutex.  
Basically, sleeping actually means calling "*sleep() (such as mtx_sleep()) or
cv_*wait*()".  Blocking on a mutex is not sleeping, it's "blocking".  Some
locks (such as sx(9)) do "sleep" when you contest them.  In the scheduler,
sleeping and blocking are actually quite different (blocking uses turnstiles
that handle priority inversions via priority propagation, sleeping uses sleep
queues which do not do any of that).  The underyling idea is that mutexes
should be held for "short" periods of time, and that any sleeps are
potentially unbounded.  Holding a mutex while sleeping could result in a
mutex being held for a long time

基本上就是拿着mutex是不能睡眠的, 虽然在争用不到的一个mutex的时候当前线程会主动放弃CPU, 但是这种放弃和sleep还是有区别的。mutex被设计为一种只能短暂holding的一种锁。 这个问题就这样吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP