qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO
@ 2012-10-31 15:30 Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 01/39] janitor: move iovector functions out of cutils.c Paolo Bonzini
                   ` (39 more replies)
  0 siblings, 40 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

The following changes since commit aee0bf7d8d7564f8f2c40e4501695c492b7dd8d1:

  tap-win32: stubs to fix win32 build (2012-10-30 19:18:53 +0000)

are available in the git repository at:

  git://github.com/bonzini/qemu.git threadpool

for you to fetch changes up to f563a5d7a820424756f358e747238f03e866838a:

  Merge remote-tracking branch 'origin/master' into threadpool (2012-10-31 10:42:51 +0100)

Patches 1 to 12 eliminate the dependencies of qemu-tool.c on the main loop
and AIO infrastructure.  Otherwise the build rules for vscclient, tests
and qemu-ga become too hairy.  Patches 13 to 30 introduce AioContext
and a new portable AIO API based on EventNotifier.  Patches 31 to 38
introduce a generic threadpool that replaces posix-aio-compat.c.
Patch 39 introduces support for Win32 native AIO.  (As usual, Win32
bits are mostly there as a testbed for the flexibility of the API).

The patches are based in the remote branch on a known-good commit for
Win32 (because TCG is a bit broken in master).  Thus there is a merge
commit at the top to fix the trivial conflicts between patch 1 and the
later introduction of iov_copy.

Paolo

----------------------------------------------------------------

Paolo Bonzini (39):
      janitor: move iovector functions out of cutils.c
      build: move cutils.o and qemu-timer-common.o to oslib-obj-y
      compiler: use weak aliases to provide default definitions
      sockets: use weak aliases instead of qemu-tool.c
      fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
      iohandler: add weak alias in qemu-sockets.c, for qemu-ga
      win32: add weak version of qemu_fd_register
      qemu-timer: make initialization functions idempotent
      main-loop: unify qemu_init_main_loop between QEMU and tools
      qemu-tool: do not depend on qemu-timer.c
      build: opts-visitor is not really part of QAPI
      build: do not include main loop where it is not actually used
      event_notifier: add Win32 implementation
      event_notifier: enable it to use pipes
      vl: init main loop earlier
      aio: change qemu_aio_set_fd_handler to return void
      aio: provide platform-independent API
      aio: introduce AioContext, move bottom halves there
      aio: add I/O handlers to the AioContext interface
      aio: test node->deleted before calling io_flush
      aio: add non-blocking variant of aio_wait
      aio: prepare for introducing GSource-based dispatch
      aio: add Win32 implementation
      aio: make AioContexts GSources
      aio: add aio_notify
      aio: call aio_notify after setting I/O handlers
      main-loop: use GSource to poll AIO file descriptors
      main-loop: use aio_notify for qemu_notify_event
      aio: clean up now-unused functions
      linux-aio: use event notifiers
      qemu-thread: add QemuSemaphore
      aio: add generic thread-pool facility
      threadpool: do not take lock in event_notifier_ready
      block: switch posix-aio-compat to threadpool
      raw: merge posix-aio-compat.c into block/raw-posix.c
      raw-posix: rename raw-posix-aio.h, hide unavailable prototypes
      raw-win32: add emulated AIO support
      raw-posix: move linux-aio.c to block/
      raw-win32: implement native asynchronous I/O

 Makefile                             |   7 +-
 Makefile.objs                        |  22 +-
 aio-posix.c                          | 268 ++++++++++++++
 aio-win32.c                          | 215 +++++++++++
 aio.c                                | 194 ----------
 arch_init.h                          |   2 +-
 async.c                              | 118 +++++-
 block/Makefile.objs                  |   9 +-
 linux-aio.c => block/linux-aio.c     |  52 ++-
 block/{raw-posix-aio.h => raw-aio.h} |  29 +-
 block/raw-posix.c                    | 308 +++++++++++++++-
 block/raw-win32.c                    | 221 +++++++++---
 block/win32-aio.c                    | 226 ++++++++++++
 compiler.h                           |  11 +-
 cutils.c                             | 108 ------
 event_notifier-posix.c               | 120 +++++++
 event_notifier-win32.c               |  59 +++
 event_notifier.c                     |  67 ----
 event_notifier.h                     |  20 +-
 hw/hw.h                              |   1 +
 iohandler.c                          |   1 +
 iov.c                                | 103 ++++++
 main-loop.c                          | 157 +++-----
 main-loop.h                          |  66 +---
 osdep.c                              |  30 ++
 oslib-posix.c                        |  31 --
 oslib-win32.c                        |   5 +
 posix-aio-compat.c                   | 679 -----------------------------------
 qapi/Makefile.objs                   |   4 +-
 qemu-aio.h                           | 206 ++++++++++-
 qemu-char.h                          |   1 +
 qemu-common.h                        |   3 +-
 qemu-coroutine-lock.c                |   2 +-
 qemu-os-win32.h                      |   1 -
 qemu-sockets.c                       |  18 +
 qemu-thread-posix.c                  |  80 +++++
 qemu-thread-posix.h                  |   5 +
 qemu-thread-win32.c                  |  35 ++
 qemu-thread-win32.h                  |   4 +
 qemu-thread.h                        |   7 +
 qemu-timer.c                         |  12 +-
 qemu-tool.c                          |  35 +-
 qemu-user.c                          |  20 --
 qmp.c                                |   3 +-
 tests/Makefile                       |   8 +-
 thread-pool.c                        | 289 +++++++++++++++
 thread-pool.h                        |  34 ++
 trace-events                         |   5 +
 vl.c                                 |  17 +-
 49 file modificati, 2429 inserzioni(+), 1489 rimozioni(-)
 create mode 100644 aio-posix.c
 create mode 100644 aio-win32.c
 delete mode 100644 aio.c
 rename linux-aio.c => block/linux-aio.c (82%)
 rename block/{raw-posix-aio.h => raw-aio.h} (71%)
 create mode 100644 block/win32-aio.c
 create mode 100644 event_notifier-posix.c
 create mode 100644 event_notifier-win32.c
 delete mode 100644 event_notifier.c
 delete mode 100644 posix-aio-compat.c
 create mode 100644 thread-pool.c
 create mode 100644 thread-pool.h
-- 
1.7.12.1

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 01/39] janitor: move iovector functions out of cutils.c
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 02/39] build: move cutils.o and qemu-timer-common.o to oslib-obj-y Paolo Bonzini
                   ` (38 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This removes the dependency of cutils.c on iov.c, and lets us remove
iov.o from several builds.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile       |   2 +-
 Makefile.objs  |   4 +--
 cutils.c       | 103 ---------------------------------------------------------
 iov.c          | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile |   2 +-
 5 file modificati, 107 inserzioni(+), 107 rimozioni(-)

diff --git a/Makefile b/Makefile
index 17e2d58..ca71601 100644
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,7 @@ qemu-img.o: qemu-img-cmds.h
 
 tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
 	qemu-timer-common.o main-loop.o notify.o \
-	iohandler.o cutils.o iov.o async.o error.o
+	iohandler.o cutils.o async.o error.o
 tools-obj-$(CONFIG_POSIX) += compatfd.o
 
 qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
diff --git a/Makefile.objs b/Makefile.objs
index 9eca179..99a268e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -92,7 +92,7 @@ common-obj-y += ui/
 common-obj-y += bt-host.o bt-vhci.o
 
 common-obj-y += dma-helpers.o
-common-obj-y += iov.o acl.o
+common-obj-y += acl.o
 common-obj-$(CONFIG_POSIX) += compatfd.o
 common-obj-y += event_notifier.o
 common-obj-y += qemu-timer.o qemu-timer-common.o
@@ -113,7 +113,7 @@ endif
 user-obj-y =
 user-obj-y += envlist.o path.o
 user-obj-y += tcg-runtime.o host-utils.o
-user-obj-y += cutils.o iov.o cache-utils.o
+user-obj-y += cutils.o cache-utils.o
 user-obj-y += module.o
 user-obj-y += qemu-user.o
 user-obj-y += $(trace-obj-y)
diff --git a/cutils.c b/cutils.c
index 8edd8fa..6f9f799 100644
--- a/cutils.c
+++ b/cutils.c
@@ -142,109 +142,6 @@ int qemu_fdatasync(int fd)
 #endif
 }
 
-/* io vectors */
-
-void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
-{
-    qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec));
-    qiov->niov = 0;
-    qiov->nalloc = alloc_hint;
-    qiov->size = 0;
-}
-
-void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
-{
-    int i;
-
-    qiov->iov = iov;
-    qiov->niov = niov;
-    qiov->nalloc = -1;
-    qiov->size = 0;
-    for (i = 0; i < niov; i++)
-        qiov->size += iov[i].iov_len;
-}
-
-void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
-{
-    assert(qiov->nalloc != -1);
-
-    if (qiov->niov == qiov->nalloc) {
-        qiov->nalloc = 2 * qiov->nalloc + 1;
-        qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
-    }
-    qiov->iov[qiov->niov].iov_base = base;
-    qiov->iov[qiov->niov].iov_len = len;
-    qiov->size += len;
-    ++qiov->niov;
-}
-
-/*
- * Concatenates (partial) iovecs from src to the end of dst.
- * It starts copying after skipping `soffset' bytes at the
- * beginning of src and adds individual vectors from src to
- * dst copies up to `sbytes' bytes total, or up to the end
- * of src if it comes first.  This way, it is okay to specify
- * very large value for `sbytes' to indicate "up to the end
- * of src".
- * Only vector pointers are processed, not the actual data buffers.
- */
-void qemu_iovec_concat(QEMUIOVector *dst,
-                       QEMUIOVector *src, size_t soffset, size_t sbytes)
-{
-    int i;
-    size_t done;
-    struct iovec *siov = src->iov;
-    assert(dst->nalloc != -1);
-    assert(src->size >= soffset);
-    for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
-        if (soffset < siov[i].iov_len) {
-            size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
-            qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
-            done += len;
-            soffset = 0;
-        } else {
-            soffset -= siov[i].iov_len;
-        }
-    }
-    /* return done; */
-}
-
-void qemu_iovec_destroy(QEMUIOVector *qiov)
-{
-    assert(qiov->nalloc != -1);
-
-    qemu_iovec_reset(qiov);
-    g_free(qiov->iov);
-    qiov->nalloc = 0;
-    qiov->iov = NULL;
-}
-
-void qemu_iovec_reset(QEMUIOVector *qiov)
-{
-    assert(qiov->nalloc != -1);
-
-    qiov->niov = 0;
-    qiov->size = 0;
-}
-
-size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
-                         void *buf, size_t bytes)
-{
-    return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
-}
-
-size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
-                           const void *buf, size_t bytes)
-{
-    return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
-}
-
-size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
-                         int fillc, size_t bytes)
-{
-    return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
-}
-
 /*
  * Checks if a buffer is all zeroes
  *
diff --git a/iov.c b/iov.c
index c6a66f0..ae17e7d 100644
--- a/iov.c
+++ b/iov.c
@@ -228,3 +228,106 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
         fprintf(fp, "\n");
     }
 }
+
+/* io vectors */
+
+void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
+{
+    qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec));
+    qiov->niov = 0;
+    qiov->nalloc = alloc_hint;
+    qiov->size = 0;
+}
+
+void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
+{
+    int i;
+
+    qiov->iov = iov;
+    qiov->niov = niov;
+    qiov->nalloc = -1;
+    qiov->size = 0;
+    for (i = 0; i < niov; i++)
+        qiov->size += iov[i].iov_len;
+}
+
+void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
+{
+    assert(qiov->nalloc != -1);
+
+    if (qiov->niov == qiov->nalloc) {
+        qiov->nalloc = 2 * qiov->nalloc + 1;
+        qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
+    }
+    qiov->iov[qiov->niov].iov_base = base;
+    qiov->iov[qiov->niov].iov_len = len;
+    qiov->size += len;
+    ++qiov->niov;
+}
+
+/*
+ * Concatenates (partial) iovecs from src to the end of dst.
+ * It starts copying after skipping `soffset' bytes at the
+ * beginning of src and adds individual vectors from src to
+ * dst copies up to `sbytes' bytes total, or up to the end
+ * of src if it comes first.  This way, it is okay to specify
+ * very large value for `sbytes' to indicate "up to the end
+ * of src".
+ * Only vector pointers are processed, not the actual data buffers.
+ */
+void qemu_iovec_concat(QEMUIOVector *dst,
+                       QEMUIOVector *src, size_t soffset, size_t sbytes)
+{
+    int i;
+    size_t done;
+    struct iovec *siov = src->iov;
+    assert(dst->nalloc != -1);
+    assert(src->size >= soffset);
+    for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
+        if (soffset < siov[i].iov_len) {
+            size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
+            qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
+            done += len;
+            soffset = 0;
+        } else {
+            soffset -= siov[i].iov_len;
+        }
+    }
+    /* return done; */
+}
+
+void qemu_iovec_destroy(QEMUIOVector *qiov)
+{
+    assert(qiov->nalloc != -1);
+
+    qemu_iovec_reset(qiov);
+    g_free(qiov->iov);
+    qiov->nalloc = 0;
+    qiov->iov = NULL;
+}
+
+void qemu_iovec_reset(QEMUIOVector *qiov)
+{
+    assert(qiov->nalloc != -1);
+
+    qiov->niov = 0;
+    qiov->size = 0;
+}
+
+size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
+                         void *buf, size_t bytes)
+{
+    return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
+}
+
+size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
+                           const void *buf, size_t bytes)
+{
+    return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
+}
+
+size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
+                         int fillc, size_t bytes)
+{
+    return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
+}
diff --git a/tests/Makefile b/tests/Makefile
index 86c9b79..945c823 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -48,7 +48,7 @@ tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.
 tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o
 tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
-tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y)
+tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) iov.o
 tests/test-iov$(EXESUF): tests/test-iov.o iov.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 02/39] build: move cutils.o and qemu-timer-common.o to oslib-obj-y
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 01/39] janitor: move iovector functions out of cutils.c Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 03/39] compiler: use weak aliases to provide default definitions Paolo Bonzini
                   ` (37 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile      | 3 +--
 Makefile.objs | 6 +++---
 2 file modificati, 4 inserzioni(+), 5 rimozioni(-)

diff --git a/Makefile b/Makefile
index ca71601..4bfeeab 100644
--- a/Makefile
+++ b/Makefile
@@ -160,8 +160,7 @@ endif
 qemu-img.o: qemu-img-cmds.h
 
 tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
-	qemu-timer-common.o main-loop.o notify.o \
-	iohandler.o cutils.o async.o error.o
+	main-loop.o notify.o iohandler.o async.o error.o
 tools-obj-$(CONFIG_POSIX) += compatfd.o
 
 qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
diff --git a/Makefile.objs b/Makefile.objs
index 99a268e..9e36166 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -19,7 +19,7 @@ universal-obj-y += $(qom-obj-y)
 
 #######################################################################
 # oslib-obj-y is code depending on the OS (win32 vs posix)
-oslib-obj-y = osdep.o
+oslib-obj-y = osdep.o cutils.o qemu-timer-common.o
 oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
 oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
 
@@ -41,7 +41,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
-block-obj-y = cutils.o iov.o cache-utils.o qemu-option.o module.o async.o
+block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
 block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o
 block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
@@ -113,7 +113,7 @@ endif
 user-obj-y =
 user-obj-y += envlist.o path.o
 user-obj-y += tcg-runtime.o host-utils.o
-user-obj-y += cutils.o cache-utils.o
+user-obj-y += cache-utils.o
 user-obj-y += module.o
 user-obj-y += qemu-user.o
 user-obj-y += $(trace-obj-y)
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 03/39] compiler: use weak aliases to provide default definitions
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 01/39] janitor: move iovector functions out of cutils.c Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 02/39] build: move cutils.o and qemu-timer-common.o to oslib-obj-y Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 04/39] sockets: use weak aliases instead of qemu-tool.c Paolo Bonzini
                   ` (36 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This is simpler and more portable.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch_init.h |  2 +-
 compiler.h  | 11 ++++-------
 qmp.c       |  3 ++-
 3 file modificati, 7 inserzioni(+), 9 rimozioni(-)

diff --git a/arch_init.h b/arch_init.h
index d9c572a..5fc780c 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -34,6 +34,6 @@ int tcg_available(void);
 int kvm_available(void);
 int xen_available(void);
 
-CpuDefinitionInfoList GCC_WEAK_DECL *arch_query_cpu_definitions(Error **errp);
+CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp);
 
 #endif
diff --git a/compiler.h b/compiler.h
index c734a71..58865d6 100644
--- a/compiler.h
+++ b/compiler.h
@@ -50,16 +50,13 @@
 #   define __printf__ __gnu_printf__
 #  endif
 # endif
-#if defined(_WIN32)
-#define GCC_WEAK __attribute__((weak))
-#define GCC_WEAK_DECL GCC_WEAK
-#else
-#define GCC_WEAK __attribute__((weak))
-#define GCC_WEAK_DECL
-#endif
+# define QEMU_WEAK_ALIAS(newname, oldname) \
+        typeof(oldname) newname __attribute__((weak, alias (#oldname)))
 #else
 #define GCC_ATTR /**/
 #define GCC_FMT_ATTR(n, m)
+#define QEMU_WEAK_ALIAS(newname, oldname) \
+        _Pragma("weak " #newname "=" #oldname)
 #endif
 
 #endif /* COMPILER_H */
diff --git a/qmp.c b/qmp.c
index 31bc3bf..df952b6 100644
--- a/qmp.c
+++ b/qmp.c
@@ -466,11 +466,12 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
     return prop_list;
 }
 
-CpuDefinitionInfoList GCC_WEAK *arch_query_cpu_definitions(Error **errp)
+static CpuDefinitionInfoList *default_arch_query_cpu_definitions(Error **errp)
 {
     error_set(errp, QERR_NOT_SUPPORTED);
     return NULL;
 }
+QEMU_WEAK_ALIAS(arch_query_cpu_definitions, default_arch_query_cpu_definitions);
 
 CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 {
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 04/39] sockets: use weak aliases instead of qemu-tool.c
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (2 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 03/39] compiler: use weak aliases to provide default definitions Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c Paolo Bonzini
                   ` (35 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

qemu-tool.c has its own (largeish) set of dependencies.  Weak aliases
can be placed directly where people use them, and do not contribute
to increasing the dependencies of generic utility files.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-sockets.c | 7 +++++++
 qemu-tool.c    | 6 ------
 2 file modificati, 7 inserzioni(+), 6 rimozioni(-)

diff --git a/qemu-sockets.c b/qemu-sockets.c
index cfed9c5..225cd0c 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -967,3 +967,10 @@ int socket_init(void)
 #endif
     return 0;
 }
+
+static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp)
+{
+    error_setg(errp, "only QEMU supports file descriptor passing");
+    return -1;
+}
+QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd);
diff --git a/qemu-tool.c b/qemu-tool.c
index da4c05a..f2f9813 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -38,12 +38,6 @@ const char *qemu_get_vm_name(void)
 
 Monitor *cur_mon;
 
-int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
-{
-    error_setg(errp, "only QEMU supports file descriptor passing");
-    return -1;
-}
-
 void vm_stop(RunState state)
 {
     abort();
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (3 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 04/39] sockets: use weak aliases instead of qemu-tool.c Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-11-15 18:01   ` Stefan Weil
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 06/39] iohandler: add weak alias in qemu-sockets.c, for qemu-ga Paolo Bonzini
                   ` (34 subsequent siblings)
  39 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cutils.c      |  5 -----
 osdep.c       | 30 ++++++++++++++++++++++++++++++
 qemu-common.h |  1 -
 qemu-tool.c   | 20 --------------------
 qemu-user.c   | 20 --------------------
 5 file modificati, 30 inserzioni(+), 46 rimozioni(-)

diff --git a/cutils.c b/cutils.c
index 6f9f799..4f0692f 100644
--- a/cutils.c
+++ b/cutils.c
@@ -280,11 +280,6 @@ int qemu_parse_fd(const char *param)
     return fd;
 }
 
-int qemu_parse_fdset(const char *param)
-{
-    return qemu_parse_fd(param);
-}
-
 /* round down to the nearest power of 2*/
 int64_t pow2floor(int64_t value)
 {
diff --git a/osdep.c b/osdep.c
index 3b25297..0061f74 100644
--- a/osdep.c
+++ b/osdep.c
@@ -144,6 +144,11 @@ fail:
     errno = serrno;
     return -1;
 }
+
+static int qemu_parse_fdset(const char *param)
+{
+    return qemu_parse_fd(param);
+}
 #endif
 
 /*
@@ -404,3 +409,28 @@ bool fips_get_state(void)
 {
     return fips_enabled;
 }
+
+
+static int default_fdset_get_fd(int64_t fdset_id, int flags)
+{
+    return -1;
+}
+QEMU_WEAK_ALIAS(monitor_fdset_get_fd, default_fdset_get_fd);
+
+static int default_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
+{
+    return -1;
+}
+QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add);
+
+static int default_fdset_dup_fd_remove(int dup_fd)
+{
+    return -1;
+}
+QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove);
+
+static int default_fdset_dup_fd_find(int dup_fd)
+{
+    return -1;
+}
+QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_find, default_fdset_dup_fd_find);
diff --git a/qemu-common.h b/qemu-common.h
index b54612b..36ce522 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -167,7 +167,6 @@ int qemu_fls(int i);
 int qemu_fdatasync(int fd);
 int fcntl_setfl(int fd, int flag);
 int qemu_parse_fd(const char *param);
-int qemu_parse_fdset(const char *param);
 
 /*
  * strtosz() suffixes used to specify the default treatment of an
diff --git a/qemu-tool.c b/qemu-tool.c
index f2f9813..84273ae 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -68,26 +68,6 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
 {
 }
 
-int monitor_fdset_get_fd(int64_t fdset_id, int flags)
-{
-    return -1;
-}
-
-int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
-{
-    return -1;
-}
-
-int monitor_fdset_dup_fd_remove(int dup_fd)
-{
-    return -1;
-}
-
-int monitor_fdset_dup_fd_find(int dup_fd)
-{
-    return -1;
-}
-
 int64_t cpu_get_clock(void)
 {
     return qemu_get_clock_ns(rt_clock);
diff --git a/qemu-user.c b/qemu-user.c
index 13fb9ae..08ccb0f 100644
--- a/qemu-user.c
+++ b/qemu-user.c
@@ -35,23 +35,3 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 void monitor_set_error(Monitor *mon, QError *qerror)
 {
 }
-
-int monitor_fdset_get_fd(int64_t fdset_id, int flags)
-{
-    return -1;
-}
-
-int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
-{
-    return -1;
-}
-
-int monitor_fdset_dup_fd_remove(int dup_fd)
-{
-    return -1;
-}
-
-int monitor_fdset_dup_fd_find(int dup_fd)
-{
-    return -1;
-}
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 06/39] iohandler: add weak alias in qemu-sockets.c, for qemu-ga
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (4 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 07/39] win32: add weak version of qemu_fd_register Paolo Bonzini
                   ` (33 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-sockets.c | 11 +++++++++++
 1 file modificato, 11 inserzioni(+)

diff --git a/qemu-sockets.c b/qemu-sockets.c
index 225cd0c..f2a6371 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -974,3 +974,14 @@ static int default_monitor_get_fd(Monitor *mon, const char *name, Error **errp)
     return -1;
 }
 QEMU_WEAK_ALIAS(monitor_get_fd, default_monitor_get_fd);
+
+static int default_qemu_set_fd_handler2(int fd,
+                                        IOCanReadHandler *fd_read_poll,
+                                        IOHandler *fd_read,
+                                        IOHandler *fd_write,
+                                        void *opaque)
+
+{
+    abort();
+}
+QEMU_WEAK_ALIAS(qemu_set_fd_handler2, default_qemu_set_fd_handler2);
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 07/39] win32: add weak version of qemu_fd_register
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (5 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 06/39] iohandler: add weak alias in qemu-sockets.c, for qemu-ga Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 08/39] qemu-timer: make initialization functions idempotent Paolo Bonzini
                   ` (32 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 oslib-win32.c | 5 +++++
 1 file modificato, 5 inserzioni(+)

diff --git a/oslib-win32.c b/oslib-win32.c
index 51b33e8..9ca83df 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -150,3 +150,8 @@ int qemu_get_thread_id(void)
 {
     return GetCurrentThreadId();
 }
+
+static void default_qemu_fd_register(int fd)
+{
+}
+QEMU_WEAK_ALIAS(qemu_fd_register, default_qemu_fd_register);
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 08/39] qemu-timer: make initialization functions idempotent
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (6 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 07/39] win32: add weak version of qemu_fd_register Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 09/39] main-loop: unify qemu_init_main_loop between QEMU and tools Paolo Bonzini
                   ` (31 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-timer.c | 12 +++++++++---
 1 file modificato, 9 inserzioni(+), 3 rimozioni(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index 908a103..b71e9a6 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -430,9 +430,11 @@ void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
 
 void init_clocks(void)
 {
-    rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
-    vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
-    host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
+    if (!rt_clock) {
+        rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
+        vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
+        host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
+    }
 }
 
 uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
@@ -745,6 +747,10 @@ int init_timer_alarm(void)
     struct qemu_alarm_timer *t = NULL;
     int i, err = -1;
 
+    if (alarm_timer) {
+        return 0;
+    }
+
     for (i = 0; alarm_timers[i].name; i++) {
         t = &alarm_timers[i];
 
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 09/39] main-loop: unify qemu_init_main_loop between QEMU and tools
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (7 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 08/39] qemu-timer: make initialization functions idempotent Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 10/39] qemu-tool: do not depend on qemu-timer.c Paolo Bonzini
                   ` (30 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 main-loop.c |  5 ++++-
 main-loop.h | 10 ----------
 qemu-tool.c |  7 -------
 vl.c        |  5 -----
 4 file modificati, 4 inserzioni(+), 23 rimozioni(-)

diff --git a/main-loop.c b/main-loop.c
index eb3b6e6..baefe41 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -199,10 +199,13 @@ static int qemu_signal_init(void)
 }
 #endif
 
-int main_loop_init(void)
+int qemu_init_main_loop(void)
 {
     int ret;
 
+    init_clocks();
+    init_timer_alarm();
+
     qemu_mutex_lock_iothread();
     ret = qemu_signal_init();
     if (ret) {
diff --git a/main-loop.h b/main-loop.h
index dce1cd9..91a0aff 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -43,16 +43,6 @@
 int qemu_init_main_loop(void);
 
 /**
- * main_loop_init: Initializes main loop
- *
- * Internal (but shared for compatibility reasons) initialization routine
- * for the main loop. This should not be used by applications directly,
- * use qemu_init_main_loop() instead.
- *
- */
-int main_loop_init(void);
-
-/**
  * main_loop_wait: Run one iteration of the main loop.
  *
  * If @nonblocking is true, poll for events, otherwise suspend until
diff --git a/qemu-tool.c b/qemu-tool.c
index 84273ae..28a4e8d 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -92,13 +92,6 @@ void qemu_clock_warp(QEMUClock *clock)
 {
 }
 
-int qemu_init_main_loop(void)
-{
-    init_clocks();
-    init_timer_alarm();
-    return main_loop_init();
-}
-
 void slirp_update_timeout(uint32_t *timeout)
 {
 }
diff --git a/vl.c b/vl.c
index 9f99ef4..b3186fa 100644
--- a/vl.c
+++ b/vl.c
@@ -2357,11 +2357,6 @@ static void free_and_trace(gpointer mem)
     free(mem);
 }
 
-int qemu_init_main_loop(void)
-{
-    return main_loop_init();
-}
-
 int main(int argc, char **argv, char **envp)
 {
     int i;
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 10/39] qemu-tool: do not depend on qemu-timer.c
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (8 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 09/39] main-loop: unify qemu_init_main_loop between QEMU and tools Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 11/39] build: opts-visitor is not really part of QAPI Paolo Bonzini
                   ` (29 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qemu-tool.c | 2 +-
 1 file modificato, 1 inserzione(+). 1 rimozione(-)

diff --git a/qemu-tool.c b/qemu-tool.c
index 28a4e8d..b46631e 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -70,7 +70,7 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
 
 int64_t cpu_get_clock(void)
 {
-    return qemu_get_clock_ns(rt_clock);
+    return get_clock_realtime();
 }
 
 int64_t cpu_get_icount(void)
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 11/39] build: opts-visitor is not really part of QAPI
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (9 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 10/39] qemu-tool: do not depend on qemu-timer.c Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 12/39] build: do not include main loop where it is not actually used Paolo Bonzini
                   ` (28 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

It is only used by QEMU itself, do not build it into the tests.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 qapi/Makefile.objs | 4 +++-
 1 file modificato, 3 inserzioni(+). 1 rimozione(-)

diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
index 5f5846e..f9bd3b9 100644
--- a/qapi/Makefile.objs
+++ b/qapi/Makefile.objs
@@ -1,3 +1,5 @@
 qapi-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
 qapi-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
-qapi-obj-y += string-input-visitor.o string-output-visitor.o opts-visitor.o
+qapi-obj-y += string-input-visitor.o string-output-visitor.o
+
+common-obj-y += opts-visitor.o
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 12/39] build: do not include main loop where it is not actually used
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (10 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 11/39] build: opts-visitor is not really part of QAPI Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 13/39] event_notifier: add Win32 implementation Paolo Bonzini
                   ` (27 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile       | 6 +++---
 Makefile.objs  | 5 ++---
 tests/Makefile | 8 ++++----
 3 file modificati, 9 inserzioni(+), 10 rimozioni(-)

diff --git a/Makefile b/Makefile
index 4bfeeab..3ff63df 100644
--- a/Makefile
+++ b/Makefile
@@ -160,7 +160,7 @@ endif
 qemu-img.o: qemu-img-cmds.h
 
 tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
-	main-loop.o notify.o iohandler.o async.o error.o
+	main-loop.o iohandler.o error.o
 tools-obj-$(CONFIG_POSIX) += compatfd.o
 
 qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
@@ -169,7 +169,7 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
-vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o
+vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) libcacard/vscclient.o
 	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
 
 fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
@@ -212,7 +212,7 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
 $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 
-qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(tools-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y)
+qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(oslib-obj-y) $(trace-obj-y) $(qapi-obj-y) $(qobject-obj-y) $(version-obj-y)
 
 QEMULIBS=libuser libdis libdis-user
 
diff --git a/Makefile.objs b/Makefile.objs
index 9e36166..54daa9f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -228,9 +228,8 @@ universal-obj-y += $(qapi-obj-y)
 ######################################################################
 # guest agent
 
-qga-obj-y = qga/ qemu-ga.o module.o
-qga-obj-$(CONFIG_WIN32) += oslib-win32.o
-qga-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-sockets.o qemu-option.o
+qga-obj-y = qga/ qemu-ga.o module.o qemu-tool.o
+qga-obj-$(CONFIG_POSIX) += qemu-sockets.o qemu-option.o
 
 vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
