1*69e10db8SAkihiko Odaki /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*69e10db8SAkihiko Odaki 3*69e10db8SAkihiko Odaki #include "qemu/osdep.h" 4*69e10db8SAkihiko Odaki #include "qemu/thread.h" 5*69e10db8SAkihiko Odaki 6*69e10db8SAkihiko Odaki /* 7*69e10db8SAkihiko Odaki * Valid transitions: 8*69e10db8SAkihiko Odaki * - FREE -> SET (qemu_event_set) 9*69e10db8SAkihiko Odaki * - BUSY -> SET (qemu_event_set) 10*69e10db8SAkihiko Odaki * - SET -> FREE (qemu_event_reset) 11*69e10db8SAkihiko Odaki * - FREE -> BUSY (qemu_event_wait) 12*69e10db8SAkihiko Odaki * 13*69e10db8SAkihiko Odaki * With futex, the waking and blocking operations follow 14*69e10db8SAkihiko Odaki * BUSY -> SET and FREE -> BUSY, respectively. 15*69e10db8SAkihiko Odaki * 16*69e10db8SAkihiko Odaki * Without futex, BUSY -> SET and FREE -> BUSY never happen. Instead, the waking 17*69e10db8SAkihiko Odaki * operation follows FREE -> SET and the blocking operation will happen in 18*69e10db8SAkihiko Odaki * qemu_event_wait() if the event is not SET. 19*69e10db8SAkihiko Odaki * 20*69e10db8SAkihiko Odaki * SET->BUSY does not happen (it can be observed from the outside but 21*69e10db8SAkihiko Odaki * it really is SET->FREE->BUSY). 22*69e10db8SAkihiko Odaki * 23*69e10db8SAkihiko Odaki * busy->free provably cannot happen; to enforce it, the set->free transition 24*69e10db8SAkihiko Odaki * is done with an OR, which becomes a no-op if the event has concurrently 25*69e10db8SAkihiko Odaki * transitioned to free or busy. 26*69e10db8SAkihiko Odaki */ 27*69e10db8SAkihiko Odaki 28*69e10db8SAkihiko Odaki #define EV_SET 0 29*69e10db8SAkihiko Odaki #define EV_FREE 1 30*69e10db8SAkihiko Odaki #define EV_BUSY -1 31*69e10db8SAkihiko Odaki 32*69e10db8SAkihiko Odaki void qemu_event_init(QemuEvent *ev, bool init) 33*69e10db8SAkihiko Odaki { 34*69e10db8SAkihiko Odaki #ifndef HAVE_FUTEX 35*69e10db8SAkihiko Odaki pthread_mutex_init(&ev->lock, NULL); 36*69e10db8SAkihiko Odaki pthread_cond_init(&ev->cond, NULL); 37*69e10db8SAkihiko Odaki #endif 38*69e10db8SAkihiko Odaki 39*69e10db8SAkihiko Odaki ev->value = (init ? EV_SET : EV_FREE); 40*69e10db8SAkihiko Odaki ev->initialized = true; 41*69e10db8SAkihiko Odaki } 42*69e10db8SAkihiko Odaki 43*69e10db8SAkihiko Odaki void qemu_event_destroy(QemuEvent *ev) 44*69e10db8SAkihiko Odaki { 45*69e10db8SAkihiko Odaki assert(ev->initialized); 46*69e10db8SAkihiko Odaki ev->initialized = false; 47*69e10db8SAkihiko Odaki #ifndef HAVE_FUTEX 48*69e10db8SAkihiko Odaki pthread_mutex_destroy(&ev->lock); 49*69e10db8SAkihiko Odaki pthread_cond_destroy(&ev->cond); 50*69e10db8SAkihiko Odaki #endif 51*69e10db8SAkihiko Odaki } 52*69e10db8SAkihiko Odaki 53*69e10db8SAkihiko Odaki void qemu_event_set(QemuEvent *ev) 54*69e10db8SAkihiko Odaki { 55*69e10db8SAkihiko Odaki assert(ev->initialized); 56*69e10db8SAkihiko Odaki 57*69e10db8SAkihiko Odaki #ifdef HAVE_FUTEX 58*69e10db8SAkihiko Odaki /* 59*69e10db8SAkihiko Odaki * Pairs with both qemu_event_reset() and qemu_event_wait(). 60*69e10db8SAkihiko Odaki * 61*69e10db8SAkihiko Odaki * qemu_event_set has release semantics, but because it *loads* 62*69e10db8SAkihiko Odaki * ev->value we need a full memory barrier here. 63*69e10db8SAkihiko Odaki */ 64*69e10db8SAkihiko Odaki smp_mb(); 65*69e10db8SAkihiko Odaki if (qatomic_read(&ev->value) != EV_SET) { 66*69e10db8SAkihiko Odaki int old = qatomic_xchg(&ev->value, EV_SET); 67*69e10db8SAkihiko Odaki 68*69e10db8SAkihiko Odaki /* Pairs with memory barrier in kernel futex_wait system call. */ 69*69e10db8SAkihiko Odaki smp_mb__after_rmw(); 70*69e10db8SAkihiko Odaki if (old == EV_BUSY) { 71*69e10db8SAkihiko Odaki /* There were waiters, wake them up. */ 72*69e10db8SAkihiko Odaki qemu_futex_wake_all(ev); 73*69e10db8SAkihiko Odaki } 74*69e10db8SAkihiko Odaki } 75*69e10db8SAkihiko Odaki #else 76*69e10db8SAkihiko Odaki pthread_mutex_lock(&ev->lock); 77*69e10db8SAkihiko Odaki /* Pairs with qemu_event_reset()'s load acquire. */ 78*69e10db8SAkihiko Odaki qatomic_store_release(&ev->value, EV_SET); 79*69e10db8SAkihiko Odaki pthread_cond_broadcast(&ev->cond); 80*69e10db8SAkihiko Odaki pthread_mutex_unlock(&ev->lock); 81*69e10db8SAkihiko Odaki #endif 82*69e10db8SAkihiko Odaki } 83*69e10db8SAkihiko Odaki 84*69e10db8SAkihiko Odaki void qemu_event_reset(QemuEvent *ev) 85*69e10db8SAkihiko Odaki { 86*69e10db8SAkihiko Odaki assert(ev->initialized); 87*69e10db8SAkihiko Odaki 88*69e10db8SAkihiko Odaki #ifdef HAVE_FUTEX 89*69e10db8SAkihiko Odaki /* 90*69e10db8SAkihiko Odaki * If there was a concurrent reset (or even reset+wait), 91*69e10db8SAkihiko Odaki * do nothing. Otherwise change EV_SET->EV_FREE. 92*69e10db8SAkihiko Odaki */ 93*69e10db8SAkihiko Odaki qatomic_or(&ev->value, EV_FREE); 94*69e10db8SAkihiko Odaki 95*69e10db8SAkihiko Odaki /* 96*69e10db8SAkihiko Odaki * Order reset before checking the condition in the caller. 97*69e10db8SAkihiko Odaki * Pairs with the first memory barrier in qemu_event_set(). 98*69e10db8SAkihiko Odaki */ 99*69e10db8SAkihiko Odaki smp_mb__after_rmw(); 100*69e10db8SAkihiko Odaki #else 101*69e10db8SAkihiko Odaki /* 102*69e10db8SAkihiko Odaki * If futexes are not available, there are no EV_FREE->EV_BUSY 103*69e10db8SAkihiko Odaki * transitions because wakeups are done entirely through the 104*69e10db8SAkihiko Odaki * condition variable. Since qatomic_set() only writes EV_FREE, 105*69e10db8SAkihiko Odaki * the load seems useless but in reality, the acquire synchronizes 106*69e10db8SAkihiko Odaki * with qemu_event_set()'s store release: if qemu_event_reset() 107*69e10db8SAkihiko Odaki * sees EV_SET here, then the caller will certainly see a 108*69e10db8SAkihiko Odaki * successful condition and skip qemu_event_wait(): 109*69e10db8SAkihiko Odaki * 110*69e10db8SAkihiko Odaki * done = 1; if (done == 0) 111*69e10db8SAkihiko Odaki * qemu_event_set() { qemu_event_reset() { 112*69e10db8SAkihiko Odaki * lock(); 113*69e10db8SAkihiko Odaki * ev->value = EV_SET -----> load ev->value 114*69e10db8SAkihiko Odaki * ev->value = old value | EV_FREE 115*69e10db8SAkihiko Odaki * cond_broadcast() 116*69e10db8SAkihiko Odaki * unlock(); } 117*69e10db8SAkihiko Odaki * } if (done == 0) 118*69e10db8SAkihiko Odaki * // qemu_event_wait() not called 119*69e10db8SAkihiko Odaki */ 120*69e10db8SAkihiko Odaki qatomic_set(&ev->value, qatomic_load_acquire(&ev->value) | EV_FREE); 121*69e10db8SAkihiko Odaki #endif 122*69e10db8SAkihiko Odaki } 123*69e10db8SAkihiko Odaki 124*69e10db8SAkihiko Odaki void qemu_event_wait(QemuEvent *ev) 125*69e10db8SAkihiko Odaki { 126*69e10db8SAkihiko Odaki assert(ev->initialized); 127*69e10db8SAkihiko Odaki 128*69e10db8SAkihiko Odaki #ifdef HAVE_FUTEX 129*69e10db8SAkihiko Odaki while (true) { 130*69e10db8SAkihiko Odaki /* 131*69e10db8SAkihiko Odaki * qemu_event_wait must synchronize with qemu_event_set even if it does 132*69e10db8SAkihiko Odaki * not go down the slow path, so this load-acquire is needed that 133*69e10db8SAkihiko Odaki * synchronizes with the first memory barrier in qemu_event_set(). 134*69e10db8SAkihiko Odaki */ 135*69e10db8SAkihiko Odaki unsigned value = qatomic_load_acquire(&ev->value); 136*69e10db8SAkihiko Odaki if (value == EV_SET) { 137*69e10db8SAkihiko Odaki break; 138*69e10db8SAkihiko Odaki } 139*69e10db8SAkihiko Odaki 140*69e10db8SAkihiko Odaki if (value == EV_FREE) { 141*69e10db8SAkihiko Odaki /* 142*69e10db8SAkihiko Odaki * Leave the event reset and tell qemu_event_set that there are 143*69e10db8SAkihiko Odaki * waiters. No need to retry, because there cannot be a concurrent 144*69e10db8SAkihiko Odaki * busy->free transition. After the CAS, the event will be either 145*69e10db8SAkihiko Odaki * set or busy. 146*69e10db8SAkihiko Odaki * 147*69e10db8SAkihiko Odaki * This cmpxchg doesn't have particular ordering requirements if it 148*69e10db8SAkihiko Odaki * succeeds (moving the store earlier can only cause 149*69e10db8SAkihiko Odaki * qemu_event_set() to issue _more_ wakeups), the failing case needs 150*69e10db8SAkihiko Odaki * acquire semantics like the load above. 151*69e10db8SAkihiko Odaki */ 152*69e10db8SAkihiko Odaki if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 153*69e10db8SAkihiko Odaki break; 154*69e10db8SAkihiko Odaki } 155*69e10db8SAkihiko Odaki } 156*69e10db8SAkihiko Odaki 157*69e10db8SAkihiko Odaki /* 158*69e10db8SAkihiko Odaki * This is the final check for a concurrent set, so it does need 159*69e10db8SAkihiko Odaki * a smp_mb() pairing with the second barrier of qemu_event_set(). 160*69e10db8SAkihiko Odaki * The barrier is inside the FUTEX_WAIT system call. 161*69e10db8SAkihiko Odaki */ 162*69e10db8SAkihiko Odaki qemu_futex_wait(ev, EV_BUSY); 163*69e10db8SAkihiko Odaki } 164*69e10db8SAkihiko Odaki #else 165*69e10db8SAkihiko Odaki pthread_mutex_lock(&ev->lock); 166*69e10db8SAkihiko Odaki while (qatomic_read(&ev->value) != EV_SET) { 167*69e10db8SAkihiko Odaki pthread_cond_wait(&ev->cond, &ev->lock); 168*69e10db8SAkihiko Odaki } 169*69e10db8SAkihiko Odaki pthread_mutex_unlock(&ev->lock); 170*69e10db8SAkihiko Odaki #endif 171*69e10db8SAkihiko Odaki } 172