static void alq_shutdown(struct alq *alq) { ALQ_LOCK(alq); /* Stop any new writers. */ alq->aq_flags |= AQ_SHUTDOWN; /* * If the ALQ isn't active but has unwritten data (possible if * the ALQ_NOACTIVATE flag has been used), explicitly activate the * ALQ here so that the pending data gets flushed by the ald_daemon. */ if (!(alq->aq_flags & AQ_ACTIVE) && HAS_PENDING_DATA(alq)) { alq->aq_flags |= AQ_ACTIVE; ALQ_UNLOCK(alq); ALD_LOCK(); ald_activate(alq); ALD_UNLOCK(); ALQ_LOCK(alq); } /* Drain IO */ while (alq->aq_flags & AQ_ACTIVE) { alq->aq_flags |= AQ_WANTED; msleep_spin(alq, &alq->aq_mtx, "aldclose", 0); } ALQ_UNLOCK(alq); vn_close(alq->aq_vp, FWRITE, alq->aq_cred, curthread); crfree(alq->aq_cred); }
static int vtballoon_detach(device_t dev) { struct vtballoon_softc *sc; sc = device_get_softc(dev); if (sc->vtballoon_kproc != NULL) { VTBALLOON_LOCK(sc); sc->vtballoon_flags |= VTBALLOON_FLAG_DETACH; wakeup_one(sc); msleep_spin(sc->vtballoon_kproc, VTBALLOON_MTX(sc), "vtbdth", 0); VTBALLOON_UNLOCK(sc); sc->vtballoon_kproc = NULL; } if (device_is_attached(dev)) { vtballoon_pop(sc); vtballoon_stop(sc); } if (sc->vtballoon_page_frames != NULL) { free(sc->vtballoon_page_frames, M_DEVBUF); sc->vtballoon_page_frames = NULL; } VTBALLOON_LOCK_DESTROY(sc); return (0); }
struct ale * alq_get(struct alq *alq, int waitok) { struct ale *ale; struct ale *aln; ale = NULL; ALQ_LOCK(alq); /* Loop until we get an entry or we're shutting down */ while ((alq->aq_flags & AQ_SHUTDOWN) == 0 && (ale = alq->aq_entfree) == NULL && (waitok & ALQ_WAITOK)) { alq->aq_flags |= AQ_WANTED; msleep_spin(alq, &alq->aq_mtx, "alqget", 0); } if (ale != NULL) { aln = ale->ae_next; if ((aln->ae_flags & AE_VALID) == 0) alq->aq_entfree = aln; else alq->aq_entfree = NULL; } else ALQ_UNLOCK(alq); return (ale); }
/* * Emulate a guest 'hlt' by sleeping until the vcpu is ready to run. */ static int vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu) { struct vm_exit *vmexit; struct vcpu *vcpu; int t, timo, spindown; vcpu = &vm->vcpu[vcpuid]; spindown = 0; vcpu_lock(vcpu); /* * Do a final check for pending NMI or interrupts before * really putting this thread to sleep. * * These interrupts could have happened any time after we * returned from VMRUN() and before we grabbed the vcpu lock. */ if (!vm_nmi_pending(vm, vcpuid) && (intr_disabled || !vlapic_pending_intr(vcpu->vlapic, NULL))) { t = ticks; vcpu_require_state_locked(vcpu, VCPU_SLEEPING); if (vlapic_enabled(vcpu->vlapic)) { /* * XXX msleep_spin() is not interruptible so use the * 'timo' to put an upper bound on the sleep time. */ timo = hz; msleep_spin(vcpu, &vcpu->mtx, "vmidle", timo); } else { /* * Spindown the vcpu if the apic is disabled and it * had entered the halted state. */ spindown = 1; } vcpu_require_state_locked(vcpu, VCPU_FROZEN); vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t); } vcpu_unlock(vcpu); /* * Since 'vm_deactivate_cpu()' grabs a sleep mutex we must call it * outside the confines of the vcpu spinlock. */ if (spindown) { *retu = true; vmexit = vm_exitinfo(vm, vcpuid); vmexit->exitcode = VM_EXITCODE_SPINDOWN_CPU; vm_deactivate_cpu(vm, vcpuid); VCPU_CTR0(vm, vcpuid, "spinning down cpu"); } return (0); }
static int ia64_highfp_ipi(struct pcpu *cpu) { int error; ipi_send(cpu, ia64_ipi_highfp); error = msleep_spin(&cpu->pc_fpcurthread, &ia64_highfp_mtx, "High FP", 0); return (error); }
static void alq_shutdown(struct alq *alq) { ALQ_LOCK(alq); /* Stop any new writers. */ alq->aq_flags |= AQ_SHUTDOWN; /* Drain IO */ while (alq->aq_flags & (AQ_FLUSHING|AQ_ACTIVE)) { alq->aq_flags |= AQ_WANTED; msleep_spin(alq, &alq->aq_mtx, "aldclose", 0); } ALQ_UNLOCK(alq); vn_close(alq->aq_vp, FWRITE, alq->aq_cred, curthread); crfree(alq->aq_cred); }
static int vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, bool from_idle) { int error; vcpu_assert_locked(vcpu); /* * State transitions from the vmmdev_ioctl() must always begin from * the VCPU_IDLE state. This guarantees that there is only a single * ioctl() operating on a vcpu at any point. */ if (from_idle) { while (vcpu->state != VCPU_IDLE) msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz); } else { KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from " "vcpu idle state")); } if (vcpu->state == VCPU_RUNNING) { KASSERT(vcpu->hostcpu == curcpu, ("curcpu %d and hostcpu %d " "mismatch for running vcpu", curcpu, vcpu->hostcpu)); } else { KASSERT(vcpu->hostcpu == NOCPU, ("Invalid hostcpu %d for a " "vcpu that is not running", vcpu->hostcpu)); } /* * The following state transitions are allowed: * IDLE -> FROZEN -> IDLE * FROZEN -> RUNNING -> FROZEN * FROZEN -> SLEEPING -> FROZEN */ switch (vcpu->state) { case VCPU_IDLE: case VCPU_RUNNING: case VCPU_SLEEPING: error = (newstate != VCPU_FROZEN); break; case VCPU_FROZEN: error = (newstate == VCPU_FROZEN); break; default: error = 1; break; } if (error) return (EBUSY); vcpu->state = newstate; if (newstate == VCPU_RUNNING) vcpu->hostcpu = curcpu; else vcpu->hostcpu = NOCPU; if (newstate == VCPU_IDLE) wakeup(&vcpu->state); return (0); }
/* * Retrieve a pointer for the ALQ to write directly into, avoiding bcopy. */ struct ale * alq_getn(struct alq *alq, int len, int flags) { int contigbytes; void *waitchan; KASSERT((len > 0 && len <= alq->aq_buflen), ("%s: len <= 0 || len > alq->aq_buflen", __func__)); waitchan = NULL; ALQ_LOCK(alq); /* * Determine the number of free contiguous bytes. * We ensure elsewhere that if aq_writehead == aq_writetail because * the buffer is empty, they will both be set to 0 and therefore * aq_freebytes == aq_buflen and is fully contiguous. * If they are equal and the buffer is not empty, aq_freebytes will * be 0 indicating the buffer is full. */ if (alq->aq_writehead <= alq->aq_writetail) contigbytes = alq->aq_freebytes; else { contigbytes = alq->aq_buflen - alq->aq_writehead; if (contigbytes < len) { /* * Insufficient space at end of buffer to handle a * contiguous write. Wrap early if there's space at * the beginning. This will leave a hole at the end * of the buffer which we will have to skip over when * flushing the buffer to disk. */ if (alq->aq_writetail >= len || flags & ALQ_WAITOK) { /* Keep track of # bytes left blank. */ alq->aq_wrapearly = contigbytes; /* Do the wrap and adjust counters. */ contigbytes = alq->aq_freebytes = alq->aq_writetail; alq->aq_writehead = 0; } } } /* * Return a NULL ALE if: * - The message is larger than our underlying buffer. * - The ALQ is being shutdown. * - There is insufficient free space in our underlying buffer * to accept the message and the user can't wait for space. * - There is insufficient free space in our underlying buffer * to accept the message and the alq is inactive due to prior * use of the ALQ_NOACTIVATE flag (which would lead to deadlock). */ if (len > alq->aq_buflen || alq->aq_flags & AQ_SHUTDOWN || (((flags & ALQ_NOWAIT) || (!(alq->aq_flags & AQ_ACTIVE) && HAS_PENDING_DATA(alq))) && contigbytes < len)) { ALQ_UNLOCK(alq); return (NULL); } /* * If we want ordered writes and there is already at least one thread * waiting for resources to become available, sleep until we're woken. */ if (alq->aq_flags & AQ_ORDERED && alq->aq_waiters > 0) { KASSERT(!(flags & ALQ_NOWAIT), ("%s: ALQ_NOWAIT set but incorrectly ignored!", __func__)); alq->aq_waiters++; msleep_spin(&alq->aq_waiters, &alq->aq_mtx, "alqgnord", 0); alq->aq_waiters--; } /* * (ALQ_WAITOK && contigbytes < len) or contigbytes >= len, either enter * while loop and sleep until we have enough contiguous free bytes * (former) or skip (latter). If AQ_ORDERED is set, only 1 thread at a * time will be in this loop. Otherwise, multiple threads may be * sleeping here competing for ALQ resources. */ while (contigbytes < len && !(alq->aq_flags & AQ_SHUTDOWN)) { KASSERT(!(flags & ALQ_NOWAIT), ("%s: ALQ_NOWAIT set but incorrectly ignored!", __func__)); alq->aq_flags |= AQ_WANTED; alq->aq_waiters++; if (waitchan) wakeup(waitchan); msleep_spin(alq, &alq->aq_mtx, "alqgnres", 0); alq->aq_waiters--; if (alq->aq_writehead <= alq->aq_writetail) contigbytes = alq->aq_freebytes; else contigbytes = alq->aq_buflen - alq->aq_writehead; /* * If we're the first thread to wake after an AQ_WANTED wakeup * but there isn't enough free space for us, we're going to loop * and sleep again. If there are other threads waiting in this * loop, schedule a wakeup so that they can see if the space * they require is available. */ if (alq->aq_waiters > 0 && !(alq->aq_flags & AQ_ORDERED) && contigbytes < len && !(alq->aq_flags & AQ_WANTED)) waitchan = alq; else waitchan = NULL; } /* * If there are waiters, we need to signal the waiting threads after we * complete our work. The alq ptr is used as a wait channel for threads * requiring resources to be freed up. In the AQ_ORDERED case, threads * are not allowed to concurrently compete for resources in the above * while loop, so we use a different wait channel in this case. */ if (alq->aq_waiters > 0) { if (alq->aq_flags & AQ_ORDERED) waitchan = &alq->aq_waiters; else waitchan = alq; } else waitchan = NULL; /* Bail if we're shutting down. */ if (alq->aq_flags & AQ_SHUTDOWN) { ALQ_UNLOCK(alq); if (waitchan != NULL) wakeup_one(waitchan); return (NULL); } /* * If we are here, we have a contiguous number of bytes >= len * available in our buffer starting at aq_writehead. */ alq->aq_getpost.ae_data = alq->aq_entbuf + alq->aq_writehead; alq->aq_getpost.ae_bytesused = len; return (&alq->aq_getpost); }
/* * Copy a new entry into the queue. If the operation would block either * wait or return an error depending on the value of waitok. */ int alq_writen(struct alq *alq, void *data, int len, int flags) { int activate, copy, ret; void *waitchan; KASSERT((len > 0 && len <= alq->aq_buflen), ("%s: len <= 0 || len > aq_buflen", __func__)); activate = ret = 0; copy = len; waitchan = NULL; ALQ_LOCK(alq); /* * Fail to perform the write and return EWOULDBLOCK if: * - The message is larger than our underlying buffer. * - The ALQ is being shutdown. * - There is insufficient free space in our underlying buffer * to accept the message and the user can't wait for space. * - There is insufficient free space in our underlying buffer * to accept the message and the alq is inactive due to prior * use of the ALQ_NOACTIVATE flag (which would lead to deadlock). */ if (len > alq->aq_buflen || alq->aq_flags & AQ_SHUTDOWN || (((flags & ALQ_NOWAIT) || (!(alq->aq_flags & AQ_ACTIVE) && HAS_PENDING_DATA(alq))) && alq->aq_freebytes < len)) { ALQ_UNLOCK(alq); return (EWOULDBLOCK); } /* * If we want ordered writes and there is already at least one thread * waiting for resources to become available, sleep until we're woken. */ if (alq->aq_flags & AQ_ORDERED && alq->aq_waiters > 0) { KASSERT(!(flags & ALQ_NOWAIT), ("%s: ALQ_NOWAIT set but incorrectly ignored!", __func__)); alq->aq_waiters++; msleep_spin(&alq->aq_waiters, &alq->aq_mtx, "alqwnord", 0); alq->aq_waiters--; } /* * (ALQ_WAITOK && aq_freebytes < len) or aq_freebytes >= len, either * enter while loop and sleep until we have enough free bytes (former) * or skip (latter). If AQ_ORDERED is set, only 1 thread at a time will * be in this loop. Otherwise, multiple threads may be sleeping here * competing for ALQ resources. */ while (alq->aq_freebytes < len && !(alq->aq_flags & AQ_SHUTDOWN)) { KASSERT(!(flags & ALQ_NOWAIT), ("%s: ALQ_NOWAIT set but incorrectly ignored!", __func__)); alq->aq_flags |= AQ_WANTED; alq->aq_waiters++; if (waitchan) wakeup(waitchan); msleep_spin(alq, &alq->aq_mtx, "alqwnres", 0); alq->aq_waiters--; /* * If we're the first thread to wake after an AQ_WANTED wakeup * but there isn't enough free space for us, we're going to loop * and sleep again. If there are other threads waiting in this * loop, schedule a wakeup so that they can see if the space * they require is available. */ if (alq->aq_waiters > 0 && !(alq->aq_flags & AQ_ORDERED) && alq->aq_freebytes < len && !(alq->aq_flags & AQ_WANTED)) waitchan = alq; else waitchan = NULL; } /* * If there are waiters, we need to signal the waiting threads after we * complete our work. The alq ptr is used as a wait channel for threads * requiring resources to be freed up. In the AQ_ORDERED case, threads * are not allowed to concurrently compete for resources in the above * while loop, so we use a different wait channel in this case. */ if (alq->aq_waiters > 0) { if (alq->aq_flags & AQ_ORDERED) waitchan = &alq->aq_waiters; else waitchan = alq; } else waitchan = NULL; /* Bail if we're shutting down. */ if (alq->aq_flags & AQ_SHUTDOWN) { ret = EWOULDBLOCK; goto unlock; } /* * If we need to wrap the buffer to accommodate the write, * we'll need 2 calls to bcopy. */ if ((alq->aq_buflen - alq->aq_writehead) < len) copy = alq->aq_buflen - alq->aq_writehead; /* Copy message (or part thereof if wrap required) to the buffer. */ bcopy(data, alq->aq_entbuf + alq->aq_writehead, copy); alq->aq_writehead += copy; if (alq->aq_writehead >= alq->aq_buflen) { KASSERT((alq->aq_writehead == alq->aq_buflen), ("%s: alq->aq_writehead (%d) > alq->aq_buflen (%d)", __func__, alq->aq_writehead, alq->aq_buflen)); alq->aq_writehead = 0; } if (copy != len) { /* * Wrap the buffer by copying the remainder of our message * to the start of the buffer and resetting aq_writehead. */ bcopy(((uint8_t *)data)+copy, alq->aq_entbuf, len - copy); alq->aq_writehead = len - copy; } KASSERT((alq->aq_writehead >= 0 && alq->aq_writehead < alq->aq_buflen), ("%s: aq_writehead < 0 || aq_writehead >= aq_buflen", __func__)); alq->aq_freebytes -= len; if (!(alq->aq_flags & AQ_ACTIVE) && !(flags & ALQ_NOACTIVATE)) { alq->aq_flags |= AQ_ACTIVE; activate = 1; } KASSERT((HAS_PENDING_DATA(alq)), ("%s: queue empty!", __func__)); unlock: ALQ_UNLOCK(alq); if (activate) { ALD_LOCK(); ald_activate(alq); ALD_UNLOCK(); } /* NB: We rely on wakeup_one waking threads in a FIFO manner. */ if (waitchan != NULL) wakeup_one(waitchan); return (ret); }