diff --git a/tests/Makefile b/tests/Makefile
index 945c823..9bf0765 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -36,7 +36,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
 	tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
 	tests/test-qmp-commands.o tests/test-visitor-serialization.o
 
-test-qapi-obj-y =  $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y)
+test-qapi-obj-y =  $(qobject-obj-y) $(qapi-obj-y) qemu-tool.o
 test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o
 test-qapi-obj-y += module.o
 
@@ -47,8 +47,8 @@ tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o
 tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o
 tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o
 tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o
-tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
-tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) iov.o
+tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) qemu-tool.o
+tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y) $(block-obj-y) iov.o
 tests/test-iov$(EXESUF): tests/test-iov.o iov.o
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
@@ -81,7 +81,7 @@ TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
 QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
 check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
 
-qtest-obj-y = tests/libqtest.o $(oslib-obj-y) $(tools-obj-y)
+qtest-obj-y = tests/libqtest.o $(oslib-obj-y)
 $(check-qtest-y): $(qtest-obj-y)
 
 .PHONY: check-help
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 13/39] event_notifier: add Win32 implementation
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (11 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 12/39] build: do not include main loop where it is not actually used Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 14/39] event_notifier: enable it to use pipes Paolo Bonzini
                   ` (26 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.objs                              |  3 +-
 event_notifier.c => event_notifier-posix.c |  0
 event_notifier-win32.c                     | 59 ++++++++++++++++++++++++++++++
 event_notifier.h                           | 17 ++++++++-
 qemu-os-win32.h                            |  1 -
 5 file modificati, 76 inserzioni(+), 4 rimozioni(-)
 rename event_notifier.c => event_notifier-posix.c (100%)
 create mode 100644 event_notifier-win32.c

diff --git a/Makefile.objs b/Makefile.objs
index 54daa9f..5b39c33 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -94,7 +94,8 @@ common-obj-y += bt-host.o bt-vhci.o
 common-obj-y += dma-helpers.o
 common-obj-y += acl.o
 common-obj-$(CONFIG_POSIX) += compatfd.o
-common-obj-y += event_notifier.o
+common-obj-$(CONFIG_POSIX) += event_notifier-posix.o
+common-obj-$(CONFIG_WIN32) += event_notifier-win32.o
 common-obj-y += qemu-timer.o qemu-timer-common.o
 common-obj-y += qtest.o
 common-obj-y += vl.o
diff --git a/event_notifier.c b/event_notifier-posix.c
similarity index 100%
rename from event_notifier.c
rename to event_notifier-posix.c
diff --git a/event_notifier-win32.c b/event_notifier-win32.c
new file mode 100644
index 0000000..c723dad
--- /dev/null
+++ b/event_notifier-win32.c
@@ -0,0 +1,59 @@
+/*
+ * event notifier support
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Authors:
+ *  Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "event_notifier.h"
+#include "main-loop.h"
+
+int event_notifier_init(EventNotifier *e, int active)
+{
+    e->event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    assert(e->event);
+    return 0;
+}
+
+void event_notifier_cleanup(EventNotifier *e)
+{
+    CloseHandle(e->event);
+}
+
+HANDLE event_notifier_get_handle(EventNotifier *e)
+{
+    return e->event;
+}
+
+int event_notifier_set_handler(EventNotifier *e,
+                               EventNotifierHandler *handler)
+{
+    if (handler) {
+        return qemu_add_wait_object(e->event, (IOHandler *)handler, e);
+    } else {
+        qemu_del_wait_object(e->event, (IOHandler *)handler, e);
+        return 0;
+    }
+}
+
+int event_notifier_set(EventNotifier *e)
+{
+    SetEvent(e->event);
+    return 0;
+}
+
+int event_notifier_test_and_clear(EventNotifier *e)
+{
+    int ret = WaitForSingleObject(e->event, 0);
+    if (ret == WAIT_OBJECT_0) {
+        ResetEvent(e->event);
+        return true;
+    }
+    return false;
+}
diff --git a/event_notifier.h b/event_notifier.h
index f0ec2f2..b283a49 100644
--- a/event_notifier.h
+++ b/event_notifier.h
@@ -15,18 +15,31 @@
 
 #include "qemu-common.h"
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 struct EventNotifier {
+#ifdef _WIN32
+    HANDLE event;
+#else
     int fd;
+#endif
 };
 
 typedef void EventNotifierHandler(EventNotifier *);
 
-void event_notifier_init_fd(EventNotifier *, int fd);
 int event_notifier_init(EventNotifier *, int active);
 void event_notifier_cleanup(EventNotifier *);
-int event_notifier_get_fd(EventNotifier *);
 int event_notifier_set(EventNotifier *);
 int event_notifier_test_and_clear(EventNotifier *);
 int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *);
 
+#ifdef CONFIG_POSIX
+void event_notifier_init_fd(EventNotifier *, int fd);
+int event_notifier_get_fd(EventNotifier *);
+#else
+HANDLE event_notifier_get_handle(EventNotifier *);
+#endif
+
 #endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 8ba466d..d0e9234 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -28,7 +28,6 @@
 
 #include <windows.h>
 #include <winsock2.h>
-#include "main-loop.h"
 
 /* Workaround for older versions of MinGW. */
 #ifndef ECONNREFUSED
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 14/39] event_notifier: enable it to use pipes
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (12 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 13/39] event_notifier: add Win32 implementation Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier Paolo Bonzini
                   ` (25 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This takes the eventfd emulation code from the main loop.  When the
EventNotifier is used for the main loop too, we need this compatibility
code.

Without CONFIG_EVENTFD, event_notifier_get_fd is only usable for the
"read" side of the notifier, for example to set a select() handler.

The return value of event_notifier_set changes to the cleaner 0/-errno.
No caller is actually checking the return value.

Reviewed-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 event_notifier-posix.c | 85 ++++++++++++++++++++++++++++++++++++++++----------
 event_notifier.h       |  3 +-
 2 file modificati, 71 inserzioni(+), 17 rimozioni(-)

diff --git a/event_notifier-posix.c b/event_notifier-posix.c
index 2c207e1..6f3239a 100644
--- a/event_notifier-posix.c
+++ b/event_notifier-posix.c
@@ -20,48 +20,101 @@
 
 void event_notifier_init_fd(EventNotifier *e, int fd)
 {
-    e->fd = fd;
+    e->rfd = fd;
+    e->wfd = fd;
 }
 
 int event_notifier_init(EventNotifier *e, int active)
 {
+    int fds[2];
+    int ret;
+
 #ifdef CONFIG_EVENTFD
-    int fd = eventfd(!!active, EFD_NONBLOCK | EFD_CLOEXEC);
-    if (fd < 0)
-        return -errno;
-    e->fd = fd;
-    return 0;
+    ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
 #else
-    return -ENOSYS;
+    ret = -1;
+    errno = ENOSYS;
 #endif
+    if (ret >= 0) {
+        e->rfd = e->wfd = ret;
+    } else {
+        if (errno != ENOSYS) {
+            return -errno;
+        }
+        if (qemu_pipe(fds) < 0) {
+            return -errno;
+        }
+        ret = fcntl_setfl(fds[0], O_NONBLOCK);
+        if (ret < 0) {
+            ret = -errno;
+            goto fail;
+        }
+        ret = fcntl_setfl(fds[1], O_NONBLOCK);
+        if (ret < 0) {
+            ret = -errno;
+            goto fail;
+        }
+        e->rfd = fds[0];
+        e->wfd = fds[1];
+    }
+    if (active) {
+        event_notifier_set(e);
+    }
+    return 0;
+
+fail:
+    close(fds[0]);
+    close(fds[1]);
+    return ret;
 }
 
 void event_notifier_cleanup(EventNotifier *e)
 {
-    close(e->fd);
+    if (e->rfd != e->wfd) {
+        close(e->rfd);
+    }
+    close(e->wfd);
 }
 
 int event_notifier_get_fd(EventNotifier *e)
 {
-    return e->fd;
+    return e->rfd;
 }
 
 int event_notifier_set_handler(EventNotifier *e,
                                EventNotifierHandler *handler)
 {
-    return qemu_set_fd_handler(e->fd, (IOHandler *)handler, NULL, e);
+    return qemu_set_fd_handler(e->rfd, (IOHandler *)handler, NULL, e);
 }
 
 int event_notifier_set(EventNotifier *e)
 {
-    uint64_t value = 1;
-    int r = write(e->fd, &value, sizeof(value));
-    return r == sizeof(value);
+    static const uint64_t value = 1;
+    ssize_t ret;
+
+    do {
+        ret = write(e->wfd, &value, sizeof(value));
+    } while (ret < 0 && errno == EINTR);
+
+    /* EAGAIN is fine, a read must be pending.  */
+    if (ret < 0 && errno != EAGAIN) {
+        return -errno;
+    }
+    return 0;
 }
 
 int event_notifier_test_and_clear(EventNotifier *e)
 {
-    uint64_t value;
-    int r = read(e->fd, &value, sizeof(value));
-    return r == sizeof(value);
+    int value;
+    ssize_t len;
+    char buffer[512];
+
+    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
+    value = 0;
+    do {
+        len = read(e->rfd, buffer, sizeof(buffer));
+        value |= (len > 0);
+    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
+
+    return value;
 }
diff --git a/event_notifier.h b/event_notifier.h
index b283a49..88b57af 100644
--- a/event_notifier.h
+++ b/event_notifier.h
@@ -23,7 +23,8 @@ struct EventNotifier {
 #ifdef _WIN32
     HANDLE event;
 #else
-    int fd;
+    int rfd;
+    int wfd;
 #endif
 };
 
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (13 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 14/39] event_notifier: enable it to use pipes Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-11-02  7:26   ` Jan Kiszka
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 16/39] aio: change qemu_aio_set_fd_handler to return void Paolo Bonzini
                   ` (24 subsequent siblings)
  39 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Otherwise, chardevs will not be able to create a bottom half as soon
as that will require an AioContext.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 vl.c | 12 ++++++------
 1 file modificato, 6 inserzioni(+), 6 rimozioni(-)

diff --git a/vl.c b/vl.c
index b3186fa..f84e969 100644
--- a/vl.c
+++ b/vl.c
@@ -3311,6 +3311,12 @@ int main(int argc, char **argv, char **envp)
     }
     loc_set_none();
 
+    qemu_init_cpu_loop();
+    if (qemu_init_main_loop()) {
+        fprintf(stderr, "qemu_init_main_loop failed\n");
+        exit(1);
+    }
+
     if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) {
         exit(1);
     }
@@ -3463,12 +3469,6 @@ int main(int argc, char **argv, char **envp)
 
     configure_accelerator();
 
