* [Qemu-devel] [PATCH v2 upstream 01/22] unlock iothread during WaitForMultipleObjects
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
@ 2011-02-26 15:39 ` Paolo Bonzini
2011-02-26 15:39 ` [Qemu-devel] [PATCH v2 upstream 02/22] implement win32 dynticks timer Paolo Bonzini
` (22 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:39 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
os-win32.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/os-win32.c b/os-win32.c
index b214e6a..c971d92 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -140,7 +140,9 @@ void os_host_main_loop_wait(int *timeout)
int err;
WaitObjects *w = &wait_objects;
+ qemu_mutex_unlock_iothread();
ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+ qemu_mutex_lock_iothread();
if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
if (w->func[ret - WAIT_OBJECT_0])
w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 02/22] implement win32 dynticks timer
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
2011-02-26 15:39 ` [Qemu-devel] [PATCH v2 upstream 01/22] unlock iothread during WaitForMultipleObjects Paolo Bonzini
@ 2011-02-26 15:39 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 03/22] use win32 timer queues Paolo Bonzini
` (21 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:39 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
qemu-timer.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/qemu-timer.c b/qemu-timer.c
index 88c7b28..122e7ed 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -1004,6 +1004,7 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
static void win32_rearm_timer(struct qemu_alarm_timer *t)
{
struct qemu_alarm_win32 *data = t->priv;
+ int nearest_delta_ms;
assert(alarm_has_dynticks(t));
if (!active_timers[QEMU_CLOCK_REALTIME] &&
@@ -1013,7 +1014,11 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
timeKillEvent(data->timerId);
- data->timerId = timeSetEvent(1,
+ nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+ if (nearest_delta_ms < 1) {
+ nearest_delta_ms = 1;
+ }
+ data->timerId = timeSetEvent(nearest_delta_ms,
data->period,
host_alarm_handler,
(DWORD)t,
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 03/22] use win32 timer queues
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
2011-02-26 15:39 ` [Qemu-devel] [PATCH v2 upstream 01/22] unlock iothread during WaitForMultipleObjects Paolo Bonzini
2011-02-26 15:39 ` [Qemu-devel] [PATCH v2 upstream 02/22] implement win32 dynticks timer Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 04/22] Refactor thread retrieval and check Paolo Bonzini
` (20 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Multimedia timers are only useful for compatibility with Windows NT 4.0
and earlier. Plus, the implementation in Wine is extremely heavyweight.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
qemu-timer.c | 86 +++++++++++++++++++++++----------------------------------
1 files changed, 35 insertions(+), 51 deletions(-)
diff --git a/qemu-timer.c b/qemu-timer.c
index 122e7ed..1939d6b 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -200,11 +200,6 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
#ifdef _WIN32
-struct qemu_alarm_win32 {
- MMRESULT timerId;
- unsigned int period;
-} alarm_win32_data = {0, 0};
-
static int win32_start_timer(struct qemu_alarm_timer *t);
static void win32_stop_timer(struct qemu_alarm_timer *t);
static void win32_rearm_timer(struct qemu_alarm_timer *t);
@@ -298,9 +293,9 @@ static struct qemu_alarm_timer alarm_timers[] = {
{"unix", unix_start_timer, unix_stop_timer, NULL, NULL},
#else
{"dynticks", win32_start_timer,
- win32_stop_timer, win32_rearm_timer, &alarm_win32_data},
+ win32_stop_timer, win32_rearm_timer, NULL},
{"win32", win32_start_timer,
- win32_stop_timer, NULL, &alarm_win32_data},
+ win32_stop_timer, NULL, NULL},
#endif
{NULL, }
};
@@ -636,9 +631,7 @@ void qemu_run_all_timers(void)
static int64_t qemu_next_alarm_deadline(void);
#ifdef _WIN32
-static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
- DWORD_PTR dwUser, DWORD_PTR dw1,
- DWORD_PTR dw2)
+static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
#else
static void host_alarm_handler(int host_signum)
#endif
@@ -961,50 +954,45 @@ static void unix_stop_timer(struct qemu_alarm_timer *t)
static int win32_start_timer(struct qemu_alarm_timer *t)
{
- TIMECAPS tc;
- struct qemu_alarm_win32 *data = t->priv;
- UINT flags;
-
- memset(&tc, 0, sizeof(tc));
- timeGetDevCaps(&tc, sizeof(tc));
-
- data->period = tc.wPeriodMin;
- timeBeginPeriod(data->period);
-
- flags = TIME_CALLBACK_FUNCTION;
- if (alarm_has_dynticks(t))
- flags |= TIME_ONESHOT;
- else
- flags |= TIME_PERIODIC;
-
- data->timerId = timeSetEvent(1, // interval (ms)
- data->period, // resolution
- host_alarm_handler, // function
- (DWORD)t, // parameter
- flags);
-
- if (!data->timerId) {
+ HANDLE hTimer;
+ BOOLEAN success;
+
+ /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
+ is zero) that has already expired, the timer is not updated. Since
+ creating a new timer is relatively expensive, set a bogus one-hour
+ interval in the dynticks case. */
+ success = CreateTimerQueueTimer(&hTimer,
+ NULL,
+ host_alarm_handler,
+ t,
+ 1,
+ alarm_has_dynticks(t) ? 3600000 : 1,
+ WT_EXECUTEINTIMERTHREAD);
+
+ if (!success) {
fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
GetLastError());
- timeEndPeriod(data->period);
return -1;
}
+ t->priv = (PVOID) hTimer;
return 0;
}
static void win32_stop_timer(struct qemu_alarm_timer *t)
{
- struct qemu_alarm_win32 *data = t->priv;
+ HANDLE hTimer = t->priv;
- timeKillEvent(data->timerId);
- timeEndPeriod(data->period);
+ if (hTimer) {
+ DeleteTimerQueueTimer(NULL, hTimer, NULL);
+ }
}
static void win32_rearm_timer(struct qemu_alarm_timer *t)
{
- struct qemu_alarm_win32 *data = t->priv;
+ HANDLE hTimer = t->priv;
int nearest_delta_ms;
+ BOOLEAN success;
assert(alarm_has_dynticks(t));
if (!active_timers[QEMU_CLOCK_REALTIME] &&
@@ -1012,25 +1000,21 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
!active_timers[QEMU_CLOCK_HOST])
return;
- timeKillEvent(data->timerId);
-
nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
if (nearest_delta_ms < 1) {
nearest_delta_ms = 1;
}
- data->timerId = timeSetEvent(nearest_delta_ms,
- data->period,
- host_alarm_handler,
- (DWORD)t,
- TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
-
- if (!data->timerId) {
- fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
- GetLastError());
+ success = ChangeTimerQueueTimer(NULL,
+ hTimer,
+ nearest_delta_ms,
+ 3600000);
- timeEndPeriod(data->period);
- exit(1);
+ if (!success) {
+ fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
+ GetLastError());
+ exit(-1);
}
+
}
#endif /* _WIN32 */
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 04/22] Refactor thread retrieval and check
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (2 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 03/22] use win32 timer queues Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 05/22] add win32 qemu-thread implementation Paolo Bonzini
` (19 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
From: Jan Kiszka <jan.kiszka@siemens.com>
We have qemu_cpu_self and qemu_thread_self. The latter is retrieving the
current thread, the former is checking for equality (using CPUState). We
also have qemu_thread_equal which is only used like qemu_cpu_self.
This refactors the interfaces, creating qemu_cpu_is_self and
qemu_thread_is_self as well ass qemu_thread_get_self.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 22 ++++++++--------------
exec.c | 2 +-
qemu-common.h | 2 +-
qemu-thread.c | 6 +++---
qemu-thread.h | 4 ++--
target-i386/kvm.c | 4 ++--
ui/vnc-jobs-async.c | 2 +-
7 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/cpus.c b/cpus.c
index 0f33945..09ce6fe 100644
--- a/cpus.c
+++ b/cpus.c
@@ -531,7 +531,7 @@ void qemu_init_vcpu(void *_env)
}
}
-int qemu_cpu_self(void *env)
+int qemu_cpu_is_self(void *env)
{
return 1;
}
@@ -699,7 +699,7 @@ int qemu_init_main_loop(void)
qemu_mutex_init(&qemu_global_mutex);
qemu_mutex_lock(&qemu_global_mutex);
- qemu_thread_self(&io_thread);
+ qemu_thread_get_self(&io_thread);
return 0;
}
@@ -714,7 +714,7 @@ void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
{
struct qemu_work_item wi;
- if (qemu_cpu_self(env)) {
+ if (qemu_cpu_is_self(env)) {
func(data);
return;
}
@@ -808,7 +808,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
int r;
qemu_mutex_lock(&qemu_global_mutex);
- qemu_thread_self(env->thread);
+ qemu_thread_get_self(env->thread);
r = kvm_init_vcpu(env);
if (r < 0) {
@@ -845,7 +845,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
CPUState *env = arg;
qemu_tcg_init_cpu_signals();
- qemu_thread_self(env->thread);
+ qemu_thread_get_self(env->thread);
/* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
@@ -888,14 +888,11 @@ void qemu_cpu_kick_self(void)
}
}
-int qemu_cpu_self(void *_env)
+int qemu_cpu_is_self(void *_env)
{
CPUState *env = _env;
- QemuThread this;
- qemu_thread_self(&this);
-
- return qemu_thread_equal(&this, env->thread);
+ return qemu_thread_is_self(env->thread);
}
void qemu_mutex_lock_iothread(void)
@@ -1023,10 +1020,7 @@ void cpu_stop_current(void)
void vm_stop(int reason)
{
- QemuThread me;
- qemu_thread_self(&me);
-
- if (!qemu_thread_equal(&me, &io_thread)) {
+ if (!qemu_thread_is_self(&io_thread)) {
qemu_system_vmstop_request(reason);
/*
* FIXME: should not return to device code in case
diff --git a/exec.c b/exec.c
index d611100..439a6f6 100644
--- a/exec.c
+++ b/exec.c
@@ -1640,7 +1640,7 @@ void cpu_interrupt(CPUState *env, int mask)
* If called from iothread context, wake the target cpu in
* case its halted.
*/
- if (!qemu_cpu_self(env)) {
+ if (!qemu_cpu_is_self(env)) {
qemu_cpu_kick(env);
return;
}
diff --git a/qemu-common.h b/qemu-common.h
index 40dad52..958a002 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -289,7 +289,7 @@ void qemu_notify_event(void);
/* Unblock cpu */
void qemu_cpu_kick(void *env);
void qemu_cpu_kick_self(void);
-int qemu_cpu_self(void *env);
+int qemu_cpu_is_self(void *env);
/* work queue */
struct qemu_work_item {
diff --git a/qemu-thread.c b/qemu-thread.c
index fbc78fe..e307773 100644
--- a/qemu-thread.c
+++ b/qemu-thread.c
@@ -176,14 +176,14 @@ void qemu_thread_signal(QemuThread *thread, int sig)
error_exit(err, __func__);
}
-void qemu_thread_self(QemuThread *thread)
+void qemu_thread_get_self(QemuThread *thread)
{
thread->thread = pthread_self();
}
-int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
+int qemu_thread_is_self(QemuThread *thread)
{
- return pthread_equal(thread1->thread, thread2->thread);
+ return pthread_equal(pthread_self(), thread->thread);
}
void qemu_thread_exit(void *retval)
diff --git a/qemu-thread.h b/qemu-thread.h
index 19bb30c..add97bf 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -37,8 +37,8 @@ void qemu_thread_create(QemuThread *thread,
void *(*start_routine)(void*),
void *arg);
void qemu_thread_signal(QemuThread *thread, int sig);
-void qemu_thread_self(QemuThread *thread);
-int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2);
+void qemu_thread_get_self(QemuThread *thread);
+int qemu_thread_is_self(QemuThread *thread);
void qemu_thread_exit(void *retval);
#endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0aa0a41..1f12cbf 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1355,7 +1355,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
{
int ret;
- assert(cpu_is_stopped(env) || qemu_cpu_self(env));
+ assert(cpu_is_stopped(env) || qemu_cpu_is_self(env));
ret = kvm_getput_regs(env, 1);
if (ret < 0) {
@@ -1403,7 +1403,7 @@ int kvm_arch_get_registers(CPUState *env)
{
int ret;
- assert(cpu_is_stopped(env) || qemu_cpu_self(env));
+ assert(cpu_is_stopped(env) || qemu_cpu_is_self(env));
ret = kvm_getput_regs(env, 0);
if (ret < 0) {
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index f596247..1dfa6c3 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -303,7 +303,7 @@ static void *vnc_worker_thread(void *arg)
{
VncJobQueue *queue = arg;
- qemu_thread_self(&queue->thread);
+ qemu_thread_get_self(&queue->thread);
while (!vnc_worker_thread_loop(queue)) ;
vnc_queue_clear(queue);
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 05/22] add win32 qemu-thread implementation
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (3 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 04/22] Refactor thread retrieval and check Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 16:47 ` Blue Swirl
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 06/22] include qemu-thread.h early Paolo Bonzini
` (18 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
For now, qemu_cond_timedwait and qemu_mutex_timedlock are left as
POSIX-only functions. They can be removed later, once the patches
that remove their uses are in.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
Makefile.objs | 4 +-
qemu-thread.c => qemu-thread-posix.c | 0
qemu-thread-posix.h | 18 +++
qemu-thread-win32.c | 260 ++++++++++++++++++++++++++++++++++
qemu-thread-win32.h | 21 +++
qemu-thread.h | 27 ++--
6 files changed, 313 insertions(+), 17 deletions(-)
rename qemu-thread.c => qemu-thread-posix.c (100%)
create mode 100644 qemu-thread-posix.h
create mode 100644 qemu-thread-win32.c
create mode 100644 qemu-thread-win32.h
diff --git a/Makefile.objs b/Makefile.objs
index 9e98a66..a52f42f 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -142,8 +142,8 @@ endif
common-obj-y += $(addprefix ui/, $(ui-obj-y))
common-obj-y += iov.o acl.o
-common-obj-$(CONFIG_THREAD) += qemu-thread.o
-common-obj-$(CONFIG_POSIX) += compatfd.o
+common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
+common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
common-obj-y += notify.o event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
diff --git a/qemu-thread.c b/qemu-thread-posix.c
similarity index 100%
rename from qemu-thread.c
rename to qemu-thread-posix.c
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
new file mode 100644
index 0000000..7af371c
--- /dev/null
+++ b/qemu-thread-posix.h
@@ -0,0 +1,18 @@
+#ifndef __QEMU_THREAD_POSIX_H
+#define __QEMU_THREAD_POSIX_H 1
+#include "pthread.h"
+
+struct QemuMutex {
+ pthread_mutex_t lock;
+};
+
+struct QemuCond {
+ pthread_cond_t cond;
+};
+
+struct QemuThread {
+ pthread_t thread;
+};
+
+void qemu_thread_signal(QemuThread *thread, int sig);
+#endif
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
new file mode 100644
index 0000000..89422ce
--- /dev/null
+++ b/qemu-thread-win32.c
@@ -0,0 +1,260 @@
+/*
+ * Win32 implementation for mutex/cond/thread functions
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Author:
+ * Paolo Bonzini <pbonzini@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 "qemu-thread.h"
+#include <process.h>
+#include <assert.h>
+#include <limits.h>
+
+static void error_exit(int err, const char *msg)
+{
+ char *pstr;
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
+ fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
+ LocalFree(pstr);
+ exit(1);
+}
+
+void qemu_mutex_init(QemuMutex *mutex)
+{
+ mutex->owner = 0;
+ InitializeCriticalSection(&mutex->lock);
+}
+
+void qemu_mutex_lock(QemuMutex *mutex)
+{
+ EnterCriticalSection(&mutex->lock);
+
+ /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not
+ * using them as such.
+ */
+ assert(mutex->owner == 0);
+ mutex->owner = GetCurrentThreadId();
+}
+
+int qemu_mutex_trylock(QemuMutex *mutex)
+{
+ int owned;
+
+ owned = TryEnterCriticalSection(&mutex->lock);
+ if (owned) {
+ assert(mutex->owner == 0);
+ mutex->owner = GetCurrentThreadId();
+ }
+ return !owned;
+}
+
+void qemu_mutex_unlock(QemuMutex *mutex)
+{
+ assert(mutex->owner == GetCurrentThreadId());
+ mutex->owner = 0;
+ LeaveCriticalSection(&mutex->lock);
+}
+
+void qemu_cond_init(QemuCond *cond)
+{
+ memset(cond, 0, sizeof(*cond));
+
+ cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+ if (!cond->sema) {
+ error_exit(GetLastError(), __func__);
+ }
+ cond->continue_event = CreateEvent(NULL, /* security */
+ FALSE, /* auto-reset */
+ FALSE, /* not signaled */
+ NULL); /* name */
+ if (!cond->continue_event) {
+ error_exit(GetLastError(), __func__);
+ }
+}
+
+void qemu_cond_signal(QemuCond *cond)
+{
+ DWORD result;
+
+ /*
+ * Signal only when there are waiters. cond->waiters is
+ * incremented by pthread_cond_wait under the external lock,
+ * so we are safe about that.
+ */
+ if (cond->waiters == 0) {
+ return;
+ }
+
+ /*
+ * Waiting threads decrement it outside the external lock, but
+ * only if another thread is executing pthread_cond_broadcast and
+ * has the mutex. So, it also cannot be decremented concurrently
+ * with this particular access.
+ */
+ cond->target = cond->waiters - 1;
+ result = SignalObjectAndWait(cond->sema, cond->continue_event,
+ INFINITE, FALSE);
+ if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
+ error_exit(GetLastError(), __func__);
+ }
+}
+
+void qemu_cond_broadcast(QemuCond *cond)
+{
+ BOOLEAN result;
+ /*
+ * As in pthread_cond_signal, access to cond->waiters and
+ * cond->target is locked via the external mutex.
+ */
+ if (cond->waiters == 0) {
+ return;
+ }
+
+ cond->target = 0;
+ result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
+ if (!result) {
+ error_exit(GetLastError(), __func__);
+ }
+
+ /*
+ * At this point all waiters continue. Each one takes its
+ * slice of the semaphore. Now it's our turn to wait: Since
+ * the external mutex is held, no thread can leave cond_wait,
+ * yet. For this reason, we can be sure that no thread gets
+ * a chance to eat *more* than one slice. OTOH, it means
+ * that the last waiter must send us a wake-up.
+ */
+ WaitForSingleObject(cond->continue_event, INFINITE);
+}
+
+void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
+{
+ /*
+ * This access is protected under the mutex.
+ */
+ cond->waiters++;
+
+ /*
+ * Unlock external mutex and wait for signal.
+ * NOTE: we've held mutex locked long enough to increment
+ * waiters count above, so there's no problem with
+ * leaving mutex unlocked before we wait on semaphore.
+ */
+ qemu_mutex_unlock(mutex);
+ WaitForSingleObject(cond->sema, INFINITE);
+
+ /* Now waiters must rendez-vous with the signaling thread and
+ * let it continue. For cond_broadcast this has heavy contention
+ * and triggers thundering herd. So goes life.
+ *
+ * Decrease waiters count. The mutex is not taken, so we have
+ * to do this atomically.
+ *
+ * All waiters contend for the mutex at the end of this function
+ * until the signaling thread relinquishes it. To ensure
+ * each waiter consumes exactly one slice of the semaphore,
+ * the signaling thread stops until it is told by the last
+ * waiter that it can go on.
+ */
+ if (InterlockedDecrement(&cond->waiters) == cond->target) {
+ SetEvent(cond->continue_event);
+ }
+
+ qemu_mutex_lock(mutex);
+}
+
+struct qemu_thread_data {
+ QemuThread *thread;
+ void *(*start_routine)(void *);
+ void *arg;
+};
+
+static int qemu_thread_tls_index = TLS_OUT_OF_INDEXES;
+
+static unsigned __stdcall win32_start_routine(void *arg)
+{
+ struct qemu_thread_data data = *(struct qemu_thread_data *) arg;
+ QemuThread *thread = data.thread;
+
+ free(arg);
+ TlsSetValue(qemu_thread_tls_index, thread);
+
+ /*
+ * Use DuplicateHandle instead of assigning thread->thread in the
+ * creating thread to avoid races. It's simpler this way than with
+ * synchronization.
+ */
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+ GetCurrentProcess(), &thread->thread,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+
+ qemu_thread_exit(data.start_routine(data.arg));
+ abort();
+}
+
+void qemu_thread_exit(void *arg)
+{
+ QemuThread *thread = TlsGetValue(qemu_thread_tls_index);
+ thread->ret = arg;
+ CloseHandle(thread->thread);
+ thread->thread = NULL;
+ ExitThread(0);
+}
+
+static inline void qemu_thread_init(void)
+{
+ if (qemu_thread_tls_index == TLS_OUT_OF_INDEXES) {
+ qemu_thread_tls_index = TlsAlloc();
+ if (qemu_thread_tls_index == TLS_OUT_OF_INDEXES) {
+ error_exit(ERROR_NO_SYSTEM_RESOURCES, __func__);
+ }
+ }
+}
+
+
+void qemu_thread_create(QemuThread *thread,
+ void *(*start_routine)(void *),
+ void *arg)
+{
+ HANDLE hThread;
+
+ struct qemu_thread_data *data;
+ qemu_thread_init();
+ data = qemu_malloc(sizeof *data);
+ data->thread = thread;
+ data->start_routine = start_routine;
+ data->arg = arg;
+
+ hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
+ data, 0, NULL);
+ if (!hThread) {
+ error_exit(GetLastError(), __func__);
+ }
+ CloseHandle(hThread);
+}
+
+void qemu_thread_get_self(QemuThread *thread)
+{
+ if (!thread->thread) {
+ /* In the main thread of the process. Initialize the QemuThread
+ pointer in TLS, and use the dummy GetCurrentThread handle as
+ the identifier for qemu_thread_is_self. */
+ qemu_thread_init();
+ TlsSetValue(qemu_thread_tls_index, thread);
+ thread->thread = GetCurrentThread();
+ }
+}
+
+int qemu_thread_is_self(QemuThread *thread)
+{
+ QemuThread *this_thread = TlsGetValue(qemu_thread_tls_index);
+ return this_thread->thread == thread->thread;
+}
diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h
new file mode 100644
index 0000000..878f86a
--- /dev/null
+++ b/qemu-thread-win32.h
@@ -0,0 +1,21 @@
+#ifndef __QEMU_THREAD_WIN32_H
+#define __QEMU_THREAD_WIN32_H 1
+#include "windows.h"
+
+struct QemuMutex {
+ CRITICAL_SECTION lock;
+ LONG owner;
+};
+
+struct QemuCond {
+ LONG waiters, target;
+ HANDLE sema;
+ HANDLE continue_event;
+};
+
+struct QemuThread {
+ HANDLE thread;
+ void *ret;
+};
+
+#endif
diff --git a/qemu-thread.h b/qemu-thread.h
index add97bf..acdb6b2 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -1,24 +1,16 @@
#ifndef __QEMU_THREAD_H
#define __QEMU_THREAD_H 1
-#include "semaphore.h"
-#include "pthread.h"
-
-struct QemuMutex {
- pthread_mutex_t lock;
-};
-
-struct QemuCond {
- pthread_cond_t cond;
-};
-
-struct QemuThread {
- pthread_t thread;
-};
typedef struct QemuMutex QemuMutex;
typedef struct QemuCond QemuCond;
typedef struct QemuThread QemuThread;
+#ifdef _WIN32
+#include "qemu-thread-win32.h"
+#else
+#include "qemu-thread-posix.h"
+#endif
+
void qemu_mutex_init(QemuMutex *mutex);
void qemu_mutex_destroy(QemuMutex *mutex);
void qemu_mutex_lock(QemuMutex *mutex);
@@ -28,6 +20,12 @@ void qemu_mutex_unlock(QemuMutex *mutex);
void qemu_cond_init(QemuCond *cond);
void qemu_cond_destroy(QemuCond *cond);
+
+/*
+ * IMPORTANT: The implementation does not guarantee that pthread_cond_signal
+ * and pthread_cond_broadcast can be called except while the same mutex is
+ * held as in the corresponding pthread_cond_wait calls!
+ */
void qemu_cond_signal(QemuCond *cond);
void qemu_cond_broadcast(QemuCond *cond);
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
@@ -36,7 +34,6 @@ int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs);
void qemu_thread_create(QemuThread *thread,
void *(*start_routine)(void*),
void *arg);
-void qemu_thread_signal(QemuThread *thread, int sig);
void qemu_thread_get_self(QemuThread *thread);
int qemu_thread_is_self(QemuThread *thread);
void qemu_thread_exit(void *retval);
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 upstream 05/22] add win32 qemu-thread implementation
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 05/22] add win32 qemu-thread implementation Paolo Bonzini
@ 2011-02-26 16:47 ` Blue Swirl
2011-02-26 17:42 ` [Qemu-devel] " Paolo Bonzini
0 siblings, 1 reply; 31+ messages in thread
From: Blue Swirl @ 2011-02-26 16:47 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, aurelien
On Sat, Feb 26, 2011 at 5:40 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> For now, qemu_cond_timedwait and qemu_mutex_timedlock are left as
> POSIX-only functions. They can be removed later, once the patches
> that remove their uses are in.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> Makefile.objs | 4 +-
> qemu-thread.c => qemu-thread-posix.c | 0
> qemu-thread-posix.h | 18 +++
> qemu-thread-win32.c | 260 ++++++++++++++++++++++++++++++++++
> qemu-thread-win32.h | 21 +++
> qemu-thread.h | 27 ++--
> 6 files changed, 313 insertions(+), 17 deletions(-)
> rename qemu-thread.c => qemu-thread-posix.c (100%)
> create mode 100644 qemu-thread-posix.h
> create mode 100644 qemu-thread-win32.c
> create mode 100644 qemu-thread-win32.h
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 9e98a66..a52f42f 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -142,8 +142,8 @@ endif
> common-obj-y += $(addprefix ui/, $(ui-obj-y))
>
> common-obj-y += iov.o acl.o
> -common-obj-$(CONFIG_THREAD) += qemu-thread.o
> -common-obj-$(CONFIG_POSIX) += compatfd.o
> +common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
> +common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
> common-obj-y += notify.o event_notifier.o
> common-obj-y += qemu-timer.o qemu-timer-common.o
>
> diff --git a/qemu-thread.c b/qemu-thread-posix.c
> similarity index 100%
> rename from qemu-thread.c
> rename to qemu-thread-posix.c
> diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
> new file mode 100644
> index 0000000..7af371c
> --- /dev/null
> +++ b/qemu-thread-posix.h
> @@ -0,0 +1,18 @@
> +#ifndef __QEMU_THREAD_POSIX_H
> +#define __QEMU_THREAD_POSIX_H 1
> +#include "pthread.h"
> +
> +struct QemuMutex {
> + pthread_mutex_t lock;
> +};
> +
> +struct QemuCond {
> + pthread_cond_t cond;
> +};
> +
> +struct QemuThread {
> + pthread_t thread;
> +};
> +
> +void qemu_thread_signal(QemuThread *thread, int sig);
> +#endif
> diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
> new file mode 100644
> index 0000000..89422ce
> --- /dev/null
> +++ b/qemu-thread-win32.c
> @@ -0,0 +1,260 @@
> +/*
> + * Win32 implementation for mutex/cond/thread functions
> + *
> + * Copyright Red Hat, Inc. 2010
> + *
> + * Author:
> + * Paolo Bonzini <pbonzini@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 "qemu-thread.h"
> +#include <process.h>
> +#include <assert.h>
> +#include <limits.h>
> +
> +static void error_exit(int err, const char *msg)
> +{
> + char *pstr;
> +
> + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
> + NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
> + fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
> + LocalFree(pstr);
> + exit(1);
> +}
> +
> +void qemu_mutex_init(QemuMutex *mutex)
> +{
> + mutex->owner = 0;
> + InitializeCriticalSection(&mutex->lock);
> +}
> +
> +void qemu_mutex_lock(QemuMutex *mutex)
> +{
> + EnterCriticalSection(&mutex->lock);
> +
> + /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not
> + * using them as such.
> + */
> + assert(mutex->owner == 0);
> + mutex->owner = GetCurrentThreadId();
> +}
> +
> +int qemu_mutex_trylock(QemuMutex *mutex)
> +{
> + int owned;
> +
> + owned = TryEnterCriticalSection(&mutex->lock);
> + if (owned) {
> + assert(mutex->owner == 0);
> + mutex->owner = GetCurrentThreadId();
> + }
> + return !owned;
> +}
> +
> +void qemu_mutex_unlock(QemuMutex *mutex)
> +{
> + assert(mutex->owner == GetCurrentThreadId());
> + mutex->owner = 0;
> + LeaveCriticalSection(&mutex->lock);
> +}
> +
> +void qemu_cond_init(QemuCond *cond)
> +{
> + memset(cond, 0, sizeof(*cond));
> +
> + cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
> + if (!cond->sema) {
> + error_exit(GetLastError(), __func__);
> + }
> + cond->continue_event = CreateEvent(NULL, /* security */
> + FALSE, /* auto-reset */
> + FALSE, /* not signaled */
> + NULL); /* name */
> + if (!cond->continue_event) {
> + error_exit(GetLastError(), __func__);
> + }
> +}
> +
> +void qemu_cond_signal(QemuCond *cond)
> +{
> + DWORD result;
> +
> + /*
> + * Signal only when there are waiters. cond->waiters is
> + * incremented by pthread_cond_wait under the external lock,
> + * so we are safe about that.
> + */
> + if (cond->waiters == 0) {
> + return;
> + }
> +
> + /*
> + * Waiting threads decrement it outside the external lock, but
> + * only if another thread is executing pthread_cond_broadcast and
> + * has the mutex. So, it also cannot be decremented concurrently
> + * with this particular access.
> + */
> + cond->target = cond->waiters - 1;
> + result = SignalObjectAndWait(cond->sema, cond->continue_event,
> + INFINITE, FALSE);
> + if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
> + error_exit(GetLastError(), __func__);
> + }
> +}
> +
> +void qemu_cond_broadcast(QemuCond *cond)
> +{
> + BOOLEAN result;
> + /*
> + * As in pthread_cond_signal, access to cond->waiters and
> + * cond->target is locked via the external mutex.
> + */
> + if (cond->waiters == 0) {
> + return;
> + }
> +
> + cond->target = 0;
> + result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
> + if (!result) {
> + error_exit(GetLastError(), __func__);
> + }
> +
> + /*
> + * At this point all waiters continue. Each one takes its
> + * slice of the semaphore. Now it's our turn to wait: Since
> + * the external mutex is held, no thread can leave cond_wait,
> + * yet. For this reason, we can be sure that no thread gets
> + * a chance to eat *more* than one slice. OTOH, it means
> + * that the last waiter must send us a wake-up.
> + */
> + WaitForSingleObject(cond->continue_event, INFINITE);
> +}
> +
> +void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
> +{
> + /*
> + * This access is protected under the mutex.
> + */
> + cond->waiters++;
> +
> + /*
> + * Unlock external mutex and wait for signal.
> + * NOTE: we've held mutex locked long enough to increment
> + * waiters count above, so there's no problem with
> + * leaving mutex unlocked before we wait on semaphore.
> + */
> + qemu_mutex_unlock(mutex);
> + WaitForSingleObject(cond->sema, INFINITE);
> +
> + /* Now waiters must rendez-vous with the signaling thread and
> + * let it continue. For cond_broadcast this has heavy contention
> + * and triggers thundering herd. So goes life.
> + *
> + * Decrease waiters count. The mutex is not taken, so we have
> + * to do this atomically.
> + *
> + * All waiters contend for the mutex at the end of this function
> + * until the signaling thread relinquishes it. To ensure
> + * each waiter consumes exactly one slice of the semaphore,
> + * the signaling thread stops until it is told by the last
> + * waiter that it can go on.
> + */
> + if (InterlockedDecrement(&cond->waiters) == cond->target) {
> + SetEvent(cond->continue_event);
> + }
> +
> + qemu_mutex_lock(mutex);
> +}
> +
> +struct qemu_thread_data {
QemuThreadData?
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] Re: [PATCH v2 upstream 05/22] add win32 qemu-thread implementation
2011-02-26 16:47 ` Blue Swirl
@ 2011-02-26 17:42 ` Paolo Bonzini
0 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 17:42 UTC (permalink / raw)
To: Blue Swirl; +Cc: jan.kiszka, qemu-devel, aurelien
On 02/26/2011 05:47 PM, Blue Swirl wrote:
> On Sat, Feb 26, 2011 at 5:40 PM, Paolo Bonzini<pbonzini@redhat.com> wrote:
>> For now, qemu_cond_timedwait and qemu_mutex_timedlock are left as
>> POSIX-only functions. They can be removed later, once the patches
>> that remove their uses are in.
>>
>> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
>> ---
>> Makefile.objs | 4 +-
>> qemu-thread.c => qemu-thread-posix.c | 0
>> qemu-thread-posix.h | 18 +++
>> qemu-thread-win32.c | 260 ++++++++++++++++++++++++++++++++++
>> qemu-thread-win32.h | 21 +++
>> qemu-thread.h | 27 ++--
>> 6 files changed, 313 insertions(+), 17 deletions(-)
>> rename qemu-thread.c => qemu-thread-posix.c (100%)
>> create mode 100644 qemu-thread-posix.h
>> create mode 100644 qemu-thread-win32.c
>> create mode 100644 qemu-thread-win32.h
>>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 9e98a66..a52f42f 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -142,8 +142,8 @@ endif
>> common-obj-y += $(addprefix ui/, $(ui-obj-y))
>>
>> common-obj-y += iov.o acl.o
>> -common-obj-$(CONFIG_THREAD) += qemu-thread.o
>> -common-obj-$(CONFIG_POSIX) += compatfd.o
>> +common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
>> +common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
>> common-obj-y += notify.o event_notifier.o
>> common-obj-y += qemu-timer.o qemu-timer-common.o
>>
>> diff --git a/qemu-thread.c b/qemu-thread-posix.c
>> similarity index 100%
>> rename from qemu-thread.c
>> rename to qemu-thread-posix.c
>> diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
>> new file mode 100644
>> index 0000000..7af371c
>> --- /dev/null
>> +++ b/qemu-thread-posix.h
>> @@ -0,0 +1,18 @@
>> +#ifndef __QEMU_THREAD_POSIX_H
>> +#define __QEMU_THREAD_POSIX_H 1
>> +#include "pthread.h"
>> +
>> +struct QemuMutex {
>> + pthread_mutex_t lock;
>> +};
>> +
>> +struct QemuCond {
>> + pthread_cond_t cond;
>> +};
>> +
>> +struct QemuThread {
>> + pthread_t thread;
>> +};
>> +
>> +void qemu_thread_signal(QemuThread *thread, int sig);
>> +#endif
>> diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
>> new file mode 100644
>> index 0000000..89422ce
>> --- /dev/null
>> +++ b/qemu-thread-win32.c
>> @@ -0,0 +1,260 @@
>> +/*
>> + * Win32 implementation for mutex/cond/thread functions
>> + *
>> + * Copyright Red Hat, Inc. 2010
>> + *
>> + * Author:
>> + * Paolo Bonzini<pbonzini@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 "qemu-thread.h"
>> +#include<process.h>
>> +#include<assert.h>
>> +#include<limits.h>
>> +
>> +static void error_exit(int err, const char *msg)
>> +{
>> + char *pstr;
>> +
>> + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
>> + NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
>> + fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
>> + LocalFree(pstr);
>> + exit(1);
>> +}
>> +
>> +void qemu_mutex_init(QemuMutex *mutex)
>> +{
>> + mutex->owner = 0;
>> + InitializeCriticalSection(&mutex->lock);
>> +}
>> +
>> +void qemu_mutex_lock(QemuMutex *mutex)
>> +{
>> + EnterCriticalSection(&mutex->lock);
>> +
>> + /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not
>> + * using them as such.
>> + */
>> + assert(mutex->owner == 0);
>> + mutex->owner = GetCurrentThreadId();
>> +}
>> +
>> +int qemu_mutex_trylock(QemuMutex *mutex)
>> +{
>> + int owned;
>> +
>> + owned = TryEnterCriticalSection(&mutex->lock);
>> + if (owned) {
>> + assert(mutex->owner == 0);
>> + mutex->owner = GetCurrentThreadId();
>> + }
>> + return !owned;
>> +}
>> +
>> +void qemu_mutex_unlock(QemuMutex *mutex)
>> +{
>> + assert(mutex->owner == GetCurrentThreadId());
>> + mutex->owner = 0;
>> + LeaveCriticalSection(&mutex->lock);
>> +}
>> +
>> +void qemu_cond_init(QemuCond *cond)
>> +{
>> + memset(cond, 0, sizeof(*cond));
>> +
>> + cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
>> + if (!cond->sema) {
>> + error_exit(GetLastError(), __func__);
>> + }
>> + cond->continue_event = CreateEvent(NULL, /* security */
>> + FALSE, /* auto-reset */
>> + FALSE, /* not signaled */
>> + NULL); /* name */
>> + if (!cond->continue_event) {
>> + error_exit(GetLastError(), __func__);
>> + }
>> +}
>> +
>> +void qemu_cond_signal(QemuCond *cond)
>> +{
>> + DWORD result;
>> +
>> + /*
>> + * Signal only when there are waiters. cond->waiters is
>> + * incremented by pthread_cond_wait under the external lock,
>> + * so we are safe about that.
>> + */
>> + if (cond->waiters == 0) {
>> + return;
>> + }
>> +
>> + /*
>> + * Waiting threads decrement it outside the external lock, but
>> + * only if another thread is executing pthread_cond_broadcast and
>> + * has the mutex. So, it also cannot be decremented concurrently
>> + * with this particular access.
>> + */
>> + cond->target = cond->waiters - 1;
>> + result = SignalObjectAndWait(cond->sema, cond->continue_event,
>> + INFINITE, FALSE);
>> + if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
>> + error_exit(GetLastError(), __func__);
>> + }
>> +}
>> +
>> +void qemu_cond_broadcast(QemuCond *cond)
>> +{
>> + BOOLEAN result;
>> + /*
>> + * As in pthread_cond_signal, access to cond->waiters and
>> + * cond->target is locked via the external mutex.
>> + */
>> + if (cond->waiters == 0) {
>> + return;
>> + }
>> +
>> + cond->target = 0;
>> + result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
>> + if (!result) {
>> + error_exit(GetLastError(), __func__);
>> + }
>> +
>> + /*
>> + * At this point all waiters continue. Each one takes its
>> + * slice of the semaphore. Now it's our turn to wait: Since
>> + * the external mutex is held, no thread can leave cond_wait,
>> + * yet. For this reason, we can be sure that no thread gets
>> + * a chance to eat *more* than one slice. OTOH, it means
>> + * that the last waiter must send us a wake-up.
>> + */
>> + WaitForSingleObject(cond->continue_event, INFINITE);
>> +}
>> +
>> +void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
>> +{
>> + /*
>> + * This access is protected under the mutex.
>> + */
>> + cond->waiters++;
>> +
>> + /*
>> + * Unlock external mutex and wait for signal.
>> + * NOTE: we've held mutex locked long enough to increment
>> + * waiters count above, so there's no problem with
>> + * leaving mutex unlocked before we wait on semaphore.
>> + */
>> + qemu_mutex_unlock(mutex);
>> + WaitForSingleObject(cond->sema, INFINITE);
>> +
>> + /* Now waiters must rendez-vous with the signaling thread and
>> + * let it continue. For cond_broadcast this has heavy contention
>> + * and triggers thundering herd. So goes life.
>> + *
>> + * Decrease waiters count. The mutex is not taken, so we have
>> + * to do this atomically.
>> + *
>> + * All waiters contend for the mutex at the end of this function
>> + * until the signaling thread relinquishes it. To ensure
>> + * each waiter consumes exactly one slice of the semaphore,
>> + * the signaling thread stops until it is told by the last
>> + * waiter that it can go on.
>> + */
>> + if (InterlockedDecrement(&cond->waiters) == cond->target) {
>> + SetEvent(cond->continue_event);
>> + }
>> +
>> + qemu_mutex_lock(mutex);
>> +}
>> +
>> +struct qemu_thread_data {
>
> QemuThreadData?
Ok, will resubmit asap. Can you add this convention to checkpatch?
Paolo
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 06/22] include qemu-thread.h early
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (4 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 05/22] add win32 qemu-thread implementation Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex Paolo Bonzini
` (17 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/cpus.c b/cpus.c
index 09ce6fe..c5743c4 100644
--- a/cpus.c
+++ b/cpus.c
@@ -32,6 +32,7 @@
#include "kvm.h"
#include "exec-all.h"
+#include "qemu-thread.h"
#include "cpus.h"
#include "compatfd.h"
@@ -592,8 +593,6 @@ void vm_stop(int reason)
#else /* CONFIG_IOTHREAD */
-#include "qemu-thread.h"
-
QemuMutex qemu_global_mutex;
static QemuMutex qemu_fair_mutex;
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (5 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 06/22] include qemu-thread.h early Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-27 9:33 ` [Qemu-devel] " Jan Kiszka
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 08/22] remove CONFIG_THREAD Paolo Bonzini
` (16 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
These are already present in the Win32 implementation, add them to
the pthread wrappers as well. Use PTHREAD_MUTEX_ERRORCHECK for mutex
operations, and track the owner separately for cond_signal/broadcast.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
qemu-thread-posix.c | 23 +++++++++++++++++++++--
qemu-thread-posix.h | 1 +
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index e307773..a4c6e25 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -16,9 +16,12 @@
#include <time.h>
#include <signal.h>
#include <stdint.h>
+#include <assert.h>
#include <string.h>
#include "qemu-thread.h"
+static pthread_t pthread_null;
+
static void error_exit(int err, const char *msg)
{
fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
@@ -28,8 +31,13 @@ static void error_exit(int err, const char *msg)
void qemu_mutex_init(QemuMutex *mutex)
{
int err;
+ pthread_mutexattr_t mutexattr;
- err = pthread_mutex_init(&mutex->lock, NULL);
+ mutex->owner = pthread_null;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
+ err = pthread_mutex_init(&mutex->lock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
if (err)
error_exit(err, __func__);
}
@@ -48,13 +56,20 @@ void qemu_mutex_lock(QemuMutex *mutex)
int err;
err = pthread_mutex_lock(&mutex->lock);
+ mutex->owner = pthread_self();
if (err)
error_exit(err, __func__);
}
int qemu_mutex_trylock(QemuMutex *mutex)
{
- return pthread_mutex_trylock(&mutex->lock);
+ int err;
+ err = pthread_mutex_trylock(&mutex->lock);
+ if (err == 0) {
+ mutex->owner = pthread_self();
+ }
+
+ return !!err;
}
static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
@@ -85,6 +100,7 @@ void qemu_mutex_unlock(QemuMutex *mutex)
{
int err;
+ mutex->owner = pthread_null;
err = pthread_mutex_unlock(&mutex->lock);
if (err)
error_exit(err, __func__);
@@ -130,7 +146,10 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
{
int err;
+ assert(pthread_equal(mutex->owner, pthread_self()));
+ mutex->owner = pthread_null;
err = pthread_cond_wait(&cond->cond, &mutex->lock);
+ mutex->owner = pthread_self();
if (err)
error_exit(err, __func__);
}
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index 7af371c..11978db 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -4,6 +4,7 @@
struct QemuMutex {
pthread_mutex_t lock;
+ pthread_t owner;
};
struct QemuCond {
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] Re: [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex Paolo Bonzini
@ 2011-02-27 9:33 ` Jan Kiszka
2011-02-27 15:06 ` Paolo Bonzini
0 siblings, 1 reply; 31+ messages in thread
From: Jan Kiszka @ 2011-02-27 9:33 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, aurelien
[-- Attachment #1: Type: text/plain, Size: 3227 bytes --]
On 2011-02-26 16:40, Paolo Bonzini wrote:
> These are already present in the Win32 implementation, add them to
> the pthread wrappers as well. Use PTHREAD_MUTEX_ERRORCHECK for mutex
> operations, and track the owner separately for cond_signal/broadcast.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> qemu-thread-posix.c | 23 +++++++++++++++++++++--
> qemu-thread-posix.h | 1 +
> 2 files changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
> index e307773..a4c6e25 100644
> --- a/qemu-thread-posix.c
> +++ b/qemu-thread-posix.c
> @@ -16,9 +16,12 @@
> #include <time.h>
> #include <signal.h>
> #include <stdint.h>
> +#include <assert.h>
> #include <string.h>
> #include "qemu-thread.h"
>
> +static pthread_t pthread_null;
> +
> static void error_exit(int err, const char *msg)
> {
> fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
> @@ -28,8 +31,13 @@ static void error_exit(int err, const char *msg)
> void qemu_mutex_init(QemuMutex *mutex)
> {
> int err;
> + pthread_mutexattr_t mutexattr;
>
> - err = pthread_mutex_init(&mutex->lock, NULL);
> + mutex->owner = pthread_null;
> + pthread_mutexattr_init(&mutexattr);
> + pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
> + err = pthread_mutex_init(&mutex->lock, &mutexattr);
> + pthread_mutexattr_destroy(&mutexattr);
> if (err)
> error_exit(err, __func__);
> }
> @@ -48,13 +56,20 @@ void qemu_mutex_lock(QemuMutex *mutex)
> int err;
>
> err = pthread_mutex_lock(&mutex->lock);
> + mutex->owner = pthread_self();
> if (err)
> error_exit(err, __func__);
> }
>
> int qemu_mutex_trylock(QemuMutex *mutex)
> {
> - return pthread_mutex_trylock(&mutex->lock);
> + int err;
> + err = pthread_mutex_trylock(&mutex->lock);
> + if (err == 0) {
> + mutex->owner = pthread_self();
> + }
> +
> + return !!err;
> }
>
> static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
> @@ -85,6 +100,7 @@ void qemu_mutex_unlock(QemuMutex *mutex)
> {
> int err;
>
> + mutex->owner = pthread_null;
> err = pthread_mutex_unlock(&mutex->lock);
> if (err)
> error_exit(err, __func__);
> @@ -130,7 +146,10 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
> {
> int err;
>
> + assert(pthread_equal(mutex->owner, pthread_self()));
> + mutex->owner = pthread_null;
> err = pthread_cond_wait(&cond->cond, &mutex->lock);
Though POSIX is not 100% explicit on this, every sane pthread_cond_wait
implementation will apply the same error checking as on
pthread_mutex_unlock when the given mutex is of
PTHREAD_MUTEX_ERRORCHECK. So, this assert is actually redundant as well.
Now that we are left without any assertions, I start wondering about one
of the original missions: enforce qemu_cond_signal/broadcast to be
called under a mutex. What about extending those services with a mutex
argument and applying the assert there? Could become a static-inline
wrapper so that the argument is optimized away if assert() is inactive.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] Re: [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex
2011-02-27 9:33 ` [Qemu-devel] " Jan Kiszka
@ 2011-02-27 15:06 ` Paolo Bonzini
0 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-27 15:06 UTC (permalink / raw)
To: Jan Kiszka; +Cc: qemu-devel, aurelien
On 02/27/2011 10:33 AM, Jan Kiszka wrote:
> Now that we are left without any assertions, I start wondering about one
> of the original missions: enforce qemu_cond_signal/broadcast to be
> called under a mutex. What about extending those services with a mutex
> argument and applying the assert there?
That is one of the patches in my queue that I haven't submitted yet. :)
Paolo
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 08/22] remove CONFIG_THREAD
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (6 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 07/22] add assertions on the owner of a QemuMutex Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 09/22] target-sh4: move intr_at_halt out of cpu_halted() Paolo Bonzini
` (15 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configure | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 3036faf..4de26d2 100755
--- a/configure
+++ b/configure
@@ -2662,7 +2662,6 @@ if test "$vnc_png" != "no" ; then
fi
if test "$vnc_thread" != "no" ; then
echo "CONFIG_VNC_THREAD=y" >> $config_host_mak
- echo "CONFIG_THREAD=y" >> $config_host_mak
fi
if test "$fnmatch" = "yes" ; then
echo "CONFIG_FNMATCH=y" >> $config_host_mak
@@ -2758,7 +2757,6 @@ if test "$xen" = "yes" ; then
fi
if test "$io_thread" = "yes" ; then
echo "CONFIG_IOTHREAD=y" >> $config_host_mak
- echo "CONFIG_THREAD=y" >> $config_host_mak
fi
if test "$linux_aio" = "yes" ; then
echo "CONFIG_LINUX_AIO=y" >> $config_host_mak
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 09/22] target-sh4: move intr_at_halt out of cpu_halted()
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (7 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 08/22] remove CONFIG_THREAD Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 10/22] inline cpu_halted into sole caller Paolo Bonzini
` (14 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
From: Aurelien Jarno <aurelien@aurel32.net>
All targets except SH4 have the same cpu_halted() routine, and it has
only one caller. It is therefore a good candidate for inlining.
The difference is the handling of the intr_at_halt, which is necessary
to ignore SR.BL when sleeping. Move intr_at_halt handling out of it, by
setting this variable while executing the sleep instruction, and
clearing it when the CPU has been woken-up by an interrupt, whatever the
state of SR.BL. Also rename this variable in_sleep.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
target-sh4/cpu.h | 2 +-
target-sh4/exec.h | 1 -
target-sh4/helper.c | 4 ++--
target-sh4/op_helper.c | 1 +
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 789d188..74ff97a 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -184,7 +184,7 @@ typedef struct CPUSH4State {
uint32_t cvr; /* Cache Version Register */
void *intc_handle;
- int intr_at_halt; /* SR_BL ignored during sleep */
+ int in_sleep; /* SR_BL ignored during sleep */
memory_content *movcal_backup;
memory_content **movcal_backup_tail;
} CPUSH4State;
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
index 2999c02..61bc121 100644
--- a/target-sh4/exec.h
+++ b/target-sh4/exec.h
@@ -37,7 +37,6 @@ static inline int cpu_halted(CPUState *env) {
return 0;
if (cpu_has_work(env)) {
env->halted = 0;
- env->intr_at_halt = 1;
return 0;
}
return EXCP_HALTED;
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index d2038bd..8f36d31 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -90,11 +90,11 @@ void do_interrupt(CPUState * env)
if (do_exp && env->exception_index != 0x1e0) {
env->exception_index = 0x000; /* masked exception -> reset */
}
- if (do_irq && !env->intr_at_halt) {
+ if (do_irq && !env->in_sleep) {
return; /* masked */
}
- env->intr_at_halt = 0;
}
+ env->in_sleep = 0;
if (do_irq) {
irq_vector = sh_intc_get_pending_vector(env->intc_handle,
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 30f9842..b8f4ca2 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -119,6 +119,7 @@ void helper_debug(void)
void helper_sleep(uint32_t next_pc)
{
env->halted = 1;
+ env->in_sleep = 1;
env->exception_index = EXCP_HLT;
env->pc = next_pc;
cpu_loop_exit();
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 10/22] inline cpu_halted into sole caller
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (8 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 09/22] target-sh4: move intr_at_halt out of cpu_halted() Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 11/22] always qemu_cpu_kick after unhalting a cpu Paolo Bonzini
` (13 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
All implementations are now the same, and there is only one caller,
so inline the function there.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpu-exec.c | 9 +++++++--
target-alpha/exec.h | 11 -----------
target-arm/exec.h | 13 -------------
target-cris/exec.h | 11 -----------
target-i386/exec.h | 12 ------------
target-m68k/exec.h | 10 ----------
target-microblaze/exec.h | 11 -----------
target-mips/exec.h | 11 -----------
target-ppc/exec.h | 11 -----------
target-s390x/exec.h | 12 ------------
target-sh4/exec.h | 10 ----------
target-sparc/exec.h | 10 ----------
12 files changed, 7 insertions(+), 124 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index b03b3a7..eed9282 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -208,8 +208,13 @@ int cpu_exec(CPUState *env1)
uint8_t *tc_ptr;
unsigned long next_tb;
- if (cpu_halted(env1) == EXCP_HALTED)
- return EXCP_HALTED;
+ if (env1->halted) {
+ if (!cpu_has_work(env1)) {
+ return EXCP_HALTED;
+ }
+
+ env1->halted = 0;
+ }
cpu_single_env = env1;
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
index a8a38d2..6ae96d1 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -42,17 +42,6 @@ static inline int cpu_has_work(CPUState *env)
return (env->interrupt_request & CPU_INTERRUPT_HARD);
}
-static inline int cpu_halted(CPUState *env)
-{
- if (!env->halted)
- return 0;
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->pc = tb->pc;
diff --git a/target-arm/exec.h b/target-arm/exec.h
index e4c35a3..44e1b55 100644
--- a/target-arm/exec.h
+++ b/target-arm/exec.h
@@ -32,19 +32,6 @@ static inline int cpu_has_work(CPUState *env)
(CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB));
}
-static inline int cpu_halted(CPUState *env) {
- if (!env->halted)
- return 0;
- /* An interrupt wakes the CPU even if the I and F CPSR bits are
- set. We use EXITTB to silently wake CPU without causing an
- actual interrupt. */
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif
diff --git a/target-cris/exec.h b/target-cris/exec.h
index 34c0132..2d5d297 100644
--- a/target-cris/exec.h
+++ b/target-cris/exec.h
@@ -33,17 +33,6 @@ static inline int cpu_has_work(CPUState *env)
return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
}
-static inline int cpu_halted(CPUState *env) {
- if (!env->halted)
- return 0;
-
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->pc = tb->pc;
diff --git a/target-i386/exec.h b/target-i386/exec.h
index fc8945b..3e7386e 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -304,18 +304,6 @@ static inline int cpu_has_work(CPUState *env)
return work;
}
-static inline int cpu_halted(CPUState *env) {
- /* handle exit of HALTED state */
- if (!env->halted)
- return 0;
- /* disable halt condition */
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
/* load efer and update the corresponding hflags. XXX: do consistency
checks with cpuid bits ? */
static inline void cpu_load_efer(CPUState *env, uint64_t val)
diff --git a/target-m68k/exec.h b/target-m68k/exec.h
index f31e06e..91daa6b 100644
--- a/target-m68k/exec.h
+++ b/target-m68k/exec.h
@@ -33,16 +33,6 @@ static inline int cpu_has_work(CPUState *env)
return (env->interrupt_request & (CPU_INTERRUPT_HARD));
}
-static inline int cpu_halted(CPUState *env) {
- if (!env->halted)
- return 0;
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->pc = tb->pc;
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
index ab19828..1efff30 100644
--- a/target-microblaze/exec.h
+++ b/target-microblaze/exec.h
@@ -32,17 +32,6 @@ static inline int cpu_has_work(CPUState *env)
return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
}
-static inline int cpu_halted(CPUState *env) {
- if (!env->halted)
- return 0;
-
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->sregs[SR_PC] = tb->pc;
diff --git a/target-mips/exec.h b/target-mips/exec.h
index 1273654..b3c5a13 100644
--- a/target-mips/exec.h
+++ b/target-mips/exec.h
@@ -36,17 +36,6 @@ static inline int cpu_has_work(CPUState *env)
return has_work;
}
-static inline int cpu_halted(CPUState *env)
-{
- if (!env->halted)
- return 0;
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void compute_hflags(CPUState *env)
{
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
diff --git a/target-ppc/exec.h b/target-ppc/exec.h
index 4688ef5..f87847a 100644
--- a/target-ppc/exec.h
+++ b/target-ppc/exec.h
@@ -38,17 +38,6 @@ static inline int cpu_has_work(CPUState *env)
}
-static inline int cpu_halted(CPUState *env)
-{
- if (!env->halted)
- return 0;
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->nip = tb->pc;
diff --git a/target-s390x/exec.h b/target-s390x/exec.h
index bf3f264..f7893f3 100644
--- a/target-s390x/exec.h
+++ b/target-s390x/exec.h
@@ -34,18 +34,6 @@ static inline int cpu_has_work(CPUState *env)
return env->interrupt_request & CPU_INTERRUPT_HARD; // guess
}
-static inline int cpu_halted(CPUState *env)
-{
- if (!env->halted) {
- return 0;
- }
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb)
{
env->psw.addr = tb->pc;
diff --git a/target-sh4/exec.h b/target-sh4/exec.h
index 61bc121..9f1c1f6 100644
--- a/target-sh4/exec.h
+++ b/target-sh4/exec.h
@@ -32,16 +32,6 @@ static inline int cpu_has_work(CPUState *env)
return (env->interrupt_request & CPU_INTERRUPT_HARD);
}
-static inline int cpu_halted(CPUState *env) {
- if (!env->halted)
- return 0;
- if (cpu_has_work(env)) {
- env->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
#ifndef CONFIG_USER_ONLY
#include "softmmu_exec.h"
#endif
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index f811571..f5c221e 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -22,16 +22,6 @@ static inline int cpu_has_work(CPUState *env1)
}
-static inline int cpu_halted(CPUState *env1) {
- if (!env1->halted)
- return 0;
- if (cpu_has_work(env1)) {
- env1->halted = 0;
- return 0;
- }
- return EXCP_HALTED;
-}
-
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->pc = tb->pc;
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 11/22] always qemu_cpu_kick after unhalting a cpu
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (9 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 10/22] inline cpu_halted into sole caller Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 12/22] exit round-robin vcpu loop if cpu->stopped is true Paolo Bonzini
` (12 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
This ensures env->halt_cond is broadcast, and the loop in
qemu_tcg_wait_io_event and qemu_kvm_wait_io_event is exited
naturally rather than through a timeout.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/ppc.c | 2 ++
hw/sun4m.c | 10 ++++++++--
hw/sun4u.c | 4 ++--
target-s390x/kvm.c | 1 +
4 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/hw/ppc.c b/hw/ppc.c
index 968aec1..de02d33 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -208,6 +208,7 @@ static void ppc970_set_irq (void *opaque, int pin, int level)
} else {
LOG_IRQ("%s: restart the CPU\n", __func__);
env->halted = 0;
+ qemu_cpu_kick(env);
}
break;
case PPC970_INPUT_HRESET:
@@ -300,6 +301,7 @@ static void ppc40x_set_irq (void *opaque, int pin, int level)
} else {
LOG_IRQ("%s: restart the CPU\n", __func__);
env->halted = 0;
+ qemu_cpu_kick(env);
}
break;
case PPC40x_INPUT_DEBUG:
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 30e8a21..df3aa32 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -253,15 +253,21 @@ void cpu_check_irqs(CPUState *env)
}
}
+static void cpu_kick_irq(CPUState *env)
+{
+ env->halted = 0;
+ cpu_check_irqs(env);
+ qemu_cpu_kick(env);
+}
+
static void cpu_set_irq(void *opaque, int irq, int level)
{
CPUState *env = opaque;
if (level) {
trace_sun4m_cpu_set_irq_raise(irq);
- env->halted = 0;
env->pil_in |= 1 << irq;
- cpu_check_irqs(env);
+ cpu_kick_irq(env);
} else {
trace_sun4m_cpu_set_irq_lower(irq);
env->pil_in &= ~(1 << irq);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 90b1ce2..d282324 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -298,6 +298,7 @@ static void cpu_kick_irq(CPUState *env)
{
env->halted = 0;
cpu_check_irqs(env);
+ qemu_cpu_kick(env);
}
static void cpu_set_irq(void *opaque, int irq, int level)
@@ -306,9 +307,8 @@ static void cpu_set_irq(void *opaque, int irq, int level)
if (level) {
CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
- env->halted = 0;
env->pil_in |= 1 << irq;
- cpu_check_irqs(env);
+ cpu_kick_irq(env);
} else {
CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
env->pil_in &= ~(1 << irq);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index b349812..6e94274 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -194,6 +194,7 @@ static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
env->halted = 0;
env->exception_index = -1;
+ qemu_cpu_kick(env);
kvmint.type = type;
kvmint.parm = parm;
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 12/22] exit round-robin vcpu loop if cpu->stopped is true
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (10 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 11/22] always qemu_cpu_kick after unhalting a cpu Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 13/22] always signal pause_cond after stopping a VCPU Paolo Bonzini
` (11 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Sometimes vcpus are stopped directly without going through ->stop = 1.
Exit the VCPU execution loop in this case as well.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cpus.c b/cpus.c
index c5743c4..785a104 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1098,7 +1098,7 @@ bool cpu_exec_all(void)
cpu_handle_debug_exception(env);
break;
}
- } else if (env->stop) {
+ } else if (env->stop || env->stopped) {
break;
}
}
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 13/22] always signal pause_cond after stopping a VCPU
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (11 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 12/22] exit round-robin vcpu loop if cpu->stopped is true Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 14/22] do not use timedwait on qemu_halt_cond Paolo Bonzini
` (10 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/cpus.c b/cpus.c
index 785a104..6cfb45b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1012,8 +1012,10 @@ void qemu_notify_event(void)
void cpu_stop_current(void)
{
if (cpu_single_env) {
+ cpu_single_env->stop = 0;
cpu_single_env->stopped = 1;
cpu_exit(cpu_single_env);
+ qemu_cond_signal(&qemu_pause_cond);
}
}
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 14/22] do not use timedwait on qemu_halt_cond
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (12 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 13/22] always signal pause_cond after stopping a VCPU Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 15/22] do not use timedwait on qemu_system_cond Paolo Bonzini
` (9 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
The following conditions can cause cpu_has_work(env) to become true:
- env->queued_work_first: run_on_cpu is already kicking the VCPU
- env->stop = 1: pause_all_vcpus is already kicking the VCPU
- env->stopped = 0: resume_all_vcpus is already kicking the VCPU
- vm_running = 1: vm_start is calling resume_all_vcpus
- env->halted = 0: see previous patch
- qemu_cpu_has_work(env): when it becomes true, board code should set
env->halted = 0 too.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpus.c b/cpus.c
index 6cfb45b..4c3837f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -771,7 +771,7 @@ static void qemu_tcg_wait_io_event(void)
CPUState *env;
while (all_cpu_threads_idle()) {
- qemu_cond_timedwait(tcg_halt_cond, &qemu_global_mutex, 1000);
+ qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
}
qemu_mutex_unlock(&qemu_global_mutex);
@@ -794,7 +794,7 @@ static void qemu_tcg_wait_io_event(void)
static void qemu_kvm_wait_io_event(CPUState *env)
{
while (cpu_thread_is_idle(env)) {
- qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
+ qemu_cond_wait(env->halt_cond, &qemu_global_mutex);
}
qemu_kvm_eat_signals(env);
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 15/22] do not use timedwait on qemu_system_cond
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (13 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 14/22] do not use timedwait on qemu_halt_cond Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 16/22] do not use timedwait on qemu_pause_cond Paolo Bonzini
` (8 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
qemu_main_loop_start is the only place where qemu_system_ready is set
to 1.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpus.c b/cpus.c
index 4c3837f..e367b3b 100644
--- a/cpus.c
+++ b/cpus.c
@@ -823,7 +823,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
/* and wait for machine initialization */
while (!qemu_system_ready) {
- qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+ qemu_cond_wait(&qemu_system_cond, &qemu_global_mutex);
}
while (1) {
@@ -855,7 +855,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
/* and wait for machine initialization */
while (!qemu_system_ready) {
- qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+ qemu_cond_wait(&qemu_system_cond, &qemu_global_mutex);
}
while (1) {
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 16/22] do not use timedwait on qemu_pause_cond
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (14 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 15/22] do not use timedwait on qemu_system_cond Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 17/22] do not use timedwait on qemu_cpu_cond Paolo Bonzini
` (7 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
all_vcpus_paused can start returning true after penv->stopped changes
from 0 to 1. When this is done, qemu_pause_cond is always signaled.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cpus.c b/cpus.c
index e367b3b..8f169ad 100644
--- a/cpus.c
+++ b/cpus.c
@@ -938,7 +938,7 @@ void pause_all_vcpus(void)
}
while (!all_vcpus_paused()) {
- qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
+ qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
penv = first_cpu;
while (penv) {
qemu_cpu_kick(penv);
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 17/22] do not use timedwait on qemu_cpu_cond
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (15 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 16/22] do not use timedwait on qemu_pause_cond Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 18/22] iothread stops the vcpu thread via IPI Paolo Bonzini
` (6 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Whenever env->created becomes true, qemu_cpu_cond is signaled by
{kvm,tcg}_cpu_thread_fn.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpus.c b/cpus.c
index 8f169ad..4305184 100644
--- a/cpus.c
+++ b/cpus.c
@@ -970,7 +970,7 @@ static void qemu_tcg_init_vcpu(void *_env)
qemu_cond_init(env->halt_cond);
qemu_thread_create(env->thread, qemu_tcg_cpu_thread_fn, env);
while (env->created == 0) {
- qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+ qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
tcg_cpu_thread = env->thread;
tcg_halt_cond = env->halt_cond;
@@ -987,7 +987,7 @@ static void qemu_kvm_start_vcpu(CPUState *env)
qemu_cond_init(env->halt_cond);
qemu_thread_create(env->thread, qemu_kvm_cpu_thread_fn, env);
while (env->created == 0) {
- qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+ qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
}
}
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 18/22] iothread stops the vcpu thread via IPI
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (16 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 17/22] do not use timedwait on qemu_cpu_cond Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init Paolo Bonzini
` (5 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/cpus.c b/cpus.c
index 4305184..32e9352 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1086,9 +1086,11 @@ bool cpu_exec_all(void)
qemu_clock_enable(vm_clock,
(env->singlestep_enabled & SSTEP_NOTIMER) == 0);
+#ifndef CONFIG_IOTHREAD
if (qemu_alarm_pending()) {
break;
}
+#endif
if (cpu_can_run(env)) {
if (kvm_enabled()) {
r = kvm_cpu_exec(env);
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (17 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 18/22] iothread stops the vcpu thread via IPI Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-27 9:41 ` [Qemu-devel] " Jan Kiszka
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 20/22] provide dummy signal init functions for win32 Paolo Bonzini
` (4 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 87 ++++++++++++++++++++++++++-------------------------------------
1 files changed, 36 insertions(+), 51 deletions(-)
diff --git a/cpus.c b/cpus.c
index 32e9352..8c440f1 100644
--- a/cpus.c
+++ b/cpus.c
@@ -346,11 +346,37 @@ static void sigfd_handler(void *opaque)
}
}
-static int qemu_signalfd_init(sigset_t mask)
+static int qemu_signalfd_init(void)
{
int sigfd;
+ sigset_t set;
- sigfd = qemu_signalfd(&mask);
+#ifdef CONFIG_IOTHREAD
+ /* SIGUSR2 used by posix-aio-compat.c */
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ sigaddset(&set, SIG_IPI);
+ sigaddset(&set, SIGBUS);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+#else
+ sigemptyset(&set);
+ sigaddset(&set, SIGBUS);
+ if (kvm_enabled()) {
+ /*
+ * We need to process timer signals synchronously to avoid a race
+ * between exit_request check and KVM vcpu entry.
+ */
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ }
+#endif
+
+ sigfd = qemu_signalfd(&set);
if (sigfd == -1) {
fprintf(stderr, "failed to create signalfd\n");
return -errno;
@@ -438,6 +464,12 @@ static void qemu_event_increment(void)
static void qemu_kvm_eat_signals(CPUState *env)
{
}
+
+static int qemu_signalfd_init(void)
+{
+ return 0;
+}
+
#endif /* _WIN32 */
#ifndef CONFIG_IOTHREAD
@@ -471,39 +503,14 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
#endif
}
-#ifndef _WIN32
-static sigset_t block_synchronous_signals(void)
-{
- sigset_t set;
-
- sigemptyset(&set);
- sigaddset(&set, SIGBUS);
- if (kvm_enabled()) {
- /*
- * We need to process timer signals synchronously to avoid a race
- * between exit_request check and KVM vcpu entry.
- */
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- }
-
- return set;
-}
-#endif
-
int qemu_init_main_loop(void)
{
-#ifndef _WIN32
- sigset_t blocked_signals;
int ret;
- blocked_signals = block_synchronous_signals();
-
- ret = qemu_signalfd_init(blocked_signals);
+ ret = qemu_signalfd_init();
if (ret) {
return ret;
}
-#endif
qemu_init_sigbus();
@@ -651,35 +658,13 @@ static void qemu_tcg_init_cpu_signals(void)
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
}
-static sigset_t block_io_signals(void)
-{
- sigset_t set;
-
- /* SIGUSR2 used by posix-aio-compat.c */
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- sigaddset(&set, SIG_IPI);
- sigaddset(&set, SIGBUS);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
-
- return set;
-}
-
int qemu_init_main_loop(void)
{
int ret;
- sigset_t blocked_signals;
qemu_init_sigbus();
- blocked_signals = block_io_signals();
-
- ret = qemu_signalfd_init(blocked_signals);
+ ret = qemu_signalfd_init();
if (ret) {
return ret;
}
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] Re: [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init Paolo Bonzini
@ 2011-02-27 9:41 ` Jan Kiszka
2011-02-27 15:07 ` Paolo Bonzini
0 siblings, 1 reply; 31+ messages in thread
From: Jan Kiszka @ 2011-02-27 9:41 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, Aurelien Jarno
[-- Attachment #1: Type: text/plain, Size: 3892 bytes --]
On 2011-02-26 16:40, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> cpus.c | 87 ++++++++++++++++++++++++++-------------------------------------
> 1 files changed, 36 insertions(+), 51 deletions(-)
>
> diff --git a/cpus.c b/cpus.c
> index 32e9352..8c440f1 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -346,11 +346,37 @@ static void sigfd_handler(void *opaque)
> }
> }
>
> -static int qemu_signalfd_init(sigset_t mask)
> +static int qemu_signalfd_init(void)
> {
> int sigfd;
> + sigset_t set;
>
> - sigfd = qemu_signalfd(&mask);
> +#ifdef CONFIG_IOTHREAD
> + /* SIGUSR2 used by posix-aio-compat.c */
> + sigemptyset(&set);
> + sigaddset(&set, SIGUSR2);
> + pthread_sigmask(SIG_UNBLOCK, &set, NULL);
Didn't you want to rename the function for the sake of non-signalfd
blocks like above?
> +
> + sigemptyset(&set);
> + sigaddset(&set, SIGIO);
> + sigaddset(&set, SIGALRM);
> + sigaddset(&set, SIG_IPI);
> + sigaddset(&set, SIGBUS);
> + pthread_sigmask(SIG_BLOCK, &set, NULL);
> +#else
> + sigemptyset(&set);
This line is shared and can be moved out of the #ifdef.
> + sigaddset(&set, SIGBUS);
> + if (kvm_enabled()) {
> + /*
> + * We need to process timer signals synchronously to avoid a race
> + * between exit_request check and KVM vcpu entry.
> + */
> + sigaddset(&set, SIGIO);
> + sigaddset(&set, SIGALRM);
> + }
> +#endif
> +
> + sigfd = qemu_signalfd(&set);
> if (sigfd == -1) {
> fprintf(stderr, "failed to create signalfd\n");
> return -errno;
> @@ -438,6 +464,12 @@ static void qemu_event_increment(void)
> static void qemu_kvm_eat_signals(CPUState *env)
> {
> }
> +
> +static int qemu_signalfd_init(void)
> +{
> + return 0;
> +}
> +
> #endif /* _WIN32 */
>
> #ifndef CONFIG_IOTHREAD
> @@ -471,39 +503,14 @@ static void qemu_kvm_init_cpu_signals(CPUState *env)
> #endif
> }
>
> -#ifndef _WIN32
> -static sigset_t block_synchronous_signals(void)
> -{
> - sigset_t set;
> -
> - sigemptyset(&set);
> - sigaddset(&set, SIGBUS);
> - if (kvm_enabled()) {
> - /*
> - * We need to process timer signals synchronously to avoid a race
> - * between exit_request check and KVM vcpu entry.
> - */
> - sigaddset(&set, SIGIO);
> - sigaddset(&set, SIGALRM);
> - }
> -
> - return set;
> -}
> -#endif
> -
> int qemu_init_main_loop(void)
> {
> -#ifndef _WIN32
> - sigset_t blocked_signals;
> int ret;
>
> - blocked_signals = block_synchronous_signals();
> -
> - ret = qemu_signalfd_init(blocked_signals);
> + ret = qemu_signalfd_init();
> if (ret) {
> return ret;
> }
> -#endif
>
> qemu_init_sigbus();
>
> @@ -651,35 +658,13 @@ static void qemu_tcg_init_cpu_signals(void)
> pthread_sigmask(SIG_UNBLOCK, &set, NULL);
> }
>
> -static sigset_t block_io_signals(void)
> -{
> - sigset_t set;
> -
> - /* SIGUSR2 used by posix-aio-compat.c */
> - sigemptyset(&set);
> - sigaddset(&set, SIGUSR2);
> - pthread_sigmask(SIG_UNBLOCK, &set, NULL);
> -
> - sigemptyset(&set);
> - sigaddset(&set, SIGIO);
> - sigaddset(&set, SIGALRM);
> - sigaddset(&set, SIG_IPI);
> - sigaddset(&set, SIGBUS);
> - pthread_sigmask(SIG_BLOCK, &set, NULL);
> -
> - return set;
> -}
> -
> int qemu_init_main_loop(void)
> {
> int ret;
> - sigset_t blocked_signals;
>
> qemu_init_sigbus();
>
> - blocked_signals = block_io_signals();
> -
> - ret = qemu_signalfd_init(blocked_signals);
> + ret = qemu_signalfd_init();
> if (ret) {
> return ret;
> }
Beside the minor nits, this looks good.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] Re: [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init
2011-02-27 9:41 ` [Qemu-devel] " Jan Kiszka
@ 2011-02-27 15:07 ` Paolo Bonzini
0 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-27 15:07 UTC (permalink / raw)
To: Jan Kiszka; +Cc: qemu-devel, Aurelien Jarno
On 02/27/2011 10:41 AM, Jan Kiszka wrote:
>> > +#ifdef CONFIG_IOTHREAD
>> > + /* SIGUSR2 used by posix-aio-compat.c */
>> > + sigemptyset(&set);
>> > + sigaddset(&set, SIGUSR2);
>> > + pthread_sigmask(SIG_UNBLOCK,&set, NULL);
>
> Didn't you want to rename the function for the sake of non-signalfd
> blocks like above?
Right.
>> > +
>> > + sigemptyset(&set);
>> > + sigaddset(&set, SIGIO);
>> > + sigaddset(&set, SIGALRM);
>> > + sigaddset(&set, SIG_IPI);
>> > + sigaddset(&set, SIGBUS);
>> > + pthread_sigmask(SIG_BLOCK,&set, NULL);
>> > +#else
>> > + sigemptyset(&set);
>
> This line is shared and can be moved out of the #ifdef.
It's shared but for different purposes (UNBLOCK for iothread,
BLOCK/signalfd for !iothread), so I decided not to hoist it out.
Paolo
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 20/22] provide dummy signal init functions for win32
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (18 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 19/22] move blocking of signals to qemu_signalfd_init Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 21/22] protect qemu_cpu_kick_self for Win32 Paolo Bonzini
` (3 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 143 ++++++++++++++++++++++++++++++++-------------------------------
1 files changed, 73 insertions(+), 70 deletions(-)
diff --git a/cpus.c b/cpus.c
index 8c440f1..3951111 100644
--- a/cpus.c
+++ b/cpus.c
@@ -196,6 +196,16 @@ static void cpu_handle_debug_exception(CPUState *env)
#endif
}
+#ifdef CONFIG_IOTHREAD
+static void cpu_signal(int sig)
+{
+ if (cpu_single_env) {
+ cpu_exit(cpu_single_env);
+ }
+ exit_request = 1;
+}
+#endif
+
#ifdef CONFIG_LINUX
static void sigbus_reraise(void)
{
@@ -390,6 +400,61 @@ static int qemu_signalfd_init(void)
return 0;
}
+static void qemu_kvm_init_cpu_signals(CPUState *env)
+{
+ int r;
+ sigset_t set;
+ struct sigaction sigact;
+
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = dummy_signal;
+ sigaction(SIG_IPI, &sigact, NULL);
+
+#ifdef CONFIG_IOTHREAD
+ pthread_sigmask(SIG_BLOCK, NULL, &set);
+ sigdelset(&set, SIG_IPI);
+ sigdelset(&set, SIGBUS);
+ r = kvm_set_signal_mask(env, &set);
+ if (r) {
+ fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
+ exit(1);
+ }
+#else
+ sigemptyset(&set);
+ sigaddset(&set, SIG_IPI);
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+ pthread_sigmask(SIG_BLOCK, NULL, &set);
+ sigdelset(&set, SIGIO);
+ sigdelset(&set, SIGALRM);
+#endif
+ sigdelset(&set, SIG_IPI);
+ sigdelset(&set, SIGBUS);
+ r = kvm_set_signal_mask(env, &set);
+ if (r) {
+ fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
+ exit(1);
+ }
+}
+
+static void qemu_tcg_init_cpu_signals(void)
+{
+#ifdef CONFIG_IOTHREAD
+ sigset_t set;
+ struct sigaction sigact;
+
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = cpu_signal;
+ sigaction(SIG_IPI, &sigact, NULL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIG_IPI);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+#endif
+}
+
static void qemu_kvm_eat_signals(CPUState *env)
{
struct timespec ts = { 0, 0 };
@@ -470,39 +535,17 @@ static int qemu_signalfd_init(void)
return 0;
}
-#endif /* _WIN32 */
-
-#ifndef CONFIG_IOTHREAD
static void qemu_kvm_init_cpu_signals(CPUState *env)
{
-#ifndef _WIN32
- int r;
- sigset_t set;
- struct sigaction sigact;
-
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = dummy_signal;
- sigaction(SIG_IPI, &sigact, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIG_IPI);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
+ abort();
+}
- pthread_sigmask(SIG_BLOCK, NULL, &set);
- sigdelset(&set, SIG_IPI);
- sigdelset(&set, SIGBUS);
- sigdelset(&set, SIGIO);
- sigdelset(&set, SIGALRM);
- r = kvm_set_signal_mask(env, &set);
- if (r) {
- fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
- exit(1);
- }
-#endif
+static void qemu_tcg_init_cpu_signals(void)
+{
}
+#endif /* _WIN32 */
+#ifndef CONFIG_IOTHREAD
int qemu_init_main_loop(void)
{
int ret;
@@ -536,6 +579,8 @@ void qemu_init_vcpu(void *_env)
exit(1);
}
qemu_kvm_init_cpu_signals(env);
+ } else {
+ qemu_tcg_init_cpu_signals();
}
}
@@ -616,48 +661,6 @@ static QemuCond qemu_system_cond;
static QemuCond qemu_pause_cond;
static QemuCond qemu_work_cond;
-static void cpu_signal(int sig)
-{
- if (cpu_single_env) {
- cpu_exit(cpu_single_env);
- }
- exit_request = 1;
-}
-
-static void qemu_kvm_init_cpu_signals(CPUState *env)
-{
- int r;
- sigset_t set;
- struct sigaction sigact;
-
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = dummy_signal;
- sigaction(SIG_IPI, &sigact, NULL);
-
- pthread_sigmask(SIG_BLOCK, NULL, &set);
- sigdelset(&set, SIG_IPI);
- sigdelset(&set, SIGBUS);
- r = kvm_set_signal_mask(env, &set);
- if (r) {
- fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
- exit(1);
- }
-}
-
-static void qemu_tcg_init_cpu_signals(void)
-{
- sigset_t set;
- struct sigaction sigact;
-
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = cpu_signal;
- sigaction(SIG_IPI, &sigact, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIG_IPI);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-}
-
int qemu_init_main_loop(void)
{
int ret;
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 21/22] protect qemu_cpu_kick_self for Win32
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (19 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 20/22] provide dummy signal init functions for win32 Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 22/22] add Win32 IPI service Paolo Bonzini
` (2 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/cpus.c b/cpus.c
index 3951111..34ef862 100644
--- a/cpus.c
+++ b/cpus.c
@@ -867,12 +867,16 @@ void qemu_cpu_kick(void *_env)
void qemu_cpu_kick_self(void)
{
+#ifndef _WIN32
assert(cpu_single_env);
if (!cpu_single_env->thread_kicked) {
qemu_thread_signal(cpu_single_env->thread, SIG_IPI);
cpu_single_env->thread_kicked = true;
}
+#else
+ abort();
+#endif
}
int qemu_cpu_is_self(void *_env)
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 upstream 22/22] add Win32 IPI service
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (20 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 21/22] protect qemu_cpu_kick_self for Win32 Paolo Bonzini
@ 2011-02-26 15:40 ` Paolo Bonzini
2011-02-26 16:49 ` [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Blue Swirl
2011-02-27 9:47 ` [Qemu-devel] " Jan Kiszka
23 siblings, 0 replies; 31+ messages in thread
From: Paolo Bonzini @ 2011-02-26 15:40 UTC (permalink / raw)
To: qemu-devel; +Cc: jan.kiszka, aurelien
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
cpus.c | 25 ++++++++++++++++++++++---
qemu-thread-posix.c | 9 ---------
qemu-thread-posix.h | 1 -
3 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/cpus.c b/cpus.c
index 34ef862..a2de3c2 100644
--- a/cpus.c
+++ b/cpus.c
@@ -854,13 +854,32 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
return NULL;
}
+static void qemu_cpu_kick_thread(CPUState *env)
+{
+#ifndef _WIN32
+ int err;
+
+ err = pthread_kill(env->thread->thread, SIG_IPI);
+ if (err) {
+ fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
+ exit(1);
+ }
+#else /* _WIN32 */
+ if (!qemu_cpu_is_self(env)) {
+ SuspendThread(env->thread->thread);
+ cpu_signal(0);
+ ResumeThread(env->thread->thread);
+ }
+#endif
+}
+
void qemu_cpu_kick(void *_env)
{
CPUState *env = _env;
qemu_cond_broadcast(env->halt_cond);
if (!env->thread_kicked) {
- qemu_thread_signal(env->thread, SIG_IPI);
+ qemu_cpu_kick_thread(env);
env->thread_kicked = true;
}
}
@@ -871,7 +890,7 @@ void qemu_cpu_kick_self(void)
assert(cpu_single_env);
if (!cpu_single_env->thread_kicked) {
- qemu_thread_signal(cpu_single_env->thread, SIG_IPI);
+ qemu_cpu_kick_thread(cpu_single_env);
cpu_single_env->thread_kicked = true;
}
#else
@@ -893,7 +912,7 @@ void qemu_mutex_lock_iothread(void)
} else {
qemu_mutex_lock(&qemu_fair_mutex);
if (qemu_mutex_trylock(&qemu_global_mutex)) {
- qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
+ qemu_cpu_kick_thread(first_cpu);
qemu_mutex_lock(&qemu_global_mutex);
}
qemu_mutex_unlock(&qemu_fair_mutex);
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index a4c6e25..9cceda7 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -186,15 +186,6 @@ void qemu_thread_create(QemuThread *thread,
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
}
-void qemu_thread_signal(QemuThread *thread, int sig)
-{
- int err;
-
- err = pthread_kill(thread->thread, sig);
- if (err)
- error_exit(err, __func__);
-}
-
void qemu_thread_get_self(QemuThread *thread)
{
thread->thread = pthread_self();
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index 11978db..35e0a8b 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -15,5 +15,4 @@ struct QemuThread {
pthread_t thread;
};
-void qemu_thread_signal(QemuThread *thread, int sig);
#endif
--
1.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (21 preceding siblings ...)
2011-02-26 15:40 ` [Qemu-devel] [PATCH v2 upstream 22/22] add Win32 IPI service Paolo Bonzini
@ 2011-02-26 16:49 ` Blue Swirl
2011-02-27 9:47 ` [Qemu-devel] " Jan Kiszka
23 siblings, 0 replies; 31+ messages in thread
From: Blue Swirl @ 2011-02-26 16:49 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, aurelien
On Sat, Feb 26, 2011 at 5:39 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> After gathering the comments about the two series I sent separately,
> here is the full series for Win32 iothread support, ready to be
> applied to uq/master.
>
> Patches 1 to 5 are generic Win32 improvements, including the qemu-thread
> implementation. Because of complex dependencies, I think it's better
> if this part is also routed through uq/master.
>
> Patches 6 to 8 are generic threading improvements, including using
> PTHREAD_MUTEX_ERRORCHECK as suggested by Jan.
>
> Patches 9 to 17 eliminate polling, replacing condition variable
> timedwait with wait.
>
> Patch 18 removes a redundant condition from the TCG cpu_exec_all
> function.
>
> Patches 19 to 21 add all necessary stubs to make iothread compile
> with Win32, except the IPI calls. These are provided by patch 22.
>
> Tested on Wine and Linux, not on "real" Windows. The series introduces
> a dependency on Windows 2K or newer. I don't think either 95/98/ME
> or Windows NT 3.x are reasonable host systems for QEMU, anyway.
>
> I incorporated all suggestions from Jan, including his renaming patch
> for qemu_*_is_self, and included Aurelien's sh4 tweak to cpu_halted.
All look OK except for a minor structure naming nitpick.
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] Re: [PATCH v2 uq/master 00/22] Win32 iothread support
2011-02-26 15:39 [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Paolo Bonzini
` (22 preceding siblings ...)
2011-02-26 16:49 ` [Qemu-devel] [PATCH v2 uq/master 00/22] Win32 iothread support Blue Swirl
@ 2011-02-27 9:47 ` Jan Kiszka
23 siblings, 0 replies; 31+ messages in thread
From: Jan Kiszka @ 2011-02-27 9:47 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel, aurelien
[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]
On 2011-02-26 16:39, Paolo Bonzini wrote:
> After gathering the comments about the two series I sent separately,
> here is the full series for Win32 iothread support, ready to be
> applied to uq/master.
>
> Patches 1 to 5 are generic Win32 improvements, including the qemu-thread
> implementation. Because of complex dependencies, I think it's better
> if this part is also routed through uq/master.
Agreed. This also ensures that the non-Win32 parts receive autotest
blessing before being applied.
>
> Patches 6 to 8 are generic threading improvements, including using
> PTHREAD_MUTEX_ERRORCHECK as suggested by Jan.
>
> Patches 9 to 17 eliminate polling, replacing condition variable
> timedwait with wait.
>
> Patch 18 removes a redundant condition from the TCG cpu_exec_all
> function.
>
> Patches 19 to 21 add all necessary stubs to make iothread compile
> with Win32, except the IPI calls. These are provided by patch 22.
>
> Tested on Wine and Linux, not on "real" Windows. The series introduces
> a dependency on Windows 2K or newer. I don't think either 95/98/ME
> or Windows NT 3.x are reasonable host systems for QEMU, anyway.
>
> I incorporated all suggestions from Jan, including his renaming patch
> for qemu_*_is_self, and included Aurelien's sh4 tweak to cpu_halted.
>
#ifndef _WIN32
Except for the minor remarks, looks very good to me.
#else
Can't asses.
#endif
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread