coroutine: introduce coroutines
commit596a6cc70143cfac17558db555d2b93ddb8cb1c9
authorKevin Wolf <kwolf@redhat.com>
Mon, 17 Jan 2011 16:08:14 +0000 (17 16:08 +0000)
committerStefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Mon, 25 Jul 2011 17:09:10 +0000 (25 18:09 +0100)
tree5d784d248c86b883b53ea45a7f68b2e8d491bb9a
parent1fc7bd4a86a2bfeafcec29445871eb97469a2699
coroutine: introduce coroutines

Asynchronous code is becoming very complex.  At the same time
synchronous code is growing because it is convenient to write.
Sometimes duplicate code paths are even added, one synchronous and the
other asynchronous.  This patch introduces coroutines which allow code
that looks synchronous but is asynchronous under the covers.

A coroutine has its own stack and is therefore able to preserve state
across blocking operations, which traditionally require callback
functions and manual marshalling of parameters.

Creating and starting a coroutine is easy:

  coroutine = qemu_coroutine_create(my_coroutine);
  qemu_coroutine_enter(coroutine, my_data);

The coroutine then executes until it returns or yields:

  void coroutine_fn my_coroutine(void *opaque) {
      MyData *my_data = opaque;

      /* do some work */

      qemu_coroutine_yield();

      /* do some more work */
  }

Yielding switches control back to the caller of qemu_coroutine_enter().
This is typically used to switch back to the main thread's event loop
after issuing an asynchronous I/O request.  The request callback will
then invoke qemu_coroutine_enter() once more to switch back to the
coroutine.

Note that if coroutines are used only from threads which hold the global
mutex they will never execute concurrently.  This makes programming with
coroutines easier than with threads.  Race conditions cannot occur since
only one coroutine may be active at any time.  Other coroutines can only
run across yield.

This coroutines implementation is based on the gtk-vnc implementation
written by Anthony Liguori <anthony@codemonkey.ws> but it has been
significantly rewritten by Kevin Wolf <kwolf@redhat.com> to use
setjmp()/longjmp() instead of the more expensive swapcontext() and by
Paolo Bonzini <pbonzini@redhat.com> for Windows Fibers support.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Makefile.objs
coroutine-ucontext.c [new file with mode: 0644]
coroutine-win32.c [new file with mode: 0644]
qemu-coroutine-int.h [new file with mode: 0644]
qemu-coroutine.c [new file with mode: 0644]
qemu-coroutine.h [new file with mode: 0644]
trace-events