-    qemu_init_cpu_loop();
-    if (qemu_init_main_loop()) {
-        fprintf(stderr, "qemu_init_main_loop failed\n");
-        exit(1);
-    }
-
     machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
     if (machine_opts) {
         kernel_filename = qemu_opt_get(machine_opts, "kernel");
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 16/39] aio: change qemu_aio_set_fd_handler to return void
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (14 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 17/39] aio: provide platform-independent API Paolo Bonzini
                   ` (23 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio.c      | 12 +++++-------
 qemu-aio.h | 10 +++++-----
 2 file modificati, 10 inserzioni(+), 12 rimozioni(-)

diff --git a/aio.c b/aio.c
index c738a4e..e062aab 100644
--- a/aio.c
+++ b/aio.c
@@ -53,11 +53,11 @@ static AioHandler *find_aio_handler(int fd)
     return NULL;
 }
 
-int qemu_aio_set_fd_handler(int fd,
-                            IOHandler *io_read,
-                            IOHandler *io_write,
-                            AioFlushHandler *io_flush,
-                            void *opaque)
+void qemu_aio_set_fd_handler(int fd,
+                             IOHandler *io_read,
+                             IOHandler *io_write,
+                             AioFlushHandler *io_flush,
+                             void *opaque)
 {
     AioHandler *node;
 
@@ -93,8 +93,6 @@ int qemu_aio_set_fd_handler(int fd,
     }
 
     qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
-
-    return 0;
 }
 
 void qemu_aio_flush(void)
diff --git a/qemu-aio.h b/qemu-aio.h
index bfdd35f..27a7e21 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -60,10 +60,10 @@ bool qemu_aio_wait(void);
  * Code that invokes AIO completion functions should rely on this function
  * instead of qemu_set_fd_handler[2].
  */
-int qemu_aio_set_fd_handler(int fd,
-                            IOHandler *io_read,
-                            IOHandler *io_write,
-                            AioFlushHandler *io_flush,
-                            void *opaque);
+void qemu_aio_set_fd_handler(int fd,
+                             IOHandler *io_read,
+                             IOHandler *io_write,
+                             AioFlushHandler *io_flush,
+                             void *opaque);
 
 #endif
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 17/39] aio: provide platform-independent API
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (15 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 16/39] aio: change qemu_aio_set_fd_handler to return void Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 18/39] aio: introduce AioContext, move bottom halves there Paolo Bonzini
                   ` (22 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This adds to aio.c a platform-independent API based on EventNotifiers, that
can be used by both POSIX and Win32.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.objs |  4 ++--
 aio.c         |  9 +++++++++
 qemu-aio.h    | 19 ++++++++++++++++++-
 3 file modificati, 29 inserzioni(+), 3 rimozioni(-)

diff --git a/Makefile.objs b/Makefile.objs
index 5b39c33..98046fc 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -46,6 +46,8 @@ block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o
 block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
+block-obj-$(CONFIG_POSIX) += event_notifier-posix.o
+block-obj-$(CONFIG_WIN32) += event_notifier-win32.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 block-obj-y += block/
 block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o
@@ -94,8 +96,6 @@ common-obj-y += bt-host.o bt-vhci.o
 common-obj-y += dma-helpers.o
 common-obj-y += acl.o
 common-obj-$(CONFIG_POSIX) += compatfd.o
-common-obj-$(CONFIG_POSIX) += event_notifier-posix.o
-common-obj-$(CONFIG_WIN32) += event_notifier-win32.o
 common-obj-y += qemu-timer.o qemu-timer-common.o
 common-obj-y += qtest.o
 common-obj-y += vl.o
diff --git a/aio.c b/aio.c
index e062aab..44214e1 100644
--- a/aio.c
+++ b/aio.c
@@ -95,6 +95,15 @@ void qemu_aio_set_fd_handler(int fd,
     qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
 }
 
+void qemu_aio_set_event_notifier(EventNotifier *notifier,
+                                 EventNotifierHandler *io_read,
+                                 AioFlushEventNotifierHandler *io_flush)
+{
+    qemu_aio_set_fd_handler(event_notifier_get_fd(notifier),
+                            (IOHandler *)io_read, NULL,
+                            (AioFlushHandler *)io_flush, notifier);
+}
+
 void qemu_aio_flush(void)
 {
     while (qemu_aio_wait());
diff --git a/qemu-aio.h b/qemu-aio.h
index 27a7e21..dc416a5 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -16,6 +16,7 @@
 
 #include "qemu-common.h"
 #include "qemu-char.h"
+#include "event_notifier.h"
 
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 typedef void BlockDriverCompletionFunc(void *opaque, int ret);
@@ -39,7 +40,7 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
 void qemu_aio_release(void *p);
 
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
-typedef int (AioFlushHandler)(void *opaque);
+typedef int (AioFlushEventNotifierHandler)(EventNotifier *e);
 
 /* Flush any pending AIO operation. This function will block until all
  * outstanding AIO operations have been completed or cancelled. */
@@ -53,6 +54,10 @@ void qemu_aio_flush(void);
  * Return whether there is still any pending AIO operation.  */
 bool qemu_aio_wait(void);
 
+#ifdef CONFIG_POSIX
+/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
+typedef int (AioFlushHandler)(void *opaque);
+
 /* Register a file descriptor and associated callbacks.  Behaves very similarly
  * to qemu_set_fd_handler2.  Unlike qemu_set_fd_handler2, these callbacks will
  * be invoked when using either qemu_aio_wait() or qemu_aio_flush().
@@ -65,5 +70,17 @@ void qemu_aio_set_fd_handler(int fd,
                              IOHandler *io_write,
                              AioFlushHandler *io_flush,
                              void *opaque);
+#endif
+
+/* Register an event notifier and associated callbacks.  Behaves very similarly
+ * to event_notifier_set_handler.  Unlike event_notifier_set_handler, these callbacks
+ * will be invoked when using either qemu_aio_wait() or qemu_aio_flush().
+ *
+ * Code that invokes AIO completion functions should rely on this function
+ * instead of event_notifier_set_handler.
+ */
+void qemu_aio_set_event_notifier(EventNotifier *notifier,
+                                 EventNotifierHandler *io_read,
+                                 AioFlushEventNotifierHandler *io_flush);
 
 #endif
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 18/39] aio: introduce AioContext, move bottom halves there
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (16 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 17/39] aio: provide platform-independent API Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 19/39] aio: add I/O handlers to the AioContext interface Paolo Bonzini
                   ` (21 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Start introducing AioContext, which will let us remove globals from
aio.c/async.c, and introduce multiple I/O threads.

The bottom half functions now take an additional AioContext argument.
A bottom half is created with a specific AioContext that remains the
same throughout the lifetime.  qemu_bh_new is just a wrapper that
uses a global context.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio.c                 |  2 --
 async.c               | 30 +++++++++----------
 hw/hw.h               |  1 +
 iohandler.c           |  1 +
 linux-aio.c           |  1 +
 main-loop.c           | 18 +++++++++++-
 main-loop.h           | 55 ++---------------------------------
 qemu-aio.h            | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 qemu-char.h           |  1 +
 qemu-common.h         |  1 +
 qemu-coroutine-lock.c |  2 +-
 11 file modificati, 119 inserzioni(+), 72 rimozioni(-)

diff --git a/aio.c b/aio.c
index 44214e1..7e3fe70 100644
--- a/aio.c
+++ b/aio.c
@@ -18,8 +18,6 @@
 #include "qemu-queue.h"
 #include "qemu_socket.h"
 
-typedef struct AioHandler AioHandler;
-
 /* The list of registered AIO handlers */
 static QLIST_HEAD(, AioHandler) aio_handlers;
 
diff --git a/async.c b/async.c
index 85cc641..189ee1b 100644
--- a/async.c
+++ b/async.c
@@ -26,9 +26,6 @@
 #include "qemu-aio.h"
 #include "main-loop.h"
 
-/* Anchor of the list of Bottom Halves belonging to the context */
-static struct QEMUBH *first_bh;
-
 /***********************************************************/
 /* bottom halves (can be seen as timers which expire ASAP) */
 
@@ -41,27 +38,26 @@ struct QEMUBH {
     bool deleted;
 };
 
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
+QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
 {
     QEMUBH *bh;
     bh = g_malloc0(sizeof(QEMUBH));
     bh->cb = cb;
     bh->opaque = opaque;
-    bh->next = first_bh;
-    first_bh = bh;
+    bh->next = ctx->first_bh;
+    ctx->first_bh = bh;
     return bh;
 }
 
-int qemu_bh_poll(void)
+int aio_bh_poll(AioContext *ctx)
 {
     QEMUBH *bh, **bhp, *next;
     int ret;
-    static int nesting = 0;
 
-    nesting++;
+    ctx->walking_bh++;
 
     ret = 0;
-    for (bh = first_bh; bh; bh = next) {
+    for (bh = ctx->first_bh; bh; bh = next) {
         next = bh->next;
         if (!bh->deleted && bh->scheduled) {
             bh->scheduled = 0;
@@ -72,11 +68,11 @@ int qemu_bh_poll(void)
         }
     }
 
-    nesting--;
+    ctx->walking_bh--;
 
     /* remove deleted bhs */
-    if (!nesting) {
-        bhp = &first_bh;
+    if (!ctx->walking_bh) {
+        bhp = &ctx->first_bh;
         while (*bhp) {
             bh = *bhp;
             if (bh->deleted) {
@@ -120,11 +116,11 @@ void qemu_bh_delete(QEMUBH *bh)
     bh->deleted = 1;
 }
 
-void qemu_bh_update_timeout(uint32_t *timeout)
+void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout)
 {
     QEMUBH *bh;
 
-    for (bh = first_bh; bh; bh = bh->next) {
+    for (bh = ctx->first_bh; bh; bh = bh->next) {
         if (!bh->deleted && bh->scheduled) {
             if (bh->idle) {
                 /* idle bottom halves will be polled at least
@@ -140,3 +136,7 @@ void qemu_bh_update_timeout(uint32_t *timeout)
     }
 }
 
+AioContext *aio_context_new(void)
+{
+    return g_new0(AioContext, 1);
+}
diff --git a/hw/hw.h b/hw/hw.h
index b337ee3..f530f6f 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -10,6 +10,7 @@
 
 #include "ioport.h"
 #include "irq.h"
+#include "qemu-aio.h"
 #include "qemu-file.h"
 #include "vmstate.h"
 #include "qemu-log.h"
diff --git a/iohandler.c b/iohandler.c
index a2d871b..60460a6 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -26,6 +26,7 @@
 #include "qemu-common.h"
 #include "qemu-char.h"
 #include "qemu-queue.h"
+#include "qemu-aio.h"
 #include "main-loop.h"
 
 #ifndef _WIN32
diff --git a/linux-aio.c b/linux-aio.c
index ce9b5d4..f3d8ef3 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -9,6 +9,7 @@
  */
 #include "qemu-common.h"
 #include "qemu-aio.h"
+#include "qemu-queue.h"
 #include "block/raw-posix-aio.h"
 
 #include <sys/eventfd.h>
diff --git a/main-loop.c b/main-loop.c
index baefe41..40fdbd3 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -26,6 +26,7 @@
 #include "qemu-timer.h"
 #include "slirp/slirp.h"
 #include "main-loop.h"
+#include "qemu-aio.h"
 
 #ifndef _WIN32
 
@@ -199,6 +200,8 @@ static int qemu_signal_init(void)
 }
 #endif
 
+static AioContext *qemu_aio_context;
+
 int qemu_init_main_loop(void)
 {
     int ret;
@@ -218,6 +221,7 @@ int qemu_init_main_loop(void)
         return ret;
     }
 
+    qemu_aio_context = aio_context_new();
     return 0;
 }
 
@@ -481,7 +485,7 @@ int main_loop_wait(int nonblocking)
     if (nonblocking) {
         timeout = 0;
     } else {
-        qemu_bh_update_timeout(&timeout);
+        aio_bh_update_timeout(qemu_aio_context, &timeout);
     }
 
     /* poll any events */
@@ -510,3 +514,15 @@ int main_loop_wait(int nonblocking)
 
     return ret;
 }
+
+/* Functions to operate on the main QEMU AioContext.  */
+
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
+{
+    return aio_bh_new(qemu_aio_context, cb, opaque);
+}
+
+int qemu_bh_poll(void)
+{
+    return aio_bh_poll(qemu_aio_context);
+}
diff --git a/main-loop.h b/main-loop.h
index 91a0aff..1d1a56b 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -25,6 +25,8 @@
 #ifndef QEMU_MAIN_LOOP_H
 #define QEMU_MAIN_LOOP_H 1
 
+#include "qemu-aio.h"
+
 #define SIG_IPI SIGUSR1
 
 /**
@@ -163,7 +165,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 
 typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
 typedef int IOCanReadHandler(void *opaque);
-typedef void IOHandler(void *opaque);
 
 /**
  * qemu_set_fd_handler2: Register a file descriptor with the main loop
@@ -244,56 +245,6 @@ int qemu_set_fd_handler(int fd,
                         IOHandler *fd_write,
                         void *opaque);
 
-typedef struct QEMUBH QEMUBH;
-typedef void QEMUBHFunc(void *opaque);
-
-/**
- * qemu_bh_new: Allocate a new bottom half structure.
- *
- * Bottom halves are lightweight callbacks whose invocation is guaranteed
- * to be wait-free, thread-safe and signal-safe.  The #QEMUBH structure
- * is opaque and must be allocated prior to its use.
- */
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
-
-/**
- * qemu_bh_schedule: Schedule a bottom half.
- *
- * Scheduling a bottom half interrupts the main loop and causes the
- * execution of the callback that was passed to qemu_bh_new.
- *
- * Bottom halves that are scheduled from a bottom half handler are instantly
- * invoked.  This can create an infinite loop if a bottom half handler
- * schedules itself.
- *
- * @bh: The bottom half to be scheduled.
- */
-void qemu_bh_schedule(QEMUBH *bh);
-
-/**
- * qemu_bh_cancel: Cancel execution of a bottom half.
- *
- * Canceling execution of a bottom half undoes the effect of calls to
- * qemu_bh_schedule without freeing its resources yet.  While cancellation
- * itself is also wait-free and thread-safe, it can of course race with the
- * loop that executes bottom halves unless you are holding the iothread
- * mutex.  This makes it mostly useless if you are not holding the mutex.
- *
- * @bh: The bottom half to be canceled.
- */
-void qemu_bh_cancel(QEMUBH *bh);
-
-/**
- *qemu_bh_delete: Cancel execution of a bottom half and free its resources.
- *
- * Deleting a bottom half frees the memory that was allocated for it by
- * qemu_bh_new.  It also implies canceling the bottom half if it was
- * scheduled.
- *
- * @bh: The bottom half to be deleted.
- */
-void qemu_bh_delete(QEMUBH *bh);
-
 #ifdef CONFIG_POSIX
 /**
  * qemu_add_child_watch: Register a child process for reaping.
@@ -349,8 +300,8 @@ void qemu_fd_register(int fd);
 void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
 void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
 
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
 void qemu_bh_schedule_idle(QEMUBH *bh);
 int qemu_bh_poll(void);
-void qemu_bh_update_timeout(uint32_t *timeout);
 
 #endif
diff --git a/qemu-aio.h b/qemu-aio.h
index dc416a5..2ed6ad3 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -15,7 +15,6 @@
 #define QEMU_AIO_H
 
 #include "qemu-common.h"
-#include "qemu-char.h"
 #include "event_notifier.h"
 
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
@@ -39,9 +38,87 @@ void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
                    BlockDriverCompletionFunc *cb, void *opaque);
 void qemu_aio_release(void *p);
 
+typedef struct AioHandler AioHandler;
+typedef void QEMUBHFunc(void *opaque);
+typedef void IOHandler(void *opaque);
+
+typedef struct AioContext {
+    /* Anchor of the list of Bottom Halves belonging to the context */
+    struct QEMUBH *first_bh;
+
+    /* A simple lock used to protect the first_bh list, and ensure that
+     * no callbacks are removed while we're walking and dispatching callbacks.
+     */
+    int walking_bh;
+} AioContext;
+
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
 typedef int (AioFlushEventNotifierHandler)(EventNotifier *e);
 
+/**
+ * aio_context_new: Allocate a new AioContext.
+ *
+ * AioContext provide a mini event-loop that can be waited on synchronously.
+ * They also provide bottom halves, a service to execute a piece of code
+ * as soon as possible.
+ */
+AioContext *aio_context_new(void);
+
+/**
+ * aio_bh_new: Allocate a new bottom half structure.
+ *
+ * Bottom halves are lightweight callbacks whose invocation is guaranteed
+ * to be wait-free, thread-safe and signal-safe.  The #QEMUBH structure
+ * is opaque and must be allocated prior to its use.
+ */
+QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
+
+/**
+ * aio_bh_poll: Poll bottom halves for an AioContext.
+ *
+ * These are internal functions used by the QEMU main loop.
+ */
+int aio_bh_poll(AioContext *ctx);
+void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout);
+
+/**
+ * qemu_bh_schedule: Schedule a bottom half.
+ *
+ * Scheduling a bottom half interrupts the main loop and causes the
+ * execution of the callback that was passed to qemu_bh_new.
+ *
+ * Bottom halves that are scheduled from a bottom half handler are instantly
+ * invoked.  This can create an infinite loop if a bottom half handler
+ * schedules itself.
+ *
+ * @bh: The bottom half to be scheduled.
+ */
+void qemu_bh_schedule(QEMUBH *bh);
+
+/**
+ * qemu_bh_cancel: Cancel execution of a bottom half.
+ *
+ * Canceling execution of a bottom half undoes the effect of calls to
+ * qemu_bh_schedule without freeing its resources yet.  While cancellation
+ * itself is also wait-free and thread-safe, it can of course race with the
+ * loop that executes bottom halves unless you are holding the iothread
+ * mutex.  This makes it mostly useless if you are not holding the mutex.
+ *
+ * @bh: The bottom half to be canceled.
+ */
+void qemu_bh_cancel(QEMUBH *bh);
+
+/**
+ *qemu_bh_delete: Cancel execution of a bottom half and free its resources.
+ *
+ * Deleting a bottom half frees the memory that was allocated for it by
+ * qemu_bh_new.  It also implies canceling the bottom half if it was
+ * scheduled.
+ *
+ * @bh: The bottom half to be deleted.
+ */
+void qemu_bh_delete(QEMUBH *bh);
+
 /* Flush any pending AIO operation. This function will block until all
  * outstanding AIO operations have been completed or cancelled. */
 void qemu_aio_flush(void);
diff --git a/qemu-char.h b/qemu-char.h
index 486644b..5087168 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -5,6 +5,7 @@
 #include "qemu-queue.h"
 #include "qemu-option.h"
 #include "qemu-config.h"
+#include "qemu-aio.h"
 #include "qobject.h"
 #include "qstring.h"
 #include "main-loop.h"
diff --git a/qemu-common.h b/qemu-common.h
index 36ce522..24e13cc 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -14,6 +14,7 @@
 
 typedef struct QEMUTimer QEMUTimer;
 typedef struct QEMUFile QEMUFile;
+typedef struct QEMUBH QEMUBH;
 typedef struct DeviceState DeviceState;
 
 struct Monitor;
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 26ad76b..9dda3f8 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -26,7 +26,7 @@
 #include "qemu-coroutine.h"
 #include "qemu-coroutine-int.h"
 #include "qemu-queue.h"
-#include "main-loop.h"
+#include "qemu-aio.h"
 #include "trace.h"
 
 static QTAILQ_HEAD(, Coroutine) unlock_bh_queue =
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 19/39] aio: add I/O handlers to the AioContext interface
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (17 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 18/39] aio: introduce AioContext, move bottom halves there Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 20/39] aio: test node->deleted before calling io_flush Paolo Bonzini
                   ` (20 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

With this patch, I/O handlers (including event notifier handlers) can be
attached to a single AioContext.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio.c       | 68 ++++++++++++++++++++++++-------------------------------------
 async.c     |  6 ++++++
 main-loop.c | 33 ++++++++++++++++++++++++++++++
 qemu-aio.h  | 42 +++++++++++++++++++++++++++++++-------
 4 file modificati, 101 inserzioni(+), 48 rimozioni(-)

diff --git a/aio.c b/aio.c
index 7e3fe70..c89f1e9 100644
--- a/aio.c
+++ b/aio.c
@@ -18,15 +18,6 @@
 #include "qemu-queue.h"
 #include "qemu_socket.h"
 
-/* The list of registered AIO handlers */
-static QLIST_HEAD(, AioHandler) aio_handlers;
-
-/* This is a simple lock used to protect the aio_handlers list.  Specifically,
- * it's used to ensure that no callbacks are removed while we're walking and
- * dispatching callbacks.
- */
-static int walking_handlers;
-
 struct AioHandler
 {
     int fd;
@@ -38,11 +29,11 @@ struct AioHandler
     QLIST_ENTRY(AioHandler) node;
 };
 
-static AioHandler *find_aio_handler(int fd)
+static AioHandler *find_aio_handler(AioContext *ctx, int fd)
 {
     AioHandler *node;
 
-    QLIST_FOREACH(node, &aio_handlers, node) {
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
         if (node->fd == fd)
             if (!node->deleted)
                 return node;
@@ -51,21 +42,22 @@ static AioHandler *find_aio_handler(int fd)
     return NULL;
 }
 
-void qemu_aio_set_fd_handler(int fd,
-                             IOHandler *io_read,
-                             IOHandler *io_write,
-                             AioFlushHandler *io_flush,
-                             void *opaque)
+void aio_set_fd_handler(AioContext *ctx,
+                        int fd,
+                        IOHandler *io_read,
+                        IOHandler *io_write,
+                        AioFlushHandler *io_flush,
+                        void *opaque)
 {
     AioHandler *node;
 
-    node = find_aio_handler(fd);
+    node = find_aio_handler(ctx, fd);
 
     /* Are we deleting the fd handler? */
     if (!io_read && !io_write) {
         if (node) {
             /* If the lock is held, just mark the node as deleted */
-            if (walking_handlers)
+            if (ctx->walking_handlers)
                 node->deleted = 1;
             else {
                 /* Otherwise, delete it for real.  We can't just mark it as
@@ -81,7 +73,7 @@ void qemu_aio_set_fd_handler(int fd,
             /* Alloc and insert if it's not already there */
             node = g_malloc0(sizeof(AioHandler));
             node->fd = fd;
-            QLIST_INSERT_HEAD(&aio_handlers, node, node);
+            QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
         }
         /* Update handler with latest information */
         node->io_read = io_read;
@@ -89,25 +81,19 @@ void qemu_aio_set_fd_handler(int fd,
         node->io_flush = io_flush;
         node->opaque = opaque;
     }
-
-    qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
-}
-
-void qemu_aio_set_event_notifier(EventNotifier *notifier,
-                                 EventNotifierHandler *io_read,
-                                 AioFlushEventNotifierHandler *io_flush)
-{
-    qemu_aio_set_fd_handler(event_notifier_get_fd(notifier),
-                            (IOHandler *)io_read, NULL,
-                            (AioFlushHandler *)io_flush, notifier);
 }
 
-void qemu_aio_flush(void)
+void aio_set_event_notifier(AioContext *ctx,
+                            EventNotifier *notifier,
+                            EventNotifierHandler *io_read,
+                            AioFlushEventNotifierHandler *io_flush)
 {
-    while (qemu_aio_wait());
+    aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
+                       (IOHandler *)io_read, NULL,
+                       (AioFlushHandler *)io_flush, notifier);
 }
 
-bool qemu_aio_wait(void)
+bool aio_wait(AioContext *ctx)
 {
     AioHandler *node;
     fd_set rdfds, wrfds;
@@ -120,18 +106,18 @@ bool qemu_aio_wait(void)
      * Do not call select in this case, because it is possible that the caller
      * does not need a complete flush (as is the case for qemu_aio_wait loops).
      */
-    if (qemu_bh_poll()) {
+    if (aio_bh_poll(ctx)) {
         return true;
     }
 
-    walking_handlers++;
+    ctx->walking_handlers++;
 
     FD_ZERO(&rdfds);
     FD_ZERO(&wrfds);
 
     /* fill fd sets */
     busy = false;
-    QLIST_FOREACH(node, &aio_handlers, node) {
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
         /* If there aren't pending AIO operations, don't invoke callbacks.
          * Otherwise, if there are no AIO requests, qemu_aio_wait() would
          * wait indefinitely.
@@ -152,7 +138,7 @@ bool qemu_aio_wait(void)
         }
     }
 
-    walking_handlers--;
+    ctx->walking_handlers--;
 
     /* No AIO operations?  Get us out of here */
     if (!busy) {
@@ -166,11 +152,11 @@ bool qemu_aio_wait(void)
     if (ret > 0) {
         /* we have to walk very carefully in case
          * qemu_aio_set_fd_handler is called while we're walking */
-        node = QLIST_FIRST(&aio_handlers);
+        node = QLIST_FIRST(&ctx->aio_handlers);
         while (node) {
             AioHandler *tmp;
 
-            walking_handlers++;
+            ctx->walking_handlers++;
 
             if (!node->deleted &&
                 FD_ISSET(node->fd, &rdfds) &&
@@ -186,9 +172,9 @@ bool qemu_aio_wait(void)
             tmp = node;
             node = QLIST_NEXT(node, node);
 
-            walking_handlers--;
+            ctx->walking_handlers--;
 
-            if (!walking_handlers && tmp->deleted) {
+            if (!ctx->walking_handlers && tmp->deleted) {
                 QLIST_REMOVE(tmp, node);
                 g_free(tmp);
             }
diff --git a/async.c b/async.c
index 189ee1b..c99db79 100644
--- a/async.c
+++ b/async.c
@@ -136,7 +136,13 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout)
     }
 }
 
+
 AioContext *aio_context_new(void)
 {
     return g_new0(AioContext, 1);
 }
+
+void aio_flush(AioContext *ctx)
+{
+    while (aio_wait(ctx));
+}
diff --git a/main-loop.c b/main-loop.c
index 40fdbd3..8f0117e 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -526,3 +526,36 @@ int qemu_bh_poll(void)
 {
     return aio_bh_poll(qemu_aio_context);
 }
+
+void qemu_aio_flush(void)
+{
+    aio_flush(qemu_aio_context);
+}
+
+bool qemu_aio_wait(void)
+{
+    return aio_wait(qemu_aio_context);
+}
+
+void qemu_aio_set_fd_handler(int fd,
+                             IOHandler *io_read,
+                             IOHandler *io_write,
+                             AioFlushHandler *io_flush,
+                             void *opaque)
+{
+    aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush,
+                       opaque);
+
+    qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
+}
+
+#ifdef CONFIG_POSIX
+void qemu_aio_set_event_notifier(EventNotifier *notifier,
+                                 EventNotifierHandler *io_read,
+                                 AioFlushEventNotifierHandler *io_flush)
+{
+    qemu_aio_set_fd_handler(event_notifier_get_fd(notifier),
+                            (IOHandler *)io_read, NULL,
+                            (AioFlushHandler *)io_flush, notifier);
+}
+#endif
diff --git a/qemu-aio.h b/qemu-aio.h
index 2ed6ad3..f8a93d8 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -15,6 +15,7 @@
 #define QEMU_AIO_H
 
 #include "qemu-common.h"
+#include "qemu-queue.h"
 #include "event_notifier.h"
 
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
@@ -43,6 +44,15 @@ typedef void QEMUBHFunc(void *opaque);
 typedef void IOHandler(void *opaque);
 
 typedef struct AioContext {
+    /* The list of registered AIO handlers */
+    QLIST_HEAD(, AioHandler) aio_handlers;
+
+    /* This is a simple lock used to protect the aio_handlers list.
+     * Specifically, it's used to ensure that no callbacks are removed while
+     * we're walking and dispatching callbacks.
+     */
+    int walking_handlers;
+
     /* Anchor of the list of Bottom Halves belonging to the context */
     struct QEMUBH *first_bh;
 
@@ -121,7 +131,7 @@ void qemu_bh_delete(QEMUBH *bh);
 
 /* Flush any pending AIO operation. This function will block until all
  * outstanding AIO operations have been completed or cancelled. */
-void qemu_aio_flush(void);
+void aio_flush(AioContext *ctx);
 
 /* Wait for a single AIO completion to occur.  This function will wait
  * until a single AIO event has completed and it will ensure something
@@ -129,7 +139,7 @@ void qemu_aio_flush(void);
  * result of executing I/O completion or bh callbacks.
  *
  * Return whether there is still any pending AIO operation.  */
-bool qemu_aio_wait(void);
+bool aio_wait(AioContext *ctx);
 
 #ifdef CONFIG_POSIX
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
@@ -142,11 +152,12 @@ typedef int (AioFlushHandler)(void *opaque);
  * Code that invokes AIO completion functions should rely on this function
  * instead of qemu_set_fd_handler[2].
  */
-void qemu_aio_set_fd_handler(int fd,
-                             IOHandler *io_read,
-                             IOHandler *io_write,
-                             AioFlushHandler *io_flush,
-                             void *opaque);
+void aio_set_fd_handler(AioContext *ctx,
+                        int fd,
+                        IOHandler *io_read,
+                        IOHandler *io_write,
+                        AioFlushHandler *io_flush,
+                        void *opaque);
 #endif
 
 /* Register an event notifier and associated callbacks.  Behaves very similarly
@@ -156,8 +167,25 @@ void qemu_aio_set_fd_handler(int fd,
  * Code that invokes AIO completion functions should rely on this function
  * instead of event_notifier_set_handler.
  */
+void aio_set_event_notifier(AioContext *ctx,
+                            EventNotifier *notifier,
+                            EventNotifierHandler *io_read,
+                            AioFlushEventNotifierHandler *io_flush);
+
+/* Functions to operate on the main QEMU AioContext.  */
+
+void qemu_aio_flush(void);
+bool qemu_aio_wait(void);
 void qemu_aio_set_event_notifier(EventNotifier *notifier,
                                  EventNotifierHandler *io_read,
                                  AioFlushEventNotifierHandler *io_flush);
 
+#ifdef CONFIG_POSIX
+void qemu_aio_set_fd_handler(int fd,
+                             IOHandler *io_read,
+                             IOHandler *io_write,
+                             AioFlushHandler *io_flush,
+                             void *opaque);
+#endif
+
 #endif
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 20/39] aio: test node->deleted before calling io_flush
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (18 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 19/39] aio: add I/O handlers to the AioContext interface Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 21/39] aio: add non-blocking variant of aio_wait Paolo Bonzini
                   ` (19 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Otherwise, there could be a case where io_flush accesses freed
memory because it should not have been called.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio.c | 2 +-
 1 file modificato, 1 inserzione(+). 1 rimozione(-)

diff --git a/aio.c b/aio.c
index c89f1e9..734d2cf 100644
--- a/aio.c
+++ b/aio.c
@@ -122,7 +122,7 @@ bool aio_wait(AioContext *ctx)
          * Otherwise, if there are no AIO requests, qemu_aio_wait() would
          * wait indefinitely.
          */
-        if (node->io_flush) {
+        if (!node->deleted && node->io_flush) {
             if (node->io_flush(node->opaque) == 0) {
                 continue;
             }
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 21/39] aio: add non-blocking variant of aio_wait
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (19 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 20/39] aio: test node->deleted before calling io_flush Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 22/39] aio: prepare for introducing GSource-based dispatch Paolo Bonzini
                   ` (18 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This will be used when polling the GSource attached to an AioContext.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio.c       | 20 +++++++++++++++-----
 async.c     |  2 +-
 main-loop.c |  2 +-
 qemu-aio.h  | 21 +++++++++++++++------
 4 file modificati, 32 inserzioni(+), 13 rimozioni(-)

diff --git a/aio.c b/aio.c
index 734d2cf..1d5e0c6 100644
--- a/aio.c
+++ b/aio.c
@@ -93,13 +93,16 @@ void aio_set_event_notifier(AioContext *ctx,
                        (AioFlushHandler *)io_flush, notifier);
 }
 
-bool aio_wait(AioContext *ctx)
+bool aio_poll(AioContext *ctx, bool blocking)
 {
+    static struct timeval tv0;
     AioHandler *node;
     fd_set rdfds, wrfds;
     int max_fd = -1;
     int ret;
-    bool busy;
+    bool busy, progress;
+
+    progress = false;
 
     /*
      * If there are callbacks left that have been queued, we need to call then.
@@ -107,6 +110,11 @@ bool aio_wait(AioContext *ctx)
      * does not need a complete flush (as is the case for qemu_aio_wait loops).
      */
     if (aio_bh_poll(ctx)) {
+        blocking = false;
+        progress = true;
+    }
+
+    if (progress && !blocking) {
         return true;
     }
 
@@ -142,11 +150,11 @@ bool aio_wait(AioContext *ctx)
 
     /* No AIO operations?  Get us out of here */
     if (!busy) {
-        return false;
+        return progress;
     }
 
     /* wait until next event */
-    ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
+    ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0);
 
     /* if we have any readable fds, dispatch event */
     if (ret > 0) {
@@ -161,11 +169,13 @@ bool aio_wait(AioContext *ctx)
             if (!node->deleted &&
                 FD_ISSET(node->fd, &rdfds) &&
                 node->io_read) {
+                progress = true;
                 node->io_read(node->opaque);
             }
             if (!node->deleted &&
                 FD_ISSET(node->fd, &wrfds) &&
                 node->io_write) {
+                progress = true;
                 node->io_write(node->opaque);
             }
 
@@ -181,5 +191,5 @@ bool aio_wait(AioContext *ctx)
         }
     }
 
-    return true;
+    return progress;
 }
diff --git a/async.c b/async.c
index c99db79..513bdd7 100644
--- a/async.c
+++ b/async.c
@@ -144,5 +144,5 @@ AioContext *aio_context_new(void)
 
 void aio_flush(AioContext *ctx)
 {
-    while (aio_wait(ctx));
+    while (aio_poll(ctx, true));
 }
diff --git a/main-loop.c b/main-loop.c
index 8f0117e..1fdc3bd 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -534,7 +534,7 @@ void qemu_aio_flush(void)
 
 bool qemu_aio_wait(void)
 {
-    return aio_wait(qemu_aio_context);
+    return aio_poll(qemu_aio_context, true);
 }
 
 void qemu_aio_set_fd_handler(int fd,
diff --git a/qemu-aio.h b/qemu-aio.h
index f8a93d8..f19201e 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -133,13 +133,22 @@ void qemu_bh_delete(QEMUBH *bh);
  * outstanding AIO operations have been completed or cancelled. */
 void aio_flush(AioContext *ctx);
 
-/* Wait for a single AIO completion to occur.  This function will wait
- * until a single AIO event has completed and it will ensure something
- * has moved before returning. This can issue new pending aio as
- * result of executing I/O completion or bh callbacks.
+/* Progress in completing AIO work to occur.  This can issue new pending
+ * aio as a result of executing I/O completion or bh callbacks.
  *
- * Return whether there is still any pending AIO operation.  */
-bool aio_wait(AioContext *ctx);
+ * If there is no pending AIO operation or completion (bottom half),
+ * return false.  If there are pending bottom halves, return true.
+ *
+ * If there are no pending bottom halves, but there are pending AIO
+ * operations, it may not be possible to make any progress without
+ * blocking.  If @blocking is true, this function will wait until one
+ * or more AIO events have completed, to ensure something has moved
+ * before returning.
+ *
+ * If @blocking is false, this function will also return false if the
+ * function cannot make any progress without blocking.
+ */
+bool aio_poll(AioContext *ctx, bool blocking);
 
 #ifdef CONFIG_POSIX
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 22/39] aio: prepare for introducing GSource-based dispatch
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (20 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 21/39] aio: add non-blocking variant of aio_wait Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 23/39] aio: add Win32 implementation Paolo Bonzini
                   ` (17 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This adds a GPollFD to each AioHandler.  It will then be possible to
attach these GPollFDs to a GSource, and from there to the main loop.
aio_wait examines the GPollFDs and avoids calling select() if any
is set (similar to what it does if bottom halves are available).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio.c      | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 qemu-aio.h |  7 +++++
 2 file modificati, 87 inserzioni(+), 13 rimozioni(-)

diff --git a/aio.c b/aio.c
index 1d5e0c6..4424722 100644
--- a/aio.c
+++ b/aio.c
@@ -20,7 +20,7 @@
 
 struct AioHandler
 {
-    int fd;
+    GPollFD pfd;
     IOHandler *io_read;
     IOHandler *io_write;
     AioFlushHandler *io_flush;
@@ -34,7 +34,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd)
     AioHandler *node;
 
     QLIST_FOREACH(node, &ctx->aio_handlers, node) {
-        if (node->fd == fd)
+        if (node->pfd.fd == fd)
             if (!node->deleted)
                 return node;
     }
@@ -57,9 +57,10 @@ void aio_set_fd_handler(AioContext *ctx,
     if (!io_read && !io_write) {
         if (node) {
             /* If the lock is held, just mark the node as deleted */
-            if (ctx->walking_handlers)
+            if (ctx->walking_handlers) {
                 node->deleted = 1;
-            else {
+                node->pfd.revents = 0;
+            } else {
                 /* Otherwise, delete it for real.  We can't just mark it as
                  * deleted because deleted nodes are only cleaned up after
                  * releasing the walking_handlers lock.
@@ -72,7 +73,7 @@ void aio_set_fd_handler(AioContext *ctx,
         if (node == NULL) {
             /* Alloc and insert if it's not already there */
             node = g_malloc0(sizeof(AioHandler));
-            node->fd = fd;
+            node->pfd.fd = fd;
             QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
         }
         /* Update handler with latest information */
@@ -80,6 +81,9 @@ void aio_set_fd_handler(AioContext *ctx,
         node->io_write = io_write;
         node->io_flush = io_flush;
         node->opaque = opaque;
+
+        node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0);
+        node->pfd.events |= (io_write ? G_IO_OUT : 0);
     }
 }
 
@@ -93,6 +97,32 @@ void aio_set_event_notifier(AioContext *ctx,
                        (AioFlushHandler *)io_flush, notifier);
 }
 
+bool aio_pending(AioContext *ctx)
+{
+    AioHandler *node;
+
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
+        int revents;
+
+        /*
+         * FIXME: right now we cannot get G_IO_HUP and G_IO_ERR because
+         * main-loop.c is still select based (due to the slirp legacy).
+         * If main-loop.c ever switches to poll, G_IO_ERR should be
+         * tested too.  Dispatching G_IO_ERR to both handlers should be
+         * okay, since handlers need to be ready for spurious wakeups.
+         */
+        revents = node->pfd.revents & node->pfd.events;
+        if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
+            return true;
+        }
+        if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 bool aio_poll(AioContext *ctx, bool blocking)
 {
     static struct timeval tv0;
@@ -114,6 +144,43 @@ bool aio_poll(AioContext *ctx, bool blocking)
         progress = true;
     }
 
+    /*
+     * Then dispatch any pending callbacks from the GSource.
+     *
+     * We have to walk very carefully in case qemu_aio_set_fd_handler is
+     * called while we're walking.
+     */
+    node = QLIST_FIRST(&ctx->aio_handlers);
+    while (node) {
+        AioHandler *tmp;
+        int revents;
+
+        ctx->walking_handlers++;
+
+        revents = node->pfd.revents & node->pfd.events;
+        node->pfd.revents = 0;
+
+        /* See comment in aio_pending.  */
+        if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) {
+            node->io_read(node->opaque);
+            progress = true;
+        }
+        if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) {
+            node->io_write(node->opaque);
+            progress = true;
+        }
+
+        tmp = node;
+        node = QLIST_NEXT(node, node);
+
+        ctx->walking_handlers--;
+
+        if (!ctx->walking_handlers && tmp->deleted) {
+            QLIST_REMOVE(tmp, node);
+            g_free(tmp);
+        }
+    }
+
     if (progress && !blocking) {
         return true;
     }
@@ -137,12 +204,12 @@ bool aio_poll(AioContext *ctx, bool blocking)
             busy = true;
         }
         if (!node->deleted && node->io_read) {
-            FD_SET(node->fd, &rdfds);
-            max_fd = MAX(max_fd, node->fd + 1);
+            FD_SET(node->pfd.fd, &rdfds);
+            max_fd = MAX(max_fd, node->pfd.fd + 1);
         }
         if (!node->deleted && node->io_write) {
-            FD_SET(node->fd, &wrfds);
-            max_fd = MAX(max_fd, node->fd + 1);
+            FD_SET(node->pfd.fd, &wrfds);
+            max_fd = MAX(max_fd, node->pfd.fd + 1);
         }
     }
 
@@ -167,16 +234,16 @@ bool aio_poll(AioContext *ctx, bool blocking)
             ctx->walking_handlers++;
 
             if (!node->deleted &&
-                FD_ISSET(node->fd, &rdfds) &&
+                FD_ISSET(node->pfd.fd, &rdfds) &&
                 node->io_read) {
-                progress = true;
                 node->io_read(node->opaque);
+                progress = true;
             }
             if (!node->deleted &&
-                FD_ISSET(node->fd, &wrfds) &&
+                FD_ISSET(node->pfd.fd, &wrfds) &&
                 node->io_write) {
-                progress = true;
                 node->io_write(node->opaque);
+                progress = true;
             }
 
             tmp = node;
diff --git a/qemu-aio.h b/qemu-aio.h
index f19201e..ac24896 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -133,6 +133,13 @@ void qemu_bh_delete(QEMUBH *bh);
  * outstanding AIO operations have been completed or cancelled. */
 void aio_flush(AioContext *ctx);
 
+/* Return whether there are any pending callbacks from the GSource
+ * attached to the AioContext.
+ *
+ * This is used internally in the implementation of the GSource.
+ */
+bool aio_pending(AioContext *ctx);
+
 /* Progress in completing AIO work to occur.  This can issue new pending
  * aio as a result of executing I/O completion or bh callbacks.
  *
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 23/39] aio: add Win32 implementation
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (21 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 22/39] aio: prepare for introducing GSource-based dispatch Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 24/39] aio: make AioContexts GSources Paolo Bonzini
                   ` (16 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

The Win32 implementation will only accept EventNotifiers, thus a few
drivers are disabled under Windows.  EventNotifiers are a good match
for the GSource implementation, too, because the Win32 port of glib
allows to place their HANDLEs in a GPollFD.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.objs        |   6 +-
 aio.c => aio-posix.c |   0
 aio-win32.c          | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++
 block/Makefile.objs  |   6 +-
 main-loop.c          |   2 +-
 5 file modificati, 218 inserzioni(+), 5 rimozioni(-)
 rename aio.c => aio-posix.c (100%)
 create mode 100644 aio-win32.c

diff --git a/Makefile.objs b/Makefile.objs
index 98046fc..a8ade04 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -42,12 +42,12 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
 block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
-block-obj-y += nbd.o block.o blockjob.o aio.o aes.o qemu-config.o
+block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o
 block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
-block-obj-$(CONFIG_POSIX) += event_notifier-posix.o
-block-obj-$(CONFIG_WIN32) += event_notifier-win32.o
+block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
+block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 block-obj-y += block/
 block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o
diff --git a/aio.c b/aio-posix.c
similarity index 100%
rename from aio.c
rename to aio-posix.c
diff --git a/aio-win32.c b/aio-win32.c
new file mode 100644
index 0000000..9881fdb
--- /dev/null
+++ b/aio-win32.c
@@ -0,0 +1,209 @@
+/*
+ * QEMU aio implementation
+ *
+ * Copyright IBM Corp., 2008
+ * Copyright Red Hat Inc., 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Paolo Bonzini     <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "qemu-common.h"
+#include "block.h"
+#include "qemu-queue.h"
+#include "qemu_socket.h"
+
+struct AioHandler {
+    EventNotifier *e;
+    EventNotifierHandler *io_notify;
+    AioFlushEventNotifierHandler *io_flush;
+    GPollFD pfd;
+    int deleted;
+    QLIST_ENTRY(AioHandler) node;
+};
+
+void aio_set_event_notifier(AioContext *ctx,
+                            EventNotifier *e,
+                            EventNotifierHandler *io_notify,
+                            AioFlushEventNotifierHandler *io_flush)
+{
+    AioHandler *node;
+
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
+        if (node->e == e && !node->deleted) {
+            break;
+        }
+    }
+
+    /* Are we deleting the fd handler? */
+    if (!io_notify) {
+        if (node) {
+            /* If the lock is held, just mark the node as deleted */
+            if (ctx->walking_handlers) {
+                node->deleted = 1;
+                node->pfd.revents = 0;
+            } else {
+                /* Otherwise, delete it for real.  We can't just mark it as
+                 * deleted because deleted nodes are only cleaned up after
+                 * releasing the walking_handlers lock.
+                 */
+                QLIST_REMOVE(node, node);
+                g_free(node);
+            }
+        }
+    } else {
+        if (node == NULL) {
+            /* Alloc and insert if it's not already there */
+            node = g_malloc0(sizeof(AioHandler));
+            node->e = e;
+            node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
+            node->pfd.events = G_IO_IN;
+            QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
+        }
+        /* Update handler with latest information */
+        node->io_notify = io_notify;
+        node->io_flush = io_flush;
+    }
+}
+
+bool aio_pending(AioContext *ctx)
+{
+    AioHandler *node;
+
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
+        if (node->pfd.revents && node->io_notify) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool aio_poll(AioContext *ctx, bool blocking)
+{
+    AioHandler *node;
+    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
+    bool busy, progress;
+    int count;
+
+    progress = false;
+
+    /*
+     * If there are callbacks left that have been queued, we need to call then.
+     * Do not call select in this case, because it is possible that the caller
+     * does not need a complete flush (as is the case for qemu_aio_wait loops).
+     */
+    if (aio_bh_poll(ctx)) {
+        blocking = false;
+        progress = true;
+    }
+
+    /*
+     * Then dispatch any pending callbacks from the GSource.
+     *
+     * We have to walk very carefully in case qemu_aio_set_fd_handler is
+     * called while we're walking.
+     */
+    node = QLIST_FIRST(&ctx->aio_handlers);
+    while (node) {
+        AioHandler *tmp;
+
+        ctx->walking_handlers++;
+
+        if (node->pfd.revents && node->io_notify) {
+            node->pfd.revents = 0;
+            node->io_notify(node->e);
+            progress = true;
+        }
+
+        tmp = node;
+        node = QLIST_NEXT(node, node);
+
+        ctx->walking_handlers--;
+
+        if (!ctx->walking_handlers && tmp->deleted) {
+            QLIST_REMOVE(tmp, node);
+            g_free(tmp);
+        }
+    }
+
+    if (progress && !blocking) {
+        return true;
+    }
+
+    ctx->walking_handlers++;
+
+    /* fill fd sets */
+    busy = false;
+    count = 0;
+    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
+        /* If there aren't pending AIO operations, don't invoke callbacks.
+         * Otherwise, if there are no AIO requests, qemu_aio_wait() would
+         * wait indefinitely.
+         */
+        if (!node->deleted && node->io_flush) {
+            if (node->io_flush(node->e) == 0) {
+                continue;
+            }
+            busy = true;
+        }
+        if (!node->deleted && node->io_notify) {
+            events[count++] = event_notifier_get_handle(node->e);
+        }
+    }
+
+    ctx->walking_handlers--;
+
+    /* No AIO operations?  Get us out of here */
+    if (!busy) {
+        return progress;
+    }
+
+    /* wait until next event */
+    for (;;) {
+        int timeout = blocking ? INFINITE : 0;
+        int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
+
+        /* if we have any signaled events, dispatch event */
+        if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
+            break;
+        }
+
+        blocking = false;
+
+        /* we have to walk very carefully in case
+         * qemu_aio_set_fd_handler is called while we're walking */
+        node = QLIST_FIRST(&ctx->aio_handlers);
+        while (node) {
+            AioHandler *tmp;
+
+            ctx->walking_handlers++;
+
+            if (!node->deleted &&
+                event_notifier_get_handle(node->e) == events[ret - WAIT_OBJECT_0] &&
+                node->io_notify) {
+                node->io_notify(node->e);
+                progress = true;
+            }
+
+            tmp = node;
+            node = QLIST_NEXT(node, node);
+
+            ctx->walking_handlers--;
+
+            if (!ctx->walking_handlers && tmp->deleted) {
+                QLIST_REMOVE(tmp, node);
+                g_free(tmp);
+            }
+        }
+    }
+
+    return progress;
+}
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 554f429..684765b 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -2,13 +2,17 @@ block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat
 block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
 block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-obj-y += qed-check.o
-block-obj-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
+block-obj-y += parallels.o blkdebug.o blkverify.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
+
+ifeq ($(CONFIG_POSIX),y)
+block-obj-y += nbd.o sheepdog.o
 block-obj-$(CONFIG_LIBISCSI) += iscsi.o
 block-obj-$(CONFIG_CURL) += curl.o
 block-obj-$(CONFIG_RBD) += rbd.o
 block-obj-$(CONFIG_GLUSTERFS) += gluster.o
+endif
 
 common-obj-y += stream.o
 common-obj-y += commit.o
diff --git a/main-loop.c b/main-loop.c
index 1fdc3bd..a86c275 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -537,6 +537,7 @@ bool qemu_aio_wait(void)
     return aio_poll(qemu_aio_context, true);
 }
 
+#ifdef CONFIG_POSIX
 void qemu_aio_set_fd_handler(int fd,
                              IOHandler *io_read,
                              IOHandler *io_write,
@@ -549,7 +550,6 @@ void qemu_aio_set_fd_handler(int fd,
     qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
 }
 
-#ifdef CONFIG_POSIX
 void qemu_aio_set_event_notifier(EventNotifier *notifier,
                                  EventNotifierHandler *io_read,
                                  AioFlushEventNotifierHandler *io_flush)
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 24/39] aio: make AioContexts GSources
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (22 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 23/39] aio: add Win32 implementation Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 25/39] aio: add aio_notify Paolo Bonzini
                   ` (15 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This lets AioContexts be used (optionally) with a glib main loop.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio-posix.c |  4 ++++
 aio-win32.c |  4 ++++
 async.c     | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 qemu-aio.h  | 23 ++++++++++++++++++++++
 4 file modificati, 95 inserzioni(+). 1 rimozione(-)

diff --git a/aio-posix.c b/aio-posix.c
index 4424722..65b2607 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -56,6 +56,8 @@ void aio_set_fd_handler(AioContext *ctx,
     /* Are we deleting the fd handler? */
     if (!io_read && !io_write) {
         if (node) {
+            g_source_remove_poll(&ctx->source, &node->pfd);
+
             /* If the lock is held, just mark the node as deleted */
             if (ctx->walking_handlers) {
                 node->deleted = 1;
@@ -75,6 +77,8 @@ void aio_set_fd_handler(AioContext *ctx,
             node = g_malloc0(sizeof(AioHandler));
             node->pfd.fd = fd;
             QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
+
+            g_source_add_poll(&ctx->source, &node->pfd);
         }
         /* Update handler with latest information */
         node->io_read = io_read;
diff --git a/aio-win32.c b/aio-win32.c
index 9881fdb..e460bd8 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -45,6 +45,8 @@ void aio_set_event_notifier(AioContext *ctx,
     /* Are we deleting the fd handler? */
     if (!io_notify) {
         if (node) {
+            g_source_remove_poll(&ctx->source, &node->pfd);
+
             /* If the lock is held, just mark the node as deleted */
             if (ctx->walking_handlers) {
                 node->deleted = 1;
@@ -66,6 +68,8 @@ void aio_set_event_notifier(AioContext *ctx,
             node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
             node->pfd.events = G_IO_IN;
             QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
+
+            g_source_add_poll(&ctx->source, &node->pfd);
         }
         /* Update handler with latest information */
         node->io_notify = io_notify;
diff --git a/async.c b/async.c
index 513bdd7..4ffdd98 100644
--- a/async.c
+++ b/async.c
@@ -136,10 +136,73 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout)
     }
 }
 
+static gboolean
+aio_ctx_prepare(GSource *source, gint    *timeout)
+{
+    AioContext *ctx = (AioContext *) source;
+    uint32_t wait = -1;
+    aio_bh_update_timeout(ctx, &wait);
+
+    if (wait != -1) {
+        *timeout = MIN(*timeout, wait);
+        return wait == 0;
+    }
+
+    return false;
+}
+
+static gboolean
+aio_ctx_check(GSource *source)
+{
+    AioContext *ctx = (AioContext *) source;
+    QEMUBH *bh;
+
+    for (bh = ctx->first_bh; bh; bh = bh->next) {
+        if (!bh->deleted && bh->scheduled) {
+            return true;
+	}
+    }
+    return aio_pending(ctx);
+}
+
+static gboolean
+aio_ctx_dispatch(GSource     *source,
+                 GSourceFunc  callback,
+                 gpointer     user_data)
+{
+    AioContext *ctx = (AioContext *) source;
+
+    assert(callback == NULL);
+    aio_poll(ctx, false);
+    return true;
+}
+
+static GSourceFuncs aio_source_funcs = {
+    aio_ctx_prepare,
+    aio_ctx_check,
+    aio_ctx_dispatch,
+    NULL
+};
+
+GSource *aio_get_g_source(AioContext *ctx)
+{
+    g_source_ref(&ctx->source);
+    return &ctx->source;
+}
 
 AioContext *aio_context_new(void)
 {
-    return g_new0(AioContext, 1);
+    return (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
+}
+
+void aio_context_ref(AioContext *ctx)
+{
+    g_source_ref(&ctx->source);
+}
+
+void aio_context_unref(AioContext *ctx)
+{
+    g_source_unref(&ctx->source);
 }
 
 void aio_flush(AioContext *ctx)
diff --git a/qemu-aio.h b/qemu-aio.h
index ac24896..aedf66c 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -44,6 +44,8 @@ typedef void QEMUBHFunc(void *opaque);
 typedef void IOHandler(void *opaque);
 
 typedef struct AioContext {
+    GSource source;
+
     /* The list of registered AIO handlers */
     QLIST_HEAD(, AioHandler) aio_handlers;
 
@@ -75,6 +77,22 @@ typedef int (AioFlushEventNotifierHandler)(EventNotifier *e);
 AioContext *aio_context_new(void);
 
 /**
+ * aio_context_ref:
+ * @ctx: The AioContext to operate on.
+ *
+ * Add a reference to an AioContext.
+ */
+void aio_context_ref(AioContext *ctx);
+
+/**
+ * aio_context_unref:
+ * @ctx: The AioContext to operate on.
+ *
+ * Drop a reference to an AioContext.
+ */
+void aio_context_unref(AioContext *ctx);
+
+/**
  * aio_bh_new: Allocate a new bottom half structure.
  *
  * Bottom halves are lightweight callbacks whose invocation is guaranteed
@@ -188,6 +206,11 @@ void aio_set_event_notifier(AioContext *ctx,
                             EventNotifierHandler *io_read,
                             AioFlushEventNotifierHandler *io_flush);
 
+/* Return a GSource that lets the main loop poll the file descriptors attached
+ * to this AioContext.
+ */
+GSource *aio_get_g_source(AioContext *ctx);
+
 /* Functions to operate on the main QEMU AioContext.  */
 
 void qemu_aio_flush(void);
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 25/39] aio: add aio_notify
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (23 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 24/39] aio: make AioContexts GSources Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 26/39] aio: call aio_notify after setting I/O handlers Paolo Bonzini
                   ` (14 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

With this change async.c does not rely anymore on any service from
main-loop.c, i.e. it is completely self-contained.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 async.c    | 30 ++++++++++++++++++++++++++----
 qemu-aio.h | 18 ++++++++++++++++++
 2 file modificati, 44 inserzioni(+), 4 rimozioni(-)

diff --git a/async.c b/async.c
index 4ffdd98..564526f 100644
--- a/async.c
+++ b/async.c
@@ -30,6 +30,7 @@
 /* bottom halves (can be seen as timers which expire ASAP) */
 
 struct QEMUBH {
+    AioContext *ctx;
     QEMUBHFunc *cb;
     void *opaque;
     QEMUBH *next;
@@ -42,6 +43,7 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
 {
     QEMUBH *bh;
     bh = g_malloc0(sizeof(QEMUBH));
+    bh->ctx = ctx;
     bh->cb = cb;
     bh->opaque = opaque;
     bh->next = ctx->first_bh;
@@ -101,8 +103,7 @@ void qemu_bh_schedule(QEMUBH *bh)
         return;
     bh->scheduled = 1;
     bh->idle = 0;
-    /* stop the currently executing CPU to execute the BH ASAP */
-    qemu_notify_event();
+    aio_notify(bh->ctx);
 }
 
 void qemu_bh_cancel(QEMUBH *bh)
@@ -177,11 +178,20 @@ aio_ctx_dispatch(GSource     *source,
     return true;
 }
 
+static void
+aio_ctx_finalize(GSource     *source)
+{
+    AioContext *ctx = (AioContext *) source;
+
+    aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
+    event_notifier_cleanup(&ctx->notifier);
+}
+
 static GSourceFuncs aio_source_funcs = {
     aio_ctx_prepare,
     aio_ctx_check,
     aio_ctx_dispatch,
-    NULL
+    aio_ctx_finalize
 };
 
 GSource *aio_get_g_source(AioContext *ctx)
@@ -190,9 +200,21 @@ GSource *aio_get_g_source(AioContext *ctx)
     return &ctx->source;
 }
 
+void aio_notify(AioContext *ctx)
+{
+    event_notifier_set(&ctx->notifier);
+}
+
 AioContext *aio_context_new(void)
 {
-    return (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
+    AioContext *ctx;
+    ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
+    event_notifier_init(&ctx->notifier, false);
+    aio_set_event_notifier(ctx, &ctx->notifier, 
+                           (EventNotifierHandler *)
+                           event_notifier_test_and_clear, NULL);
+
+    return ctx;
 }
 
 void aio_context_ref(AioContext *ctx)
diff --git a/qemu-aio.h b/qemu-aio.h
index aedf66c..2354617 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -62,6 +62,9 @@ typedef struct AioContext {
      * no callbacks are removed while we're walking and dispatching callbacks.
      */
     int walking_bh;
+
+    /* Used for aio_notify.  */
+    EventNotifier notifier;
 } AioContext;
 
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
@@ -102,6 +105,21 @@ void aio_context_unref(AioContext *ctx);
 QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
 
 /**
+ * aio_notify: Force processing of pending events.
+ *
+ * Similar to signaling a condition variable, aio_notify forces
+ * aio_wait to exit, so that the next call will re-examine pending events.
+ * The caller of aio_notify will usually call aio_wait again very soon,
+ * or go through another iteration of the GLib main loop.  Hence, aio_notify
+ * also has the side effect of recalculating the sets of file descriptors
+ * that the main loop waits for.
+ *
+ * Calling aio_notify is rarely necessary, because for example scheduling
+ * a bottom half calls it already.
+ */
+void aio_notify(AioContext *ctx);
+
+/**
  * aio_bh_poll: Poll bottom halves for an AioContext.
  *
  * These are internal functions used by the QEMU main loop.
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 26/39] aio: call aio_notify after setting I/O handlers
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (24 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 25/39] aio: add aio_notify Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 27/39] main-loop: use GSource to poll AIO file descriptors Paolo Bonzini
                   ` (13 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

In the current code, this is done by qemu_set_fd_handler2, which is
called by qemu_aio_set_fd_handler.  We need to keep the same behavior
even after removing the call to qemu_set_fd_handler2.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 aio-posix.c | 2 ++
 aio-win32.c | 2 ++
 2 file modificati, 4 inserzioni(+)

diff --git a/aio-posix.c b/aio-posix.c
index 65b2607..05cc84e 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -89,6 +89,8 @@ void aio_set_fd_handler(AioContext *ctx,
         node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0);
         node->pfd.events |= (io_write ? G_IO_OUT : 0);
     }
+
+    aio_notify(ctx);
 }
 
 void aio_set_event_notifier(AioContext *ctx,
diff --git a/aio-win32.c b/aio-win32.c
index e460bd8..a84eb71 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -75,6 +75,8 @@ void aio_set_event_notifier(AioContext *ctx,
         node->io_notify = io_notify;
         node->io_flush = io_flush;
     }
+
+    aio_notify(ctx);
 }
 
 bool aio_pending(AioContext *ctx)
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 27/39] main-loop: use GSource to poll AIO file descriptors
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (25 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 26/39] aio: call aio_notify after setting I/O handlers Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 28/39] main-loop: use aio_notify for qemu_notify_event Paolo Bonzini
                   ` (12 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This lets us remove the hooks for the main loop in async.c.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 main-loop.c | 23 ++++++-----------------
 main-loop.h |  1 -
 2 file modificati, 6 inserzioni(+), 18 rimozioni(-)

diff --git a/main-loop.c b/main-loop.c
index a86c275..365c9d3 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -205,6 +205,7 @@ static AioContext *qemu_aio_context;
 int qemu_init_main_loop(void)
 {
     int ret;
+    GSource *src;
 
     init_clocks();
     init_timer_alarm();
@@ -222,6 +223,9 @@ int qemu_init_main_loop(void)
     }
 
     qemu_aio_context = aio_context_new();
+    src = aio_get_g_source(qemu_aio_context);
+    g_source_attach(src, NULL);
+    g_source_unref(src);
     return 0;
 }
 
@@ -484,8 +488,6 @@ int main_loop_wait(int nonblocking)
 
     if (nonblocking) {
         timeout = 0;
-    } else {
-        aio_bh_update_timeout(qemu_aio_context, &timeout);
     }
 
     /* poll any events */
@@ -508,10 +510,6 @@ int main_loop_wait(int nonblocking)
 
     qemu_run_all_timers();
 
-    /* Check bottom-halves last in case any of the earlier events triggered
-       them.  */
-    qemu_bh_poll();
-
     return ret;
 }
 
@@ -522,11 +520,6 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
     return aio_bh_new(qemu_aio_context, cb, opaque);
 }
 
