* 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. */
| 198 | * release their locks before this thread can run again. |
| 199 | */ |
| 200 | static void |
| 201 | propagate_priority(struct thread *td) |
| 202 | { |
| 203 | struct turnstile *ts, *top; |
| 204 | int pri; |
| 205 | |
| 206 | THREAD_LOCK_ASSERT(td, MA_OWNED); |
| 207 | pri = td->td_priority; |
| 208 | top = ts = td->td_blocked; |
| 209 | THREAD_LOCKPTR_ASSERT(td, &ts->ts_lock); |
| 210 | |
| 211 | /* |
| 212 | * The original turnstile lock is held across the entire |
| 213 | * operation. We only ever lock down the chain so the lock |
| 214 | * order is constant. |
| 215 | */ |
| 216 | for (;;) { |
| 217 | td = ts->ts_owner; |
| 218 | |
| 219 | if (td == NULL) { |
| 220 | /* |
| 221 | * This might be a read lock with no owner. There's |
| 222 | * not much we can do, so just bail. |
| 223 | */ |
| 224 | propagate_unlock_ts(top, ts); |
| 225 | return; |
| 226 | } |
| 227 | |
| 228 | /* |
| 229 | * Wait for the thread lock to be stable and then only |
| 230 | * acquire if it is not the turnstile lock. |
| 231 | */ |
| 232 | thread_lock_block_wait(td); |
| 233 | if (td->td_lock != &ts->ts_lock) { |
| 234 | thread_lock_flags(td, MTX_DUPOK); |
| 235 | propagate_unlock_ts(top, ts); |
| 236 | } |
| 237 | MPASS(td->td_proc != NULL); |
| 238 | MPASS(td->td_proc->p_magic == P_MAGIC); |
| 239 | |
| 240 | /* |
| 241 | * If the thread is asleep, then we are probably about |
| 242 | * to deadlock. To make debugging this easier, show |
| 243 | * backtrace of misbehaving thread and panic to not |
| 244 | * leave the kernel deadlocked. |
| 245 | */ |
| 246 | if (TD_IS_SLEEPING(td)) { |
| 247 | printf( |
| 248 | "Sleeping thread (tid %d, pid %d) owns a non-sleepable lock\n", |
| 249 | td->td_tid, td->td_proc->p_pid); |
| 250 | kdb_backtrace_thread(td); |
| 251 | panic("sleeping thread"); |
| 252 | } |
| 253 | |
| 254 | /* |
| 255 | * If this thread already has higher priority than the |
| 256 | * thread that is being blocked, we are finished. |
| 257 | */ |
no test coverage detected