2
0

qemu-coroutine-sleep.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. #include "qemu/osdep.h"
  14. #include "qemu/coroutine_int.h"
  15. #include "qemu/timer.h"
  16. #include "block/aio.h"
  17. static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
  18. void qemu_co_sleep_wake(QemuCoSleep *w)
  19. {
  20. Coroutine *co;
  21. co = w->to_wake;
  22. w->to_wake = NULL;
  23. if (co) {
  24. /* Write of schedule protected by barrier write in aio_co_schedule */
  25. const char *scheduled = qatomic_cmpxchg(&co->scheduled,
  26. qemu_co_sleep_ns__scheduled, NULL);
  27. assert(scheduled == qemu_co_sleep_ns__scheduled);
  28. aio_co_wake(co);
  29. }
  30. }
  31. static void co_sleep_cb(void *opaque)
  32. {
  33. QemuCoSleep *w = opaque;
  34. qemu_co_sleep_wake(w);
  35. }
  36. void coroutine_fn qemu_co_sleep(QemuCoSleep *w)
  37. {
  38. Coroutine *co = qemu_coroutine_self();
  39. const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL,
  40. qemu_co_sleep_ns__scheduled);
  41. if (scheduled) {
  42. fprintf(stderr,
  43. "%s: Co-routine was already scheduled in '%s'\n",
  44. __func__, scheduled);
  45. abort();
  46. }
  47. w->to_wake = co;
  48. qemu_coroutine_yield();
  49. /* w->to_wake is cleared before resuming this coroutine. */
  50. assert(w->to_wake == NULL);
  51. }
  52. void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
  53. QEMUClockType type, int64_t ns)
  54. {
  55. AioContext *ctx = qemu_get_current_aio_context();
  56. QEMUTimer ts;
  57. aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w);
  58. timer_mod(&ts, qemu_clock_get_ns(type) + ns);
  59. /*
  60. * The timer will fire in the current AiOContext, so the callback
  61. * must happen after qemu_co_sleep yields and there is no race
  62. * between timer_mod and qemu_co_sleep.
  63. */
  64. qemu_co_sleep(w);
  65. timer_del(&ts);
  66. }