-int qemu_bh_poll(void)
-{
-    return aio_bh_poll(qemu_aio_context);
-}
-
 void qemu_aio_flush(void)
 {
     aio_flush(qemu_aio_context);
@@ -546,16 +539,12 @@ void qemu_aio_set_fd_handler(int fd,
 {
     aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush,
                        opaque);
-
-    qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
 }
+#endif
 
 void qemu_aio_set_event_notifier(EventNotifier *notifier,
                                  EventNotifierHandler *io_read,
                                  AioFlushEventNotifierHandler *io_flush)
 {
-    qemu_aio_set_fd_handler(event_notifier_get_fd(notifier),
-                            (IOHandler *)io_read, NULL,
-                            (AioFlushHandler *)io_flush, notifier);
+    aio_set_event_notifier(qemu_aio_context, notifier, io_read, io_flush);
 }
-#endif
diff --git a/main-loop.h b/main-loop.h
index 1d1a56b..326c742 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -302,6 +302,5 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc
 
 QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
 void qemu_bh_schedule_idle(QEMUBH *bh);
-int qemu_bh_poll(void);
 
 #endif
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 28/39] main-loop: use aio_notify for qemu_notify_event
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (26 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 27/39] main-loop: use GSource to poll AIO file descriptors Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 29/39] aio: clean up now-unused functions Paolo Bonzini
                   ` (11 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 main-loop.c | 106 +++++-------------------------------------------------------
 1 file modificato, 8 inserzioni(+), 98 rimozioni(-)

diff --git a/main-loop.c b/main-loop.c
index 365c9d3..e43c7c8 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -32,70 +32,6 @@
 
 #include "compatfd.h"
 
-static int io_thread_fd = -1;
-
-void qemu_notify_event(void)
-{
-    /* Write 8 bytes to be compatible with eventfd.  */
-    static const uint64_t val = 1;
-    ssize_t ret;
-
-    if (io_thread_fd == -1) {
-        return;
-    }
-    do {
-        ret = write(io_thread_fd, &val, sizeof(val));
-    } while (ret < 0 && errno == EINTR);
-
-    /* EAGAIN is fine, a read must be pending.  */
-    if (ret < 0 && errno != EAGAIN) {
-        fprintf(stderr, "qemu_notify_event: write() failed: %s\n",
-                strerror(errno));
-        exit(1);
-    }
-}
-
-static void qemu_event_read(void *opaque)
-{
-    int fd = (intptr_t)opaque;
-    ssize_t len;
-    char buffer[512];
-
-    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
-    do {
-        len = read(fd, buffer, sizeof(buffer));
-    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
-}
-
-static int qemu_event_init(void)
-{
-    int err;
-    int fds[2];
-
-    err = qemu_eventfd(fds);
-    if (err == -1) {
-        return -errno;
-    }
-    err = fcntl_setfl(fds[0], O_NONBLOCK);
-    if (err < 0) {
-        goto fail;
-    }
-    err = fcntl_setfl(fds[1], O_NONBLOCK);
-    if (err < 0) {
-        goto fail;
-    }
-    qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
-                         (void *)(intptr_t)fds[0]);
-
-    io_thread_fd = fds[1];
-    return 0;
-
-fail:
-    close(fds[0]);
-    close(fds[1]);
-    return err;
-}
-
 /* If we have signalfd, we mask out the signals we want to handle and then
  * use signalfd to listen for them.  We rely on whatever the current signal
  * handler is to dispatch the signals when we receive them.
@@ -165,43 +101,22 @@ static int qemu_signal_init(void)
 
 #else /* _WIN32 */
 
-static HANDLE qemu_event_handle = NULL;
-
-static void dummy_event_handler(void *opaque)
-{
-}
-
-static int qemu_event_init(void)
+static int qemu_signal_init(void)
 {
-    qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (!qemu_event_handle) {
-        fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
-        return -1;
-    }
-    qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
     return 0;
 }
+#endif
+
+static AioContext *qemu_aio_context;
 
 void qemu_notify_event(void)
 {
-    if (!qemu_event_handle) {
+    if (!qemu_aio_context) {
         return;
     }
-    if (!SetEvent(qemu_event_handle)) {
-        fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n",
-                GetLastError());
-        exit(1);
-    }
+    aio_notify(qemu_aio_context);
 }
 
-static int qemu_signal_init(void)
-{
-    return 0;
-}
-#endif
-
-static AioContext *qemu_aio_context;
-
 int qemu_init_main_loop(void)
 {
     int ret;
@@ -216,12 +131,6 @@ int qemu_init_main_loop(void)
         return ret;
     }
 
-    /* Note eventfd must be drained before signalfd handlers run */
-    ret = qemu_event_init();
-    if (ret) {
-        return ret;
-    }
-
     qemu_aio_context = aio_context_new();
     src = aio_get_g_source(qemu_aio_context);
     g_source_attach(src, NULL);
@@ -411,7 +320,8 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
 
 void qemu_fd_register(int fd)
 {
-    WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE |
+    WSAEventSelect(fd, event_notifier_get_handle(&qemu_aio_context->notifier),
+                   FD_READ | FD_ACCEPT | FD_CLOSE |
                    FD_CONNECT | FD_WRITE | FD_OOB);
 }
 
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 29/39] aio: clean up now-unused functions
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (27 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 28/39] main-loop: use aio_notify for qemu_notify_event Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 30/39] linux-aio: use event notifiers Paolo Bonzini
                   ` (10 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Some cleanups can now be made, now that the main loop does not anymore need
hooks into the bottom half code.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 async.c       | 23 +++++++----------------
 oslib-posix.c | 31 -------------------------------
 qemu-aio.h    |  1 -
 qemu-common.h |  1 -
 4 file modificati, 7 inserzioni(+), 49 rimozioni(-)

diff --git a/async.c b/async.c
index 564526f..04f9dcb 100644
--- a/async.c
+++ b/async.c
@@ -117,16 +117,20 @@ void qemu_bh_delete(QEMUBH *bh)
     bh->deleted = 1;
 }
 
-void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout)
+static gboolean
+aio_ctx_prepare(GSource *source, gint    *timeout)
 {
+    AioContext *ctx = (AioContext *) source;
     QEMUBH *bh;
+    bool scheduled = false;
 
     for (bh = ctx->first_bh; bh; bh = bh->next) {
         if (!bh->deleted && bh->scheduled) {
+            scheduled = true;
             if (bh->idle) {
                 /* idle bottom halves will be polled at least
                  * every 10ms */
-                *timeout = MIN(10, *timeout);
+                *timeout = 10;
             } else {
                 /* non-idle bottom halves will be executed
                  * immediately */
@@ -135,21 +139,8 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout)
             }
         }
     }
-}
-
-static gboolean
-aio_ctx_prepare(GSource *source, gint    *timeout)
-{
-    AioContext *ctx = (AioContext *) source;
-    uint32_t wait = -1;
-    aio_bh_update_timeout(ctx, &wait);
-
-    if (wait != -1) {
-        *timeout = MIN(*timeout, wait);
-        return wait == 0;
-    }
 
-    return false;
+    return scheduled;
 }
 
 static gboolean
diff --git a/oslib-posix.c b/oslib-posix.c
index dbeb627..9db9c3d 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -61,9 +61,6 @@ static int running_on_valgrind = -1;
 #ifdef CONFIG_LINUX
 #include <sys/syscall.h>
 #endif
-#ifdef CONFIG_EVENTFD
-#include <sys/eventfd.h>
-#endif
 
 int qemu_get_thread_id(void)
 {
@@ -183,34 +180,6 @@ int qemu_pipe(int pipefd[2])
     return ret;
 }
 
-/*
- * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
- */
-int qemu_eventfd(int fds[2])
-{
-#ifdef CONFIG_EVENTFD
-    int ret;
-
-    ret = eventfd(0, 0);
-    if (ret >= 0) {
-        fds[0] = ret;
-        fds[1] = dup(ret);
-        if (fds[1] == -1) {
-            close(ret);
-            return -1;
-        }
-        qemu_set_cloexec(ret);
-        qemu_set_cloexec(fds[1]);
-        return 0;
-    }
-    if (errno != ENOSYS) {
-        return -1;
-    }
-#endif
-
-    return qemu_pipe(fds);
-}
-
 int qemu_utimens(const char *path, const struct timespec *times)
 {
     struct timeval tv[2], tv_now;
diff --git a/qemu-aio.h b/qemu-aio.h
index 2354617..1b7eb6e 100644
--- a/qemu-aio.h
+++ b/qemu-aio.h
@@ -125,7 +125,6 @@ void aio_notify(AioContext *ctx);
  * These are internal functions used by the QEMU main loop.
  */
 int aio_bh_poll(AioContext *ctx);
-void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout);
 
 /**
  * qemu_bh_schedule: Schedule a bottom half.
diff --git a/qemu-common.h b/qemu-common.h
index 24e13cc..c3328d2 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -218,7 +218,6 @@ ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
     QEMU_WARN_UNUSED_RESULT;
 
 #ifndef _WIN32
-int qemu_eventfd(int pipefd[2]);
 int qemu_pipe(int pipefd[2]);
 #endif
 
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 30/39] linux-aio: use event notifiers
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (28 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 29/39] aio: clean up now-unused functions Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 31/39] qemu-thread: add QemuSemaphore Paolo Bonzini
                   ` (9 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Since linux-aio already uses an eventfd, converting it to use the
EventNotifier-based API simplifies the code even though it is not
meant to be portable.

Reviewed-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 linux-aio.c | 49 +++++++++++++++++++------------------------------
 1 file modificato, 19 inserzioni(+), 30 rimozioni(-)

diff --git a/linux-aio.c b/linux-aio.c
index f3d8ef3..d1afb46 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -11,8 +11,8 @@
 #include "qemu-aio.h"
 #include "qemu-queue.h"
 #include "block/raw-posix-aio.h"
+#include "event_notifier.h"
 
-#include <sys/eventfd.h>
 #include <libaio.h>
 
 /*
@@ -38,7 +38,7 @@ struct qemu_laiocb {
 
 struct qemu_laio_state {
     io_context_t ctx;
-    int efd;
+    EventNotifier e;
     int count;
 };
 
@@ -77,29 +77,17 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
     qemu_aio_release(laiocb);
 }
 
-static void qemu_laio_completion_cb(void *opaque)
+static void qemu_laio_completion_cb(EventNotifier *e)
 {
-    struct qemu_laio_state *s = opaque;
+    struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
 
-    while (1) {
+    while (event_notifier_test_and_clear(&s->e)) {
         struct io_event events[MAX_EVENTS];
-        uint64_t val;
-        ssize_t ret;
         struct timespec ts = { 0 };
         int nevents, i;
 
         do {
-            ret = read(s->efd, &val, sizeof(val));
-        } while (ret == -1 && errno == EINTR);
-
-        if (ret == -1 && errno == EAGAIN)
-            break;
-
-        if (ret != 8)
-            break;
-
-        do {
-            nevents = io_getevents(s->ctx, val, MAX_EVENTS, events, &ts);
+            nevents = io_getevents(s->ctx, MAX_EVENTS, MAX_EVENTS, events, &ts);
         } while (nevents == -EINTR);
 
         for (i = 0; i < nevents; i++) {
@@ -113,9 +101,9 @@ static void qemu_laio_completion_cb(void *opaque)
     }
 }
 
-static int qemu_laio_flush_cb(void *opaque)
+static int qemu_laio_flush_cb(EventNotifier *e)
 {
-    struct qemu_laio_state *s = opaque;
+    struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
 
     return (s->count > 0) ? 1 : 0;
 }
@@ -147,8 +135,9 @@ static void laio_cancel(BlockDriverAIOCB *blockacb)
      * We might be able to do this slightly more optimal by removing the
      * O_NONBLOCK flag.
      */
-    while (laiocb->ret == -EINPROGRESS)
-        qemu_laio_completion_cb(laiocb->ctx);
+    while (laiocb->ret == -EINPROGRESS) {
+        qemu_laio_completion_cb(&laiocb->ctx->e);
+    }
 }
 
 static AIOPool laio_pool = {
@@ -187,7 +176,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
                         __func__, type);
         goto out_free_aiocb;
     }
-    io_set_eventfd(&laiocb->iocb, s->efd);
+    io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));
     s->count++;
 
     if (io_submit(s->ctx, 1, &iocbs) < 0)
@@ -206,21 +195,21 @@ void *laio_init(void)
     struct qemu_laio_state *s;
 
     s = g_malloc0(sizeof(*s));
-    s->efd = eventfd(0, 0);
-    if (s->efd == -1)
+    if (event_notifier_init(&s->e, false) < 0) {
         goto out_free_state;
-    fcntl(s->efd, F_SETFL, O_NONBLOCK);
+    }
 
-    if (io_setup(MAX_EVENTS, &s->ctx) != 0)
+    if (io_setup(MAX_EVENTS, &s->ctx) != 0) {
         goto out_close_efd;
+    }
 
-    qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL,
-        qemu_laio_flush_cb, s);
+    qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb,
+                                qemu_laio_flush_cb);
 
     return s;
 
 out_close_efd:
