1. 12 Sep, 2013 1 commit
    • Stefan Hajnoczi's avatar
      coroutine: add ./configure --disable-coroutine-pool · 70c60c08
      Stefan Hajnoczi authored
      The 'gthread' coroutine backend was written before the freelist (aka
      pool) existed in qemu-coroutine.c.
      
      This means that every thread is expected to exit when its coroutine
      terminates.  It is not possible to reuse threads from a pool.
      
      This patch automatically disables the pool when 'gthread' is used.  This
      allows the 'gthread' backend to work again (for example,
      tests/test-coroutine completes successfully instead of hanging).
      
      I considered implementing thread reuse but I don't want quirks like CPU
      affinity differences due to coroutine threads being recycled.  The
      'gthread' backend is a reference backend and it's therefore okay to skip
      the pool optimization.
      
      Note this patch also makes it easy to toggle the pool for benchmarking
      purposes:
      
        ./configure --with-coroutine-backend=ucontext \
                    --disable-coroutine-pool
      Reported-by: default avatarGabriel Kerneis <gabriel@kerneis.info>
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      Reviewed-by: default avatarGabriel Kerneis <gabriel@kerneis.info>
      Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
      70c60c08
  2. 24 May, 2013 2 commits
    • Stefan Hajnoczi's avatar
      coroutine: stop using AioContext in CoQueue · 02ffb504
      Stefan Hajnoczi authored
      qemu_co_queue_next(&queue) arranges that the next queued coroutine is
      run at a later point in time.  This deferred restart is useful because
      the caller may not want to transfer control yet.
      
      This behavior was implemented using QEMUBH in the past, which meant that
      CoQueue (and hence CoMutex and CoRwlock) had a dependency on the
      AioContext event loop.  This hidden dependency causes trouble when we
      move to a world with multiple event loops - now qemu_co_queue_next()
      needs to know which event loop to schedule the QEMUBH in.
      
      After pondering how to stash AioContext I realized the best solution is
      to not use AioContext at all.  This patch implements the deferred
      restart behavior purely in terms of coroutines and no longer uses
      QEMUBH.
      
      Here is how it works:
      
      Each Coroutine has a wakeup queue that starts out empty.  When
      qemu_co_queue_next() is called, the next coroutine is added to our
      wakeup queue.  The wakeup queue is processed when we yield or terminate.
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      02ffb504
    • Stefan Hajnoczi's avatar
      coroutine: protect global pool with a mutex · b84c4586
      Stefan Hajnoczi authored
      The coroutine freelist is a global pool of unused coroutines.  It avoids
      the setup/teardown overhead associated with the coroutine lifecycle.
      Since the pool is global, we need to synchronize access so that
      coroutines can be used outside the BQL.
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
      b84c4586
  3. 22 Feb, 2013 1 commit
  4. 19 Dec, 2012 1 commit
  5. 01 Aug, 2011 1 commit
    • Kevin Wolf's avatar
      coroutine: introduce coroutines · 00dccaf1
      Kevin Wolf authored
      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: default avatarKevin Wolf <kwolf@redhat.com>
      Signed-off-by: default avatarStefan Hajnoczi <stefanha@linux.vnet.ibm.com>
      00dccaf1