- /*
- * Block the current thread on the turnstile assicated with 'lock'. This
- * function will context switch and not return until this thread has been
- * woken back up. This function must be called with the appropriate
- * turnstile chain locked and will return with it unlocked.
- */
- void
- turnstile_wait(struct turnstile *ts, struct thread *owner, int queue)
- {
- struct turnstile_chain *tc;
- struct thread *td, *td1;
- struct lock_object *lock;
- td = curthread;
- /*一些断言,当前线程是不是拥有turnstile的锁,输入是否合理*/
- mtx_assert(&ts->ts_lock, MA_OWNED);
- if (owner)
- MPASS(owner->td_proc->p_magic == P_MAGIC);
- MPASS(queue == TS_SHARED_QUEUE || queue == TS_EXCLUSIVE_QUEUE);
- /*
- * If the lock does not already have a turnstile, use this thread's
- * turnstile. Otherwise insert the current thread into the
- * turnstile already in use by this lock.
- * 没有turnstile则用自己的新建一个(每个kernel线程是绑定一个turnstile的)
- * 有就用现成的,把自己放到turnstile即可。
- */
- tc = TC_LOOKUP(ts->ts_lockobj); /*根据锁找turnstile chain*/
- if (ts == td->td_turnstile) {/*这个这个turnstile就是自己线程的turnstile,看
- turnstile_trywait函数 */
- mtx_assert(&tc->tc_lock, MA_OWNED);
- #ifdef TURNSTILE_PROFILING
- tc->tc_depth++;
- if (tc->tc_depth > tc->tc_max_depth) {
- tc->tc_max_depth = tc->tc_depth;
- if (tc->tc_max_depth > turnstile_max_depth)
- turnstile_max_depth = tc->tc_max_depth;
- }
- #endif
- tc = TC_LOOKUP(ts->ts_lockobj); /*又来??*/
- LIST_INSERT_HEAD(&tc->tc_turnstiles, ts, ts_hash);/*加入turnstile chain*/
- KASSERT(TAILQ_EMPTY(&ts->ts_pending),
- ("thread's turnstile has pending threads"));
- KASSERT(TAILQ_EMPTY(&ts->ts_blocked[TS_EXCLUSIVE_QUEUE]),
- ("thread's turnstile has exclusive waiters"));
- KASSERT(TAILQ_EMPTY(&ts->ts_blocked[TS_SHARED_QUEUE]),
- ("thread's turnstile has shared waiters"));
- KASSERT(LIST_EMPTY(&ts->ts_free),
- ("thread's turnstile has a non-empty free list"));
- MPASS(ts->ts_lockobj != NULL);
- /*加入到本turnstile的等待队列,居然turnstile的owner也是当前锁的owner*/
- mtx_lock_spin(&td_contested_lock);
- TAILQ_INSERT_TAIL(&ts->ts_blocked[queue], td, td_lockq);
- turnstile_setowner(ts, owner);
- mtx_unlock_spin(&td_contested_lock);
- } else {
- /*turnstile里的等待该锁的所有线程是按优先级排序的*/
- TAILQ_FOREACH(td1, &ts->ts_blocked[queue], td_lockq)
- if (td1->td_priority > td->td_priority)
- break;
- mtx_lock_spin(&td_contested_lock);
- if (td1 != NULL)
- TAILQ_INSERT_BEFORE(td1, td, td_lockq);
- else
- TAILQ_INSERT_TAIL(&ts->ts_blocked[queue], td, td_lockq);
- MPASS(owner == ts->ts_owner);
- mtx_unlock_spin(&td_contested_lock);
- MPASS(td->td_turnstile != NULL);
- LIST_INSERT_HEAD(&ts->ts_free, td->td_turnstile, ts_hash);/*我不知道ts_free干啥的*/
- }
- thread_lock(td);
- thread_lock_set(td, &ts->ts_lock);
- td->td_turnstile = NULL;/*看来一个thread的turnstile要么就用给lock对象,要么就放到ts_free里*/
- /* Save who we are blocked on and switch. 记录当前线程的状态,卡住了?卡哪里了?*/
- lock = ts->ts_lockobj;
- td->td_tsqueue = queue;
- td->td_blocked = ts;
- td->td_lockname = lock->lo_name;
- td->td_blktick = ticks;
- TD_SET_LOCK(td);
- mtx_unlock_spin(&tc->tc_lock);
- propagate_priority(td);/*很重要的一步,优先级传播*/
- if (LOCK_LOG_TEST(lock, 0))
- CTR4(KTR_LOCK, "%s: td %d blocked on [%p] %s", __func__,
- td->td_tid, lock, lock->lo_name);
- THREAD_LOCKPTR_ASSERT(td, &ts->ts_lock);
- mi_switch(SW_VOL | SWT_TURNSTILE, NULL);
- if (LOCK_LOG_TEST(lock, 0))
- CTR4(KTR_LOCK, "%s: td %d free from blocked on [%p] %s",
- __func__, td->td_tid, lock, lock->lo_name);
- thread_unlock(td);
- }
阅读(613) | 评论(0) | 转发(0) |