-    close(s->efd);
+    event_notifier_cleanup(&s->e);
 out_free_state:
     g_free(s);
     return NULL;
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 31/39] qemu-thread: add QemuSemaphore
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (29 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 30/39] linux-aio: use event notifiers Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 32/39] aio: add generic thread-pool facility Paolo Bonzini
                   ` (8 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

The new thread pool will use semaphores instead of condition
variables, because QemuCond does not have qemu_cond_timedwait.
(I also like it more this way).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
        Difference from previous submission: handle EINTR

 qemu-thread-posix.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-thread-posix.h |  5 ++++
 qemu-thread-win32.c | 35 +++++++++++++++++++++++
 qemu-thread-win32.h |  4 +++
 qemu-thread.h       |  7 +++++
 5 file modificati, 131 inserzioni(+)

diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 8fbabda..6a3d3a1 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -17,6 +17,9 @@
 #include <signal.h>
 #include <stdint.h>
 #include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/time.h>
 #include "qemu-thread.h"
 
 static void error_exit(int err, const char *msg)
@@ -115,6 +118,83 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
         error_exit(err, __func__);
 }
 
+void qemu_sem_init(QemuSemaphore *sem, int init)
+{
+    int rc;
+
+    rc = sem_init(&sem->sem, 0, init);
+    if (rc < 0) {
+        error_exit(errno, __func__);
+    }
+}
+
+void qemu_sem_destroy(QemuSemaphore *sem)
+{
+    int rc;
+
+    rc = sem_destroy(&sem->sem);
+    if (rc < 0) {
+        error_exit(errno, __func__);
+    }
+}
+
+void qemu_sem_post(QemuSemaphore *sem)
+{
+    int rc;
+
+    rc = sem_post(&sem->sem);
+    if (rc < 0) {
+        error_exit(errno, __func__);
+    }
+}
+
+int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
+{
+    int rc;
+
+    if (ms <= 0) {
+        /* This is cheaper than sem_timedwait.  */
+        do {
+            rc = sem_trywait(&sem->sem);
+        } while (rc == -1 && errno == EINTR);
+        if (rc == -1 && errno == EAGAIN) {
+            return -1;
+        }
+    } else {
+        struct timeval tv;
+        struct timespec ts;
+        gettimeofday(&tv, NULL);
+        ts.tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
+        ts.tv_sec = tv.tv_sec + ms / 1000;
+        if (ts.tv_nsec >= 1000000000) {
+            ts.tv_sec++;
+            ts.tv_nsec -= 1000000000;
+        }
+        do {
+            rc = sem_timedwait(&sem->sem, &ts);
+        } while (rc == -1 && errno == EINTR);
+        if (rc == -1 && errno == ETIMEDOUT) {
+            return -1;
+        }
+    }
+    if (rc < 0) {
+        error_exit(errno, __func__);
+    }
+    return 0;
+}
+
+void qemu_sem_wait(QemuSemaphore *sem)
+{
+    int rc;
+
+    do {
+        rc = sem_wait(&sem->sem);
+    } while (rc == -1 && errno == EINTR);
+    if (rc < 0) {
+        error_exit(errno, __func__);
+    }
+}
+
 void qemu_thread_create(QemuThread *thread,
                        void *(*start_routine)(void*),
                        void *arg, int mode)
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index ee4618e..2542c15 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -1,6 +1,7 @@
 #ifndef __QEMU_THREAD_POSIX_H
 #define __QEMU_THREAD_POSIX_H 1
 #include "pthread.h"
+#include <semaphore.h>
 
 struct QemuMutex {
     pthread_mutex_t lock;
@@ -10,6 +11,10 @@ struct QemuCond {
     pthread_cond_t cond;
 };
 
+struct QemuSemaphore {
+    sem_t sem;
+};
+
 struct QemuThread {
     pthread_t thread;
 };
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index 177b398..4b3db60 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -192,6 +192,41 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
     qemu_mutex_lock(mutex);
 }
 
+void qemu_sem_init(QemuSemaphore *sem, int init)
+{
+    /* Manual reset.  */
+    sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
+}
+
+void qemu_sem_destroy(QemuSemaphore *sem)
+{
+    CloseHandle(sem->sema);
+}
+
+void qemu_sem_post(QemuSemaphore *sem)
+{
+    ReleaseSemaphore(sem->sema, 1, NULL);
+}
+
+int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
+{
+    int rc = WaitForSingleObject(sem->sema, ms);
+    if (rc == WAIT_OBJECT_0) {
+        return 0;
+    }
+    if (rc != WAIT_TIMEOUT) {
+        error_exit(GetLastError(), __func__);
+    }
+    return -1;
+}
+
+void qemu_sem_wait(QemuSemaphore *sem)
+{
+    if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
+        error_exit(GetLastError(), __func__);
+    }
+}
+
 struct QemuThreadData {
     /* Passed to win32_start_routine.  */
     void             *(*start_routine)(void *);
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
index b9d1be8..13adb95 100644
--- a/qemu-thread-win32.h
+++ b/qemu-thread-win32.h
@@ -13,6 +13,10 @@ struct QemuCond {
     HANDLE continue_event;
 };
 
+struct QemuSemaphore {
+    HANDLE sema;
+};
+
 typedef struct QemuThreadData QemuThreadData;
 struct QemuThread {
     QemuThreadData *data;
diff --git a/qemu-thread.h b/qemu-thread.h
index 05fdaaf..3ee2f6b 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -6,6 +6,7 @@
 
 typedef struct QemuMutex QemuMutex;
 typedef struct QemuCond QemuCond;
+typedef struct QemuSemaphore QemuSemaphore;
 typedef struct QemuThread QemuThread;
 
 #ifdef _WIN32
@@ -38,6 +39,12 @@ void qemu_cond_signal(QemuCond *cond);
 void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
 
+void qemu_sem_init(QemuSemaphore *sem, int init);
+void qemu_sem_post(QemuSemaphore *sem);
+void qemu_sem_wait(QemuSemaphore *sem);
+int qemu_sem_timedwait(QemuSemaphore *sem, int ms);
+void qemu_sem_destroy(QemuSemaphore *sem);
+
 void qemu_thread_create(QemuThread *thread,
                         void *(*start_routine)(void *),
                         void *arg, int mode);
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 32/39] aio: add generic thread-pool facility
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (30 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 31/39] qemu-thread: add QemuSemaphore Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 33/39] threadpool: do not take lock in event_notifier_ready Paolo Bonzini
                   ` (7 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Add a generic thread-pool.  The code is roughly based on posix-aio-compat.c,
with some changes, especially the following:

- use QemuSemaphore instead of QemuCond;

- separate the state of the thread from the return code of the worker
function.  The return code is totally opaque for the thread pool;

- do not busy wait when doing cancellation.

A more generic threadpool (but still specific to I/O so that in the future
it can use special scheduling classes or PI mutexes) can have many uses:
it allows more flexibility in raw-posix.c and can more easily be extended
to Win32, and it will also be used to do an msync of the persistent bitmap.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
        Difference from previous submission: add locking documentation,
        fix locking in event_notifier_ready.

 Makefile.objs |   2 +-
 thread-pool.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 thread-pool.h |  34 +++++++
 trace-events  |   5 ++
 4 file modificati, 322 inserzioni(+). 1 rimozione(-)
 create mode 100644 thread-pool.c
 create mode 100644 thread-pool.h

diff --git a/Makefile.objs b/Makefile.objs
index a8ade04..f8ae031 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -43,7 +43,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
 
 block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
 block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o
-block-obj-y += qemu-progress.o qemu-sockets.o uri.o notify.o
+block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
diff --git a/thread-pool.c b/thread-pool.c
new file mode 100644
index 0000000..80749b7
--- /dev/null
+++ b/thread-pool.c
@@ -0,0 +1,282 @@
+/*
+ * QEMU block layer thread pool
+ *
+ * Copyright IBM, Corp. 2008
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Paolo Bonzini     <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "qemu-common.h"
+#include "qemu-queue.h"
+#include "qemu-thread.h"
+#include "osdep.h"
+#include "qemu-coroutine.h"
+#include "trace.h"
+#include "block_int.h"
+#include "event_notifier.h"
+#include "thread-pool.h"
+
+static void do_spawn_thread(void);
+
+typedef struct ThreadPoolElement ThreadPoolElement;
+
+enum ThreadState {
+    THREAD_QUEUED,
+    THREAD_ACTIVE,
+    THREAD_DONE,
+    THREAD_CANCELED,
+};
+
+struct ThreadPoolElement {
+    BlockDriverAIOCB common;
+    ThreadPoolFunc *func;
+    void *arg;
+    enum ThreadState state;
+    int ret;
+
+    /* Access to this list is protected by lock.  */
+    QTAILQ_ENTRY(ThreadPoolElement) reqs;
+
+    /* Access to this list is protected by the global mutex.  */
+    QLIST_ENTRY(ThreadPoolElement) all;
+};
+
+static EventNotifier notifier;
+static QemuMutex lock;
+static QemuCond check_cancel;
+static QemuSemaphore sem;
+static int max_threads = 64;
+static QEMUBH *new_thread_bh;
+
+/* The following variables are protected by the global mutex.  */
+static QLIST_HEAD(, ThreadPoolElement) head;
+
+/* The following variables are protected by lock.  */
+static QTAILQ_HEAD(, ThreadPoolElement) request_list;
+static int cur_threads;
+static int idle_threads;
+static int new_threads;     /* backlog of threads we need to create */
+static int pending_threads; /* threads created but not running yet */
+static int pending_cancellations; /* whether we need a cond_broadcast */
+
+static void *worker_thread(void *unused)
+{
+    qemu_mutex_lock(&lock);
+    pending_threads--;
+    do_spawn_thread();
+
+    while (1) {
+        ThreadPoolElement *req;
+        int ret;
+
+        do {
+            idle_threads++;
+            qemu_mutex_unlock(&lock);
+            ret = qemu_sem_timedwait(&sem, 10000);
+            qemu_mutex_lock(&lock);
+            idle_threads--;
+        } while (ret == -1 && !QTAILQ_EMPTY(&request_list));
+        if (ret == -1) {
+            break;
+        }
+
+        req = QTAILQ_FIRST(&request_list);
+        QTAILQ_REMOVE(&request_list, req, reqs);
+        req->state = THREAD_ACTIVE;
+        qemu_mutex_unlock(&lock);
+
+        ret = req->func(req->arg);
+
+        qemu_mutex_lock(&lock);
+        req->state = THREAD_DONE;
+        req->ret = ret;
+        if (pending_cancellations) {
+            qemu_cond_broadcast(&check_cancel);
+        }
+
+        event_notifier_set(&notifier);
+    }
+
+    cur_threads--;
+    qemu_mutex_unlock(&lock);
+    return NULL;
+}
+
+static void do_spawn_thread(void)
+{
+    QemuThread t;
+
+    /* Runs with lock taken.  */
+    if (!new_threads) {
+        return;
+    }
+
+    new_threads--;
+    pending_threads++;
+
+    qemu_thread_create(&t, worker_thread, NULL, QEMU_THREAD_DETACHED);
+}
+
+static void spawn_thread_bh_fn(void *opaque)
+{
+    qemu_mutex_lock(&lock);
+    do_spawn_thread();
+    qemu_mutex_unlock(&lock);
+}
+
+static void spawn_thread(void)
+{
+    cur_threads++;
+    new_threads++;
+    /* If there are threads being created, they will spawn new workers, so
+     * we don't spend time creating many threads in a loop holding a mutex or
+     * starving the current vcpu.
+     *
+     * If there are no idle threads, ask the main thread to create one, so we
+     * inherit the correct affinity instead of the vcpu affinity.
+     */
+    if (!pending_threads) {
+        qemu_bh_schedule(new_thread_bh);
+    }
+}
+
+static void event_notifier_ready(EventNotifier *notifier)
+{
+    ThreadPoolElement *elem, *next;
+
+    event_notifier_test_and_clear(notifier);
+restart:
+    QLIST_FOREACH_SAFE(elem, &head, all, next) {
+        if (elem->state != THREAD_CANCELED && elem->state != THREAD_DONE) {
+            continue;
+        }
+        if (elem->state == THREAD_DONE) {
+            trace_thread_pool_complete(elem, elem->common.opaque, elem->ret);
+        }
+        if (elem->state == THREAD_DONE && elem->common.cb) {
+            qemu_mutex_lock(&lock);
+            int ret = elem->ret;
+            qemu_mutex_unlock(&lock);
+            QLIST_REMOVE(elem, all);
+            elem->common.cb(elem->common.opaque, ret);
+            qemu_aio_release(elem);
+            goto restart;
+        } else {
+            /* remove the request */
+            QLIST_REMOVE(elem, all);
+            qemu_aio_release(elem);
+        }
+    }
+}
+
+static int thread_pool_active(EventNotifier *notifier)
+{
+    return !QLIST_EMPTY(&head);
+}
+
+static void thread_pool_cancel(BlockDriverAIOCB *acb)
+{
+    ThreadPoolElement *elem = (ThreadPoolElement *)acb;
+
+    trace_thread_pool_cancel(elem, elem->common.opaque);
+
+    qemu_mutex_lock(&lock);
+    if (elem->state == THREAD_QUEUED &&
+        /* No thread has yet started working on elem. we can try to "steal"
+         * the item from the worker if we can get a signal from the
+         * semaphore.  Because this is non-blocking, we can do it with
+         * the lock taken and ensure that elem will remain THREAD_QUEUED.
+         */
+        qemu_sem_timedwait(&sem, 0) == 0) {
+        QTAILQ_REMOVE(&request_list, elem, reqs);
+        elem->state = THREAD_CANCELED;
+        event_notifier_set(&notifier);
+    } else {
+        pending_cancellations++;
+        while (elem->state != THREAD_CANCELED && elem->state != THREAD_DONE) {
+            qemu_cond_wait(&check_cancel, &lock);
+        }
+        pending_cancellations--;
+    }
+    qemu_mutex_unlock(&lock);
+}
+
+static AIOPool thread_pool_cb_pool = {
+    .aiocb_size         = sizeof(ThreadPoolElement),
+    .cancel             = thread_pool_cancel,
+};
+
+BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    ThreadPoolElement *req;
+
+    req = qemu_aio_get(&thread_pool_cb_pool, NULL, cb, opaque);
+    req->func = func;
+    req->arg = arg;
+    req->state = THREAD_QUEUED;
+
+    QLIST_INSERT_HEAD(&head, req, all);
+
+    trace_thread_pool_submit(req, arg);
+
+    qemu_mutex_lock(&lock);
+    if (idle_threads == 0 && cur_threads < max_threads) {
+        spawn_thread();
+    }
+    QTAILQ_INSERT_TAIL(&request_list, req, reqs);
+    qemu_mutex_unlock(&lock);
+    qemu_sem_post(&sem);
+    return &req->common;
+}
+
+typedef struct ThreadPoolCo {
+    Coroutine *co;
+    int ret;
+} ThreadPoolCo;
+
+static void thread_pool_co_cb(void *opaque, int ret)
+{
+    ThreadPoolCo *co = opaque;
+
+    co->ret = ret;
+    qemu_coroutine_enter(co->co, NULL);
+}
+
+int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg)
+{
+    ThreadPoolCo tpc = { .co = qemu_coroutine_self(), .ret = -EINPROGRESS };
+    assert(qemu_in_coroutine());
+    thread_pool_submit_aio(func, arg, thread_pool_co_cb, &tpc);
+    qemu_coroutine_yield();
+    return tpc.ret;
+}
+
+void thread_pool_submit(ThreadPoolFunc *func, void *arg)
+{
+    thread_pool_submit_aio(func, arg, NULL, NULL);
+}
+
+static void thread_pool_init(void)
+{
+    QLIST_INIT(&head);
+    event_notifier_init(&notifier, false);
+    qemu_mutex_init(&lock);
+    qemu_cond_init(&check_cancel);
+    qemu_sem_init(&sem, 0);
+    qemu_aio_set_event_notifier(&notifier, event_notifier_ready,
+                                thread_pool_active);
+
+    QTAILQ_INIT(&request_list);
+    new_thread_bh = qemu_bh_new(spawn_thread_bh_fn, NULL);
+}
+
+block_init(thread_pool_init)
diff --git a/thread-pool.h b/thread-pool.h
new file mode 100644
index 0000000..378a4ac
--- /dev/null
+++ b/thread-pool.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU block layer thread pool
+ *
+ * Copyright IBM, Corp. 2008
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  Paolo Bonzini     <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef QEMU_THREAD_POOL_H
+#define QEMU_THREAD_POOL_H 1
+
+#include "qemu-common.h"
+#include "qemu-queue.h"
+#include "qemu-thread.h"
+#include "qemu-coroutine.h"
+#include "block_int.h"
+
+typedef int ThreadPoolFunc(void *opaque);
+
+BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
+     BlockDriverCompletionFunc *cb, void *opaque);
+int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg);
+void thread_pool_submit(ThreadPoolFunc *func, void *arg);
+
+#endif
diff --git a/trace-events b/trace-events
index e2d4580..58c18eb 100644
--- a/trace-events
+++ b/trace-events
@@ -90,6 +90,11 @@ virtio_blk_rw_complete(void *req, int ret) "req %p ret %d"
 virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu"
 virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu"
 
+# thread-pool.c
+thread_pool_submit(void *req, void *opaque) "req %p opaque %p"
+thread_pool_complete(void *req, void *opaque, int ret) "req %p opaque %p ret %d"
+thread_pool_cancel(void *req, void *opaque) "req %p opaque %p"
+
 # posix-aio-compat.c
 paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d"
 paio_complete(void *acb, void *opaque, int ret) "acb %p opaque %p ret %d"
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 33/39] threadpool: do not take lock in event_notifier_ready
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (31 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 32/39] aio: add generic thread-pool facility Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 34/39] block: switch posix-aio-compat to threadpool Paolo Bonzini
                   ` (6 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

The ordering is:

    worker thread                         consumer thread
    -------------------------------------------------------------------
    write ret                             event_notifier_test_and_clear
    wmb()                                 read state
    write state                           rmb()
    event_notifier_set                    read ret

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
        New patch.

 thread-pool.c | 19 +++++++++++++------
 1 file modificato, 13 inserzioni(+), 6 rimozioni(-)

diff --git a/thread-pool.c b/thread-pool.c
index 80749b7..651b324 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -39,6 +39,11 @@ struct ThreadPoolElement {
     BlockDriverAIOCB common;
     ThreadPoolFunc *func;
     void *arg;
+
+    /* Moving state out of THREAD_QUEUED is protected by lock.  After
+     * that, only the worker thread can write to it.  Reads and writes
+     * of state and ret are ordered with memory barriers.
+     */
     enum ThreadState state;
     int ret;
 
@@ -95,9 +100,12 @@ static void *worker_thread(void *unused)
 
         ret = req->func(req->arg);
 
-        qemu_mutex_lock(&lock);
-        req->state = THREAD_DONE;
         req->ret = ret;
+        /* Write ret before state.  */
+        smp_wmb();
+        req->state = THREAD_DONE;
+
+        qemu_mutex_lock(&lock);
         if (pending_cancellations) {
             qemu_cond_broadcast(&check_cancel);
         }
@@ -162,11 +170,10 @@ restart:
             trace_thread_pool_complete(elem, elem->common.opaque, elem->ret);
         }
         if (elem->state == THREAD_DONE && elem->common.cb) {
-            qemu_mutex_lock(&lock);
-            int ret = elem->ret;
-            qemu_mutex_unlock(&lock);
             QLIST_REMOVE(elem, all);
-            elem->common.cb(elem->common.opaque, ret);
+            /* Read state before ret.  */
+            smp_rmb();
+            elem->common.cb(elem->common.opaque, elem->ret);
             qemu_aio_release(elem);
             goto restart;
         } else {
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 34/39] block: switch posix-aio-compat to threadpool
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (32 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 33/39] threadpool: do not take lock in event_notifier_ready Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 35/39] raw: merge posix-aio-compat.c into block/raw-posix.c Paolo Bonzini
                   ` (5 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

This is not meant for portability, but to remove code duplication.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/raw-posix-aio.h |   1 -
 block/raw-posix.c     |  12 +-
 posix-aio-compat.c    | 427 +++++---------------------------------------------
 3 file modificati, 41 inserzioni(+), 399 rimozioni(-)

diff --git a/block/raw-posix-aio.h b/block/raw-posix-aio.h
index ba118f6..6725135 100644
--- a/block/raw-posix-aio.h
+++ b/block/raw-posix-aio.h
@@ -28,7 +28,6 @@
 
 
 /* posix-aio-compat.c - thread pool based implementation */
-int paio_init(void);
 BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque, int type);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 28d439f..9ae2c50 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -266,14 +266,10 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
     }
     s->fd = fd;
 
-    /* We're falling back to POSIX AIO in some cases so init always */
-    if (paio_init() < 0) {
-        goto out_close;
-    }
-
 #ifdef CONFIG_LINUX_AIO
     if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
-        goto out_close;
+        qemu_close(fd);
+        return -errno;
     }
 #endif
 
@@ -284,10 +280,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
 #endif
 
     return 0;
-
-out_close:
-    qemu_close(fd);
-    return -errno;
 }
 
 static int raw_open(BlockDriverState *bs, const char *filename, int flags)
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index 96e4daf..4a1e3d3 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -28,13 +28,12 @@
 #include "sysemu.h"
 #include "qemu-common.h"
 #include "trace.h"
+#include "thread-pool.h"
 #include "block_int.h"
 #include "iov.h"
 
 #include "block/raw-posix-aio.h"
 
-static void do_spawn_thread(void);
-
 struct qemu_paiocb {
     BlockDriverAIOCB common;
     int aio_fildes;
@@ -46,82 +45,15 @@ struct qemu_paiocb {
     size_t aio_nbytes;
 #define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
     off_t aio_offset;
-
-    QTAILQ_ENTRY(qemu_paiocb) node;
     int aio_type;
-    ssize_t ret;
-    int active;
-    struct qemu_paiocb *next;
 };
 
-typedef struct PosixAioState {
-    int rfd, wfd;
-    struct qemu_paiocb *first_aio;
-} PosixAioState;
-
-
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-static pthread_t thread_id;
-static pthread_attr_t attr;
-static int max_threads = 64;
-static int cur_threads = 0;
-static int idle_threads = 0;
-static int new_threads = 0;     /* backlog of threads we need to create */
-static int pending_threads = 0; /* threads created but not running yet */
-static QEMUBH *new_thread_bh;
-static QTAILQ_HEAD(, qemu_paiocb) request_list;
-
 #ifdef CONFIG_PREADV
 static int preadv_present = 1;
 #else
 static int preadv_present = 0;
 #endif
 
-static void die2(int err, const char *what)
-{
-    fprintf(stderr, "%s failed: %s\n", what, strerror(err));
-    abort();
-}
-
-static void die(const char *what)
-{
-    die2(errno, what);
-}
-
-static void mutex_lock(pthread_mutex_t *mutex)
-{
-    int ret = pthread_mutex_lock(mutex);
-    if (ret) die2(ret, "pthread_mutex_lock");
-}
-
-static void mutex_unlock(pthread_mutex_t *mutex)
-{
-    int ret = pthread_mutex_unlock(mutex);
-    if (ret) die2(ret, "pthread_mutex_unlock");
-}
-
-static int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
-                           struct timespec *ts)
-{
-    int ret = pthread_cond_timedwait(cond, mutex, ts);
-    if (ret && ret != ETIMEDOUT) die2(ret, "pthread_cond_timedwait");
-    return ret;
-}
-
-static void cond_signal(pthread_cond_t *cond)
-{
-    int ret = pthread_cond_signal(cond);
-    if (ret) die2(ret, "pthread_cond_signal");
-}
-
-static void thread_create(pthread_t *thread, pthread_attr_t *attr,
-                          void *(*start_routine)(void*), void *arg)
-{
-    int ret = pthread_create(thread, attr, start_routine, arg);
-    if (ret) die2(ret, "pthread_create");
-}
-
 static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
 {
     int ret;
@@ -310,286 +242,54 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
     return nbytes;
 }
 
-static void posix_aio_notify_event(void);
-
-static void *aio_thread(void *unused)
+static int aio_worker(void *arg)
 {
-    mutex_lock(&lock);
-    pending_threads--;
-    mutex_unlock(&lock);
-    do_spawn_thread();
-
-    while (1) {
-        struct qemu_paiocb *aiocb;
-        ssize_t ret = 0;
-        qemu_timeval tv;
-        struct timespec ts;
-
-        qemu_gettimeofday(&tv);
-        ts.tv_sec = tv.tv_sec + 10;
-        ts.tv_nsec = 0;
-
-        mutex_lock(&lock);
-
-        while (QTAILQ_EMPTY(&request_list) &&
-               !(ret == ETIMEDOUT)) {
-            idle_threads++;
-            ret = cond_timedwait(&cond, &lock, &ts);
-            idle_threads--;
+    struct qemu_paiocb *aiocb = arg;
+    ssize_t ret = 0;
+
+    switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
+    case QEMU_AIO_READ:
+        ret = handle_aiocb_rw(aiocb);
+        if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) {
+            /* A short read means that we have reached EOF. Pad the buffer
+             * with zeros for bytes after EOF. */
+            iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
+                       0, aiocb->aio_nbytes - ret);
+
+            ret = aiocb->aio_nbytes;
         }
-
-        if (QTAILQ_EMPTY(&request_list))
-            break;
-
-        aiocb = QTAILQ_FIRST(&request_list);
-        QTAILQ_REMOVE(&request_list, aiocb, node);
-        aiocb->active = 1;
-        mutex_unlock(&lock);
-
-        switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
-        case QEMU_AIO_READ:
-            ret = handle_aiocb_rw(aiocb);
-            if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) {
-                /* A short read means that we have reached EOF. Pad the buffer
-                 * with zeros for bytes after EOF. */
-                iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
-                           0, aiocb->aio_nbytes - ret);
-
-                ret = aiocb->aio_nbytes;
-            }
-            break;
-        case QEMU_AIO_WRITE:
-            ret = handle_aiocb_rw(aiocb);
-            break;
-        case QEMU_AIO_FLUSH:
-            ret = handle_aiocb_flush(aiocb);
-            break;
-        case QEMU_AIO_IOCTL:
-            ret = handle_aiocb_ioctl(aiocb);
-            break;
-        default:
-            fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
+        if (ret == aiocb->aio_nbytes) {
+            ret = 0;
+        } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
             ret = -EINVAL;
-            break;
         }
-
-        mutex_lock(&lock);
-        aiocb->ret = ret;
-        mutex_unlock(&lock);
-
-        posix_aio_notify_event();
-    }
-
-    cur_threads--;
-    mutex_unlock(&lock);
-
-    return NULL;
-}
-
-static void do_spawn_thread(void)
-{
-    sigset_t set, oldset;
-
-    mutex_lock(&lock);
-    if (!new_threads) {
-        mutex_unlock(&lock);
-        return;
-    }
-
-    new_threads--;
-    pending_threads++;
-
-    mutex_unlock(&lock);
-
-    /* block all signals */
-    if (sigfillset(&set)) die("sigfillset");
-    if (sigprocmask(SIG_SETMASK, &set, &oldset)) die("sigprocmask");
-
-    thread_create(&thread_id, &attr, aio_thread, NULL);
-
-    if (sigprocmask(SIG_SETMASK, &oldset, NULL)) die("sigprocmask restore");
-}
-
-static void spawn_thread_bh_fn(void *opaque)
-{
-    do_spawn_thread();
-}
-
-static void spawn_thread(void)
-{
-    cur_threads++;
-    new_threads++;
-    /* If there are threads being created, they will spawn new workers, so
-     * we don't spend time creating many threads in a loop holding a mutex or
-     * starving the current vcpu.
-     *
-     * If there are no idle threads, ask the main thread to create one, so we
-     * inherit the correct affinity instead of the vcpu affinity.
-     */
-    if (!pending_threads) {
-        qemu_bh_schedule(new_thread_bh);
-    }
-}
-
-static void qemu_paio_submit(struct qemu_paiocb *aiocb)
-{
-    aiocb->ret = -EINPROGRESS;
-    aiocb->active = 0;
-    mutex_lock(&lock);
-    if (idle_threads == 0 && cur_threads < max_threads)
-        spawn_thread();
-    QTAILQ_INSERT_TAIL(&request_list, aiocb, node);
-    mutex_unlock(&lock);
-    cond_signal(&cond);
-}
-
-static ssize_t qemu_paio_return(struct qemu_paiocb *aiocb)
-{
-    ssize_t ret;
-
-    mutex_lock(&lock);
-    ret = aiocb->ret;
-    mutex_unlock(&lock);
-
-    return ret;
-}
-
-static int qemu_paio_error(struct qemu_paiocb *aiocb)
-{
-    ssize_t ret = qemu_paio_return(aiocb);
-
-    if (ret < 0)
-        ret = -ret;
-    else
-        ret = 0;
-
-    return ret;
-}
-
-static void posix_aio_read(void *opaque)
-{
-    PosixAioState *s = opaque;
-    struct qemu_paiocb *acb, **pacb;
-    int ret;
-    ssize_t len;
-
-    /* read all bytes from signal pipe */
-    for (;;) {
-        char bytes[16];
-
-        len = read(s->rfd, bytes, sizeof(bytes));
-        if (len == -1 && errno == EINTR)
-            continue; /* try again */
-        if (len == sizeof(bytes))
-            continue; /* more to read */
         break;
-    }
-
-    for(;;) {
-        pacb = &s->first_aio;
-        for(;;) {
-            acb = *pacb;
-            if (!acb)
-                return;
-
-            ret = qemu_paio_error(acb);
-            if (ret == ECANCELED) {
-                /* remove the request */
-                *pacb = acb->next;
-                qemu_aio_release(acb);
-            } else if (ret != EINPROGRESS) {
-                /* end of aio */
-                if (ret == 0) {
-                    ret = qemu_paio_return(acb);
-                    if (ret == acb->aio_nbytes)
-                        ret = 0;
-                    else
-                        ret = -EINVAL;
-                } else {
-                    ret = -ret;
-                }
-
-                trace_paio_complete(acb, acb->common.opaque, ret);
-
-                /* remove the request */
-                *pacb = acb->next;
-                /* call the callback */
-                acb->common.cb(acb->common.opaque, ret);
-                qemu_aio_release(acb);
-                break;
-            } else {
-                pacb = &acb->next;
-            }
-        }
-    }
-}
-
-static int posix_aio_flush(void *opaque)
-{
-    PosixAioState *s = opaque;
-    return !!s->first_aio;
-}
-
-static PosixAioState *posix_aio_state;
-
-static void posix_aio_notify_event(void)
-{
-    char byte = 0;
-    ssize_t ret;
-
-    ret = write(posix_aio_state->wfd, &byte, sizeof(byte));
-    if (ret < 0 && errno != EAGAIN)
-        die("write()");
-}
-
-static void paio_remove(struct qemu_paiocb *acb)
-{
-    struct qemu_paiocb **pacb;
-
-    /* remove the callback from the queue */
-    pacb = &posix_aio_state->first_aio;
-    for(;;) {
-        if (*pacb == NULL) {
-            fprintf(stderr, "paio_remove: aio request not found!\n");
-            break;
-        } else if (*pacb == acb) {
-            *pacb = acb->next;
-            qemu_aio_release(acb);
-            break;
+    case QEMU_AIO_WRITE:
+        ret = handle_aiocb_rw(aiocb);
+        if (ret == aiocb->aio_nbytes) {
+            ret = 0;
+        } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
+            ret = -EINVAL;
         }
-        pacb = &(*pacb)->next;
-    }
-}
-
-static void paio_cancel(BlockDriverAIOCB *blockacb)
-{
-    struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb;
-    int active = 0;
-
-    trace_paio_cancel(acb, acb->common.opaque);
-
-    mutex_lock(&lock);
-    if (!acb->active) {
-        QTAILQ_REMOVE(&request_list, acb, node);
-        acb->ret = -ECANCELED;
-    } else if (acb->ret == -EINPROGRESS) {
-        active = 1;
-    }
-    mutex_unlock(&lock);
-
-    if (active) {
-        /* fail safe: if the aio could not be canceled, we wait for
-           it */
-        while (qemu_paio_error(acb) == EINPROGRESS)
-            ;
+        break;
+    case QEMU_AIO_FLUSH:
+        ret = handle_aiocb_flush(aiocb);
+        break;
+    case QEMU_AIO_IOCTL:
+        ret = handle_aiocb_ioctl(aiocb);
+        break;
+    default:
+        fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
+        ret = -EINVAL;
+        break;
     }
 
-    paio_remove(acb);
+    qemu_aio_release(aiocb);
+    return ret;
 }
 
 static AIOPool raw_aio_pool = {
     .aiocb_size         = sizeof(struct qemu_paiocb),
-    .cancel             = paio_cancel,
 };
 
 BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
@@ -609,12 +309,8 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     acb->aio_nbytes = nb_sectors * 512;
     acb->aio_offset = sector_num * 512;
 
-    acb->next = posix_aio_state->first_aio;
-    posix_aio_state->first_aio = acb;
-
     trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
-    qemu_paio_submit(acb);
-    return &acb->common;
+    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
 }
 
 BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
@@ -630,50 +326,5 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
     acb->aio_ioctl_buf = buf;
     acb->aio_ioctl_cmd = req;
 
-    acb->next = posix_aio_state->first_aio;
-    posix_aio_state->first_aio = acb;
-
-    qemu_paio_submit(acb);
-    return &acb->common;
-}
-
-int paio_init(void)
-{
-    PosixAioState *s;
-    int fds[2];
-    int ret;
-
-    if (posix_aio_state)
-        return 0;
-
-    s = g_malloc(sizeof(PosixAioState));
-
-    s->first_aio = NULL;
-    if (qemu_pipe(fds) == -1) {
-        fprintf(stderr, "failed to create pipe\n");
-        g_free(s);
-        return -1;
-    }
-
-    s->rfd = fds[0];
-    s->wfd = fds[1];
-
-    fcntl(s->rfd, F_SETFL, O_NONBLOCK);
-    fcntl(s->wfd, F_SETFL, O_NONBLOCK);
-
-    qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s);
-
-    ret = pthread_attr_init(&attr);
-    if (ret)
-        die2(ret, "pthread_attr_init");
-
-    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    if (ret)
-        die2(ret, "pthread_attr_setdetachstate");
-
-    QTAILQ_INIT(&request_list);
-    new_thread_bh = qemu_bh_new(spawn_thread_bh_fn, NULL);
-
-    posix_aio_state = s;
-    return 0;
+    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
 }
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 35/39] raw: merge posix-aio-compat.c into block/raw-posix.c
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (33 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 34/39] block: switch posix-aio-compat to threadpool Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-11-02 15:00   ` Peter Maydell
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 36/39] raw-posix: rename raw-posix-aio.h, hide unavailable prototypes Paolo Bonzini
                   ` (4 subsequent siblings)
  39 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Making the qemu_paiocb specific to raw devices will let us access members
of the BDRVRawState arbitrarily.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.objs         |   1 -
 block/raw-posix-aio.h |   8 --
 block/raw-posix.c     | 294 ++++++++++++++++++++++++++++++++++++++++++++
 posix-aio-compat.c    | 330 --------------------------------------------------
 4 file modificati, 294 inserzioni(+), 339 rimozioni(-)
 delete mode 100644 posix-aio-compat.c

diff --git a/Makefile.objs b/Makefile.objs
index f8ae031..35c2355 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -45,7 +45,6 @@ block-obj-y = iov.o cache-utils.o qemu-option.o module.o async.o
 block-obj-y += nbd.o block.o blockjob.o aes.o qemu-config.o
 block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
-block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
 block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
diff --git a/block/raw-posix-aio.h b/block/raw-posix-aio.h
index 6725135..c714367 100644
--- a/block/raw-posix-aio.h
+++ b/block/raw-posix-aio.h
@@ -27,14 +27,6 @@
 #define QEMU_AIO_MISALIGNED   0x1000
 
 
-/* posix-aio-compat.c - thread pool based implementation */
-BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type);
-BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
-        unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque);
-
 /* linux-aio.c - Linux native implementation */
 void *laio_init(void);
 BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 9ae2c50..4d6d5df 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -27,6 +27,9 @@
 #include "qemu-log.h"
 #include "block_int.h"
 #include "module.h"
+#include "trace.h"
+#include "thread-pool.h"
+#include "iov.h"
 #include "block/raw-posix-aio.h"
 
 #if defined(__APPLE__) && (__MACH__)
@@ -149,6 +152,20 @@ typedef struct BDRVRawReopenState {
 static int fd_open(BlockDriverState *bs);
 static int64_t raw_getlength(BlockDriverState *bs);
 
+typedef struct RawPosixAIOData {
+    BlockDriverState *bs;
+    int aio_fildes;
+    union {
+        struct iovec *aio_iov;
+        void *aio_ioctl_buf;
+    };
+    int aio_niov;
+    size_t aio_nbytes;
+#define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
+    off_t aio_offset;
+    int aio_type;
+} RawPosixAIOData;
+
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 static int cdrom_reopen(BlockDriverState *bs);
 #endif
@@ -426,6 +443,283 @@ static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
     return 1;
 }
 
