* [Qemu-devel] [PATCH v4 upstream 01/21] unlock iothread during WaitForMultipleObjects
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 02/21] implement win32 dynticks timer Paolo Bonzini
` (20 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 02/21] implement win32 dynticks timer
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 01/21] unlock iothread during WaitForMultipleObjects Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 03/21] use win32 timer queues Paolo Bonzini
` (19 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 03/21] use win32 timer queues
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 01/21] unlock iothread during WaitForMultipleObjects Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 02/21] implement win32 dynticks timer Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 04/21] Refactor thread retrieval and check Paolo Bonzini
` (18 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 04/21] Refactor thread retrieval and check
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (2 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 03/21] use win32 timer queues Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 05/21] add win32 qemu-thread implementation Paolo Bonzini
` (17 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel, Jan Kiszka
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 81f08b7..3d78063 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 18e648f..3fe1719 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -290,7 +290,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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 05/21] add win32 qemu-thread implementation
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (3 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 04/21] Refactor thread retrieval and check Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 06/21] include qemu-thread.h early Paolo Bonzini
` (16 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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..2edcb1a
--- /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 QemuThreadData {
+ 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 QemuThreadData data = *(struct QemuThreadData *) 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 QemuThreadData *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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 06/21] include qemu-thread.h early
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (4 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 05/21] add win32 qemu-thread implementation Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 07/21] add assertions on the owner of a QemuMutex Paolo Bonzini
` (15 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 07/21] add assertions on the owner of a QemuMutex
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (5 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 06/21] include qemu-thread.h early Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 08/21] remove CONFIG_THREAD Paolo Bonzini
` (14 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
These are already present in the Win32 implementation, add them to
the pthread wrappers as well. Use PTHREAD_MUTEX_ERRORCHECK for mutex
operations. Later we'll add tracking of the owner for cond_signal/broadcast.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
qemu-thread-posix.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index e307773..8b54cc0 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -28,8 +28,12 @@ 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);
+ 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__);
}
--
1.7.4
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 08/21] remove CONFIG_THREAD
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (6 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 07/21] add assertions on the owner of a QemuMutex Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 09/21] inline cpu_halted into sole caller Paolo Bonzini
` (13 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configure | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 5513d3e..a166de0 100755
--- a/configure
+++ b/configure
@@ -2667,7 +2667,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
@@ -2763,7 +2762,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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 09/21] inline cpu_halted into sole caller
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (7 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 08/21] remove CONFIG_THREAD Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 10/21] always qemu_cpu_kick after unhalting a cpu Paolo Bonzini
` (12 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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 70c3e5a..34eaedc 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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 10/21] always qemu_cpu_kick after unhalting a cpu
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (8 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 09/21] inline cpu_halted into sole caller Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 11/21] exit round-robin vcpu loop if cpu->stopped is true Paolo Bonzini
` (11 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 11/21] exit round-robin vcpu loop if cpu->stopped is true
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (9 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 10/21] always qemu_cpu_kick after unhalting a cpu Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 12/21] always signal pause_cond after stopping a VCPU Paolo Bonzini
` (10 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 12/21] always signal pause_cond after stopping a VCPU
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (10 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 11/21] exit round-robin vcpu loop if cpu->stopped is true Paolo Bonzini
@ 2011-03-12 16:43 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 13/21] do not use timedwait on qemu_halt_cond Paolo Bonzini
` (9 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:43 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 13/21] do not use timedwait on qemu_halt_cond
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (11 preceding siblings ...)
2011-03-12 16:43 ` [Qemu-devel] [PATCH v4 upstream 12/21] always signal pause_cond after stopping a VCPU Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 14/21] do not use timedwait on qemu_system_cond Paolo Bonzini
` (8 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 14/21] do not use timedwait on qemu_system_cond
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (12 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 13/21] do not use timedwait on qemu_halt_cond Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 15/21] do not use timedwait on qemu_pause_cond Paolo Bonzini
` (7 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 15/21] do not use timedwait on qemu_pause_cond
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (13 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 14/21] do not use timedwait on qemu_system_cond Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 16/21] do not use timedwait on qemu_cpu_cond Paolo Bonzini
` (6 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 16/21] do not use timedwait on qemu_cpu_cond
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (14 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 15/21] do not use timedwait on qemu_pause_cond Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 17/21] iothread stops the vcpu thread via IPI Paolo Bonzini
` (5 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 17/21] iothread stops the vcpu thread via IPI
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (15 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 16/21] do not use timedwait on qemu_cpu_cond Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 18/21] merge all signal initialization with qemu_signalfd_init, rename Paolo Bonzini
` (4 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 18/21] merge all signal initialization with qemu_signalfd_init, rename
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (16 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 17/21] iothread stops the vcpu thread via IPI Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 19/21] provide dummy signal init functions for win32 Paolo Bonzini
` (3 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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..2b491a9 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_signal_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_signal_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_signal_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_signal_init();
if (ret) {
return ret;
}
--
1.7.4
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 19/21] provide dummy signal init functions for win32
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (17 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 18/21] merge all signal initialization with qemu_signalfd_init, rename Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 20/21] protect qemu_cpu_kick_self for Win32 Paolo Bonzini
` (2 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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 2b491a9..e0bcb5c 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_signal_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_signal_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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 20/21] protect qemu_cpu_kick_self for Win32
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (18 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 19/21] provide dummy signal init functions for win32 Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 21/21] add Win32 IPI service Paolo Bonzini
2011-03-13 14:45 ` [Qemu-devel] Re: [PATCH v4 upstream 00/21] Win32 iothread support Blue Swirl
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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 e0bcb5c..7559a02 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] 23+ messages in thread
* [Qemu-devel] [PATCH v4 upstream 21/21] add Win32 IPI service
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (19 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 20/21] protect qemu_cpu_kick_self for Win32 Paolo Bonzini
@ 2011-03-12 16:44 ` Paolo Bonzini
2011-03-13 14:45 ` [Qemu-devel] Re: [PATCH v4 upstream 00/21] Win32 iothread support Blue Swirl
21 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2011-03-12 16:44 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
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 7559a02..077729c 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 8b54cc0..87c1a9f 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -171,15 +171,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 7af371c..ee4618e 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -14,5 +14,4 @@ struct QemuThread {
pthread_t thread;
};
-void qemu_thread_signal(QemuThread *thread, int sig);
#endif
--
1.7.4
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] Re: [PATCH v4 upstream 00/21] Win32 iothread support
2011-03-12 16:43 [Qemu-devel] [PATCH v4 upstream 00/21] Win32 iothread support Paolo Bonzini
` (20 preceding siblings ...)
2011-03-12 16:44 ` [Qemu-devel] [PATCH v4 upstream 21/21] add Win32 IPI service Paolo Bonzini
@ 2011-03-13 14:45 ` Blue Swirl
21 siblings, 0 replies; 23+ messages in thread
From: Blue Swirl @ 2011-03-13 14:45 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel
Thanks, applied all.
On Sat, Mar 12, 2011 at 6:43 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Here is again the full series for Win32 iothread support. It should be
> ready now.
>
> Patches 1 to 5 are generic Win32 improvements, including the qemu-thread
> implementation. To simplify the 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 16 eliminate polling, replacing condition variable
> timedwait with wait.
>
> Patch 17 removes a redundant condition from the TCG cpu_exec_all
> function.
>
> Patches 18 to 20 add all necessary stubs to make iothread compile
> with Win32, except the IPI calls. These are provided by patch 21.
>
> 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.
>
> v1->v2
> I incorporated all suggestions from Jan, including his renaming patch
> for qemu_*_is_self; sh4 now doesn't have a special cpu_halted anymore.
>
> v2->v3
> Fixed structure naming, renamed qemu_signalfd_init, dropped ownership
> tracking in QemuMutex for now.
>
> v3->v4
> Consistently using qemu_free.
>
> Jan Kiszka (1):
> Refactor thread retrieval and check
>
> Paolo Bonzini (20):
> unlock iothread during WaitForMultipleObjects
> implement win32 dynticks timer
> use win32 timer queues
> add win32 qemu-thread implementation
> include qemu-thread.h early
> add assertions on the owner of a QemuMutex
> remove CONFIG_THREAD
> inline cpu_halted into sole caller
> always qemu_cpu_kick after unhalting a cpu
> exit round-robin vcpu loop if cpu->stopped is true
> always signal pause_cond after stopping a VCPU
> do not use timedwait on qemu_halt_cond
> do not use timedwait on qemu_system_cond
> do not use timedwait on qemu_pause_cond
> do not use timedwait on qemu_cpu_cond
> iothread stops the vcpu thread via IPI
> merge all signal initialization with qemu_signalfd_init, rename
> provide dummy signal init functions for win32
> protect qemu_cpu_kick_self for Win32
> add Win32 IPI service
>
> Makefile.objs | 4 +-
> configure | 2 -
> cpu-exec.c | 9 +-
> cpus.c | 298 +++++++++++++++++-----------------
> exec.c | 2 +-
> hw/ppc.c | 2 +
> hw/sun4m.c | 10 +-
> hw/sun4u.c | 4 +-
> os-win32.c | 2 +
> qemu-common.h | 2 +-
> qemu-thread.c => qemu-thread-posix.c | 21 +--
> qemu-thread-posix.h | 17 ++
> qemu-thread-win32.c | 260 +++++++++++++++++++++++++++++
> qemu-thread-win32.h | 21 +++
> qemu-thread.h | 31 ++--
> qemu-timer.c | 89 +++++------
> target-alpha/exec.h | 11 --
> target-arm/exec.h | 13 --
> target-cris/exec.h | 11 --
> target-i386/exec.h | 12 --
> target-i386/kvm.c | 4 +-
> 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-s390x/kvm.c | 1 +
> target-sh4/exec.h | 10 --
> target-sparc/exec.h | 10 --
> ui/vnc-jobs-async.c | 2 +-
> 30 files changed, 541 insertions(+), 362 deletions(-)
> rename qemu-thread.c => qemu-thread-posix.c (90%)
> create mode 100644 qemu-thread-posix.h
> create mode 100644 qemu-thread-win32.c
> create mode 100644 qemu-thread-win32.h
>
> --
> 1.7.4
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread