qemu-coroutine.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * QEMU coroutines
  3. *
  4. * Copyright IBM, Corp. 2011
  5. *
  6. * Authors:
  7. * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
  8. * Kevin Wolf <kwolf@redhat.com>
  9. *
  10. * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  11. * See the COPYING.LIB file in the top-level directory.
  12. *
  13. */
  14. #include "trace.h"
  15. #include "qemu-common.h"
  16. #include "qemu/thread.h"
  17. #include "block/coroutine.h"
  18. #include "block/coroutine_int.h"
  19. enum {
  20. POOL_DEFAULT_SIZE = 64,
  21. };
  22. /** Free list to speed up creation */
  23. static QemuMutex pool_lock;
  24. static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
  25. static unsigned int pool_size;
  26. static unsigned int pool_max_size = POOL_DEFAULT_SIZE;
  27. Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
  28. {
  29. Coroutine *co = NULL;
  30. if (CONFIG_COROUTINE_POOL) {
  31. qemu_mutex_lock(&pool_lock);
  32. co = QSLIST_FIRST(&pool);
  33. if (co) {
  34. QSLIST_REMOVE_HEAD(&pool, pool_next);
  35. pool_size--;
  36. }
  37. qemu_mutex_unlock(&pool_lock);
  38. }
  39. if (!co) {
  40. co = qemu_coroutine_new();
  41. }
  42. co->entry = entry;
  43. QTAILQ_INIT(&co->co_queue_wakeup);
  44. return co;
  45. }
  46. static void coroutine_delete(Coroutine *co)
  47. {
  48. if (CONFIG_COROUTINE_POOL) {
  49. qemu_mutex_lock(&pool_lock);
  50. if (pool_size < pool_max_size) {
  51. QSLIST_INSERT_HEAD(&pool, co, pool_next);
  52. co->caller = NULL;
  53. pool_size++;
  54. qemu_mutex_unlock(&pool_lock);
  55. return;
  56. }
  57. qemu_mutex_unlock(&pool_lock);
  58. }
  59. qemu_coroutine_delete(co);
  60. }
  61. static void __attribute__((constructor)) coroutine_pool_init(void)
  62. {
  63. qemu_mutex_init(&pool_lock);
  64. }
  65. static void __attribute__((destructor)) coroutine_pool_cleanup(void)
  66. {
  67. Coroutine *co;
  68. Coroutine *tmp;
  69. QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
  70. QSLIST_REMOVE_HEAD(&pool, pool_next);
  71. qemu_coroutine_delete(co);
  72. }
  73. qemu_mutex_destroy(&pool_lock);
  74. }
  75. static void coroutine_swap(Coroutine *from, Coroutine *to)
  76. {
  77. CoroutineAction ret;
  78. ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD);
  79. qemu_co_queue_run_restart(to);
  80. switch (ret) {
  81. case COROUTINE_YIELD:
  82. return;
  83. case COROUTINE_TERMINATE:
  84. trace_qemu_coroutine_terminate(to);
  85. coroutine_delete(to);
  86. return;
  87. default:
  88. abort();
  89. }
  90. }
  91. void qemu_coroutine_enter(Coroutine *co, void *opaque)
  92. {
  93. Coroutine *self = qemu_coroutine_self();
  94. trace_qemu_coroutine_enter(self, co, opaque);
  95. if (co->caller) {
  96. fprintf(stderr, "Co-routine re-entered recursively\n");
  97. abort();
  98. }
  99. co->caller = self;
  100. co->entry_arg = opaque;
  101. coroutine_swap(self, co);
  102. }
  103. void coroutine_fn qemu_coroutine_yield(void)
  104. {
  105. Coroutine *self = qemu_coroutine_self();
  106. Coroutine *to = self->caller;
  107. trace_qemu_coroutine_yield(self, to);
  108. if (!to) {
  109. fprintf(stderr, "Co-routine is yielding to no one\n");
  110. abort();
  111. }
  112. self->caller = NULL;
  113. qemu_coroutine_switch(self, to, COROUTINE_YIELD);
  114. }
  115. void qemu_coroutine_adjust_pool_size(int n)
  116. {
  117. qemu_mutex_lock(&pool_lock);
  118. pool_max_size += n;
  119. /* Callers should never take away more than they added */
  120. assert(pool_max_size >= POOL_DEFAULT_SIZE);
  121. /* Trim oversized pool down to new max */
  122. while (pool_size > pool_max_size) {
  123. Coroutine *co = QSLIST_FIRST(&pool);
  124. QSLIST_REMOVE_HEAD(&pool, pool_next);
  125. pool_size--;
  126. qemu_coroutine_delete(co);
  127. }
  128. qemu_mutex_unlock(&pool_lock);
  129. }