+static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
+{
+    int ret;
+
+    ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
+    if (ret == -1) {
+        return -errno;
+    }
+
+    /*
+     * This looks weird, but the aio code only considers a request
+     * successful if it has written the full number of bytes.
+     *
+     * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
+     * so in fact we return the ioctl command here to make posix_aio_read()
+     * happy..
+     */
+    return aiocb->aio_nbytes;
+}
+
+static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb)
+{
+    int ret;
+
+    ret = qemu_fdatasync(aiocb->aio_fildes);
+    if (ret == -1) {
+        return -errno;
+    }
+    return 0;
+}
+
+#ifdef CONFIG_PREADV
+
+static bool preadv_present = true;
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+    return preadv(fd, iov, nr_iov, offset);
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+    return pwritev(fd, iov, nr_iov, offset);
+}
+
+#else
+
+static bool preadv_present = false;
+
+static ssize_t
+qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+    return -ENOSYS;
+}
+
+static ssize_t
+qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
+{
+    return -ENOSYS;
+}
+
+#endif
+
+static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
+{
+    ssize_t len;
+
+    do {
+        if (aiocb->aio_type & QEMU_AIO_WRITE)
+            len = qemu_pwritev(aiocb->aio_fildes,
+                               aiocb->aio_iov,
+                               aiocb->aio_niov,
+                               aiocb->aio_offset);
+         else
+            len = qemu_preadv(aiocb->aio_fildes,
+                              aiocb->aio_iov,
+                              aiocb->aio_niov,
+                              aiocb->aio_offset);
+    } while (len == -1 && errno == EINTR);
+
+    if (len == -1) {
+        return -errno;
+    }
+    return len;
+}
+
+/*
+ * Read/writes the data to/from a given linear buffer.
+ *
+ * Returns the number of bytes handles or -errno in case of an error. Short
+ * reads are only returned if the end of the file is reached.
+ */
+static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
+{
+    ssize_t offset = 0;
+    ssize_t len;
+
+    while (offset < aiocb->aio_nbytes) {
+        if (aiocb->aio_type & QEMU_AIO_WRITE) {
+            len = pwrite(aiocb->aio_fildes,
+                         (const char *)buf + offset,
+                         aiocb->aio_nbytes - offset,
+                         aiocb->aio_offset + offset);
+        } else {
+            len = pread(aiocb->aio_fildes,
+                        buf + offset,
+                        aiocb->aio_nbytes - offset,
+                        aiocb->aio_offset + offset);
+        }
+        if (len == -1 && errno == EINTR) {
+            continue;
+        } else if (len == -1) {
+            offset = -errno;
+            break;
+        } else if (len == 0) {
+            break;
+        }
+        offset += len;
+    }
+
+    return offset;
+}
+
+static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
+{
+    ssize_t nbytes;
+    char *buf;
+
+    if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
+        /*
+         * If there is just a single buffer, and it is properly aligned
+         * we can just use plain pread/pwrite without any problems.
+         */
+        if (aiocb->aio_niov == 1) {
+             return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
+        }
+        /*
+         * We have more than one iovec, and all are properly aligned.
+         *
+         * Try preadv/pwritev first and fall back to linearizing the
+         * buffer if it's not supported.
+         */
+        if (preadv_present) {
+            nbytes = handle_aiocb_rw_vector(aiocb);
+            if (nbytes == aiocb->aio_nbytes ||
+                (nbytes < 0 && nbytes != -ENOSYS)) {
+                return nbytes;
+            }
+            preadv_present = false;
+        }
+
+        /*
+         * XXX(hch): short read/write.  no easy way to handle the reminder
+         * using these interfaces.  For now retry using plain
+         * pread/pwrite?
+         */
+    }
+
+    /*
+     * Ok, we have to do it the hard way, copy all segments into
+     * a single aligned buffer.
+     */
+    buf = qemu_blockalign(aiocb->bs, aiocb->aio_nbytes);
+    if (aiocb->aio_type & QEMU_AIO_WRITE) {
+        char *p = buf;
+        int i;
+
+        for (i = 0; i < aiocb->aio_niov; ++i) {
+            memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
+            p += aiocb->aio_iov[i].iov_len;
+        }
+    }
+
+    nbytes = handle_aiocb_rw_linear(aiocb, buf);
+    if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
+        char *p = buf;
+        size_t count = aiocb->aio_nbytes, copy;
+        int i;
+
+        for (i = 0; i < aiocb->aio_niov && count; ++i) {
+            copy = count;
+            if (copy > aiocb->aio_iov[i].iov_len) {
+                copy = aiocb->aio_iov[i].iov_len;
+            }
+            memcpy(aiocb->aio_iov[i].iov_base, p, copy);
+            p     += copy;
+            count -= copy;
+        }
+    }
+    qemu_vfree(buf);
+
+    return nbytes;
+}
+
+static int aio_worker(void *arg)
+{
+    RawPosixAIOData *aiocb = arg;
+    ssize_t ret = 0;
+
+    switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
+    case QEMU_AIO_READ:
+        ret = handle_aiocb_rw(aiocb);
+        if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->bs->growable) {
+            iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
+                      0, aiocb->aio_nbytes - ret);
+
+            ret = aiocb->aio_nbytes;
+        }
+        if (ret == aiocb->aio_nbytes) {
+            ret = 0;
+        } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
+            ret = -EINVAL;
+        }
+        break;
+    case QEMU_AIO_WRITE:
+        ret = handle_aiocb_rw(aiocb);
+        if (ret == aiocb->aio_nbytes) {
+            ret = 0;
+        } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
+            ret = -EINVAL;
+        }
+        break;
+    case QEMU_AIO_FLUSH:
+        ret = handle_aiocb_flush(aiocb);
+        break;
+    case QEMU_AIO_IOCTL:
+        ret = handle_aiocb_ioctl(aiocb);
+        break;
+    default:
+        fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
+        ret = -EINVAL;
+        break;
+    }
+
+    g_slice_free(RawPosixAIOData, aiocb);
+    return ret;
+}
+
+static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque, int type)
+{
+    RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
+
+    acb->bs = bs;
+    acb->aio_type = type;
+    acb->aio_fildes = fd;
+
+    if (qiov) {
+        acb->aio_iov = qiov->iov;
+        acb->aio_niov = qiov->niov;
+    }
+    acb->aio_nbytes = nb_sectors * 512;
+    acb->aio_offset = sector_num * 512;
+
+    trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
+    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
+}
+
+static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
+        unsigned long int req, void *buf,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
+
+    acb->bs = bs;
+    acb->aio_type = QEMU_AIO_IOCTL;
+    acb->aio_fildes = fd;
+    acb->aio_offset = 0;
+    acb->aio_ioctl_buf = buf;
+    acb->aio_ioctl_cmd = req;
+
+    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
+}
+
 static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque, int type)
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
deleted file mode 100644
index 4a1e3d3..0000000
--- a/posix-aio-compat.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * QEMU posix-aio emulation
- *
- * Copyright IBM, Corp. 2008
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <errno.h>
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "qemu-queue.h"
-#include "osdep.h"
-#include "sysemu.h"
-#include "qemu-common.h"
-#include "trace.h"
-#include "thread-pool.h"
-#include "block_int.h"
-#include "iov.h"
-
-#include "block/raw-posix-aio.h"
-
-struct qemu_paiocb {
-    BlockDriverAIOCB common;
-    int aio_fildes;
-    union {
-        struct iovec *aio_iov;
-        void *aio_ioctl_buf;
-    };
-    int aio_niov;
-    size_t aio_nbytes;
-#define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
-    off_t aio_offset;
-    int aio_type;
-};
-
-#ifdef CONFIG_PREADV
-static int preadv_present = 1;
-#else
-static int preadv_present = 0;
-#endif
-
-static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
-{
-    int ret;
-
-    ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
-    if (ret == -1)
-        return -errno;
-
-    /*
-     * This looks weird, but the aio code only considers a request
-     * successful if it has written the full number of bytes.
-     *
-     * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
-     * so in fact we return the ioctl command here to make posix_aio_read()
-     * happy..
-     */
-    return aiocb->aio_nbytes;
-}
-
-static ssize_t handle_aiocb_flush(struct qemu_paiocb *aiocb)
-{
-    int ret;
-
-    ret = qemu_fdatasync(aiocb->aio_fildes);
-    if (ret == -1)
-        return -errno;
-    return 0;
-}
-
-#ifdef CONFIG_PREADV
-
-static ssize_t
-qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
-{
-    return preadv(fd, iov, nr_iov, offset);
-}
-
-static ssize_t
-qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
-{
-    return pwritev(fd, iov, nr_iov, offset);
-}
-
-#else
-
-static ssize_t
-qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
-{
-    return -ENOSYS;
-}
-
-static ssize_t
-qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
-{
-    return -ENOSYS;
-}
-
-#endif
-
-static ssize_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
-{
-    ssize_t len;
-
-    do {
-        if (aiocb->aio_type & QEMU_AIO_WRITE)
-            len = qemu_pwritev(aiocb->aio_fildes,
-                               aiocb->aio_iov,
-                               aiocb->aio_niov,
-                               aiocb->aio_offset);
-         else
-            len = qemu_preadv(aiocb->aio_fildes,
-                              aiocb->aio_iov,
-                              aiocb->aio_niov,
-                              aiocb->aio_offset);
-    } while (len == -1 && errno == EINTR);
-
-    if (len == -1)
-        return -errno;
-    return len;
-}
-
-/*
- * Read/writes the data to/from a given linear buffer.
- *
- * Returns the number of bytes handles or -errno in case of an error. Short
- * reads are only returned if the end of the file is reached.
- */
-static ssize_t handle_aiocb_rw_linear(struct qemu_paiocb *aiocb, char *buf)
-{
-    ssize_t offset = 0;
-    ssize_t len;
-
-    while (offset < aiocb->aio_nbytes) {
-         if (aiocb->aio_type & QEMU_AIO_WRITE)
-             len = pwrite(aiocb->aio_fildes,
-                          (const char *)buf + offset,
-                          aiocb->aio_nbytes - offset,
-                          aiocb->aio_offset + offset);
-         else
-             len = pread(aiocb->aio_fildes,
-                         buf + offset,
-                         aiocb->aio_nbytes - offset,
-                         aiocb->aio_offset + offset);
-
-         if (len == -1 && errno == EINTR)
-             continue;
-         else if (len == -1) {
-             offset = -errno;
-             break;
-         } else if (len == 0)
-             break;
-
-         offset += len;
-    }
-
-    return offset;
-}
-
-static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
-{
-    ssize_t nbytes;
-    char *buf;
-
-    if (!(aiocb->aio_type & QEMU_AIO_MISALIGNED)) {
-        /*
-         * If there is just a single buffer, and it is properly aligned
-         * we can just use plain pread/pwrite without any problems.
-         */
-        if (aiocb->aio_niov == 1)
-             return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
-
-        /*
-         * We have more than one iovec, and all are properly aligned.
-         *
-         * Try preadv/pwritev first and fall back to linearizing the
-         * buffer if it's not supported.
-         */
-        if (preadv_present) {
-            nbytes = handle_aiocb_rw_vector(aiocb);
-            if (nbytes == aiocb->aio_nbytes)
-                return nbytes;
-            if (nbytes < 0 && nbytes != -ENOSYS)
-                return nbytes;
-            preadv_present = 0;
-        }
-
-        /*
-         * XXX(hch): short read/write.  no easy way to handle the reminder
-         * using these interfaces.  For now retry using plain
-         * pread/pwrite?
-         */
-    }
-
-    /*
-     * Ok, we have to do it the hard way, copy all segments into
-     * a single aligned buffer.
-     */
-    buf = qemu_blockalign(aiocb->common.bs, aiocb->aio_nbytes);
-    if (aiocb->aio_type & QEMU_AIO_WRITE) {
-        char *p = buf;
-        int i;
-
-        for (i = 0; i < aiocb->aio_niov; ++i) {
-            memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
-            p += aiocb->aio_iov[i].iov_len;
-        }
-    }
-
-    nbytes = handle_aiocb_rw_linear(aiocb, buf);
-    if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
-        char *p = buf;
-        size_t count = aiocb->aio_nbytes, copy;
-        int i;
-
-        for (i = 0; i < aiocb->aio_niov && count; ++i) {
-            copy = count;
-            if (copy > aiocb->aio_iov[i].iov_len)
-                copy = aiocb->aio_iov[i].iov_len;
-            memcpy(aiocb->aio_iov[i].iov_base, p, copy);
-            p     += copy;
-            count -= copy;
-        }
-    }
-    qemu_vfree(buf);
-
-    return nbytes;
-}
-
-static int aio_worker(void *arg)
-{
-    struct qemu_paiocb *aiocb = arg;
-    ssize_t ret = 0;
-
-    switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
-    case QEMU_AIO_READ:
-        ret = handle_aiocb_rw(aiocb);
-        if (ret >= 0 && ret < aiocb->aio_nbytes && aiocb->common.bs->growable) {
-            /* A short read means that we have reached EOF. Pad the buffer
-             * with zeros for bytes after EOF. */
-            iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
-                       0, aiocb->aio_nbytes - ret);
-
-            ret = aiocb->aio_nbytes;
-        }
-        if (ret == aiocb->aio_nbytes) {
-            ret = 0;
-        } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
-            ret = -EINVAL;
-        }
-        break;
-    case QEMU_AIO_WRITE:
-        ret = handle_aiocb_rw(aiocb);
-        if (ret == aiocb->aio_nbytes) {
-            ret = 0;
-        } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
-            ret = -EINVAL;
-        }
-        break;
-    case QEMU_AIO_FLUSH:
-        ret = handle_aiocb_flush(aiocb);
-        break;
-    case QEMU_AIO_IOCTL:
-        ret = handle_aiocb_ioctl(aiocb);
-        break;
-    default:
-        fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
-        ret = -EINVAL;
-        break;
-    }
-
-    qemu_aio_release(aiocb);
-    return ret;
-}
-
-static AIOPool raw_aio_pool = {
-    .aiocb_size         = sizeof(struct qemu_paiocb),
-};
-
-BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type)
-{
-    struct qemu_paiocb *acb;
-
-    acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
-    acb->aio_type = type;
-    acb->aio_fildes = fd;
-
-    if (qiov) {
-        acb->aio_iov = qiov->iov;
-        acb->aio_niov = qiov->niov;
-    }
-    acb->aio_nbytes = nb_sectors * 512;
-    acb->aio_offset = sector_num * 512;
-
-    trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
-    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
-}
-
-BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
-        unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque)
-{
-    struct qemu_paiocb *acb;
-
-    acb = qemu_aio_get(&raw_aio_pool, bs, cb, opaque);
-    acb->aio_type = QEMU_AIO_IOCTL;
-    acb->aio_fildes = fd;
-    acb->aio_offset = 0;
-    acb->aio_ioctl_buf = buf;
-    acb->aio_ioctl_cmd = req;
-
-    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
-}
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 36/39] raw-posix: rename raw-posix-aio.h, hide unavailable prototypes
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (34 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 35/39] raw: merge posix-aio-compat.c into block/raw-posix.c Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 37/39] raw-win32: add emulated AIO support Paolo Bonzini
                   ` (3 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/{raw-posix-aio.h => raw-aio.h} | 10 ++++++----
 block/raw-posix.c                    |  2 +-
 linux-aio.c                          |  2 +-
 3 file modificati, 8 inserzioni(+), 6 rimozioni(-)
 rename block/{raw-posix-aio.h => raw-aio.h} (86%)

diff --git a/block/raw-posix-aio.h b/block/raw-aio.h
similarity index 86%
rename from block/raw-posix-aio.h
rename to block/raw-aio.h
index c714367..b3bb073 100644
--- a/block/raw-posix-aio.h
+++ b/block/raw-aio.h
@@ -1,5 +1,5 @@
 /*
- * QEMU Posix block I/O backend AIO support
+ * Declarations for AIO in the raw protocol
  *
  * Copyright IBM, Corp. 2008
  *
@@ -12,8 +12,8 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#ifndef QEMU_RAW_POSIX_AIO_H
-#define QEMU_RAW_POSIX_AIO_H
+#ifndef QEMU_RAW_AIO_H
+#define QEMU_RAW_AIO_H
 
 /* AIO request types */
 #define QEMU_AIO_READ         0x0001
@@ -28,9 +28,11 @@
 
 
 /* linux-aio.c - Linux native implementation */
+#ifdef CONFIG_LINUX_AIO
 void *laio_init(void);
 BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque, int type);
+#endif
 
-#endif /* QEMU_RAW_POSIX_AIO_H */
+#endif /* QEMU_RAW_AIO_H */
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 4d6d5df..f2f0404 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -30,7 +30,7 @@
 #include "trace.h"
 #include "thread-pool.h"
 #include "iov.h"
-#include "block/raw-posix-aio.h"
+#include "raw-aio.h"
 
 #if defined(__APPLE__) && (__MACH__)
 #include <paths.h>
diff --git a/linux-aio.c b/linux-aio.c
index d1afb46..6ca984d 100644
--- a/linux-aio.c
+++ b/linux-aio.c
@@ -10,7 +10,7 @@
 #include "qemu-common.h"
 #include "qemu-aio.h"
 #include "qemu-queue.h"
-#include "block/raw-posix-aio.h"
+#include "block/raw-aio.h"
 #include "event_notifier.h"
 
 #include <libaio.h>
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 37/39] raw-win32: add emulated AIO support
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (35 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 36/39] raw-posix: rename raw-posix-aio.h, hide unavailable prototypes Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 38/39] raw-posix: move linux-aio.c to block/ Paolo Bonzini
                   ` (2 subsequent siblings)
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/raw-win32.c | 187 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file modificato, 138 inserzioni(+), 49 rimozioni(-)

diff --git a/block/raw-win32.c b/block/raw-win32.c
index 78c8306..ffd86e3 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -25,6 +25,10 @@
 #include "qemu-timer.h"
 #include "block_int.h"
 #include "module.h"
+#include "raw-aio.h"
+#include "trace.h"
+#include "thread-pool.h"
+#include "iov.h"
 #include <windows.h>
 #include <winioctl.h>
 
@@ -32,12 +36,127 @@
 #define FTYPE_CD     1
 #define FTYPE_HARDDISK 2
 
+typedef struct RawWin32AIOData {
+    BlockDriverState *bs;
+    HANDLE hfile;
+    struct iovec *aio_iov;
+    int aio_niov;
+    size_t aio_nbytes;
+    off64_t aio_offset;
+    int aio_type;
+} RawWin32AIOData;
+
 typedef struct BDRVRawState {
     HANDLE hfile;
     int type;
     char drive_path[16]; /* format: "d:\" */
 } BDRVRawState;
 
+/*
+ * Read/writes the data to/from a given linear buffer.
+ *
+ * Returns the number of bytes handles or -errno in case of an error. Short
+ * reads are only returned if the end of the file is reached.
+ */
+static size_t handle_aiocb_rw(RawWin32AIOData *aiocb)
+{
+    size_t offset = 0;
+    int i;
+
+    for (i = 0; i < aiocb->aio_niov; i++) {
+        OVERLAPPED ov;
+        DWORD ret, ret_count, len;
+
+        memset(&ov, 0, sizeof(ov));
+        ov.Offset = (aiocb->aio_offset + offset);
+        ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32;
+        len = aiocb->aio_iov[i].iov_len;
+        if (aiocb->aio_type & QEMU_AIO_WRITE) {
+            ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
+                            len, &ret_count, &ov);
+        } else {
+            ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base,
+                           len, &ret_count, &ov);
+        }
+        if (!ret) {
+            ret_count = 0;
+        }
+        if (ret_count != len) {
+            break;
+        }
+        offset += len;
+    }
+
+    return offset;
+}
+
+static int aio_worker(void *arg)
+{
+    RawWin32AIOData *aiocb = arg;
+    ssize_t ret = 0;
+    size_t count;
+
+    switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
+    case QEMU_AIO_READ:
+        count = handle_aiocb_rw(aiocb);
+        if (count < aiocb->aio_nbytes && aiocb->bs->growable) {
+            /* A short read means that we have reached EOF. Pad the buffer
+             * with zeros for bytes after EOF. */
+            iov_memset(aiocb->aio_iov, aiocb->aio_niov, count,
+                      0, aiocb->aio_nbytes - count);
+
+            count = aiocb->aio_nbytes;
+        }
+        if (count == aiocb->aio_nbytes) {
+            ret = 0;
+        } else {
+            ret = -EINVAL;
+        }
+        break;
+    case QEMU_AIO_WRITE:
+        count = handle_aiocb_rw(aiocb);
+        if (count == aiocb->aio_nbytes) {
+            count = 0;
+        } else {
+            count = -EINVAL;
+        }
+        break;
+    case QEMU_AIO_FLUSH:
+        if (!FlushFileBuffers(aiocb->hfile)) {
+            return -EIO;
+        }
+        break;
+    default:
+        fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
+        ret = -EINVAL;
+        break;
+    }
+
+    g_slice_free(RawWin32AIOData, aiocb);
+    return ret;
+}
+
+static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque, int type)
+{
+    RawWin32AIOData *acb = g_slice_new(RawWin32AIOData);
+
+    acb->bs = bs;
+    acb->hfile = hfile;
+    acb->aio_type = type;
+
+    if (qiov) {
+        acb->aio_iov = qiov->iov;
+        acb->aio_niov = qiov->niov;
+    }
+    acb->aio_nbytes = nb_sectors * 512;
+    acb->aio_offset = sector_num * 512;
+
+    trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
+    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
+}
+
 int qemu_ftruncate64(int fd, int64_t length)
 {
     LARGE_INTEGER li;
@@ -117,59 +236,29 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
     return 0;
 }
 
-static int raw_read(BlockDriverState *bs, int64_t sector_num,
-                    uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
+                         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+                         BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
-    OVERLAPPED ov;
-    DWORD ret_count;
-    int ret;
-    int64_t offset = sector_num * 512;
-    int count = nb_sectors * 512;
-
-    memset(&ov, 0, sizeof(ov));
-    ov.Offset = offset;
-    ov.OffsetHigh = offset >> 32;
-    ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
-    if (!ret)
-        return ret_count;
-    if (ret_count == count)
-        ret_count = 0;
-    return ret_count;
+    return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
+                       cb, opaque, QEMU_AIO_READ);
 }
 
-static int raw_write(BlockDriverState *bs, int64_t sector_num,
-                     const uint8_t *buf, int nb_sectors)
+static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
+                          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+                          BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
-    OVERLAPPED ov;
-    DWORD ret_count;
-    int ret;
-    int64_t offset = sector_num * 512;
-    int count = nb_sectors * 512;
-
-    memset(&ov, 0, sizeof(ov));
-    ov.Offset = offset;
-    ov.OffsetHigh = offset >> 32;
-    ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
-    if (!ret)
-        return ret_count;
-    if (ret_count == count)
-        ret_count = 0;
-    return ret_count;
+    return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
+                       cb, opaque, QEMU_AIO_WRITE);
 }
 
-static int raw_flush(BlockDriverState *bs)
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+                         BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
-    int ret;
-
-    ret = FlushFileBuffers(s->hfile);
-    if (ret == 0) {
-        return -EIO;
-    }
-
-    return 0;
+    return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
 }
 
 static void raw_close(BlockDriverState *bs)
@@ -290,9 +379,9 @@ static BlockDriver bdrv_file = {
     .bdrv_close		= raw_close,
     .bdrv_create	= raw_create,
 
-    .bdrv_read              = raw_read,
-    .bdrv_write             = raw_write,
-    .bdrv_co_flush_to_disk  = raw_flush,
+    .bdrv_aio_readv     = raw_aio_readv,
+    .bdrv_aio_writev    = raw_aio_writev,
+    .bdrv_aio_flush     = raw_aio_flush,
 
     .bdrv_truncate	= raw_truncate,
     .bdrv_getlength	= raw_getlength,
@@ -413,9 +502,9 @@ static BlockDriver bdrv_host_device = {
     .bdrv_close		= raw_close,
     .bdrv_has_zero_init = hdev_has_zero_init,
 
-    .bdrv_read              = raw_read,
-    .bdrv_write             = raw_write,
-    .bdrv_co_flush_to_disk  = raw_flush,
+    .bdrv_aio_readv     = raw_aio_readv,
+    .bdrv_aio_writev    = raw_aio_writev,
+    .bdrv_aio_flush     = raw_aio_flush,
 
     .bdrv_getlength	= raw_getlength,
     .bdrv_get_allocated_file_size
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 38/39] raw-posix: move linux-aio.c to block/
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (36 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 37/39] raw-win32: add emulated AIO support Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O Paolo Bonzini
  2012-11-01 19:33 ` [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Anthony Liguori
  39 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.objs                    | 1 -
 block/Makefile.objs              | 1 +
 linux-aio.c => block/linux-aio.c | 0
 3 file modificati, 1 inserzione(+). 1 rimozione(-)
 rename linux-aio.c => block/linux-aio.c (100%)

diff --git a/Makefile.objs b/Makefile.objs
index 35c2355..2b5427e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -47,7 +47,6 @@ block-obj-y += thread-pool.o qemu-progress.o qemu-sockets.o uri.o notify.o
 block-obj-y += $(coroutine-obj-y) $(qobject-obj-y) $(version-obj-y)
 block-obj-$(CONFIG_POSIX) += event_notifier-posix.o aio-posix.o
 block-obj-$(CONFIG_WIN32) += event_notifier-win32.o aio-win32.o
-block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 block-obj-y += block/
 block-obj-y += $(qapi-obj-y) qapi-types.o qapi-visit.o
 
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 684765b..771d341 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -5,6 +5,7 @@ block-obj-y += qed-check.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
+block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
 ifeq ($(CONFIG_POSIX),y)
 block-obj-y += nbd.o sheepdog.o
diff --git a/linux-aio.c b/block/linux-aio.c
similarity index 100%
rename from linux-aio.c
rename to block/linux-aio.c
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (37 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 38/39] raw-posix: move linux-aio.c to block/ Paolo Bonzini
@ 2012-10-31 15:30 ` Paolo Bonzini
  2012-11-21 13:20   ` Jan Kiszka
  2012-11-01 19:33 ` [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Anthony Liguori
  39 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-10-31 15:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, stefanha

With the new support for EventNotifiers in the AIO event loop, we
can hook a completion port to every opened file and use asynchronous
I/O on them.

Wine's support is extremely inefficient, also because it really does
the I/O synchronously on regular files. (!)  But it works, and it is
good to keep the Win32 and POSIX ports as similar as possible.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 block/Makefile.objs |   2 +-
 block/raw-aio.h     |  10 +++
 block/raw-win32.c   |  42 ++++++++--
 block/win32-aio.c   | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 file modificati, 274 inserzioni(+), 6 rimozioni(-)
 create mode 100644 block/win32-aio.c

diff --git a/block/Makefile.objs b/block/Makefile.objs
index 771d341..30ef6ae 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-c
 block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-obj-y += qed-check.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
-block-obj-$(CONFIG_WIN32) += raw-win32.o
+block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
diff --git a/block/raw-aio.h b/block/raw-aio.h
index b3bb073..e77f361 100644
--- a/block/raw-aio.h
+++ b/block/raw-aio.h
@@ -35,4 +35,14 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
         BlockDriverCompletionFunc *cb, void *opaque, int type);
 #endif
 
+#ifdef _WIN32
+typedef struct QEMUWin32AIOState QEMUWin32AIOState;
+QEMUWin32AIOState *win32_aio_init(void);
+int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
+BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
+        QEMUWin32AIOState *aio, HANDLE hfile,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque, int type);
+#endif
+
 #endif /* QEMU_RAW_AIO_H */
diff --git a/block/raw-win32.c b/block/raw-win32.c
index ffd86e3..0c05c58 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -36,6 +36,8 @@
 #define FTYPE_CD     1
 #define FTYPE_HARDDISK 2
 
