* Pick the highest priority thread on this turnstile and put it on the * pending list. This must be called with the turnstile chain locked. */
| 826 | * pending list. This must be called with the turnstile chain locked. |
| 827 | */ |
| 828 | int |
| 829 | turnstile_signal(struct turnstile *ts, int queue) |
| 830 | { |
| 831 | struct turnstile_chain *tc __unused; |
| 832 | struct thread *td; |
| 833 | int empty; |
| 834 | |
| 835 | MPASS(ts != NULL); |
| 836 | mtx_assert(&ts->ts_lock, MA_OWNED); |
| 837 | MPASS(curthread->td_proc->p_magic == P_MAGIC); |
| 838 | MPASS(ts->ts_owner == curthread || ts->ts_owner == NULL); |
| 839 | MPASS(queue == TS_SHARED_QUEUE || queue == TS_EXCLUSIVE_QUEUE); |
| 840 | |
| 841 | /* |
| 842 | * Pick the highest priority thread blocked on this lock and |
| 843 | * move it to the pending list. |
| 844 | */ |
| 845 | td = TAILQ_FIRST(&ts->ts_blocked[queue]); |
| 846 | MPASS(td->td_proc->p_magic == P_MAGIC); |
| 847 | mtx_lock_spin(&td_contested_lock); |
| 848 | TAILQ_REMOVE(&ts->ts_blocked[queue], td, td_lockq); |
| 849 | mtx_unlock_spin(&td_contested_lock); |
| 850 | TAILQ_INSERT_TAIL(&ts->ts_pending, td, td_lockq); |
| 851 | |
| 852 | /* |
| 853 | * If the turnstile is now empty, remove it from its chain and |
| 854 | * give it to the about-to-be-woken thread. Otherwise take a |
| 855 | * turnstile from the free list and give it to the thread. |
| 856 | */ |
| 857 | empty = TAILQ_EMPTY(&ts->ts_blocked[TS_EXCLUSIVE_QUEUE]) && |
| 858 | TAILQ_EMPTY(&ts->ts_blocked[TS_SHARED_QUEUE]); |
| 859 | if (empty) { |
| 860 | tc = TC_LOOKUP(ts->ts_lockobj); |
| 861 | mtx_assert(&tc->tc_lock, MA_OWNED); |
| 862 | MPASS(LIST_EMPTY(&ts->ts_free)); |
| 863 | #ifdef TURNSTILE_PROFILING |
| 864 | tc->tc_depth--; |
| 865 | #endif |
| 866 | } else |
| 867 | ts = LIST_FIRST(&ts->ts_free); |
| 868 | MPASS(ts != NULL); |
| 869 | LIST_REMOVE(ts, ts_hash); |
| 870 | td->td_turnstile = ts; |
| 871 | |
| 872 | return (empty); |
| 873 | } |
| 874 | |
| 875 | /* |
| 876 | * Put all blocked threads on the pending list. This must be called with |
no test coverage detected