MCPcopy Create free account
hub / github.com/F-Stack/f-stack / _blockcount_sleep

Function _blockcount_sleep

freebsd/kern/kern_synch.c:410–471  ·  view source on GitHub ↗

* Wait for a wakeup or a signal. This does not guarantee that the count is * still zero on return. Callers wanting a precise answer should use * blockcount_wait() with an interlock. * * If there is no work to wait for, return 0. If the sleep was interrupted by a * signal, return EINTR or ERESTART, and return EAGAIN otherwise. */

Source from the content-addressed store, hash-verified

408 * signal, return EINTR or ERESTART, and return EAGAIN otherwise.
409 */
410int
411_blockcount_sleep(blockcount_t *bc, struct lock_object *lock, const char *wmesg,
412 int prio)
413{
414 void *wchan;
415 uintptr_t lock_state;
416 u_int old;
417 int ret;
418 bool catch, drop;
419
420 KASSERT(lock != &Giant.lock_object,
421 ("%s: cannot use Giant as the interlock", __func__));
422
423 catch = (prio & PCATCH) != 0;
424 drop = (prio & PDROP) != 0;
425 prio &= PRIMASK;
426
427 /*
428 * Synchronize with the fence in blockcount_release(). If we end up
429 * waiting, the sleepqueue lock acquisition will provide the required
430 * side effects.
431 *
432 * If there is no work to wait for, but waiters are present, try to put
433 * ourselves to sleep to avoid jumping ahead.
434 */
435 if (atomic_load_acq_int(&bc->__count) == 0) {
436 if (lock != NULL && drop)
437 LOCK_CLASS(lock)->lc_unlock(lock);
438 return (0);
439 }
440 lock_state = 0;
441 wchan = bc;
442 sleepq_lock(wchan);
443 DROP_GIANT();
444 if (lock != NULL)
445 lock_state = LOCK_CLASS(lock)->lc_unlock(lock);
446 old = blockcount_read(bc);
447 ret = 0;
448 do {
449 if (_BLOCKCOUNT_COUNT(old) == 0) {
450 sleepq_release(wchan);
451 goto out;
452 }
453 if (_BLOCKCOUNT_WAITERS(old))
454 break;
455 } while (!atomic_fcmpset_int(&bc->__count, &old,
456 old | _BLOCKCOUNT_WAITERS_FLAG));
457 sleepq_add(wchan, NULL, wmesg, catch ? SLEEPQ_INTERRUPTIBLE : 0, 0);
458 if (catch)
459 ret = sleepq_wait_sig(wchan, prio);
460 else
461 sleepq_wait(wchan, prio);
462 if (ret == 0)
463 ret = EAGAIN;
464
465out:
466 PICKUP_GIANT();
467 if (lock != NULL && !drop)

Callers 1

_blockcount_waitFunction · 0.85

Calls 6

sleepq_lockFunction · 0.85
blockcount_readFunction · 0.85
sleepq_releaseFunction · 0.85
sleepq_addFunction · 0.85
sleepq_wait_sigFunction · 0.85
sleepq_waitFunction · 0.85

Tested by

no test coverage detected