* It assumes sleepq_lock held and returns with this one unheld. * It also assumes the generic interlock is sane and previously checked. * If LK_INTERLOCK is specified the interlock is not reacquired after the * sleep. */
| 263 | * sleep. |
| 264 | */ |
| 265 | static __inline int |
| 266 | sleeplk(struct lock *lk, u_int flags, struct lock_object *ilk, |
| 267 | const char *wmesg, int pri, int timo, int queue) |
| 268 | { |
| 269 | GIANT_DECLARE; |
| 270 | struct lock_class *class; |
| 271 | int catch, error; |
| 272 | |
| 273 | class = (flags & LK_INTERLOCK) ? LOCK_CLASS(ilk) : NULL; |
| 274 | catch = pri & PCATCH; |
| 275 | pri &= PRIMASK; |
| 276 | error = 0; |
| 277 | |
| 278 | LOCK_LOG3(lk, "%s: %p blocking on the %s sleepqueue", __func__, lk, |
| 279 | (queue == SQ_EXCLUSIVE_QUEUE) ? "exclusive" : "shared"); |
| 280 | |
| 281 | if (flags & LK_INTERLOCK) |
| 282 | class->lc_unlock(ilk); |
| 283 | if (queue == SQ_EXCLUSIVE_QUEUE && (flags & LK_SLEEPFAIL) != 0) |
| 284 | lk->lk_exslpfail++; |
| 285 | GIANT_SAVE(); |
| 286 | sleepq_add(&lk->lock_object, NULL, wmesg, SLEEPQ_LK | (catch ? |
| 287 | SLEEPQ_INTERRUPTIBLE : 0), queue); |
| 288 | if ((flags & LK_TIMELOCK) && timo) |
| 289 | sleepq_set_timeout(&lk->lock_object, timo); |
| 290 | |
| 291 | /* |
| 292 | * Decisional switch for real sleeping. |
| 293 | */ |
| 294 | if ((flags & LK_TIMELOCK) && timo && catch) |
| 295 | error = sleepq_timedwait_sig(&lk->lock_object, pri); |
| 296 | else if ((flags & LK_TIMELOCK) && timo) |
| 297 | error = sleepq_timedwait(&lk->lock_object, pri); |
| 298 | else if (catch) |
| 299 | error = sleepq_wait_sig(&lk->lock_object, pri); |
| 300 | else |
| 301 | sleepq_wait(&lk->lock_object, pri); |
| 302 | GIANT_RESTORE(); |
| 303 | if ((flags & LK_SLEEPFAIL) && error == 0) |
| 304 | error = ENOLCK; |
| 305 | |
| 306 | return (error); |
| 307 | } |
| 308 | |
| 309 | static __inline int |
| 310 | wakeupshlk(struct lock *lk, const char *file, int line) |
no test coverage detected