summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-05-13 10:35:46 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-05-13 10:35:47 +0100
commit1b5498f6874ad661bcd9558bc2b0a4e25643a5bf (patch)
tree08bd27ec88d368d9c7ae2b8bb5d233ab74c903a0 /util
parente5bfd64050e81774b6bf71ab5dd064f7bcef0c4c (diff)
parent5a007547df76446ab891df93ebc55749716609bf (diff)
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request # gpg: Signature made Fri 09 May 2014 19:57:53 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: glib: fix g_poll early timeout on windows block: qemu-iotests - test for live migration block: qemu-iotests - update 085 to use common.qemu block: qemu-iotests - add common.qemu, for bash-controlled qemu tests block/raw-posix: Try both FIEMAP and SEEK_HOLE gluster: Correctly propagate errors when volume isn't accessible vl.c: remove init_clocks call from main block: Fix open flags with BDRV_O_SNAPSHOT qemu-iotests: Test converting to streamOptimized from small cluster size vmdk: Implement .bdrv_get_info() vmdk: Implement .bdrv_write_compressed qemu-img: Convert by cluster size if target is compressed block/iscsi: bump year in copyright notice block/nfs: Check for NULL server part qemu-img: sort block formats in help message iotests: Use configured python qcow2: Fix alloc_clusters_noref() overflow detection Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util')
-rw-r--r--util/oslib-win32.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 93f7d351d3..69552f7ec3 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -238,3 +238,115 @@ char *qemu_get_exec_dir(void)
{
return g_strdup(exec_dir);
}
+
+/*
+ * g_poll has a problem on Windows when using
+ * timeouts < 10ms, in glib/gpoll.c:
+ *
+ * // If not, and we have a significant timeout, poll again with
+ * // timeout then. Note that this will return indication for only
+ * // one event, or only for messages. We ignore timeouts less than
+ * // ten milliseconds as they are mostly pointless on Windows, the
+ * // MsgWaitForMultipleObjectsEx() call will timeout right away
+ * // anyway.
+ *
+ * if (retval == 0 && (timeout == INFINITE || timeout >= 10))
+ * retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout);
+ *
+ * So whenever g_poll is called with timeout < 10ms it does
+ * a quick poll instead of wait, this causes significant performance
+ * degradation of QEMU, thus we should use WaitForMultipleObjectsEx
+ * directly
+ */
+gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout)
+{
+ guint i;
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+ gint nhandles = 0;
+ int num_completed = 0;
+
+ for (i = 0; i < nfds; i++) {
+ gint j;
+
+ if (fds[i].fd <= 0) {
+ continue;
+ }
+
+ /* don't add same handle several times
+ */
+ for (j = 0; j < nhandles; j++) {
+ if (handles[j] == (HANDLE)fds[i].fd) {
+ break;
+ }
+ }
+
+ if (j == nhandles) {
+ if (nhandles == MAXIMUM_WAIT_OBJECTS) {
+ fprintf(stderr, "Too many handles to wait for!\n");
+ break;
+ } else {
+ handles[nhandles++] = (HANDLE)fds[i].fd;
+ }
+ }
+ }
+
+ for (i = 0; i < nfds; ++i) {
+ fds[i].revents = 0;
+ }
+
+ if (timeout == -1) {
+ timeout = INFINITE;
+ }
+
+ if (nhandles == 0) {
+ if (timeout == INFINITE) {
+ return -1;
+ } else {
+ SleepEx(timeout, TRUE);
+ return 0;
+ }
+ }
+
+ while (1) {
+ DWORD res;
+ gint j;
+
+ res = WaitForMultipleObjectsEx(nhandles, handles, FALSE,
+ timeout, TRUE);
+
+ if (res == WAIT_FAILED) {
+ for (i = 0; i < nfds; ++i) {
+ fds[i].revents = 0;
+ }
+
+ return -1;
+ } else if ((res == WAIT_TIMEOUT) || (res == WAIT_IO_COMPLETION) ||
+ ((int)res < (int)WAIT_OBJECT_0) ||
+ (res >= (WAIT_OBJECT_0 + nhandles))) {
+ break;
+ }
+
+ for (i = 0; i < nfds; ++i) {
+ if (handles[res - WAIT_OBJECT_0] == (HANDLE)fds[i].fd) {
+ fds[i].revents = fds[i].events;
+ }
+ }
+
+ ++num_completed;
+
+ if (nhandles <= 1) {
+ break;
+ }
+
+ /* poll the rest of the handles
+ */
+ for (j = res - WAIT_OBJECT_0 + 1; j < nhandles; j++) {
+ handles[j - 1] = handles[j];
+ }
+ --nhandles;
+
+ timeout = 0;
+ }
+
+ return num_completed;
+}