From 805d8a67647768173c27761cd86e6f99a9d3b7cd Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 3 May 2015 19:57:09 +0200 Subject: [PATCH 1/5] nsis: Add QEMU version information to Windows registry The uninstall keys include an option key "DisplayVersion" which we set now. By default the version value is read from file VERSION, but it is also possible to pass VERSION=#.#.# to make. Signed-off-by: Stefan Weil --- Makefile | 1 + qemu.nsi | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 9e753620e6..68e2e1b3fe 100644 --- a/Makefile +++ b/Makefile @@ -623,6 +623,7 @@ endif # SIGNCODE $(if $(DLL_PATH),-DDLLDIR="$(DLL_PATH)") \ -DSRCDIR="$(SRC_PATH)" \ -DOUTFILE="$(INSTALLER)" \ + -DDISPLAYVERSION="$(VERSION)" \ $(SRC_PATH)/qemu.nsi rm -r ${INSTDIR} ifdef SIGNCODE diff --git a/qemu.nsi b/qemu.nsi index cc5fafd579..a20f6ef35b 100644 --- a/qemu.nsi +++ b/qemu.nsi @@ -139,6 +139,9 @@ Section "${PRODUCT} (required)" ; Write the uninstall keys for Windows WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "QEMU" +!ifdef DISPLAYVERSION + WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${DISPLAYVERSION}" +!endif WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" '"${UNINST_EXE}"' WriteRegDWORD HKLM "${UNINST_KEY}" "NoModify" 1 WriteRegDWORD HKLM "${UNINST_KEY}" "NoRepair" 1 From a246a01631f90230374c2b8ffce608232e2aa654 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 30 Jul 2015 23:08:12 +0200 Subject: [PATCH 2/5] slirp: Fix non blocking connect for w32 Signed-off-by: Stefan Weil --- slirp/tcp_input.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index f946db8dc0..00a77b4a5f 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -584,7 +584,13 @@ findso: goto cont_input; } - if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + if ((tcp_fconnect(so) == -1) && +#if defined(_WIN32) + socket_error() != WSAEWOULDBLOCK +#else + (errno != EINPROGRESS) && (errno != EWOULDBLOCK) +#endif + ) { u_char code=ICMP_UNREACH_NET; DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n", errno,strerror(errno))); From 7c9b2bf67775ecc1359ce973580807d173e7f710 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 12 Aug 2015 15:38:18 +0200 Subject: [PATCH 3/5] qemu-thread: add a fast path to the Win32 QemuEvent QemuEvents are used heavily by call_rcu. We do not want them to be slow, but the current implementation does a kernel call on every invocation of qemu_event_* and won't cut it. So, wrap a Win32 manual-reset event with a fast userspace path. The states and transitions are the same as for the futex and mutex/condvar implementations, but the slow path is different of course. The idea is to reset the Win32 event lazily, as part of a test-reset-test-wait sequence. Such a sequence is, indeed, how QemuEvents are used by RCU and other subsystems! The patch includes a formal model of the algorithm. Tested-by: Stefan Weil Signed-off-by: Paolo Bonzini Signed-off-by: Stefan Weil --- docs/win32-qemu-event.promela | 98 +++++++++++++++++++++++++++++++++++ include/qemu/thread-win32.h | 1 + util/qemu-thread-win32.c | 66 +++++++++++++++++++++-- 3 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 docs/win32-qemu-event.promela diff --git a/docs/win32-qemu-event.promela b/docs/win32-qemu-event.promela new file mode 100644 index 0000000000..c446a71555 --- /dev/null +++ b/docs/win32-qemu-event.promela @@ -0,0 +1,98 @@ +/* + * This model describes the implementation of QemuEvent in + * util/qemu-thread-win32.c. + * + * Author: Paolo Bonzini + * + * This file is in the public domain. If you really want a license, + * the WTFPL will do. + * + * To verify it: + * spin -a docs/event.promela + * gcc -O2 pan.c -DSAFETY + * ./a.out + */ + +bool event; +int value; + +/* Primitives for a Win32 event */ +#define RAW_RESET event = false +#define RAW_SET event = true +#define RAW_WAIT do :: event -> break; od + +#if 0 +/* Basic sanity checking: test the Win32 event primitives */ +#define RESET RAW_RESET +#define SET RAW_SET +#define WAIT RAW_WAIT +#else +/* Full model: layer a userspace-only fast path on top of the RAW_* + * primitives. SET/RESET/WAIT have exactly the same semantics as + * RAW_SET/RAW_RESET/RAW_WAIT, but try to avoid invoking them. + */ +#define EV_SET 0 +#define EV_FREE 1 +#define EV_BUSY -1 + +int state = EV_FREE; + +int xchg_result; +#define SET if :: state != EV_SET -> \ + atomic { /* xchg_result=xchg(state, EV_SET) */ \ + xchg_result = state; \ + state = EV_SET; \ + } \ + if :: xchg_result == EV_BUSY -> RAW_SET; \ + :: else -> skip; \ + fi; \ + :: else -> skip; \ + fi + +#define RESET if :: state == EV_SET -> atomic { state = state | EV_FREE; } \ + :: else -> skip; \ + fi + +int tmp1, tmp2; +#define WAIT tmp1 = state; \ + if :: tmp1 != EV_SET -> \ + if :: tmp1 == EV_FREE -> \ + RAW_RESET; \ + atomic { /* tmp2=cas(state, EV_FREE, EV_BUSY) */ \ + tmp2 = state; \ + if :: tmp2 == EV_FREE -> state = EV_BUSY; \ + :: else -> skip; \ + fi; \ + } \ + if :: tmp2 == EV_SET -> tmp1 = EV_SET; \ + :: else -> tmp1 = EV_BUSY; \ + fi; \ + :: else -> skip; \ + fi; \ + assert(tmp1 != EV_FREE); \ + if :: tmp1 == EV_BUSY -> RAW_WAIT; \ + :: else -> skip; \ + fi; \ + :: else -> skip; \ + fi +#endif + +active proctype waiter() +{ + if + :: !value -> + RESET; + if + :: !value -> WAIT; + :: else -> skip; + fi; + :: else -> skip; + fi; + assert(value); +} + +active proctype notifier() +{ + value = true; + SET; +} diff --git a/include/qemu/thread-win32.h b/include/qemu/thread-win32.h index 3d58081bed..385ff5f76a 100644 --- a/include/qemu/thread-win32.h +++ b/include/qemu/thread-win32.h @@ -18,6 +18,7 @@ struct QemuSemaphore { }; struct QemuEvent { + int value; HANDLE event; }; diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c index 406b52f91d..6cdd553e9a 100644 --- a/util/qemu-thread-win32.c +++ b/util/qemu-thread-win32.c @@ -238,10 +238,34 @@ void qemu_sem_wait(QemuSemaphore *sem) } } +/* Wrap a Win32 manual-reset event with a fast userspace path. The idea + * is to reset the Win32 event lazily, as part of a test-reset-test-wait + * sequence. Such a sequence is, indeed, how QemuEvents are used by + * RCU and other subsystems! + * + * Valid transitions: + * - free->set, when setting the event + * - busy->set, when setting the event, followed by futex_wake + * - set->free, when resetting the event + * - free->busy, when waiting + * + * set->busy does not happen (it can be observed from the outside but + * it really is set->free->busy). + * + * busy->free provably cannot happen; to enforce it, the set->free transition + * is done with an OR, which becomes a no-op if the event has concurrently + * transitioned to free or busy (and is faster than cmpxchg). + */ + +#define EV_SET 0 +#define EV_FREE 1 +#define EV_BUSY -1 + void qemu_event_init(QemuEvent *ev, bool init) { /* Manual reset. */ - ev->event = CreateEvent(NULL, TRUE, init, NULL); + ev->event = CreateEvent(NULL, TRUE, TRUE, NULL); + ev->value = (init ? EV_SET : EV_FREE); } void qemu_event_destroy(QemuEvent *ev) @@ -251,17 +275,51 @@ void qemu_event_destroy(QemuEvent *ev) void qemu_event_set(QemuEvent *ev) { - SetEvent(ev->event); + if (atomic_mb_read(&ev->value) != EV_SET) { + if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { + /* There were waiters, wake them up. */ + SetEvent(ev->event); + } + } } void qemu_event_reset(QemuEvent *ev) { - ResetEvent(ev->event); + if (atomic_mb_read(&ev->value) == EV_SET) { + /* If there was a concurrent reset (or even reset+wait), + * do nothing. Otherwise change EV_SET->EV_FREE. + */ + atomic_or(&ev->value, EV_FREE); + } } void qemu_event_wait(QemuEvent *ev) { - WaitForSingleObject(ev->event, INFINITE); + unsigned value; + + value = atomic_mb_read(&ev->value); + if (value != EV_SET) { + if (value == EV_FREE) { + /* qemu_event_set is not yet going to call SetEvent, but we are + * going to do another check for EV_SET below when setting EV_BUSY. + * At that point it is safe to call WaitForSingleObject. + */ + ResetEvent(ev->event); + + /* Tell qemu_event_set that there are waiters. No need to retry + * because there cannot be a concurent busy->free transition. + * After the CAS, the event will be either set or busy. + */ + if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { + value = EV_SET; + } else { + value = EV_BUSY; + } + } + if (value == EV_BUSY) { + WaitForSingleObject(ev->event, INFINITE); + } + } } struct QemuThreadData { From c8f3f17cf1015d6621f79aa6a88280539621a108 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 8 Sep 2015 11:34:35 +0100 Subject: [PATCH 4/5] gtk: avoid redefining _WIN32_WINNT macro When building for Mingw64 target on Fedora 22 a warning is issued about _WIN32_WINNT being redefined. In file included from ui/gtk.c:40:0: include/ui/gtk.h:5:0: warning: "_WIN32_WINNT" redefined # define _WIN32_WINNT 0x0601 /* needed to get definition of MAPVK_VK_TO_VSC */ ^ In file included from /usr/i686-w64-mingw32/sys-root/mingw/include/crtdefs.h:10:0, from /usr/i686-w64-mingw32/sys-root/mingw/include/stdio.h:9, from /home/berrange/src/virt/qemu/include/qemu/fprintf-fn.h:12, from /home/berrange/src/virt/qemu/include/qemu-common.h:18, from ui/gtk.c:37: /usr/i686-w64-mingw32/sys-root/mingw/include/_mingw.h:225:0: note: this is the location of the previous definition #define _WIN32_WINNT 0x502 ^ Rather than try to get MAPVK_VK_TO_VSC defined indirectly by defining _WIN32_WINNT, instead just define it explicitly if missing. Signed-off-by: Daniel P. Berrange Signed-off-by: Stefan Weil Acked-by: Paolo Bonzini --- include/ui/gtk.h | 4 ---- ui/gtk.c | 9 +++++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index ee6dffd306..0359333fce 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -1,10 +1,6 @@ #ifndef UI_GTK_H #define UI_GTK_H -#ifdef _WIN32 -# define _WIN32_WINNT 0x0601 /* needed to get definition of MAPVK_VK_TO_VSC */ -#endif - #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE /* Work around an -Wstrict-prototypes warning in GTK headers */ #pragma GCC diagnostic push diff --git a/ui/gtk.c b/ui/gtk.c index 187de74b2c..3057cdc3f7 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -104,6 +104,15 @@ #define GDK_KEY_Pause GDK_Pause #endif +/* Some older mingw versions lack this constant or have + * it conditionally defined */ +#ifdef _WIN32 +# ifndef MAPVK_VK_TO_VSC +# define MAPVK_VK_TO_VSC 0 +# endif +#endif + + #define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK) static const int modifier_keycode[] = { From 4d9310f427b477a126f6f2006c3a73b9764948b6 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 22 Sep 2015 15:13:26 +0100 Subject: [PATCH 5/5] oslib-win32: only provide localtime_r/gmtime_r if missing The oslib-win32 file currently provides a localtime_r and gmtime_r replacement unconditionally. Some versions of Mingw-w64 would provide crude macros for localtime_r/gmtime_r which QEMU takes care to disable. Latest versions of Mingw-w64 now provide actual functions for localtime_r/gmtime_r, but with a twist that you have to include unistd.h or pthread.h before including time.h. By luck some files in QEMU have such an include order, resulting in compile errors: CC util/osdep.o In file included from include/qemu-common.h:48:0, from util/osdep.c:48: include/sysemu/os-win32.h:77:12: error: redundant redeclaration of 'gmtime_r' [-Werror=redundant-decls] struct tm *gmtime_r(const time_t *timep, struct tm *result); ^ In file included from include/qemu-common.h:35:0, from util/osdep.c:48: /usr/i686-w64-mingw32/sys-root/mingw/include/time.h:272:107: note: previous definition of 'gmtime_r' was here In file included from include/qemu-common.h:48:0, from util/osdep.c:48: include/sysemu/os-win32.h:79:12: error: redundant redeclaration of 'localtime_r' [-Werror=redundant-decls] struct tm *localtime_r(const time_t *timep, struct tm *result); ^ In file included from include/qemu-common.h:35:0, from util/osdep.c:48: /usr/i686-w64-mingw32/sys-root/mingw/include/time.h:269:107: note: previous definition of 'localtime_r' was here This change adds a configure test to see if localtime_r exits, and only enables the QEMU impl if missing. We also re-arrange qemu-common.h try attempt to guarantee that all source files get unistd.h before time.h and thus see the localtime_r/gmtime_r defs. [sw: Use "official" spellings for Mingw-w64, MinGW in comments.] [sw: Terminate sentences with a dot in comments.] Signed-off-by: Daniel P. Berrange Reviewed-by: Denis V. Lunev Signed-off-by: Stefan Weil --- configure | 34 ++++++++++++++++++++++++++++++++++ include/qemu/osdep.h | 4 +++- include/sysemu/os-win32.h | 2 ++ util/oslib-win32.c | 2 ++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 29009ee6d8..f14454e691 100755 --- a/configure +++ b/configure @@ -1736,6 +1736,37 @@ else l2tpv3=no fi +########################################## +# MinGW / Mingw-w64 localtime_r/gmtime_r check + +if test "$mingw32" = "yes"; then + # Some versions of MinGW / Mingw-w64 lack localtime_r + # and gmtime_r entirely. + # + # Some versions of Mingw-w64 define a macro for + # localtime_r/gmtime_r. + # + # Some versions of Mingw-w64 will define functions + # for localtime_r/gmtime_r, but only if you have + # _POSIX_THREAD_SAFE_FUNCTIONS defined. For fun + # though, unistd.h and pthread.h both define + # that for you. + # + # So this #undef localtime_r and #include + # are not in fact redundant. +cat > $TMPC << EOF +#include +#include +#undef localtime_r +int main(void) { localtime_r(NULL, NULL); return 0; } +EOF + if compile_prog "" "" ; then + localtime_r="yes" + else + localtime_r="no" + fi +fi + ########################################## # pkg-config probe @@ -5034,6 +5065,9 @@ fi if test "$zero_malloc" = "yes" ; then echo "CONFIG_ZERO_MALLOC=y" >> $config_host_mak fi +if test "$localtime_r" = "yes" ; then + echo "CONFIG_LOCALTIME_R=y" >> $config_host_mak +fi if test "$qom_cast_debug" = "yes" ; then echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak fi diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index ab3c8766b4..ef21efb683 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -38,10 +38,12 @@ #include #include #include +/* Put unistd.h before time.h as that triggers localtime_r/gmtime_r + * function availability on recentish Mingw-w64 platforms. */ +#include #include #include #include -#include #include #include #include diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h index 706d85a98e..13dcef6b4c 100644 --- a/include/sysemu/os-win32.h +++ b/include/sysemu/os-win32.h @@ -73,10 +73,12 @@ #define siglongjmp(env, val) longjmp(env, val) /* Missing POSIX functions. Don't use MinGW-w64 macros. */ +#ifndef CONFIG_LOCALTIME_R #undef gmtime_r struct tm *gmtime_r(const time_t *timep, struct tm *result); #undef localtime_r struct tm *localtime_r(const time_t *timep, struct tm *result); +#endif /* CONFIG_LOCALTIME_R */ static inline void os_setup_signal_handling(void) {} diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 730a6707a0..08f5a9cda2 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -95,6 +95,7 @@ void qemu_anon_ram_free(void *ptr, size_t size) } } +#ifndef CONFIG_LOCALTIME_R /* FIXME: add proper locking */ struct tm *gmtime_r(const time_t *timep, struct tm *result) { @@ -118,6 +119,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) } return p; } +#endif /* CONFIG_LOCALTIME_R */ void qemu_set_block(int fd) {