+static QEMUWin32AIOState *aio;
+
 typedef struct RawWin32AIOData {
     BlockDriverState *bs;
     HANDLE hfile;
@@ -50,6 +52,7 @@ typedef struct BDRVRawState {
     HANDLE hfile;
     int type;
     char drive_path[16]; /* format: "d:\" */
+    QEMUWin32AIOState *aio;
 } BDRVRawState;
 
 /*
@@ -208,6 +211,9 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
     }
 
     *overlapped = FILE_ATTRIBUTE_NORMAL;
+    if (flags & BDRV_O_NATIVE_AIO) {
+        *overlapped |= FILE_FLAG_OVERLAPPED;
+    }
     if (flags & BDRV_O_NOCACHE) {
         *overlapped |= FILE_FLAG_NO_BUFFERING;
     }
@@ -222,6 +228,13 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
     s->type = FTYPE_FILE;
 
     raw_parse_flags(flags, &access_flags, &overlapped);
+    
+    if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
+        aio = win32_aio_init();
+        if (aio == NULL) {
+            return -EINVAL;
+        }
+    }
 
     s->hfile = CreateFile(filename, access_flags,
                           FILE_SHARE_READ, NULL,
@@ -231,7 +244,16 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
 
         if (err == ERROR_ACCESS_DENIED)
             return -EACCES;
-        return -1;
+        return -EINVAL;
+    }
+
+    if (flags & BDRV_O_NATIVE_AIO) {
+        int ret = win32_aio_attach(aio, s->hfile);
+        if (ret < 0) {
+            CloseHandle(s->hfile);
+            return ret;
+        }
+        s->aio = aio;
     }
     return 0;
 }
@@ -241,8 +263,13 @@ static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
                          BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
-    return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
-                       cb, opaque, QEMU_AIO_READ);
+    if (s->aio) {
+        return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
+                                nb_sectors, cb, opaque, QEMU_AIO_READ); 
+    } else {
+        return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
+                           cb, opaque, QEMU_AIO_READ);
+    }
 }
 
 static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
@@ -250,8 +277,13 @@ static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
                           BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
-    return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
-                       cb, opaque, QEMU_AIO_WRITE);
+    if (s->aio) {
+        return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
+                                nb_sectors, cb, opaque, QEMU_AIO_WRITE); 
+    } else {
+        return paio_submit(bs, s->hfile, sector_num, qiov, nb_sectors,
+                           cb, opaque, QEMU_AIO_WRITE);
+    }
 }
 
 static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
diff --git a/block/win32-aio.c b/block/win32-aio.c
new file mode 100644
index 0000000..c34dc73
--- /dev/null
+++ b/block/win32-aio.c
@@ -0,0 +1,226 @@
+/*
+ * Block driver for RAW files (win32)
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "block_int.h"
+#include "module.h"
+#include "qemu-common.h"
+#include "qemu-aio.h"
+#include "raw-aio.h"
+#include "event_notifier.h"
+#include <windows.h>
+#include <winioctl.h>
+
+#define FTYPE_FILE 0
+#define FTYPE_CD     1
+#define FTYPE_HARDDISK 2
+
+struct QEMUWin32AIOState {
+    HANDLE hIOCP;
+    EventNotifier e;
+    int count;
+};
+
+typedef struct QEMUWin32AIOCB {
+    BlockDriverAIOCB common;
+    struct QEMUWin32AIOState *ctx;
+    int nbytes;
+    OVERLAPPED ov;
+    QEMUIOVector *qiov;
+    void *buf;
+    bool is_read;
+    bool is_linear;
+} QEMUWin32AIOCB;
+
+/*
+ * Completes an AIO request (calls the callback and frees the ACB).
+ */
+static void win32_aio_process_completion(QEMUWin32AIOState *s,
+    QEMUWin32AIOCB *waiocb, DWORD count)
+{
+    int ret;
+    s->count--;
+
+    if (waiocb->ov.Internal != 0) {
+        ret = -EIO;
+    } else {
+        ret = 0;
+        if (count < waiocb->nbytes) {
+            /* Short reads mean EOF, pad with zeros. */
+            if (waiocb->is_read) {
+                qemu_iovec_memset(waiocb->qiov, count, 0,
+                    waiocb->qiov->size - count);
+            } else {
+                ret = -EINVAL;
+            }
+       }
+    }
+
+    if (!waiocb->is_linear) {
+        if (ret == 0 && waiocb->is_read) {
+            QEMUIOVector *qiov = waiocb->qiov;
+            char *p = waiocb->buf;
+            int i;
+
+            for (i = 0; i < qiov->niov; ++i) {
+                memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);
+                p += qiov->iov[i].iov_len;
+            }
+            g_free(waiocb->buf);
+        }
+    }
+
+
+    waiocb->common.cb(waiocb->common.opaque, ret);
+    qemu_aio_release(waiocb);
+}
+
+static void win32_aio_completion_cb(EventNotifier *e)
+{
+    QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
+    DWORD count;
+    ULONG_PTR key;
+    OVERLAPPED *ov;
+
+    event_notifier_test_and_clear(&s->e);
+    while (GetQueuedCompletionStatus(s->hIOCP, &count, &key, &ov, 0)) {
+        QEMUWin32AIOCB *waiocb = container_of(ov, QEMUWin32AIOCB, ov);
+
+        win32_aio_process_completion(s, waiocb, count);
+    }
+}
+
+static int win32_aio_flush_cb(EventNotifier *e)
+{
+    QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
+
+    return (s->count > 0) ? 1 : 0;
+}
+
+static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;
+
+    /*
+     * CancelIoEx is only supported in Vista and newer.  For now, just
+     * wait for completion.
+     */
+    while (!HasOverlappedIoCompleted(&waiocb->ov)) {
+        qemu_aio_wait();
+    }
+}
+
+static AIOPool win32_aio_pool = {
+    .aiocb_size         = sizeof(QEMUWin32AIOCB),
+    .cancel             = win32_aio_cancel,
+};
+
+BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
+        QEMUWin32AIOState *aio, HANDLE hfile,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        BlockDriverCompletionFunc *cb, void *opaque, int type)
+{
+    struct QEMUWin32AIOCB *waiocb;
+    uint64_t offset = sector_num * 512;
+    DWORD rc;
+
+    waiocb = qemu_aio_get(&win32_aio_pool, bs, cb, opaque);
+    waiocb->nbytes = nb_sectors * 512;
+    waiocb->qiov = qiov;
+    waiocb->is_read = (type == QEMU_AIO_READ);
+
+    if (qiov->niov > 1) {
+        waiocb->buf = qemu_blockalign(bs, qiov->size);
+        if (type & QEMU_AIO_WRITE) {
+            char *p = waiocb->buf;
+            int i;
+
+            for (i = 0; i < qiov->niov; ++i) {
+                memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);
+                p += qiov->iov[i].iov_len;
+            }
+        }
+        waiocb->is_linear = false;
+    } else {
+        waiocb->buf = qiov->iov[0].iov_base;
+        waiocb->is_linear = true;
+    }
+
+    waiocb->ov = (OVERLAPPED) {
+        .Offset = (DWORD) offset,
+        .OffsetHigh = (DWORD) (offset >> 32),
+        .hEvent = event_notifier_get_handle(&aio->e)
+    };
+    aio->count++;
+
+    if (type & QEMU_AIO_READ) {
+        rc = ReadFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);
+    } else {
+        rc = WriteFile(hfile, waiocb->buf, waiocb->nbytes, NULL, &waiocb->ov);
+    }
+    if(rc == 0 && GetLastError() != ERROR_IO_PENDING) {
+        goto out_dec_count;
+    }
+    return &waiocb->common;
+
+out_dec_count:
+    aio->count--;
+    qemu_aio_release(waiocb);
+    return NULL;
+}
+
+int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
+{
+    if (CreateIoCompletionPort(hfile, aio->hIOCP, (ULONG_PTR) 0, 0) == NULL) {
+        return -EINVAL;
+    } else {
+        return 0;
+    }
+}
+
+QEMUWin32AIOState *win32_aio_init(void)
+{
+    QEMUWin32AIOState *s;
+
+    s = g_malloc0(sizeof(*s));
+    if (event_notifier_init(&s->e, false) < 0) {
+        goto out_free_state;
+    }
+
+    s->hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
+    if (s->hIOCP == NULL) {
+        goto out_close_efd;
+    }
+
+    qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb,
+                                win32_aio_flush_cb);
+
+    return s;
+
+out_close_efd:
+    event_notifier_cleanup(&s->e);
+out_free_state:
+    g_free(s);
+    return NULL;
+}
-- 
1.7.12.1

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO
  2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
                   ` (38 preceding siblings ...)
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O Paolo Bonzini
@ 2012-11-01 19:33 ` Anthony Liguori
  39 siblings, 0 replies; 62+ messages in thread
From: Anthony Liguori @ 2012-11-01 19:33 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: stefanha

Paolo Bonzini <pbonzini@redhat.com> writes:

> The following changes since commit aee0bf7d8d7564f8f2c40e4501695c492b7dd8d1:
>
>   tap-win32: stubs to fix win32 build (2012-10-30 19:18:53 +0000)
>
> are available in the git repository at:
>
>   git://github.com/bonzini/qemu.git threadpool
>
> for you to fetch changes up to f563a5d7a820424756f358e747238f03e866838a:
>
>   Merge remote-tracking branch 'origin/master' into threadpool (2012-10-31 10:42:51 +0100)
>
> Patches 1 to 12 eliminate the dependencies of qemu-tool.c on the main loop
> and AIO infrastructure.  Otherwise the build rules for vscclient, tests
> and qemu-ga become too hairy.  Patches 13 to 30 introduce AioContext
> and a new portable AIO API based on EventNotifier.  Patches 31 to 38
> introduce a generic threadpool that replaces posix-aio-compat.c.
> Patch 39 introduces support for Win32 native AIO.  (As usual, Win32
> bits are mostly there as a testbed for the flexibility of the API).
>
> The patches are based in the remote branch on a known-good commit for
> Win32 (because TCG is a bit broken in master).  Thus there is a merge
> commit at the top to fix the trivial conflicts between patch 1 and the
> later introduction of iov_copy.
>
> Paolo
>

Pulled. Thanks.

Regards,

Anthony Liguori

> ----------------------------------------------------------------
>
> Paolo Bonzini (39):
>       janitor: move iovector functions out of cutils.c
>       build: move cutils.o and qemu-timer-common.o to oslib-obj-y
>       compiler: use weak aliases to provide default definitions
>       sockets: use weak aliases instead of qemu-tool.c
>       fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
>       iohandler: add weak alias in qemu-sockets.c, for qemu-ga
>       win32: add weak version of qemu_fd_register
>       qemu-timer: make initialization functions idempotent
>       main-loop: unify qemu_init_main_loop between QEMU and tools
>       qemu-tool: do not depend on qemu-timer.c
>       build: opts-visitor is not really part of QAPI
>       build: do not include main loop where it is not actually used
>       event_notifier: add Win32 implementation
>       event_notifier: enable it to use pipes
>       vl: init main loop earlier
>       aio: change qemu_aio_set_fd_handler to return void
>       aio: provide platform-independent API
>       aio: introduce AioContext, move bottom halves there
>       aio: add I/O handlers to the AioContext interface
>       aio: test node->deleted before calling io_flush
>       aio: add non-blocking variant of aio_wait
>       aio: prepare for introducing GSource-based dispatch
>       aio: add Win32 implementation
>       aio: make AioContexts GSources
>       aio: add aio_notify
>       aio: call aio_notify after setting I/O handlers
>       main-loop: use GSource to poll AIO file descriptors
>       main-loop: use aio_notify for qemu_notify_event
>       aio: clean up now-unused functions
>       linux-aio: use event notifiers
>       qemu-thread: add QemuSemaphore
>       aio: add generic thread-pool facility
>       threadpool: do not take lock in event_notifier_ready
>       block: switch posix-aio-compat to threadpool
>       raw: merge posix-aio-compat.c into block/raw-posix.c
>       raw-posix: rename raw-posix-aio.h, hide unavailable prototypes
>       raw-win32: add emulated AIO support
>       raw-posix: move linux-aio.c to block/
>       raw-win32: implement native asynchronous I/O
>
>  Makefile                             |   7 +-
>  Makefile.objs                        |  22 +-
>  aio-posix.c                          | 268 ++++++++++++++
>  aio-win32.c                          | 215 +++++++++++
>  aio.c                                | 194 ----------
>  arch_init.h                          |   2 +-
>  async.c                              | 118 +++++-
>  block/Makefile.objs                  |   9 +-
>  linux-aio.c => block/linux-aio.c     |  52 ++-
>  block/{raw-posix-aio.h => raw-aio.h} |  29 +-
>  block/raw-posix.c                    | 308 +++++++++++++++-
>  block/raw-win32.c                    | 221 +++++++++---
>  block/win32-aio.c                    | 226 ++++++++++++
>  compiler.h                           |  11 +-
>  cutils.c                             | 108 ------
>  event_notifier-posix.c               | 120 +++++++
>  event_notifier-win32.c               |  59 +++
>  event_notifier.c                     |  67 ----
>  event_notifier.h                     |  20 +-
>  hw/hw.h                              |   1 +
>  iohandler.c                          |   1 +
>  iov.c                                | 103 ++++++
>  main-loop.c                          | 157 +++-----
>  main-loop.h                          |  66 +---
>  osdep.c                              |  30 ++
>  oslib-posix.c                        |  31 --
>  oslib-win32.c                        |   5 +
>  posix-aio-compat.c                   | 679 -----------------------------------
>  qapi/Makefile.objs                   |   4 +-
>  qemu-aio.h                           | 206 ++++++++++-
>  qemu-char.h                          |   1 +
>  qemu-common.h                        |   3 +-
>  qemu-coroutine-lock.c                |   2 +-
>  qemu-os-win32.h                      |   1 -
>  qemu-sockets.c                       |  18 +
>  qemu-thread-posix.c                  |  80 +++++
>  qemu-thread-posix.h                  |   5 +
>  qemu-thread-win32.c                  |  35 ++
>  qemu-thread-win32.h                  |   4 +
>  qemu-thread.h                        |   7 +
>  qemu-timer.c                         |  12 +-
>  qemu-tool.c                          |  35 +-
>  qemu-user.c                          |  20 --
>  qmp.c                                |   3 +-
>  tests/Makefile                       |   8 +-
>  thread-pool.c                        | 289 +++++++++++++++
>  thread-pool.h                        |  34 ++
>  trace-events                         |   5 +
>  vl.c                                 |  17 +-
>  49 file modificati, 2429 inserzioni(+), 1489 rimozioni(-)
>  create mode 100644 aio-posix.c
>  create mode 100644 aio-win32.c
>  delete mode 100644 aio.c
>  rename linux-aio.c => block/linux-aio.c (82%)
>  rename block/{raw-posix-aio.h => raw-aio.h} (71%)
>  create mode 100644 block/win32-aio.c
>  create mode 100644 event_notifier-posix.c
>  create mode 100644 event_notifier-win32.c
>  delete mode 100644 event_notifier.c
>  delete mode 100644 posix-aio-compat.c
>  create mode 100644 thread-pool.c
>  create mode 100644 thread-pool.h
> -- 
> 1.7.12.1

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier Paolo Bonzini
@ 2012-11-02  7:26   ` Jan Kiszka
  2012-11-02  9:55     ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Jan Kiszka @ 2012-11-02  7:26 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: aliguori, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 1546 bytes --]

On 2012-10-31 16:30, Paolo Bonzini wrote:
> Otherwise, chardevs will not be able to create a bottom half as soon
> as that will require an AioContext.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  vl.c | 12 ++++++------
>  1 file modificato, 6 inserzioni(+), 6 rimozioni(-)
> 
> diff --git a/vl.c b/vl.c
> index b3186fa..f84e969 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -3311,6 +3311,12 @@ int main(int argc, char **argv, char **envp)
>      }
>      loc_set_none();
>  
> +    qemu_init_cpu_loop();
> +    if (qemu_init_main_loop()) {
> +        fprintf(stderr, "qemu_init_main_loop failed\n");
> +        exit(1);
> +    }
> +
>      if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) {
>          exit(1);
>      }
> @@ -3463,12 +3469,6 @@ int main(int argc, char **argv, char **envp)
>  
>      configure_accelerator();
>  
> -    qemu_init_cpu_loop();
> -    if (qemu_init_main_loop()) {
> -        fprintf(stderr, "qemu_init_main_loop failed\n");
> -        exit(1);
> -    }
> -
>      machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
>      if (machine_opts) {
>          kernel_filename = qemu_opt_get(machine_opts, "kernel");
> 

This breaks daemonize as the BQL is marked as owned by the father
process. See also [1] in this context.

Can we move os_daemonize before that, or what are its dependencies? I
have an increasingly bad feeling about this code shuffling.

Jan

[1] http://thread.gmane.org/gmane.comp.emulators.qemu/179311


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier
  2012-11-02  7:26   ` Jan Kiszka
@ 2012-11-02  9:55     ` Paolo Bonzini
  2012-11-02 10:32       ` Jan Kiszka
  0 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-02  9:55 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: aliguori, qemu-devel, stefanha

Il 02/11/2012 08:26, Jan Kiszka ha scritto:
> Can we move os_daemonize before that, or what are its dependencies? I
> have an increasingly bad feeling about this code shuffling.

Moving os_daemonize too early ruins error messages.  I would just
pull qemu_mutex_lock_iothread later, even just before cpu_exec_init_all.
Something like this (untested):

diff --git a/main-loop.c b/main-loop.c
index e43c7c8..07c4b84 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -125,7 +125,6 @@ int qemu_init_main_loop(void)
     init_clocks();
     init_timer_alarm();
 
-    qemu_mutex_lock_iothread();
     ret = qemu_signal_init();
     if (ret) {
         return ret;
diff --git a/vl.c b/vl.c
index 99681da..210d525 100644
--- a/vl.c
+++ b/vl.c
@@ -3631,13 +3631,6 @@ int main(int argc, char **argv, char **envp)
     }
 #endif
 
-    os_daemonize();
-
-    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
-        os_pidfile_error();
-        exit(1);
-    }
-
     /* init the memory */
     if (ram_size == 0) {
         ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
@@ -3682,11 +3675,6 @@ int main(int argc, char **argv, char **envp)
 
     os_set_line_buffering();
 
-#ifdef CONFIG_SPICE
-    /* spice needs the timers to be initialized by this point */
-    qemu_spice_init();
-#endif
-
     if (icount_option && (kvm_enabled() || xen_enabled())) {
         fprintf(stderr, "-icount is not allowed with kvm or xen\n");
         exit(1);
@@ -3709,6 +3697,20 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
+    os_daemonize();
+
+    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
+        os_pidfile_error();
+        exit(1);
+    }
+
+    qemu_mutex_lock_iothread();
+
+#ifdef CONFIG_SPICE
+    /* spice needs timers & threads to be initialized by this point */
+    qemu_spice_init();
+#endif
+
     cpu_exec_init_all();
 
     bdrv_init_with_whitelist();

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier
  2012-11-02  9:55     ` Paolo Bonzini
@ 2012-11-02 10:32       ` Jan Kiszka
  2012-11-02 11:04         ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Jan Kiszka @ 2012-11-02 10:32 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: aliguori, qemu-devel, stefanha

On 2012-11-02 10:55, Paolo Bonzini wrote:
> Il 02/11/2012 08:26, Jan Kiszka ha scritto:
>> Can we move os_daemonize before that, or what are its dependencies? I
>> have an increasingly bad feeling about this code shuffling.
> 
> Moving os_daemonize too early ruins error messages.  I would just
> pull qemu_mutex_lock_iothread later, even just before cpu_exec_init_all.
> Something like this (untested):
> 
> diff --git a/main-loop.c b/main-loop.c
> index e43c7c8..07c4b84 100644
> --- a/main-loop.c
> +++ b/main-loop.c
> @@ -125,7 +125,6 @@ int qemu_init_main_loop(void)
>      init_clocks();
>      init_timer_alarm();
>  
> -    qemu_mutex_lock_iothread();
>      ret = qemu_signal_init();
>      if (ret) {
>          return ret;
> diff --git a/vl.c b/vl.c
> index 99681da..210d525 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -3631,13 +3631,6 @@ int main(int argc, char **argv, char **envp)
>      }
>  #endif
>  
> -    os_daemonize();
> -
> -    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
> -        os_pidfile_error();
> -        exit(1);
> -    }
> -
>      /* init the memory */
>      if (ram_size == 0) {
>          ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
> @@ -3682,11 +3675,6 @@ int main(int argc, char **argv, char **envp)
>  
>      os_set_line_buffering();
>  
> -#ifdef CONFIG_SPICE
> -    /* spice needs the timers to be initialized by this point */
> -    qemu_spice_init();
> -#endif
> -
>      if (icount_option && (kvm_enabled() || xen_enabled())) {
>          fprintf(stderr, "-icount is not allowed with kvm or xen\n");
>          exit(1);
> @@ -3709,6 +3697,20 @@ int main(int argc, char **argv, char **envp)
>          }
>      }
>  
> +    os_daemonize();
> +
> +    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
> +        os_pidfile_error();
> +        exit(1);
> +    }
> +
> +    qemu_mutex_lock_iothread();
> +
> +#ifdef CONFIG_SPICE
> +    /* spice needs timers & threads to be initialized by this point */
> +    qemu_spice_init();
> +#endif
> +
>      cpu_exec_init_all();
>  
>      bdrv_init_with_whitelist();
> 

Would have been too easy:

# qemu-system-x86_64 -daemonize
gettime: Invalid argument
Internal timer error: aborting

Haven't looked at details yet.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier
  2012-11-02 10:32       ` Jan Kiszka
@ 2012-11-02 11:04         ` Paolo Bonzini
  0 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-02 11:04 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: aliguori, qemu-devel, stefanha

Il 02/11/2012 11:32, Jan Kiszka ha scritto:
> On 2012-11-02 10:55, Paolo Bonzini wrote:
>> Il 02/11/2012 08:26, Jan Kiszka ha scritto:
>>> Can we move os_daemonize before that, or what are its dependencies? I
>>> have an increasingly bad feeling about this code shuffling.
>>
>> Moving os_daemonize too early ruins error messages.  I would just
>> pull qemu_mutex_lock_iothread later, even just before cpu_exec_init_all.
>> Something like this (untested):
>>
>> diff --git a/main-loop.c b/main-loop.c
>> index e43c7c8..07c4b84 100644
>> --- a/main-loop.c
>> +++ b/main-loop.c
>> @@ -125,7 +125,6 @@ int qemu_init_main_loop(void)
>>      init_clocks();
>>      init_timer_alarm();
>>  
>> -    qemu_mutex_lock_iothread();
>>      ret = qemu_signal_init();
>>      if (ret) {
>>          return ret;
>> diff --git a/vl.c b/vl.c
>> index 99681da..210d525 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -3631,13 +3631,6 @@ int main(int argc, char **argv, char **envp)
>>      }
>>  #endif
>>  
>> -    os_daemonize();
>> -
>> -    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
>> -        os_pidfile_error();
>> -        exit(1);
>> -    }
>> -
>>      /* init the memory */
>>      if (ram_size == 0) {
>>          ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
>> @@ -3682,11 +3675,6 @@ int main(int argc, char **argv, char **envp)
>>  
>>      os_set_line_buffering();
>>  
>> -#ifdef CONFIG_SPICE
>> -    /* spice needs the timers to be initialized by this point */
>> -    qemu_spice_init();
>> -#endif
>> -
>>      if (icount_option && (kvm_enabled() || xen_enabled())) {
>>          fprintf(stderr, "-icount is not allowed with kvm or xen\n");
>>          exit(1);
>> @@ -3709,6 +3697,20 @@ int main(int argc, char **argv, char **envp)
>>          }
>>      }
>>  
>> +    os_daemonize();
>> +
>> +    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
>> +        os_pidfile_error();
>> +        exit(1);
>> +    }
>> +
>> +    qemu_mutex_lock_iothread();
>> +
>> +#ifdef CONFIG_SPICE
>> +    /* spice needs timers & threads to be initialized by this point */
>> +    qemu_spice_init();
>> +#endif
>> +
>>      cpu_exec_init_all();
>>  
>>      bdrv_init_with_whitelist();
>>
> 
> Would have been too easy:
> 
> # qemu-system-x86_64 -daemonize
> gettime: Invalid argument
> Internal timer error: aborting
> 
> Haven't looked at details yet.

np, will do so now.

Paolo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 35/39] raw: merge posix-aio-compat.c into block/raw-posix.c
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 35/39] raw: merge posix-aio-compat.c into block/raw-posix.c Paolo Bonzini
@ 2012-11-02 15:00   ` Peter Maydell
  0 siblings, 0 replies; 62+ messages in thread
From: Peter Maydell @ 2012-11-02 15:00 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: aliguori, qemu-devel, stefanha

On 31 October 2012 16:30, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Making the qemu_paiocb specific to raw devices will let us access members
> of the BDRVRawState arbitrarily.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

clang now warns about an unused function:
  CC    block/raw-posix.o
block/raw-posix.c:707:26: warning: unused function 'paio_ioctl'
[-Wunused-function]
static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
                         ^
1 warning generated.

because the only use of paio_ioctl() is inside a #if defined(__linux__)
guard and it's 'static' now.

-- PMM

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c Paolo Bonzini
@ 2012-11-15 18:01   ` Stefan Weil
  2012-11-15 20:52     ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Stefan Weil @ 2012-11-15 18:01 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Blue Swirl, aliguori, qemu-devel, stefanha

