void qemu_event_set(QemuEvent *ev) { if (atomic_mb_read(&ev->value) != EV_SET) { if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { /* There were waiters, wake them up. */ futex_wake(ev, INT_MAX); } } }
void qemu_event_reset(QemuEvent *ev) { if (atomic_mb_read(&ev->value) == EV_SET) { /* * If there was a concurrent reset (or even reset+wait), * do nothing. Otherwise change EV_SET->EV_FREE. */ atomic_or(&ev->value, EV_FREE); } }
void qemu_event_wait(QemuEvent *ev) { unsigned value; value = atomic_mb_read(&ev->value); if (value != EV_SET) { if (value == EV_FREE) { /* * Leave the event reset and tell qemu_event_set that there * are waiters. No need to retry, because there cannot be * a concurent busy->free transition. After the CAS, the * event will be either set or busy. */ if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { return; } } futex_wait(ev, EV_BUSY); } }
void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data, QemuMutex *mutex) { struct qemu_work_item wi; if (qemu_cpu_is_self(cpu)) { func(cpu, data); return; } wi.func = func; wi.data = data; wi.done = false; wi.free = false; wi.exclusive = false; queue_work_on_cpu(cpu, &wi); while (!atomic_mb_read(&wi.done)) { CPUState *self_cpu = current_cpu; qemu_cond_wait(&qemu_work_cond, mutex); current_cpu = self_cpu; } }
PostcopyState postcopy_state_get(void) { return atomic_mb_read(&incoming_postcopy_state); }