Chinaunix首页 | 论坛 | 博客
  • 博客访问: 178221
  • 博文数量: 60
  • 博客积分: 677
  • 博客等级: 上士
  • 技术积分: 667
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-30 15:49
文章分类

全部博文(60)

文章存档

2015年(1)

2013年(6)

2012年(16)

2011年(9)

2010年(28)

我的朋友

分类: BSD

2012-08-24 18:18:21


点击(此处)折叠或打开

  1. /*
  2. * Walks the chain of turnstiles and their owners to propagate the priority
  3. * of the thread being blocked to all the threads holding locks that have to
  4. * release their locks before this thread can run again.
  5. */
  6. /*
  7.  * 这样做的目的就是防止优先级翻转,但我不明白为什么涉及多个turnstile,按理一个锁只涉及一个turnstile,参数的线程是被block的那个线程
  8.  */
  9. static void
  10. propagate_priority(struct thread *td)
  11. {
  12. struct turnstile *ts;
  13. int pri;
  14. THREAD_LOCK_ASSERT(td, MA_OWNED);
  15. pri = td->td_priority; 
  16. ts = td->td_blocked;
  17. THREAD_LOCKPTR_ASSERT(td, &ts->ts_lock);
  18. /*
  19. * Grab a recursive lock on this turnstile chain so it stays locked
  20. * for the whole operation. The caller expects us to return with
  21. * the original lock held. We only ever lock down the chain so
  22. * the lock order is constant.
  23. */
  24. mtx_lock_spin(&ts->ts_lock);
  25. for (;;) {
  26. td = ts->ts_owner; /*拥有锁的那个thread*/
  27. if (td == NULL) {
  28. /*
  29. * This might be a read lock with no owner. There's
  30. * not much we can do, so just bail.
  31. */
  32. mtx_unlock_spin(&ts->ts_lock);
  33. return;
  34. }
  35. thread_lock_flags(td, MTX_DUPOK);
  36. mtx_unlock_spin(&ts->ts_lock);
  37. MPASS(td->td_proc != NULL);
  38. MPASS(td->td_proc->p_magic == P_MAGIC);
  39. /*
  40. * If the thread is asleep, then we are probably about
  41. * to deadlock. To make debugging this easier, just
  42. * panic and tell the user which thread misbehaved so
  43. * they can hopefully get a stack trace from the truly
  44. * misbehaving thread.
  45. */
  46. if (TD_IS_SLEEPING(td)) {/*如果拥有锁的线程在sleep,则直接panic,所以获得mutex锁后不调用msleep或者tsleep这类的函数否则新线程起来等这个锁的时候会挂*/
  47. printf(
  48. "Sleeping thread (tid %d, pid %d) owns a non-sleepable lock\n",
  49. td->td_tid, td->td_proc->p_pid);
  50. #ifdef DDB
  51. db_trace_thread(td, -1);
  52. #endif
  53. panic("sleeping thread");
  54. }
  55. /*
  56. * If this thread already has higher priority than the
  57. * thread that is being blocked, we are finished.
  58. */
  59. /*看这意思是优先级数值越小,则优先级越高,如果执行的优先级比较高,则没事*/
  60. if (td->td_priority <= pri) {
  61. thread_unlock(td);
  62. return;
  63. }
  64. /*
  65. * Bump this thread's priority.
  66. */
  67. sched_lend_prio(td, pri);/*调整有锁线程的优先级,让他快点跑完*/
  68. /*
  69. * If lock holder is actually running or on the run queue
  70. * then we are done.
  71. */
  72. if (TD_IS_RUNNING(td) || TD_ON_RUNQ(td)) {
  73. MPASS(td->td_blocked == NULL);
  74. thread_unlock(td);
  75. return;
  76. }
  77. #ifndef SMP
  78. /*
  79. * For UP, we check to see if td is curthread (this shouldn't
  80. * ever happen however as it would mean we are in a deadlock.)
  81. */
  82. KASSERT(td != curthread, ("Deadlock detected"));
  83. #endif
  84. /*
  85. * If we aren't blocked on a lock, we should be.
  86. */
  87. KASSERT(TD_ON_LOCK(td), (
  88. "thread %d(%s):%d holds %s but isn't blocked on a lock\n",
  89. td->td_tid, td->td_name, td->td_state,
  90. ts->ts_lockobj->lo_name));
  91. /*
  92. * Pick up the lock that td is blocked on.
  93. */
  94. ts = td->td_blocked;
  95. MPASS(ts != NULL);
  96. THREAD_LOCKPTR_ASSERT(td, &ts->ts_lock);
  97. /* Resort td on the list if needed. */
  98. if (!turnstile_adjust_thread(ts, td)) {
  99. mtx_unlock_spin(&ts->ts_lock);
  100. return;
  101. }
  102. /* The thread lock is released as ts lock above. */
  103. }
  104. }

阅读(873) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~