Am 31.10.2012 16:30, schrieb Paolo Bonzini:
> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> ---
>   cutils.c      |  5 -----
>   osdep.c       | 30 ++++++++++++++++++++++++++++++
>   qemu-common.h |  1 -
>   qemu-tool.c   | 20 --------------------
>   qemu-user.c   | 20 --------------------
>   5 file modificati, 30 inserzioni(+), 46 rimozioni(-)
>
> diff --git a/cutils.c b/cutils.c
> index 6f9f799..4f0692f 100644
> --- a/cutils.c
> +++ b/cutils.c
> @@ -280,11 +280,6 @@ int qemu_parse_fd(const char *param)
>       return fd;
>   }
>
> -int qemu_parse_fdset(const char *param)
> -{
> -    return qemu_parse_fd(param);
> -}
> -
>   /* round down to the nearest power of 2*/
>   int64_t pow2floor(int64_t value)
>   {
> diff --git a/osdep.c b/osdep.c
> index 3b25297..0061f74 100644
> --- a/osdep.c
> +++ b/osdep.c
> @@ -144,6 +144,11 @@ fail:
>       errno = serrno;
>       return -1;
>   }
> +
> +static int qemu_parse_fdset(const char *param)
> +{
> +    return qemu_parse_fd(param);
> +}
>   #endif
>
>   /*
> @@ -404,3 +409,28 @@ bool fips_get_state(void)
>   {
>       return fips_enabled;
>   }
> +
> +
> +static int default_fdset_get_fd(int64_t fdset_id, int flags)
> +{
> +    return -1;
> +}
> +QEMU_WEAK_ALIAS(monitor_fdset_get_fd, default_fdset_get_fd);
> +
> +static int default_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
> +{
> +    return -1;
> +}
> +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_add, default_fdset_dup_fd_add);
> +
> +static int default_fdset_dup_fd_remove(int dup_fd)
> +{
> +    return -1;
> +}
> +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_remove, default_fdset_dup_fd_remove);
> +
> +static int default_fdset_dup_fd_find(int dup_fd)
> +{
> +    return -1;
> +}
> +QEMU_WEAK_ALIAS(monitor_fdset_dup_fd_find, default_fdset_dup_fd_find);
> diff --git a/qemu-common.h b/qemu-common.h
> index b54612b..36ce522 100644
> --- a/qemu-common.h
> +++ b/qemu-common.h
> @@ -167,7 +167,6 @@ int qemu_fls(int i);
>   int qemu_fdatasync(int fd);
>   int fcntl_setfl(int fd, int flag);
>   int qemu_parse_fd(const char *param);
> -int qemu_parse_fdset(const char *param);
>
>   /*
>    * strtosz() suffixes used to specify the default treatment of an
> diff --git a/qemu-tool.c b/qemu-tool.c
> index f2f9813..84273ae 100644
> --- a/qemu-tool.c
> +++ b/qemu-tool.c
> @@ -68,26 +68,6 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
>   {
>   }
>
> -int monitor_fdset_get_fd(int64_t fdset_id, int flags)
> -{
> -    return -1;
> -}
> -
> -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
> -{
> -    return -1;
> -}
> -
> -int monitor_fdset_dup_fd_remove(int dup_fd)
> -{
> -    return -1;
> -}
> -
> -int monitor_fdset_dup_fd_find(int dup_fd)
> -{
> -    return -1;
> -}
> -
>   int64_t cpu_get_clock(void)
>   {
>       return qemu_get_clock_ns(rt_clock);
> diff --git a/qemu-user.c b/qemu-user.c
> index 13fb9ae..08ccb0f 100644
> --- a/qemu-user.c
> +++ b/qemu-user.c
> @@ -35,23 +35,3 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
>   void monitor_set_error(Monitor *mon, QError *qerror)
>   {
>   }
> -
> -int monitor_fdset_get_fd(int64_t fdset_id, int flags)
> -{
> -    return -1;
> -}
> -
> -int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
> -{
> -    return -1;
> -}
> -
> -int monitor_fdset_dup_fd_remove(int dup_fd)
> -{
> -    return -1;
> -}
> -
> -int monitor_fdset_dup_fd_find(int dup_fd)
> -{
> -    return -1;
> -}


Hi Paolo,

this patch breaks QEMU on 32 and 64 bit hosts, native and with Wine.
It's easy to reproduce the SIGSEGV crash: just add a -snapshot option.
Obviously the critical code is executed only when this option was used.

Here is a simple command line using Wine:

wine i386-softmmu/qemu-system-i386 -L pc-bios -snapshot Makefile

The disk image does not matter, so I just selected QEMU's Makefile.

It looks like weak symbols are not really working with MinGW
(Blue Swirl previously pointed out that only ELF and a.out are
officially supported).

I can see in the debugger that QEMU wants to call monitor_fdset_dup_fd_find
from qemu_close.

In previous versions, this was just a dummy function returning 0.
Now, it is the function in monitor.c, but the address does not match
exactly, so the code addresses lines near the beginning of
monitor_fdset_dup_fd_find which does not work of course.

A trivial workaround is calling default_fdset_dup_fd_find which
restores the old behaviour. I expect that all other weak functions
would show the same problem if they were used.

Regards,

Stefan

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-15 18:01   ` Stefan Weil
@ 2012-11-15 20:52     ` Paolo Bonzini
  2012-11-15 22:18       ` Stefan Weil
  0 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-15 20:52 UTC (permalink / raw)
  To: Stefan Weil; +Cc: Blue Swirl, aliguori, qemu-devel, stefanha

Il 15/11/2012 19:01, Stefan Weil ha scritto:
> Hi Paolo,
> 
> this patch breaks QEMU on 32 and 64 bit hosts, native and with Wine.
> It's easy to reproduce the SIGSEGV crash: just add a -snapshot option.
> Obviously the critical code is executed only when this option was used.

I cannot reproduce this, so it must be an assembler or linker bug.

Can you try the alternative code that is used for Mac OS X?

Paolo

> Here is a simple command line using Wine:
> 
> wine i386-softmmu/qemu-system-i386 -L pc-bios -snapshot Makefile
> 
> The disk image does not matter, so I just selected QEMU's Makefile.
> 
> It looks like weak symbols are not really working with MinGW
> (Blue Swirl previously pointed out that only ELF and a.out are
> officially supported).
> 
> I can see in the debugger that QEMU wants to call monitor_fdset_dup_fd_find
> from qemu_close.
> 
> In previous versions, this was just a dummy function returning 0.
> Now, it is the function in monitor.c, but the address does not match
> exactly, so the code addresses lines near the beginning of
> monitor_fdset_dup_fd_find which does not work of course.
> 
> A trivial workaround is calling default_fdset_dup_fd_find which
> restores the old behaviour. I expect that all other weak functions
> would show the same problem if they were used.
> 
> Regards,
> 
> Stefan
> 
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-15 20:52     ` Paolo Bonzini
@ 2012-11-15 22:18       ` Stefan Weil
  2012-11-16  9:35         ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Stefan Weil @ 2012-11-15 22:18 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Blue Swirl, aliguori, qemu-devel, stefanha

Am 15.11.2012 21:52, schrieb Paolo Bonzini:
> Il 15/11/2012 19:01, Stefan Weil ha scritto:
>> Hi Paolo,
>>
>> this patch breaks QEMU on 32 and 64 bit hosts, native and with Wine.
>> It's easy to reproduce the SIGSEGV crash: just add a -snapshot option.
>> Obviously the critical code is executed only when this option was used.
>
> I cannot reproduce this, so it must be an assembler or linker bug.
>
> Can you try the alternative code that is used for Mac OS X?
>
> Paolo

The code which is used for Mac OS X also compiles and
results in the same run-time bug with Wine:

wine: Unhandled page fault on write access to 0x00000004 at address 
0x7b845d6e (thread 001b), starting debugger...

(immediately after BIOS says "Booting from hard disk...")

This was the modification used:

diff --git a/compiler.h b/compiler.h
index 55d7d74..62427e4 100644
--- a/compiler.h
+++ b/compiler.h
@@ -50,11 +50,12 @@
  #   define __printf__ __gnu_printf__
  #  endif
  # endif
-# if defined(__APPLE__)
+# if defined(__APPLE__) || defined(_WIN32)
  #  define QEMU_WEAK_ALIAS(newname, oldname) \
          static typeof(oldname) weak_##newname __attribute__((unused, 
weakref(#oldname)))
  #  define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? 
weak_##newname : oldname)
  # else
+#error
  #  define QEMU_WEAK_ALIAS(newname, oldname) \
          typeof(oldname) newname __attribute__((weak, alias (#oldname)))
  #  define QEMU_WEAK_REF(newname, oldname) newname


These are my Debian packages (only the 32 bit ones are needed for the test):

ii  binutils-mingw-w64-i686                     
2.22-7+2                           Cross-binutils for Win32 (x86) using 
MinGW-w64
ii  binutils-mingw-w64-x86-64                   
2.22-7+2                           Cross-binutils for Win64 (x64) using 
MinGW-w64
ii  gcc-mingw-w64                               
4.6.3-8+7                          GNU C compiler for MinGW-w64
ii  gcc-mingw-w64-base                          
4.6.3-8+7                          GNU Compiler Collection for MinGW-w64 
(base package)
ii  gcc-mingw-w64-i686                          
4.6.3-8+7                          GNU C compiler for MinGW-w64 
targeting Win32
ii  gcc-mingw-w64-x86-64                        
4.6.3-8+7                          GNU C compiler for MinGW-w64 
targeting Win64
ii  mingw-w64                                   
3.0~svn4933-1                      Development environment targetting 
32- and 64-bit Windows
ii  mingw-w64-dev                               
3.0~svn4933-1                      Development files for MinGW-w64
ii  mingw-w64-tools                             
3.0~svn4933-1                      Development tools for 32- and 64-bit 
Windows

On Windows, I used a rather new MinGW standard installation.

I'll run more tests with other Linux distributions tomorrow.

Cheers,

Stefan


>> Here is a simple command line using Wine:
>>
>> wine i386-softmmu/qemu-system-i386 -L pc-bios -snapshot Makefile
>>
>> The disk image does not matter, so I just selected QEMU's Makefile.
>>
>> It looks like weak symbols are not really working with MinGW
>> (Blue Swirl previously pointed out that only ELF and a.out are
>> officially supported).
>>
>> I can see in the debugger that QEMU wants to call monitor_fdset_dup_fd_find
>> from qemu_close.
>>
>> In previous versions, this was just a dummy function returning 0.
>> Now, it is the function in monitor.c, but the address does not match
>> exactly, so the code addresses lines near the beginning of
>> monitor_fdset_dup_fd_find which does not work of course.
>>
>> A trivial workaround is calling default_fdset_dup_fd_find which
>> restores the old behaviour. I expect that all other weak functions
>> would show the same problem if they were used.
>>
>> Regards,
>>
>> Stefan
>>
>>
>
>

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-15 22:18       ` Stefan Weil
@ 2012-11-16  9:35         ` Paolo Bonzini
  2012-11-16 17:15           ` Stefan Weil
  2012-11-16 17:52           ` Peter Maydell
  0 siblings, 2 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-16  9:35 UTC (permalink / raw)
  To: Stefan Weil; +Cc: Blue Swirl, aliguori, qemu-devel, stefanha

Il 15/11/2012 23:18, Stefan Weil ha scritto:
> Am 15.11.2012 21:52, schrieb Paolo Bonzini:
>> Il 15/11/2012 19:01, Stefan Weil ha scritto:
>>> Hi Paolo,
>>>
>>> this patch breaks QEMU on 32 and 64 bit hosts, native and with Wine.
>>> It's easy to reproduce the SIGSEGV crash: just add a -snapshot option.
>>> Obviously the critical code is executed only when this option was used.
>>
>> I cannot reproduce this, so it must be an assembler or linker bug.
>>
>> Can you try the alternative code that is used for Mac OS X?
> 
> The code which is used for Mac OS X also compiles and
> results in the same run-time bug with Wine:

Ok, I reproduced the original binutils bug, and found a typo in the
weakrefs implementation.  Does this work for you?

diff --git a/compiler.h b/compiler.h
index 55d7d74..d552757 100644
--- a/compiler.h
+++ b/compiler.h
@@ -50,11 +50,12 @@
 #   define __printf__ __gnu_printf__
 #  endif
 # endif
-# if defined(__APPLE__)
+# if defined(__APPLE__) || defined(_WIN32)
 #  define QEMU_WEAK_ALIAS(newname, oldname) \
-        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#oldname)))
+        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#newname)))
 #  define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? weak_##newname : oldname)
 # else
+#error
 #  define QEMU_WEAK_ALIAS(newname, oldname) \
         typeof(oldname) newname __attribute__((weak, alias (#oldname)))
 #  define QEMU_WEAK_REF(newname, oldname) newname


If it still doesn't work, let's make sure that this reduced testcase works
for you:

g1.c:
#include <stdio.h>
int f() { printf("strong"); return 82; }
int g() { printf("strong"); return 83; }

g2.c:
#include <stdio.h>
static int weak_f() { return 42; }
static int weak_g() { return 43; }
typeof(weak_f) f __attribute__((__weak__, __alias__("weak_f")));
typeof(weak_g) g __attribute__((__weak__, __alias__("weak_g")));
int main() { printf("%d/%d\n", f(), g()); }

g3.c:
#include <stdio.h>
static int default_f() { return 42; }
static int default_g() { return 43; }
static typeof(default_f) weak_f __attribute__((__weakref__("f")));
static typeof(default_g) weak_g __attribute__((__weakref__("g")));
int main() { printf("%d/%d\n", (weak_f?:default_f)(), (weak_g?:default_g)()); }

Output should be:
- 42/43 for "gcc g2.c"
- 42/43 for "gcc g3.c"
- strongstrong82/83 for "gcc g1.c g2.c"
- strongstrong82/83 for "gcc g1.c g3.c"

Output on Windows is:
- 42/42 for "gcc g2.c"
- 42/43 for "gcc g3.c"
- segfault for "gcc g1.c g2.c"
- strongstrong82/83 for "gcc g1.c g3.c"

So, indeed "normal" weak symbols are broken, but weakrefs seem to work.

If the above patch doesn't work, and/or the reduced testcase fails,
please send to me:

- the .exe for "gcc g1.c g3.c"
- the .s file for g3.s
- the .o file for osdep.o
- the linked .exe (I assume both the windows and console versions fail)
- perhaps the .s file for osdep too; add --save-temps to the compiler command line to get it

Paolo

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-16  9:35         ` Paolo Bonzini
@ 2012-11-16 17:15           ` Stefan Weil
  2012-11-16 17:39             ` Paolo Bonzini
  2012-11-16 17:52           ` Peter Maydell
  1 sibling, 1 reply; 62+ messages in thread
From: Stefan Weil @ 2012-11-16 17:15 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Blue Swirl, aliguori, qemu-devel, stefanha

Am 16.11.2012 10:35, schrieb Paolo Bonzini:
> Il 15/11/2012 23:18, Stefan Weil ha scritto:
>> Am 15.11.2012 21:52, schrieb Paolo Bonzini:
>>> Il 15/11/2012 19:01, Stefan Weil ha scritto:
>>>> Hi Paolo,
>>>>
>>>> this patch breaks QEMU on 32 and 64 bit hosts, native and with Wine.
>>>> It's easy to reproduce the SIGSEGV crash: just add a -snapshot option.
>>>> Obviously the critical code is executed only when this option was used.
>>>
>>> I cannot reproduce this, so it must be an assembler or linker bug.
>>>
>>> Can you try the alternative code that is used for Mac OS X?
>>
>> The code which is used for Mac OS X also compiles and
>> results in the same run-time bug with Wine:
>
> Ok, I reproduced the original binutils bug, and found a typo in the
> weakrefs implementation.  Does this work for you?
>
> diff --git a/compiler.h b/compiler.h
> index 55d7d74..d552757 100644
> --- a/compiler.h
> +++ b/compiler.h
> @@ -50,11 +50,12 @@
>   #   define __printf__ __gnu_printf__
>   #  endif
>   # endif
> -# if defined(__APPLE__)
> +# if defined(__APPLE__) || defined(_WIN32)
>   #  define QEMU_WEAK_ALIAS(newname, oldname) \
> -        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#oldname)))
> +        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#newname)))
>   #  define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? weak_##newname : oldname)
>   # else
> +#error
>   #  define QEMU_WEAK_ALIAS(newname, oldname) \
>           typeof(oldname) newname __attribute__((weak, alias (#oldname)))
>   #  define QEMU_WEAK_REF(newname, oldname) newname
>
>
> If it still doesn't work, let's make sure that this reduced testcase works
> for you:

Tested-by: Stefan Weil <sw@weilnetz.de>

Great, the above patch fixes w32/w64 (native and with Wine).
Is this modification needed / does it work with MacOS X, too?

With the reduced testcase, I get the same results as in your test.

Regards
Stefan


>
> g1.c:
> #include<stdio.h>
> int f() { printf("strong"); return 82; }
> int g() { printf("strong"); return 83; }
>
> g2.c:
> #include<stdio.h>
> static int weak_f() { return 42; }
> static int weak_g() { return 43; }
> typeof(weak_f) f __attribute__((__weak__, __alias__("weak_f")));
> typeof(weak_g) g __attribute__((__weak__, __alias__("weak_g")));
> int main() { printf("%d/%d\n", f(), g()); }
>
> g3.c:
> #include<stdio.h>
> static int default_f() { return 42; }
> static int default_g() { return 43; }
> static typeof(default_f) weak_f __attribute__((__weakref__("f")));
> static typeof(default_g) weak_g __attribute__((__weakref__("g")));
> int main() { printf("%d/%d\n", (weak_f?:default_f)(), (weak_g?:default_g)()); }
>
> Output should be:
> - 42/43 for "gcc g2.c"
> - 42/43 for "gcc g3.c"
> - strongstrong82/83 for "gcc g1.c g2.c"
> - strongstrong82/83 for "gcc g1.c g3.c"
>
> Output on Windows is:
> - 42/42 for "gcc g2.c"
> - 42/43 for "gcc g3.c"
> - segfault for "gcc g1.c g2.c"
> - strongstrong82/83 for "gcc g1.c g3.c"
>
> So, indeed "normal" weak symbols are broken, but weakrefs seem to work.
>
> If the above patch doesn't work, and/or the reduced testcase fails,
> please send to me:
>
> - the .exe for "gcc g1.c g3.c"
> - the .s file for g3.s
> - the .o file for osdep.o
> - the linked .exe (I assume both the windows and console versions fail)
> - perhaps the .s file for osdep too; add --save-temps to the compiler command line to get it
>
> Paolo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-16 17:15           ` Stefan Weil
@ 2012-11-16 17:39             ` Paolo Bonzini
  0 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-16 17:39 UTC (permalink / raw)
  To: Stefan Weil; +Cc: Blue Swirl, aliguori, qemu-devel, stefanha

Il 16/11/2012 18:15, Stefan Weil ha scritto:
> 
> Tested-by: Stefan Weil <sw@weilnetz.de>
> 
> Great, the above patch fixes w32/w64 (native and with Wine).
> Is this modification needed / does it work with MacOS X, too?

Yes, but I found a way to get rid of weak references completely.  The
testing is still precious---thanks very much.

> With the reduced testcase, I get the same results as in your test.

Good to know, too. :)  llvm-gcc totally botches it on Mac OS X, by the
way (while clang works there).

Paolo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-16  9:35         ` Paolo Bonzini
  2012-11-16 17:15           ` Stefan Weil
@ 2012-11-16 17:52           ` Peter Maydell
  2012-11-16 17:55             ` Paolo Bonzini
  1 sibling, 1 reply; 62+ messages in thread
From: Peter Maydell @ 2012-11-16 17:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Blue Swirl, Stefan Weil, aliguori, qemu-devel, stefanha

On 16 November 2012 09:35, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Ok, I reproduced the original binutils bug, and found a typo in the
> weakrefs implementation.  Does this work for you?
>
> diff --git a/compiler.h b/compiler.h
> index 55d7d74..d552757 100644
> --- a/compiler.h
> +++ b/compiler.h
> @@ -50,11 +50,12 @@
>  #   define __printf__ __gnu_printf__
>  #  endif
>  # endif
> -# if defined(__APPLE__)
> +# if defined(__APPLE__) || defined(_WIN32)
>  #  define QEMU_WEAK_ALIAS(newname, oldname) \
> -        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#oldname)))
> +        static typeof(oldname) weak_##newname __attribute__((unused, weakref(#newname)))
>  #  define QEMU_WEAK_REF(newname, oldname) (weak_##newname ? weak_##newname : oldname)
>  # else
> +#error
>  #  define QEMU_WEAK_ALIAS(newname, oldname) \
>          typeof(oldname) newname __attribute__((weak, alias (#oldname)))
>  #  define QEMU_WEAK_REF(newname, oldname) newname

This change makes compilation fail with clang:
  LINK  qemu-ga
Undefined symbols for architecture x86_64:
  "_monitor_fdset_dup_fd_add", referenced from:
      _qemu_open in osdep.o
  "_monitor_fdset_dup_fd_remove", referenced from:
      _qemu_close in osdep.o
  "_monitor_fdset_get_fd", referenced from:
      _qemu_open in osdep.o
  "_monitor_get_fd", referenced from:
      _socket_connect in qemu-sockets.o
      _socket_listen in qemu-sockets.o
  "_qemu_set_fd_handler2", referenced from:
      _inet_connect_addr in qemu-sockets.o
      _unix_connect_opts in qemu-sockets.o
      _wait_for_connect in qemu-sockets.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

(clang builds OK with current git master.)

-- PMM

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c
  2012-11-16 17:52           ` Peter Maydell
@ 2012-11-16 17:55             ` Paolo Bonzini
  0 siblings, 0 replies; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-16 17:55 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Blue Swirl, Stefan Weil, aliguori, qemu-devel, stefanha

Il 16/11/2012 18:52, Peter Maydell ha scritto:
> clang: error: linker command failed with exit code 1 (use -v to see invocation)
> 
> (clang builds OK with current git master.)

But I have no idea why, or whether the generated code is correct...

Looks like the safest bet is to go with the good old static library.

Paolo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O Paolo Bonzini
@ 2012-11-21 13:20   ` Jan Kiszka
  2012-11-21 13:25     ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Jan Kiszka @ 2012-11-21 13:20 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: aliguori, qemu-devel, stefanha

On 2012-10-31 16:30, Paolo Bonzini wrote:
> With the new support for EventNotifiers in the AIO event loop, we
> can hook a completion port to every opened file and use asynchronous
> I/O on them.
> 
> Wine's support is extremely inefficient, also because it really does
> the I/O synchronously on regular files. (!)  But it works, and it is
> good to keep the Win32 and POSIX ports as similar as possible.
> 

I'm seeing a regression with this patch when cross-compiling with
mingw32 for Win7. QEMU is stuck while booting a versatilepb guest that
accesses the block layer via pflash. Enabling tracing "fixes" the issue,
of course...

Are there any patches flying around that are supposed to resolve this?

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-21 13:20   ` Jan Kiszka
@ 2012-11-21 13:25     ` Paolo Bonzini
  2012-11-21 13:27       ` Jan Kiszka
  0 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-21 13:25 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: aliguori, qemu-devel, stefanha

Il 21/11/2012 14:20, Jan Kiszka ha scritto:
> I'm seeing a regression with this patch when cross-compiling with
> mingw32 for Win7. QEMU is stuck while booting a versatilepb guest that
> accesses the block layer via pflash. Enabling tracing "fixes" the issue,
> of course...
> 
> Are there any patches flying around that are supposed to resolve this?

No.  Is this with aio=native or aio=threads?

Paolo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-21 13:25     ` Paolo Bonzini
@ 2012-11-21 13:27       ` Jan Kiszka
  2012-11-21 13:33         ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Jan Kiszka @ 2012-11-21 13:27 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com

On 2012-11-21 14:25, Paolo Bonzini wrote:
> Il 21/11/2012 14:20, Jan Kiszka ha scritto:
>> I'm seeing a regression with this patch when cross-compiling with
>> mingw32 for Win7. QEMU is stuck while booting a versatilepb guest that
>> accesses the block layer via pflash. Enabling tracing "fixes" the issue,
>> of course...
>>
>> Are there any patches flying around that are supposed to resolve this?
> 
> No.  Is this with aio=native or aio=threads?

aio=<default> - whatever that is on win32.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-21 13:27       ` Jan Kiszka
@ 2012-11-21 13:33         ` Paolo Bonzini
  2012-11-21 13:38           ` Jan Kiszka
  0 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-21 13:33 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com

Il 21/11/2012 14:27, Jan Kiszka ha scritto:
>>> >> Are there any patches flying around that are supposed to resolve this?
>> > 
>> > No.  Is this with aio=native or aio=threads?
> aio=<default> - whatever that is on win32.

That's aio=threads, just like POSIX.  I'm curious (but not too
optimistic) whether aio=native fixes it.

Anyhow, do you have a reproducer that I can download?

Paolo

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-21 13:33         ` Paolo Bonzini
@ 2012-11-21 13:38           ` Jan Kiszka
  2012-11-22 13:34             ` Jan Kiszka
  0 siblings, 1 reply; 62+ messages in thread
From: Jan Kiszka @ 2012-11-21 13:38 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com

On 2012-11-21 14:33, Paolo Bonzini wrote:
> Il 21/11/2012 14:27, Jan Kiszka ha scritto:
>>>>>> Are there any patches flying around that are supposed to resolve this?
>>>>
>>>> No.  Is this with aio=native or aio=threads?
>> aio=<default> - whatever that is on win32.
> 
> That's aio=threads, just like POSIX.  I'm curious (but not too
> optimistic) whether aio=native fixes it.

Just tried, and it actually makes no difference.

> 
> Anyhow, do you have a reproducer that I can download?

Unfortunately, not at this point. Have to check, maybe I can trip the
image to the bare Linux guest.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-21 13:38           ` Jan Kiszka
@ 2012-11-22 13:34             ` Jan Kiszka
  2012-11-22 15:16               ` Paolo Bonzini
  0 siblings, 1 reply; 62+ messages in thread
From: Jan Kiszka @ 2012-11-22 13:34 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com

On 2012-11-21 14:38, Jan Kiszka wrote:
> On 2012-11-21 14:33, Paolo Bonzini wrote:
>> Il 21/11/2012 14:27, Jan Kiszka ha scritto:
>>>>>>> Are there any patches flying around that are supposed to resolve this?
>>>>>
>>>>> No.  Is this with aio=native or aio=threads?
>>> aio=<default> - whatever that is on win32.
>>
>> That's aio=threads, just like POSIX.  I'm curious (but not too
>> optimistic) whether aio=native fixes it.
> 
> Just tried, and it actually makes no difference.
> 
>>
>> Anyhow, do you have a reproducer that I can download?
> 
> Unfortunately, not at this point. Have to check, maybe I can trip the
> image to the bare Linux guest.

Maybe this helps:

=>0 0xf77c242e __kernel_vsyscall+0xe() in [vdso].so (0x0519df88)
  1 0xf761f10b __libc_read+0x4a() in libpthread.so.0 (0x0519df88)
  2 0x7bc78c98 in ntdll (+0x68c97) (0x0519df88)
  3 0x7bc7b0a3 in ntdll (+0x6b0a2) (0x0519e1b8)
  4 0x7bc7b195 NtWaitForMultipleObjects+0x54() in ntdll (0x0519e1e8)
  5 0x7b86de9f WaitForMultipleObjectsEx+0xee() in kernel32 (0x0519e338)
  6 0x7b86df1a WaitForMultipleObjects+0x39() in kernel32 (0x0519e368)
  7 0x0040301b aio_poll+0x16a(ctx=0x157610, blocking=<is not available>) [/data/qemu/aio-win32.c:178] in qemu-system-arm (0x00000001)
  8 0x004feec3 qemu_aio_wait+0x22() [/data/qemu/main-loop.c:442] in qemu-system-arm (0x0105bdec)
  9 0x00417166 bdrv_rw_co+0xa5(bs=0x159648, sector_num=<internal error>, buf="¹¸ÿ¦
                                                                                  ", nb_sectors=0x4, is_write=true) [/data/qemu/block.c:1997] in qemu-system-arm (0x0105bdec)
  10 0x00495544 in qemu-system-arm (+0x95543) (0x0105bdec)
  11 0x0049592a pflash_write+0x3b9(pfl=0xd6f16e0, offset=<internal error>, value=0x98f7fb1d, width=0x4, be=0) [/data/qemu/hw/pflash_cfi01.c:405] in qemu-system-arm (0x0105bdec)
  12 0x00618a7e io_mem_write+0xed(mr=0xd6f2a48, addr=0x105bdec, val=0x98f7fb1d, size=0x4) [/data/qemu/memory.c:911] in qemu-system-arm (0x00000004)
  13 0x0064088c helper_stl_mmu+0x2fb(env=0x15e268, addr=0xca05bdec, val=0x98f7fb1d, mmu_idx=0) [/data/qemu/softmmu_template.h:231] in qemu-system-arm (0x3700001e)
  14 0x02136637 (0x0015e268)

It's the VCPU thread stuck in aio_poll, holding the BQL, blocking the
iothread this way as well. Is there some race that prevents we receive
the proper IO completion signal? Any states I should check?

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-22 13:34             ` Jan Kiszka
@ 2012-11-22 15:16               ` Paolo Bonzini
  2012-11-22 15:53                 ` Jan Kiszka
  0 siblings, 1 reply; 62+ messages in thread
From: Paolo Bonzini @ 2012-11-22 15:16 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com

Il 22/11/2012 14:34, Jan Kiszka ha scritto:
> 
> =>0 0xf77c242e __kernel_vsyscall+0xe() in [vdso].so (0x0519df88)
>   1 0xf761f10b __libc_read+0x4a() in libpthread.so.0 (0x0519df88)
>   2 0x7bc78c98 in ntdll (+0x68c97) (0x0519df88)
>   3 0x7bc7b0a3 in ntdll (+0x6b0a2) (0x0519e1b8)
>   4 0x7bc7b195 NtWaitForMultipleObjects+0x54() in ntdll (0x0519e1e8)
>   5 0x7b86de9f WaitForMultipleObjectsEx+0xee() in kernel32 (0x0519e338)
>   6 0x7b86df1a WaitForMultipleObjects+0x39() in kernel32 (0x0519e368)
>   7 0x0040301b aio_poll+0x16a(ctx=0x157610, blocking=<is not available>) [/data/qemu/aio-win32.c:178] in qemu-system-arm (0x00000001)
>   8 0x004feec3 qemu_aio_wait+0x22() [/data/qemu/main-loop.c:442] in qemu-system-arm (0x0105bdec)
>   9 0x00417166 bdrv_rw_co+0xa5(bs=0x159648, sector_num=<internal error>, buf="¹¸ÿ¦
>                                                                                   ", nb_sectors=0x4, is_write=true) [/data/qemu/block.c:1997] in qemu-system-arm (0x0105bdec)
>   10 0x00495544 in qemu-system-arm (+0x95543) (0x0105bdec)
>   11 0x0049592a pflash_write+0x3b9(pfl=0xd6f16e0, offset=<internal error>, value=0x98f7fb1d, width=0x4, be=0) [/data/qemu/hw/pflash_cfi01.c:405] in qemu-system-arm (0x0105bdec)
>   12 0x00618a7e io_mem_write+0xed(mr=0xd6f2a48, addr=0x105bdec, val=0x98f7fb1d, size=0x4) [/data/qemu/memory.c:911] in qemu-system-arm (0x00000004)
>   13 0x0064088c helper_stl_mmu+0x2fb(env=0x15e268, addr=0xca05bdec, val=0x98f7fb1d, mmu_idx=0) [/data/qemu/softmmu_template.h:231] in qemu-system-arm (0x3700001e)
>   14 0x02136637 (0x0015e268)
> 
> It's the VCPU thread stuck in aio_poll, holding the BQL, blocking the
> iothread this way as well. Is there some race that prevents we receive
> the proper IO completion signal? Any states I should check?

Ah, so it wasn't fixed by the TLS change?

Instead of tracing, can you try adding printfs in aio_worker
(block/raw-win32.c), and also in thread_pool_active and
event_notifier_ready (thread-pool.c)?

This patch can help gathering debug output, it will place it into a
console window.

diff --git a/vl.c b/vl.c
index c8e9c78..5398178 100644
--- a/vl.c
+++ b/vl.c
@@ -3531,6 +3531,10 @@ int main(int argc, char **argv, char **envp)
     }
     loc_set_none();

+    AllocConsole();
+    freopen("CONIN$", "rb", stdin);
+    freopen("CONOUT$", "wb", stdout);
+    freopen("CONOUT$", "wb", stderr);
     if (qemu_init_main_loop()) {
         fprintf(stderr, "qemu_init_main_loop failed\n");
         exit(1);

Paolo

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O
  2012-11-22 15:16               ` Paolo Bonzini
@ 2012-11-22 15:53                 ` Jan Kiszka
  0 siblings, 0 replies; 62+ messages in thread
From: Jan Kiszka @ 2012-11-22 15:53 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: aliguori@us.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com

On 2012-11-22 16:16, Paolo Bonzini wrote:
> Il 22/11/2012 14:34, Jan Kiszka ha scritto:
>>
>> =>0 0xf77c242e __kernel_vsyscall+0xe() in [vdso].so (0x0519df88)
>>   1 0xf761f10b __libc_read+0x4a() in libpthread.so.0 (0x0519df88)
>>   2 0x7bc78c98 in ntdll (+0x68c97) (0x0519df88)
>>   3 0x7bc7b0a3 in ntdll (+0x6b0a2) (0x0519e1b8)
>>   4 0x7bc7b195 NtWaitForMultipleObjects+0x54() in ntdll (0x0519e1e8)
>>   5 0x7b86de9f WaitForMultipleObjectsEx+0xee() in kernel32 (0x0519e338)
>>   6 0x7b86df1a WaitForMultipleObjects+0x39() in kernel32 (0x0519e368)
>>   7 0x0040301b aio_poll+0x16a(ctx=0x157610, blocking=<is not available>) [/data/qemu/aio-win32.c:178] in qemu-system-arm (0x00000001)
>>   8 0x004feec3 qemu_aio_wait+0x22() [/data/qemu/main-loop.c:442] in qemu-system-arm (0x0105bdec)
>>   9 0x00417166 bdrv_rw_co+0xa5(bs=0x159648, sector_num=<internal error>, buf="¹¸ÿ¦
>>                                                                                   ", nb_sectors=0x4, is_write=true) [/data/qemu/block.c:1997] in qemu-system-arm (0x0105bdec)
>>   10 0x00495544 in qemu-system-arm (+0x95543) (0x0105bdec)
>>   11 0x0049592a pflash_write+0x3b9(pfl=0xd6f16e0, offset=<internal error>, value=0x98f7fb1d, width=0x4, be=0) [/data/qemu/hw/pflash_cfi01.c:405] in qemu-system-arm (0x0105bdec)
>>   12 0x00618a7e io_mem_write+0xed(mr=0xd6f2a48, addr=0x105bdec, val=0x98f7fb1d, size=0x4) [/data/qemu/memory.c:911] in qemu-system-arm (0x00000004)
>>   13 0x0064088c helper_stl_mmu+0x2fb(env=0x15e268, addr=0xca05bdec, val=0x98f7fb1d, mmu_idx=0) [/data/qemu/softmmu_template.h:231] in qemu-system-arm (0x3700001e)
>>   14 0x02136637 (0x0015e268)
>>
>> It's the VCPU thread stuck in aio_poll, holding the BQL, blocking the
>> iothread this way as well. Is there some race that prevents we receive
>> the proper IO completion signal? Any states I should check?
> 
> Ah, so it wasn't fixed by the TLS change?

This version was built with my more recent opensuse mingw toolchain,
thus isn't affected by the TLS issue.

> 
> Instead of tracing, can you try adding printfs in aio_worker
> (block/raw-win32.c), and also in thread_pool_active and
> event_notifier_ready (thread-pool.c)?
> 
> This patch can help gathering debug output, it will place it into a
> console window.
> 
> diff --git a/vl.c b/vl.c
> index c8e9c78..5398178 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -3531,6 +3531,10 @@ int main(int argc, char **argv, char **envp)
>      }
>      loc_set_none();
> 
> +    AllocConsole();
> +    freopen("CONIN$", "rb", stdin);
> +    freopen("CONOUT$", "wb", stdout);
> +    freopen("CONOUT$", "wb", stderr);
>      if (qemu_init_main_loop()) {
>          fprintf(stderr, "qemu_init_main_loop failed\n");
>          exit(1);

Ok, will dig into this.

Thanks,
Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2012-11-22 15:53 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-31 15:30 [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 01/39] janitor: move iovector functions out of cutils.c Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 02/39] build: move cutils.o and qemu-timer-common.o to oslib-obj-y Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 03/39] compiler: use weak aliases to provide default definitions Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 04/39] sockets: use weak aliases instead of qemu-tool.c Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 05/39] fdsets: use weak aliases instead of qemu-tool.c/qemu-user.c Paolo Bonzini
2012-11-15 18:01   ` Stefan Weil
2012-11-15 20:52     ` Paolo Bonzini
2012-11-15 22:18       ` Stefan Weil
2012-11-16  9:35         ` Paolo Bonzini
2012-11-16 17:15           ` Stefan Weil
2012-11-16 17:39             ` Paolo Bonzini
2012-11-16 17:52           ` Peter Maydell
2012-11-16 17:55             ` Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 06/39] iohandler: add weak alias in qemu-sockets.c, for qemu-ga Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 07/39] win32: add weak version of qemu_fd_register Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 08/39] qemu-timer: make initialization functions idempotent Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 09/39] main-loop: unify qemu_init_main_loop between QEMU and tools Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 10/39] qemu-tool: do not depend on qemu-timer.c Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 11/39] build: opts-visitor is not really part of QAPI Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 12/39] build: do not include main loop where it is not actually used Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 13/39] event_notifier: add Win32 implementation Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 14/39] event_notifier: enable it to use pipes Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 15/39] vl: init main loop earlier Paolo Bonzini
2012-11-02  7:26   ` Jan Kiszka
2012-11-02  9:55     ` Paolo Bonzini
2012-11-02 10:32       ` Jan Kiszka
2012-11-02 11:04         ` Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 16/39] aio: change qemu_aio_set_fd_handler to return void Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 17/39] aio: provide platform-independent API Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 18/39] aio: introduce AioContext, move bottom halves there Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 19/39] aio: add I/O handlers to the AioContext interface Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 20/39] aio: test node->deleted before calling io_flush Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 21/39] aio: add non-blocking variant of aio_wait Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 22/39] aio: prepare for introducing GSource-based dispatch Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 23/39] aio: add Win32 implementation Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 24/39] aio: make AioContexts GSources Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 25/39] aio: add aio_notify Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 26/39] aio: call aio_notify after setting I/O handlers Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 27/39] main-loop: use GSource to poll AIO file descriptors Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 28/39] main-loop: use aio_notify for qemu_notify_event Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 29/39] aio: clean up now-unused functions Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 30/39] linux-aio: use event notifiers Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 31/39] qemu-thread: add QemuSemaphore Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 32/39] aio: add generic thread-pool facility Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 33/39] threadpool: do not take lock in event_notifier_ready Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 34/39] block: switch posix-aio-compat to threadpool Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 35/39] raw: merge posix-aio-compat.c into block/raw-posix.c Paolo Bonzini
2012-11-02 15:00   ` Peter Maydell
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 36/39] raw-posix: rename raw-posix-aio.h, hide unavailable prototypes Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 37/39] raw-win32: add emulated AIO support Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 38/39] raw-posix: move linux-aio.c to block/ Paolo Bonzini
2012-10-31 15:30 ` [Qemu-devel] [PATCH v2 39/39] raw-win32: implement native asynchronous I/O Paolo Bonzini
2012-11-21 13:20   ` Jan Kiszka
2012-11-21 13:25     ` Paolo Bonzini
2012-11-21 13:27       ` Jan Kiszka
2012-11-21 13:33         ` Paolo Bonzini
2012-11-21 13:38           ` Jan Kiszka
2012-11-22 13:34             ` Jan Kiszka
2012-11-22 15:16               ` Paolo Bonzini
2012-11-22 15:53                 ` Jan Kiszka
2012-11-01 19:33 ` [Qemu-devel] [PULL v2 00/39] AioContext, thread pool, Win32 AIO Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).