qemu/util/qemu-coroutine-sleep.c
<<
>>
Prefs
   1/*
   2 * QEMU coroutine sleep
   3 *
   4 * Copyright IBM, Corp. 2011
   5 *
   6 * Authors:
   7 *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
   8 *
   9 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  10 * See the COPYING.LIB file in the top-level directory.
  11 *
  12 */
  13
  14#include "qemu/osdep.h"
  15#include "qemu/coroutine.h"
  16#include "qemu/coroutine_int.h"
  17#include "qemu/timer.h"
  18#include "block/aio.h"
  19
  20typedef struct CoSleepCB {
  21    QEMUTimer *ts;
  22    Coroutine *co;
  23} CoSleepCB;
  24
  25static void co_sleep_cb(void *opaque)
  26{
  27    CoSleepCB *sleep_cb = opaque;
  28
  29    /* Write of schedule protected by barrier write in aio_co_schedule */
  30    atomic_set(&sleep_cb->co->scheduled, NULL);
  31    aio_co_wake(sleep_cb->co);
  32}
  33
  34void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
  35{
  36    AioContext *ctx = qemu_get_current_aio_context();
  37    CoSleepCB sleep_cb = {
  38        .co = qemu_coroutine_self(),
  39    };
  40
  41    const char *scheduled = atomic_cmpxchg(&sleep_cb.co->scheduled, NULL,
  42                                           __func__);
  43    if (scheduled) {
  44        fprintf(stderr,
  45                "%s: Co-routine was already scheduled in '%s'\n",
  46                __func__, scheduled);
  47        abort();
  48    }
  49    sleep_cb.ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &sleep_cb);
  50    timer_mod(sleep_cb.ts, qemu_clock_get_ns(type) + ns);
  51    qemu_coroutine_yield();
  52    timer_del(sleep_cb.ts);
  53    timer_free(sleep_cb.ts);
  54}
  55