* [Qemu-devel] Re: [patch 01/11] qemu: create helper for event notification
[not found] ` <20090407195442.646407971@localhost.localdomain>
@ 2009-04-16 20:53 ` Anthony Liguori
2009-04-16 20:58 ` Marcelo Tosatti
0 siblings, 1 reply; 30+ messages in thread
From: Anthony Liguori @ 2009-04-16 20:53 UTC (permalink / raw)
To: mtosatti, qemu-devel
mtosatti@redhat.com wrote:
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/vl.c
> ===================================================================
> --- trunk.orig/vl.c
> +++ trunk/vl.c
> @@ -1183,9 +1183,8 @@ void qemu_mod_timer(QEMUTimer *ts, int64
> qemu_rearm_alarm_timer(alarm_timer);
> }
> /* Interrupt execution to force deadline recalculation. */
> - if (use_icount && cpu_single_env) {
> - cpu_exit(cpu_single_env);
> - }
> + if (use_icount)
> + qemu_notify_event();
> }
> }
>
> @@ -1338,8 +1337,6 @@ static void host_alarm_handler(int host_
> qemu_get_clock(vm_clock))) ||
> qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
> qemu_get_clock(rt_clock))) {
> - CPUState *env = next_cpu;
> -
> #ifdef _WIN32
> struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv;
> SetEvent(data->host_alarm);
> @@ -1349,16 +1346,7 @@ static void host_alarm_handler(int host_
> #endif
> alarm_timer->flags |= ALARM_FLAG_EXPIRED;
>
> - if (env) {
> - /* stop the currently executing cpu because a timer occured */
> - cpu_exit(env);
> -#ifdef USE_KQEMU
> - if (env->kqemu_enabled) {
> - kqemu_cpu_interrupt(env);
> - }
> -#endif
> - }
> - event_pending = 1;
> + qemu_notify_event();
> }
> }
>
I always thought next_cpu was used here to cover an explicit race condition.
If you're using TCG, and you get a single after running the loop, but
before assigning cpu_single_env, then you'll set the interrupt exit
request on the old CPU state. You'll eventually exit I guess but you
potentially have to run through multiple VCPUs.
I'd feel more comfortable if we preserved the behavior here that we had
before.
--
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 01/11] qemu: create helper for event notification
2009-04-16 20:53 ` [Qemu-devel] Re: [patch 01/11] qemu: create helper for event notification Anthony Liguori
@ 2009-04-16 20:58 ` Marcelo Tosatti
2009-04-17 17:21 ` Anthony Liguori
0 siblings, 1 reply; 30+ messages in thread
From: Marcelo Tosatti @ 2009-04-16 20:58 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel
On Thu, Apr 16, 2009 at 03:53:04PM -0500, Anthony Liguori wrote:
>> }
>> }
>>
>
> I always thought next_cpu was used here to cover an explicit race condition.
>
> If you're using TCG, and you get a single after running the loop, but
> before assigning cpu_single_env, then you'll set the interrupt exit
> request on the old CPU state. You'll eventually exit I guess but you
> potentially have to run through multiple VCPUs.
>
> I'd feel more comfortable if we preserved the behavior here that we had
> before.
Right. Patch 7 reverts to the old behaviour.
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 02/11] qemu: mutex/thread/cond wrappers
[not found] ` <20090407195442.764405844@localhost.localdomain>
@ 2009-04-17 13:53 ` Anthony Liguori
0 siblings, 0 replies; 30+ messages in thread
From: Anthony Liguori @ 2009-04-17 13:53 UTC (permalink / raw)
To: mtosatti, qemu-devel
mtosatti@redhat.com wrote:
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
>
> Index: trunk/configure
> ===================================================================
> --- trunk.orig/configure
> +++ trunk/configure
> @@ -180,6 +180,7 @@ build_docs="no"
> uname_release=""
> curses="yes"
> aio="yes"
> +io_thread="no"
> nptl="yes"
> mixemu="no"
> bluez="yes"
> @@ -463,6 +464,8 @@ for opt do
> ;;
> --disable-aio) aio="no"
> ;;
> + --enable-io-thread) io_thread="yes"
> + ;;
> --disable-blobs) blobs="no"
> ;;
> --kerneldir=*) kerneldir="$optarg"
> @@ -577,6 +580,7 @@ echo " --enable-uname-release=R Return
> echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
> echo " --disable-vde disable support for vde network"
> echo " --disable-aio disable AIO support"
> +echo " --enable-io-thread enable IO thread"
> echo " --disable-blobs disable installing provided firmware blobs"
> echo " --kerneldir=PATH look for kernel includes in PATH"
> echo ""
> @@ -1204,6 +1208,7 @@ echo "uname -r $uname_release"
> echo "NPTL support $nptl"
> echo "vde support $vde"
> echo "AIO support $aio"
> +echo "IO thread $io_thread"
> echo "Install blobs $blobs"
> echo "KVM support $kvm"
> echo "fdt support $fdt"
> @@ -1500,6 +1505,10 @@ if test "$aio" = "yes" ; then
> echo "#define CONFIG_AIO 1" >> $config_h
> echo "CONFIG_AIO=yes" >> $config_mak
> fi
> +if test "$io_thread" = "yes" ; then
> + echo "CONFIG_IOTHREAD=yes" >> $config_mak
> + echo "#define CONFIG_IOTHREAD 1" >> $config_h
> +fi
> if test "$blobs" = "yes" ; then
> echo "INSTALL_BLOBS=yes" >> $config_mak
> fi
>
You'll need to probe pthread. For instance, 'configure --disable-aio
--enable-io-thread' would succeed but result in a broken build. You
should probably break out the pthread probing from CONFIG_AIO, then make
CONFIG_AIO and CONFIG_IO_THREAD depend on CONFIG_PTHREAD.
Also, we should convert posix-aio-compat.c to qemu_thread but that can
wait...
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 04/11] qemu: introduce main_loop_break
[not found] ` <20090407195443.004166674@localhost.localdomain>
@ 2009-04-17 13:57 ` Anthony Liguori
0 siblings, 0 replies; 30+ messages in thread
From: Anthony Liguori @ 2009-04-17 13:57 UTC (permalink / raw)
To: mtosatti, qemu-devel
mtosatti@redhat.com wrote:
> Use a pipe to signal pending work for the iothread.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/qemu-common.h
> ===================================================================
> --- trunk.orig/qemu-common.h
> +++ trunk/qemu-common.h
> @@ -186,6 +186,8 @@ int cpu_load(QEMUFile *f, void *opaque,
> /* Force QEMU to stop what it's doing and service IO */
> void qemu_service_io(void);
>
> +void main_loop_break(void);
> +
> /* Force QEMU to process pending events */
> void qemu_notify_event(void);
>
> Index: trunk/vl.c
> ===================================================================
> --- trunk.orig/vl.c
> +++ trunk/vl.c
> @@ -276,6 +276,8 @@ static QEMUTimer *nographic_timer;
>
> uint8_t qemu_uuid[16];
>
> +static int io_thread_fd = -1;
> +
> /***********************************************************/
> /* x86 ISA bus support */
>
> @@ -3632,6 +3634,55 @@ void qemu_notify_event(void)
> }
> }
>
> +void main_loop_break(void)
> +{
> + uint64_t value = 1;
> + char buffer[8];
> + size_t offset = 0;
> +
> + if (io_thread_fd == -1)
> + return;
> +
> + memcpy(buffer, &value, sizeof(value));
> +
> + while (offset < 8) {
> + ssize_t len;
> +
> + len = write(io_thread_fd, buffer + offset, 8 - offset);
> + if (len == -1 && errno == EINTR)
> + continue;
> +
> + if (len <= 0)
> + break;
> +
> + offset += len;
> + }
> +
> + if (offset != 8)
> + fprintf(stderr, "failed to notify io thread\n");
> +}
>
I'd like to see a higher level abstraction here. This is trying to be
eventfd compatible which is great, but we should have something like:
qemu_event_increment();
qemu_event_read();
It'll simplify this code a lot. We can also switch some of the other
existing code to use this too later.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 05/11] qemu: separate thread for io
[not found] ` <20090407195443.121795529@localhost.localdomain>
@ 2009-04-17 14:05 ` Anthony Liguori
2009-04-18 20:45 ` Marcelo Tosatti
0 siblings, 1 reply; 30+ messages in thread
From: Anthony Liguori @ 2009-04-17 14:05 UTC (permalink / raw)
To: mtosatti, qemu-devel
mtosatti@redhat.com wrote:
> Introduce a thread to handle host IO events.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/qemu-common.h
> ===================================================================
> --- trunk.orig/qemu-common.h
> +++ trunk/qemu-common.h
> @@ -191,6 +191,10 @@ void main_loop_break(void);
> /* Force QEMU to process pending events */
> void qemu_notify_event(void);
>
> +/* Unblock cpu */
> +void qemu_cpu_kick(void *env);
> +int qemu_cpu_self(void *env);
> +
> typedef struct QEMUIOVector {
> struct iovec *iov;
> int niov;
> Index: trunk/vl.c
> ===================================================================
> --- trunk.orig/vl.c
> +++ trunk/vl.c
> @@ -146,6 +146,7 @@ int main(int argc, char **argv)
> #include "gdbstub.h"
> #include "qemu-timer.h"
> #include "qemu-char.h"
> +#include "qemu-thread.h"
> #include "cache-utils.h"
> #include "block.h"
> #include "dma.h"
> @@ -278,6 +279,13 @@ uint8_t qemu_uuid[16];
>
> static int io_thread_fd = -1;
>
> +QemuMutex qemu_global_mutex;
> +QemuMutex qemu_fair_mutex;
> +
> +QemuThread io_thread;
> +QemuThread cpus_thread;
> +QemuCond halt_cond;
> +
> /***********************************************************/
> /* x86 ISA bus support */
>
> @@ -1347,8 +1355,6 @@ static void host_alarm_handler(int host_
> write(alarm_timer_wfd, &byte, sizeof(byte));
> #endif
> alarm_timer->flags |= ALARM_FLAG_EXPIRED;
> -
> - qemu_notify_event();
> }
> }
>
Isn't this unsafe in TCG? If you have chained TBs in a tight loop,
removing qemu_notify_event() eliminates the cpu_interrupt call which
then means that you'll never break out of that tight TB loop.
> @@ -2957,6 +2963,7 @@ int qemu_set_fd_handler2(int fd,
> ioh->opaque = opaque;
> ioh->deleted = 0;
> }
> + main_loop_break();
> return 0;
> }
>
> @@ -3324,7 +3331,6 @@ static int ram_load(QEMUFile *f, void *o
>
> void qemu_service_io(void)
> {
> - qemu_notify_event();
> }
>
The same comment from above is applicable here. qemu_service_io() is
called from a signal handler. We should
s/qemu_service_io/qemu_notify_event/.
> void main_loop_break(void)
> @@ -3733,6 +3731,105 @@ static void host_main_loop_wait(int *tim
> }
> #endif
>
#ifndef CONFIG_IO_THREAD, doesn't main_loop_break need to do cpu_interrupt?
> +static void qemu_wait_io_event(CPUState *env, int timeout)
> +{
> + if (timeout)
> + while (!tcg_has_work(env))
> + qemu_cond_timedwait(&halt_cond, &qemu_global_mutex, timeout);
>
What's the point of having a timeout?
> +
> +static void qemu_signal_lock(unsigned int msecs)
> +{
> + qemu_mutex_lock(&qemu_fair_mutex);
> +
> + while (qemu_mutex_trylock(&qemu_global_mutex)) {
> + qemu_thread_signal(&cpus_thread, SIGUSR1);
> + if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
> + break;
> + }
> + qemu_mutex_unlock(&qemu_fair_mutex);
> +}
> +
>
Now's a good time to attempt to move a lot of the main loop stuff into a
separate file. We can do it after the IO thread series or you can make
it part of the IO thread series.
--
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 10/11] qemu: make iothread selectable at compile time
[not found] ` <20090407195443.716079176@localhost.localdomain>
@ 2009-04-17 14:07 ` Anthony Liguori
0 siblings, 0 replies; 30+ messages in thread
From: Anthony Liguori @ 2009-04-17 14:07 UTC (permalink / raw)
To: mtosatti, qemu-devel
mtosatti@redhat.com wrote:
> Turned off by default.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
This has to come early in the series. The series can't break bisect on
win32.
--
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 11/11] qemu: basic kvm iothread support
[not found] ` <20090407195443.832269134@localhost.localdomain>
@ 2009-04-17 14:09 ` Anthony Liguori
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
0 siblings, 1 reply; 30+ messages in thread
From: Anthony Liguori @ 2009-04-17 14:09 UTC (permalink / raw)
To: mtosatti, qemu-devel
mtosatti@redhat.com wrote:
> Allow the iothread to run while vcpu is in guest mode.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/kvm-all.c
> ===================================================================
> --- trunk.orig/kvm-all.c
> +++ trunk/kvm-all.c
> @@ -451,6 +451,7 @@ int kvm_cpu_exec(CPUState *env)
>
> do {
> kvm_arch_pre_run(env, run);
> + kvm_pre_run(env);
>
Avoid introduce kvm_pre_run() et al. Eventually, we want to avoid
grabbing the mutex as long as humanly possible so we can support
lockless MMIO/PIO. So let's avoid adding abstractions that will just
make this harder.
--
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] Re: [patch 01/11] qemu: create helper for event notification
2009-04-16 20:58 ` Marcelo Tosatti
@ 2009-04-17 17:21 ` Anthony Liguori
0 siblings, 0 replies; 30+ messages in thread
From: Anthony Liguori @ 2009-04-17 17:21 UTC (permalink / raw)
To: qemu-devel
Marcelo Tosatti wrote:
> On Thu, Apr 16, 2009 at 03:53:04PM -0500, Anthony Liguori wrote:
>
>>> }
>>> }
>>>
>>>
>> I always thought next_cpu was used here to cover an explicit race condition.
>>
>> If you're using TCG, and you get a single after running the loop, but
>> before assigning cpu_single_env, then you'll set the interrupt exit
>> request on the old CPU state. You'll eventually exit I guess but you
>> potentially have to run through multiple VCPUs.
>>
>> I'd feel more comfortable if we preserved the behavior here that we had
>> before.
>>
>
> Right. Patch 7 reverts to the old behaviour.
>
We need to do this series in a way such that we aren't breaking things
as we go along.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 05/11] qemu: separate thread for io
2009-04-17 14:05 ` [Qemu-devel] Re: [patch 05/11] qemu: separate thread for io Anthony Liguori
@ 2009-04-18 20:45 ` Marcelo Tosatti
0 siblings, 0 replies; 30+ messages in thread
From: Marcelo Tosatti @ 2009-04-18 20:45 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel
On Fri, Apr 17, 2009 at 09:05:15AM -0500, Anthony Liguori wrote:
> #ifndef CONFIG_IO_THREAD, doesn't main_loop_break need to do cpu_interrupt?
Yes, also about the previous comments. Will be fixed by bisectable
series as suggested.
>> +static void qemu_wait_io_event(CPUState *env, int timeout)
>> +{
>> + if (timeout)
>> + while (!tcg_has_work(env))
>> + qemu_cond_timedwait(&halt_cond, &qemu_global_mutex, timeout);
>>
>
> What's the point of having a timeout?
I don't think there's much other than honouring the behaviour
of the non-io-thread version. Now, I believe icount breaks
if you don't honour it.
>> +
>> +static void qemu_signal_lock(unsigned int msecs)
>> +{
>> + qemu_mutex_lock(&qemu_fair_mutex);
>> +
>> + while (qemu_mutex_trylock(&qemu_global_mutex)) {
>> + qemu_thread_signal(&cpus_thread, SIGUSR1);
>> + if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
>> + break;
>> + }
>> + qemu_mutex_unlock(&qemu_fair_mutex);
>> +}
>> +
>>
>
> Now's a good time to attempt to move a lot of the main loop stuff into a
> separate file. We can do it after the IO thread series or you can make
> it part of the IO thread series.
Sure.
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4)
2009-04-17 14:09 ` [Qemu-devel] Re: [patch 11/11] qemu: basic kvm iothread support Anthony Liguori
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 01/14] qemu: create helper for event notification mtosatti
` (13 more replies)
0 siblings, 14 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori
Addressing earlier comments.
Anthony, most of the KVM interaction (with global mutex) is missing,
since i'm not exactly sure what you want to do there.
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 01/14] qemu: create helper for event notification
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 02/14] qemu: mutex/thread/cond wrappers and configure tweaks mtosatti
` (12 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: abstract-qemu-event --]
[-- Type: text/plain, Size: 3048 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu/vl.c
===================================================================
--- qemu.orig/vl.c
+++ qemu/vl.c
@@ -1186,9 +1186,8 @@ void qemu_mod_timer(QEMUTimer *ts, int64
qemu_rearm_alarm_timer(alarm_timer);
}
/* Interrupt execution to force deadline recalculation. */
- if (use_icount && cpu_single_env) {
- cpu_exit(cpu_single_env);
- }
+ if (use_icount)
+ qemu_notify_event();
}
}
@@ -1363,6 +1362,7 @@ static void host_alarm_handler(int host_
#endif
}
event_pending = 1;
+ qemu_notify_event();
}
}
@@ -3339,15 +3339,7 @@ static int ram_load(QEMUFile *f, void *o
void qemu_service_io(void)
{
- CPUState *env = cpu_single_env;
- if (env) {
- cpu_exit(env);
-#ifdef USE_KQEMU
- if (env->kqemu_enabled) {
- kqemu_cpu_interrupt(env);
- }
-#endif
- }
+ qemu_notify_event();
}
/***********************************************************/
@@ -3415,15 +3407,12 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
void qemu_bh_schedule(QEMUBH *bh)
{
- CPUState *env = cpu_single_env;
if (bh->scheduled)
return;
bh->scheduled = 1;
bh->idle = 0;
/* stop the currently executing CPU to execute the BH ASAP */
- if (env) {
- cpu_exit(env);
- }
+ qemu_notify_event();
}
void qemu_bh_cancel(QEMUBH *bh)
@@ -3634,22 +3623,32 @@ void qemu_system_reset_request(void)
} else {
reset_requested = 1;
}
- if (cpu_single_env)
- cpu_exit(cpu_single_env);
+ qemu_notify_event();
}
void qemu_system_shutdown_request(void)
{
shutdown_requested = 1;
- if (cpu_single_env)
- cpu_exit(cpu_single_env);
+ qemu_notify_event();
}
void qemu_system_powerdown_request(void)
{
powerdown_requested = 1;
- if (cpu_single_env)
- cpu_exit(cpu_single_env);
+ qemu_notify_event();
+}
+
+void qemu_notify_event(void)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env) {
+ cpu_exit(env);
+#ifdef USE_KQEMU
+ if (env->kqemu_enabled)
+ kqemu_cpu_interrupt(env);
+#endif
+ }
}
#ifdef _WIN32
Index: qemu/qemu-common.h
===================================================================
--- qemu.orig/qemu-common.h
+++ qemu/qemu-common.h
@@ -186,6 +186,9 @@ int cpu_load(QEMUFile *f, void *opaque,
/* Force QEMU to stop what it's doing and service IO */
void qemu_service_io(void);
+/* Force QEMU to process pending events */
+void qemu_notify_event(void);
+
typedef struct QEMUIOVector {
struct iovec *iov;
int niov;
Index: qemu/hw/mac_dbdma.c
===================================================================
--- qemu.orig/hw/mac_dbdma.c
+++ qemu/hw/mac_dbdma.c
@@ -651,9 +651,7 @@ void DBDMA_register_channel(void *dbdma,
void DBDMA_schedule(void)
{
- CPUState *env = cpu_single_env;
- if (env)
- cpu_exit(env);
+ qemu_notify_event();
}
static void
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 02/14] qemu: mutex/thread/cond wrappers and configure tweaks
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 01/14] qemu: create helper for event notification mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 20:33 ` [Qemu-devel] " Anthony Liguori
2009-04-22 19:15 ` [Qemu-devel] [patch 03/14] qemu: per-arch cpu_has_work mtosatti
` (11 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: iothread-mutex --]
[-- Type: text/plain, Size: 9587 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu/Makefile
===================================================================
--- qemu.orig/Makefile
+++ qemu/Makefile
@@ -30,7 +30,8 @@ else
DOCS=
endif
-LIBS+=$(AIOLIBS)
+LIBS+=$(PTHREADLIBS)
+LIBS+=$(CLOCKLIBS)
ifdef CONFIG_SOLARIS
LIBS+=-lsocket -lnsl -lresolv
@@ -170,6 +171,10 @@ ifdef CONFIG_COCOA
OBJS+=cocoa.o
endif
+ifdef CONFIG_IOTHREAD
+OBJS+=qemu-thread.o
+endif
+
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
Index: qemu/Makefile.target
===================================================================
--- qemu.orig/Makefile.target
+++ qemu/Makefile.target
@@ -315,7 +315,8 @@ endif
OBJS= main.o syscall.o strace.o mmap.o signal.o path.o thunk.o \
elfload.o linuxload.o uaccess.o envlist.o
-LIBS+= $(AIOLIBS)
+LIBS+= $(PTHREADLIBS)
+LIBS+= $(CLOCKLIBS)
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
endif
@@ -683,7 +684,8 @@ ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
endif
-LIBS+=$(AIOLIBS)
+LIBS+=$(PTHREADLIBS)
+LIBS+=$(CLOCKLIBS)
# specific flags are needed for non soft mmu emulator
ifdef CONFIG_STATIC
LDFLAGS+=-static
Index: qemu/configure
===================================================================
--- qemu.orig/configure
+++ qemu/configure
@@ -181,7 +181,9 @@ bsd_user="no"
build_docs="no"
uname_release=""
curses="yes"
+pthread="yes"
aio="yes"
+io_thread="no"
nptl="yes"
mixemu="no"
bluez="yes"
@@ -476,8 +478,12 @@ for opt do
;;
--enable-mixemu) mixemu="yes"
;;
+ --disable-pthread) pthread="no"
+ ;;
--disable-aio) aio="no"
;;
+ --enable-io-thread) io_thread="yes"
+ ;;
--disable-blobs) blobs="no"
;;
--kerneldir=*) kerneldir="$optarg"
@@ -607,7 +613,9 @@ echo " --oss-lib path to
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
echo " --disable-vde disable support for vde network"
+echo " --disable-pthread disable pthread support"
echo " --disable-aio disable AIO support"
+echo " --enable-io-thread enable IO thread"
echo " --disable-blobs disable installing provided firmware blobs"
echo " --kerneldir=PATH look for kernel includes in PATH"
echo ""
@@ -1103,21 +1111,26 @@ EOF
fi
##########################################
-# AIO probe
-AIOLIBS=""
+# pthread probe
+PTHREADLIBS=""
-if test "$aio" = "yes" ; then
- aio=no
- cat > $TMPC << EOF
+if test "$pthread" = yes; then
+ pthread=no
+cat > $TMPC << EOF
#include <pthread.h>
int main(void) { pthread_mutex_t lock; return 0; }
EOF
- if $cc $ARCH_CFLAGS -o $TMPE $AIOLIBS $TMPC 2> /dev/null ; then
- aio=yes
- AIOLIBS="-lpthread"
+ if $cc $ARCH_CFLAGS -o $TMPE $PTHREADLIBS $TMPC 2> /dev/null ; then
+ pthread=yes
+ PTHREADLIBS="-lpthread"
fi
fi
+if test "$pthread" = no; then
+ aio=no
+ io_thread=no
+fi
+
##########################################
# iovec probe
cat > $TMPC <<EOF
@@ -1211,6 +1224,7 @@ fi
##########################################
# Do we need librt
+CLOCKLIBS=""
cat > $TMPC <<EOF
#include <signal.h>
#include <time.h>
@@ -1225,8 +1239,7 @@ elif $cc $ARCH_CFLAGS -o $TMPE $TMPC -lr
fi
if test "$rt" = "yes" ; then
- # Hack, we should have a general purpose LIBS for this sort of thing
- AIOLIBS="$AIOLIBS -lrt"
+ CLOCKLIBS="-lrt"
fi
if test "$mingw32" = "yes" ; then
@@ -1302,7 +1315,8 @@ echo "Documentation $build_docs"
echo "uname -r $uname_release"
echo "NPTL support $nptl"
echo "vde support $vde"
-echo "AIO support $aio"
+echo "IO support $aio"
+echo "IO thread $io_thread"
echo "Install blobs $blobs"
echo "KVM support $kvm"
echo "fdt support $fdt"
@@ -1352,7 +1366,8 @@ echo "ARCH_LDFLAGS=$ARCH_LDFLAGS" >> $co
echo "CFLAGS=$CFLAGS" >> $config_mak
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
-echo "AIOLIBS=$AIOLIBS" >> $config_mak
+echo "PTHREADLIBS=$PTHREADLIBS" >> $config_mak
+echo "CLOCKLIBS=$CLOCKLIBS" >> $config_mak
case "$cpu" in
i386)
echo "ARCH=i386" >> $config_mak
@@ -1613,6 +1628,10 @@ if test "$aio" = "yes" ; then
echo "#define CONFIG_AIO 1" >> $config_h
echo "CONFIG_AIO=yes" >> $config_mak
fi
+if test "$io_thread" = "yes" ; then
+ echo "CONFIG_IOTHREAD=yes" >> $config_mak
+ echo "#define CONFIG_IOTHREAD 1" >> $config_h
+fi
if test "$blobs" = "yes" ; then
echo "INSTALL_BLOBS=yes" >> $config_mak
fi
Index: qemu/qemu-thread.c
===================================================================
--- /dev/null
+++ qemu/qemu-thread.c
@@ -0,0 +1,163 @@
+/*
+ * Wrappers around mutex/cond/thread functions
+ *
+ * Copyright Red Hat, Inc. 2009
+ *
+ * Author:
+ * Marcelo Tosatti <mtosatti@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 <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+#include "qemu-thread.h"
+
+static void error_exit(int err, const char *msg)
+{
+ fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
+ exit(1);
+}
+
+void qemu_mutex_init(QemuMutex *mutex)
+{
+ int err;
+
+ err = pthread_mutex_init(&mutex->lock, NULL);
+ if (err)
+ error_exit(err, __func__);
+}
+
+void qemu_mutex_lock(QemuMutex *mutex)
+{
+ int err;
+
+ err = pthread_mutex_lock(&mutex->lock);
+ if (err)
+ error_exit(err, __func__);
+}
+
+int qemu_mutex_trylock(QemuMutex *mutex)
+{
+ return pthread_mutex_trylock(&mutex->lock);
+}
+
+static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
+{
+ ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
+ ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
+ if (ts->tv_nsec >= 1000000000) {
+ ts->tv_nsec -= 1000000000;
+ ts->tv_sec++;
+ }
+}
+
+int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
+{
+ int err;
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ timespec_add_ms(&ts, msecs);
+
+ err = pthread_mutex_timedlock(&mutex->lock, &ts);
+ if (err && err != ETIMEDOUT)
+ error_exit(err, __func__);
+ return err;
+}
+
+void qemu_mutex_unlock(QemuMutex *mutex)
+{
+ int err;
+
+ err = pthread_mutex_unlock(&mutex->lock);
+ if (err)
+ error_exit(err, __func__);
+}
+
+void qemu_cond_init(QemuCond *cond)
+{
+ int err;
+
+ err = pthread_cond_init(&cond->cond, NULL);
+ if (err)
+ error_exit(err, __func__);
+}
+
+void qemu_cond_signal(QemuCond *cond)
+{
+ int err;
+
+ err = pthread_cond_signal(&cond->cond);
+ if (err)
+ error_exit(err, __func__);
+}
+
+void qemu_cond_broadcast(QemuCond *cond)
+{
+ int err;
+
+ err = pthread_cond_broadcast(&cond->cond);
+ if (err)
+ error_exit(err, __func__);
+}
+
+void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
+{
+ int err;
+
+ err = pthread_cond_wait(&cond->cond, &mutex->lock);
+ if (err)
+ error_exit(err, __func__);
+}
+
+int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
+{
+ struct timespec ts;
+ int err;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ timespec_add_ms(&ts, msecs);
+
+ err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
+ if (err && err != ETIMEDOUT)
+ error_exit(err, __func__);
+ return err;
+}
+
+void qemu_thread_create(QemuThread *thread,
+ void *(*start_routine)(void*),
+ void *arg)
+{
+ int err;
+
+ err = pthread_create(&thread->thread, NULL, start_routine, arg);
+ if (err)
+ error_exit(err, __func__);
+}
+
+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_self(QemuThread *thread)
+{
+ thread->thread = pthread_self();
+}
+
+int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
+{
+ return (thread1->thread == thread2->thread);
+}
+
Index: qemu/qemu-thread.h
===================================================================
--- /dev/null
+++ qemu/qemu-thread.h
@@ -0,0 +1,40 @@
+#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;
+
+void qemu_mutex_init(QemuMutex *mutex);
+void qemu_mutex_lock(QemuMutex *mutex);
+int qemu_mutex_trylock(QemuMutex *mutex);
+int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs);
+void qemu_mutex_unlock(QemuMutex *mutex);
+
+void qemu_cond_init(QemuCond *cond);
+void qemu_cond_signal(QemuCond *cond);
+void qemu_cond_broadcast(QemuCond *cond);
+void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
+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_self(QemuThread *thread);
+int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2);
+#endif
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 03/14] qemu: per-arch cpu_has_work
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 01/14] qemu: create helper for event notification mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 02/14] qemu: mutex/thread/cond wrappers and configure tweaks mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 04/14] qemu: explictly rearm alarm timer on main_loop_wait mtosatti
` (10 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: qemu-arch-has-work --]
[-- Type: text/plain, Size: 6889 bytes --]
Blue Swirl: fix Sparc32 breakage
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu/target-alpha/exec.h
===================================================================
--- qemu.orig/target-alpha/exec.h
+++ qemu/target-alpha/exec.h
@@ -48,10 +48,15 @@ static always_inline void regs_to_env(vo
{
}
+static always_inline int cpu_has_work(CPUState *env)
+{
+ return (env->interrupt_request & CPU_INTERRUPT_HARD);
+}
+
static always_inline int cpu_halted(CPUState *env) {
if (!env->halted)
return 0;
- if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
Index: qemu/target-i386/exec.h
===================================================================
--- qemu.orig/target-i386/exec.h
+++ qemu/target-i386/exec.h
@@ -338,14 +338,23 @@ static inline void regs_to_env(void)
#endif
}
+static inline int cpu_has_work(CPUState *env)
+{
+ int work;
+
+ work = (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->eflags & IF_MASK);
+ work |= env->interrupt_request & CPU_INTERRUPT_NMI;
+
+ return work;
+}
+
static inline int cpu_halted(CPUState *env) {
/* handle exit of HALTED state */
if (!env->halted)
return 0;
/* disable halt condition */
- if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK)) ||
- (env->interrupt_request & CPU_INTERRUPT_NMI)) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
Index: qemu/cpu-all.h
===================================================================
--- qemu.orig/cpu-all.h
+++ qemu/cpu-all.h
@@ -775,6 +775,8 @@ void cpu_reset_interrupt(CPUState *env,
void cpu_exit(CPUState *s);
+int qemu_cpu_has_work(CPUState *env);
+
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ 0x01
#define BP_MEM_WRITE 0x02
Index: qemu/cpu-exec.c
===================================================================
--- qemu.orig/cpu-exec.c
+++ qemu/cpu-exec.c
@@ -50,6 +50,11 @@ int tb_invalidated_flag;
//#define DEBUG_EXEC
//#define DEBUG_SIGNAL
+int qemu_cpu_has_work(CPUState *env)
+{
+ return cpu_has_work(env);
+}
+
void cpu_loop_exit(void)
{
/* NOTE: the register at this point must be saved by hand because
Index: qemu/target-arm/exec.h
===================================================================
--- qemu.orig/target-arm/exec.h
+++ qemu/target-arm/exec.h
@@ -37,14 +37,19 @@ static inline void regs_to_env(void)
{
}
+static inline int cpu_has_work(CPUState *env)
+{
+ return (env->interrupt_request &
+ (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 (env->interrupt_request &
- (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
Index: qemu/target-cris/exec.h
===================================================================
--- qemu.orig/target-cris/exec.h
+++ qemu/target-cris/exec.h
@@ -40,6 +40,11 @@ static inline void regs_to_env(void)
void cpu_cris_flush_flags(CPUCRISState *env, int cc_op);
void helper_movec(CPUCRISState *env, int reg, uint32_t val);
+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;
Index: qemu/target-m68k/exec.h
===================================================================
--- qemu.orig/target-m68k/exec.h
+++ qemu/target-m68k/exec.h
@@ -41,10 +41,15 @@ static inline void regs_to_env(void)
#include "softmmu_exec.h"
#endif
+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 (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
Index: qemu/target-mips/exec.h
===================================================================
--- qemu.orig/target-mips/exec.h
+++ qemu/target-mips/exec.h
@@ -33,12 +33,18 @@ static inline void regs_to_env(void)
{
}
+static inline int cpu_has_work(CPUState *env)
+{
+ return (env->interrupt_request &
+ (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER));
+}
+
+
static inline int cpu_halted(CPUState *env)
{
if (!env->halted)
return 0;
- if (env->interrupt_request &
- (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
Index: qemu/target-ppc/exec.h
===================================================================
--- qemu.orig/target-ppc/exec.h
+++ qemu/target-ppc/exec.h
@@ -44,11 +44,17 @@ static always_inline void regs_to_env (v
{
}
+static always_inline int cpu_has_work(CPUState *env)
+{
+ return (msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD));
+}
+
+
static always_inline int cpu_halted (CPUState *env)
{
if (!env->halted)
return 0;
- if (msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD)) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
Index: qemu/target-sh4/exec.h
===================================================================
--- qemu.orig/target-sh4/exec.h
+++ qemu/target-sh4/exec.h
@@ -28,10 +28,15 @@ register struct CPUSH4State *env asm(ARE
#include "cpu.h"
#include "exec-all.h"
+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 (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ if (cpu_has_work(env)) {
env->halted = 0;
env->intr_at_halt = 1;
return 0;
Index: qemu/target-sparc/exec.h
===================================================================
--- qemu.orig/target-sparc/exec.h
+++ qemu/target-sparc/exec.h
@@ -24,10 +24,17 @@ static inline void regs_to_env(void)
/* op_helper.c */
void do_interrupt(CPUState *env);
+static inline int cpu_has_work(CPUState *env1)
+{
+ return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env1->psret != 0);
+}
+
+
static inline int cpu_halted(CPUState *env1) {
if (!env1->halted)
return 0;
- if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && (env1->psret != 0)) {
+ if (cpu_has_work(env1)) {
env1->halted = 0;
return 0;
}
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 04/14] qemu: explictly rearm alarm timer on main_loop_wait
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (2 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 03/14] qemu: per-arch cpu_has_work mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 05/14] qemu: factor out special event notification mtosatti
` (9 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: move-dyntick-rearm-to-main-loop --]
[-- Type: text/plain, Size: 2363 bytes --]
- lift notification code out of try_to_rearm_timer/host_alarm_handler
- probably going to remove alarm timers via signals sometime soon anyway
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -1346,9 +1346,6 @@ static void host_alarm_handler(int host_
#ifdef _WIN32
struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv;
SetEvent(data->host_alarm);
-#else
- static const char byte = 0;
- write(alarm_timer_wfd, &byte, sizeof(byte));
#endif
alarm_timer->flags |= ALARM_FLAG_EXPIRED;
@@ -1638,27 +1635,13 @@ static void unix_stop_timer(struct qemu_
#endif /* !defined(_WIN32) */
-static void try_to_rearm_timer(void *opaque)
-{
- struct qemu_alarm_timer *t = opaque;
-#ifndef _WIN32
- ssize_t len;
- /* Drain the notify pipe */
- do {
- char buffer[512];
- len = read(alarm_timer_rfd, buffer, sizeof(buffer));
- } while ((len == -1 && errno == EINTR) || len > 0);
-#endif
+#ifdef _WIN32
- if (t->flags & ALARM_FLAG_EXPIRED) {
- alarm_timer->flags &= ~ALARM_FLAG_EXPIRED;
- qemu_rearm_alarm_timer(alarm_timer);
- }
+static void dummy_event_handler(void *opaque)
+{
}
-#ifdef _WIN32
-
static int win32_start_timer(struct qemu_alarm_timer *t)
{
TIMECAPS tc;
@@ -1699,7 +1682,7 @@ static int win32_start_timer(struct qemu
return -1;
}
- qemu_add_wait_object(data->host_alarm, try_to_rearm_timer, t);
+ qemu_add_wait_object(data->host_alarm, dummy_event_handler, t);
return 0;
}
@@ -1782,11 +1765,6 @@ static int init_timer_alarm(void)
goto fail;
}
-#ifndef _WIN32
- qemu_set_fd_handler2(alarm_timer_rfd, NULL,
- try_to_rearm_timer, NULL, t);
-#endif
-
alarm_timer = t;
return 0;
@@ -3778,6 +3756,12 @@ void main_loop_wait(int timeout)
}
#endif
+ /* rearm timer, if not periodic */
+ if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
+ alarm_timer->flags &= ~ALARM_FLAG_EXPIRED;
+ qemu_rearm_alarm_timer(alarm_timer);
+ }
+
/* vm time timers */
if (vm_running && likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 05/14] qemu: factor out special event notification
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (3 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 04/14] qemu: explictly rearm alarm timer on main_loop_wait mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 20:58 ` Anthony Liguori
2009-04-22 19:15 ` [Qemu-devel] [patch 06/14] qemu: refactor main_loop mtosatti
` (8 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: move-to-generic-m-l-b --]
[-- Type: text/plain, Size: 4180 bytes --]
Special events that have no particular event descriptor (either fd for UNIX
or HANDLE for Windows) associated with make use of an artificial one.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -921,15 +921,11 @@ static void qemu_rearm_alarm_timer(struc
#define MIN_TIMER_REARM_US 250
static struct qemu_alarm_timer *alarm_timer;
-#ifndef _WIN32
-static int alarm_timer_rfd, alarm_timer_wfd;
-#endif
#ifdef _WIN32
struct qemu_alarm_win32 {
MMRESULT timerId;
- HANDLE host_alarm;
unsigned int period;
} alarm_win32_data = {0, NULL, -1};
@@ -1343,10 +1339,6 @@ static void host_alarm_handler(int host_
qemu_get_clock(rt_clock))) {
CPUState *env = next_cpu;
-#ifdef _WIN32
- struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv;
- SetEvent(data->host_alarm);
-#endif
alarm_timer->flags |= ALARM_FLAG_EXPIRED;
if (env) {
@@ -1638,9 +1630,6 @@ static void unix_stop_timer(struct qemu_
#ifdef _WIN32
-static void dummy_event_handler(void *opaque)
-{
-}
static int win32_start_timer(struct qemu_alarm_timer *t)
{
@@ -1648,12 +1637,6 @@ static int win32_start_timer(struct qemu
struct qemu_alarm_win32 *data = t->priv;
UINT flags;
- data->host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!data->host_alarm) {
- perror("Failed CreateEvent");
- return -1;
- }
-
memset(&tc, 0, sizeof(tc));
timeGetDevCaps(&tc, sizeof(tc));
@@ -1682,8 +1665,6 @@ static int win32_start_timer(struct qemu
return -1;
}
- qemu_add_wait_object(data->host_alarm, dummy_event_handler, t);
-
return 0;
}
@@ -1733,25 +1714,6 @@ static int init_timer_alarm(void)
struct qemu_alarm_timer *t = NULL;
int i, err = -1;
-#ifndef _WIN32
- int fds[2];
-
- err = pipe(fds);
- if (err == -1)
- return -errno;
-
- err = fcntl_setfl(fds[0], O_NONBLOCK);
- if (err < 0)
- goto fail;
-
- err = fcntl_setfl(fds[1], O_NONBLOCK);
- if (err < 0)
- goto fail;
-
- alarm_timer_rfd = fds[0];
- alarm_timer_wfd = fds[1];
-#endif
-
for (i = 0; alarm_timers[i].name; i++) {
t = &alarm_timers[i];
@@ -1770,10 +1732,6 @@ static int init_timer_alarm(void)
return 0;
fail:
-#ifndef _WIN32
- close(fds[0]);
- close(fds[1]);
-#endif
return err;
}
@@ -3629,6 +3587,82 @@ void qemu_notify_event(void)
}
}
+#ifdef CONFIG_IOTHREAD
+#ifndef _WIN32
+static int io_thread_fd = -1;
+
+static void qemu_event_increment(void)
+{
+ static const char byte = 0;
+
+ if (io_thread_fd == -1)
+ return;
+
+ write(io_thread_fd, &byte, sizeof(byte));
+}
+
+static void qemu_event_read(void *opaque)
+{
+ int fd = (unsigned long)opaque;
+ ssize_t len;
+
+ /* Drain the notify pipe */
+ do {
+ char buffer[512];
+ len = read(fd, buffer, sizeof(buffer));
+ } while ((len == -1 && errno == EINTR) || len > 0);
+}
+
+static int qemu_event_init(void)
+{
+ int err;
+ int fds[2];
+
+ err = pipe(fds);
+ if (err == -1)
+ return -errno;
+
+ err = fcntl_setfl(fds[0], O_NONBLOCK);
+ if (err < 0)
+ goto fail;
+
+ err = fcntl_setfl(fds[1], O_NONBLOCK);
+ if (err < 0)
+ goto fail;
+
+ qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
+ (void *)(unsigned long)fds[0]);
+
+ io_thread_fd = fds[1];
+fail:
+ close(fds[0]);
+ close(fds[1]);
+ return err;
+}
+#else
+HANDLE qemu_event_handle;
+
+static void dummy_event_handler(void *opaque)
+{
+}
+
+static int qemu_event_init(void)
+{
+ qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!qemu_event_handle) {
+ perror("Failed CreateEvent");
+ return -1;
+ }
+ qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
+}
+
+static void qemu_event_increment(void)
+{
+ SetEvent(qemu_event_handle);
+}
+#endif
+#endif
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 06/14] qemu: refactor main_loop
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (4 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 05/14] qemu: factor out special event notification mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 07/14] qemu: introduce qemu_init_vcpu mtosatti
` (7 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: refactor-main-loop --]
[-- Type: text/plain, Size: 10732 bytes --]
Break main loop into 3 main functions.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -266,7 +266,7 @@ struct drive_opt drives_opt[MAX_DRIVES];
static CPUState *cur_cpu;
static CPUState *next_cpu;
-static int event_pending = 1;
+static int timer_alarm_pending = 1;
/* Conversion factor from emulated instructions to virtual clock ticks. */
static int icount_time_shift;
/* Arbitrarily pick 1MIPS as the minimum allowable speed. */
@@ -1350,7 +1350,7 @@ static void host_alarm_handler(int host_
}
#endif
}
- event_pending = 1;
+ timer_alarm_pending = 1;
qemu_notify_event();
}
}
@@ -3811,153 +3811,175 @@ void main_loop_wait(int timeout)
}
-static int main_loop(void)
+static int qemu_cpu_exec(CPUState *env)
{
- int ret, timeout;
+ int ret;
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
- CPUState *env;
- cur_cpu = first_cpu;
- next_cpu = cur_cpu->next_cpu ?: first_cpu;
- for(;;) {
- if (vm_running) {
-
- for(;;) {
- /* get next cpu */
- env = next_cpu;
#ifdef CONFIG_PROFILER
- ti = profile_getclock();
+ ti = profile_getclock();
#endif
- if (use_icount) {
- int64_t count;
- int decr;
- qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
- env->icount_decr.u16.low = 0;
- env->icount_extra = 0;
- count = qemu_next_deadline();
- count = (count + (1 << icount_time_shift) - 1)
- >> icount_time_shift;
- qemu_icount += count;
- decr = (count > 0xffff) ? 0xffff : count;
- count -= decr;
- env->icount_decr.u16.low = decr;
- env->icount_extra = count;
- }
- ret = cpu_exec(env);
+ if (use_icount) {
+ int64_t count;
+ int decr;
+ qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
+ env->icount_decr.u16.low = 0;
+ env->icount_extra = 0;
+ count = qemu_next_deadline();
+ count = (count + (1 << icount_time_shift) - 1)
+ >> icount_time_shift;
+ qemu_icount += count;
+ decr = (count > 0xffff) ? 0xffff : count;
+ count -= decr;
+ env->icount_decr.u16.low = decr;
+ env->icount_extra = count;
+ }
+ ret = cpu_exec(env);
#ifdef CONFIG_PROFILER
- qemu_time += profile_getclock() - ti;
+ qemu_time += profile_getclock() - ti;
#endif
- if (use_icount) {
- /* Fold pending instructions back into the
- instruction counter, and clear the interrupt flag. */
- qemu_icount -= (env->icount_decr.u16.low
- + env->icount_extra);
- env->icount_decr.u32 = 0;
- env->icount_extra = 0;
- }
- next_cpu = env->next_cpu ?: first_cpu;
- if (event_pending && likely(ret != EXCP_DEBUG)) {
- ret = EXCP_INTERRUPT;
- event_pending = 0;
- break;
- }
- if (ret == EXCP_HLT) {
- /* Give the next CPU a chance to run. */
- cur_cpu = env;
- continue;
- }
- if (ret != EXCP_HALTED)
+ if (use_icount) {
+ /* Fold pending instructions back into the
+ instruction counter, and clear the interrupt flag. */
+ qemu_icount -= (env->icount_decr.u16.low
+ + env->icount_extra);
+ env->icount_decr.u32 = 0;
+ env->icount_extra = 0;
+ }
+ return ret;
+}
+
+static int cpu_has_work(CPUState *env)
+{
+ if (!env->halted)
+ return 1;
+ if (qemu_cpu_has_work(env))
+ return 1;
+ return 0;
+}
+
+static int tcg_has_work(void)
+{
+ CPUState *env;
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu)
+ if (cpu_has_work(env))
+ return 1;
+ return 0;
+}
+
+static int qemu_calculate_timeout(void)
+{
+ int timeout;
+
+ if (!vm_running)
+ timeout = 5000;
+ else if (tcg_has_work())
+ timeout = 0;
+ else if (!use_icount)
+ timeout = 5000;
+ else {
+ /* XXX: use timeout computed from timers */
+ int64_t add;
+ int64_t delta;
+ /* Advance virtual time to the next event. */
+ if (use_icount == 1) {
+ /* When not using an adaptive execution frequency
+ we tend to get badly out of sync with real time,
+ so just delay for a reasonable amount of time. */
+ delta = 0;
+ } else {
+ delta = cpu_get_icount() - cpu_get_clock();
+ }
+ if (delta > 0) {
+ /* If virtual time is ahead of real time then just
+ wait for IO. */
+ timeout = (delta / 1000000) + 1;
+ } else {
+ /* Wait for either IO to occur or the next
+ timer event. */
+ add = qemu_next_deadline();
+ /* We advance the timer before checking for IO.
+ Limit the amount we advance so that early IO
+ activity won't get the guest too far ahead. */
+ if (add > 10000000)
+ add = 10000000;
+ delta += add;
+ add = (add + (1 << icount_time_shift) - 1)
+ >> icount_time_shift;
+ qemu_icount += add;
+ timeout = delta / 1000000;
+ if (timeout < 0)
+ timeout = 0;
+ }
+ }
+
+ return timeout;
+}
+
+static int vm_can_run(void)
+{
+ if (powerdown_requested)
+ return 0;
+ if (reset_requested)
+ return 0;
+ if (shutdown_requested)
+ return 0;
+ return 1;
+}
+
+static void main_loop(void)
+{
+ int ret = 0;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
+
+ for (;;) {
+ do {
+ if (next_cpu == NULL)
+ next_cpu = first_cpu;
+ for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
+ CPUState *env = cur_cpu = next_cpu;
+
+ if (!vm_running)
break;
- /* all CPUs are halted ? */
- if (env == cur_cpu)
+ if (timer_alarm_pending) {
+ timer_alarm_pending = 0;
break;
- }
- cur_cpu = env;
-
- if (shutdown_requested) {
- ret = EXCP_INTERRUPT;
- if (no_shutdown) {
- vm_stop(0);
- no_shutdown = 0;
}
- else
+ ret = qemu_cpu_exec(env);
+ if (ret == EXCP_DEBUG) {
+ gdb_set_stop_cpu(env);
break;
- }
- if (reset_requested) {
- reset_requested = 0;
- qemu_system_reset();
- ret = EXCP_INTERRUPT;
- }
- if (powerdown_requested) {
- powerdown_requested = 0;
- qemu_system_powerdown();
- ret = EXCP_INTERRUPT;
- }
- if (unlikely(ret == EXCP_DEBUG)) {
- gdb_set_stop_cpu(cur_cpu);
- vm_stop(EXCP_DEBUG);
- }
- /* If all cpus are halted then wait until the next IRQ */
- /* XXX: use timeout computed from timers */
- if (ret == EXCP_HALTED) {
- if (use_icount) {
- int64_t add;
- int64_t delta;
- /* Advance virtual time to the next event. */
- if (use_icount == 1) {
- /* When not using an adaptive execution frequency
- we tend to get badly out of sync with real time,
- so just delay for a reasonable amount of time. */
- delta = 0;
- } else {
- delta = cpu_get_icount() - cpu_get_clock();
- }
- if (delta > 0) {
- /* If virtual time is ahead of real time then just
- wait for IO. */
- timeout = (delta / 1000000) + 1;
- } else {
- /* Wait for either IO to occur or the next
- timer event. */
- add = qemu_next_deadline();
- /* We advance the timer before checking for IO.
- Limit the amount we advance so that early IO
- activity won't get the guest too far ahead. */
- if (add > 10000000)
- add = 10000000;
- delta += add;
- add = (add + (1 << icount_time_shift) - 1)
- >> icount_time_shift;
- qemu_icount += add;
- timeout = delta / 1000000;
- if (timeout < 0)
- timeout = 0;
- }
- } else {
- timeout = 5000;
}
- } else {
- timeout = 0;
}
- } else {
- if (shutdown_requested) {
- ret = EXCP_INTERRUPT;
- break;
- }
- timeout = 5000;
- }
#ifdef CONFIG_PROFILER
- ti = profile_getclock();
+ ti = profile_getclock();
#endif
- main_loop_wait(timeout);
+ main_loop_wait(qemu_calculate_timeout());
#ifdef CONFIG_PROFILER
- dev_time += profile_getclock() - ti;
+ dev_time += profile_getclock() - ti;
#endif
+ } while (ret != EXCP_DEBUG && vm_can_run());
+
+ if (ret == EXCP_DEBUG)
+ vm_stop(EXCP_DEBUG);
+
+ if (qemu_shutdown_requested()) {
+ if (no_shutdown) {
+ vm_stop(0);
+ no_shutdown = 0;
+ } else
+ break;
+ }
+ if (qemu_reset_requested())
+ qemu_system_reset();
+ if (qemu_powerdown_requested())
+ qemu_system_powerdown();
}
- cpu_disable_ticks();
- return ret;
}
static void version(void)
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 07/14] qemu: introduce qemu_init_vcpu
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (5 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 06/14] qemu: refactor main_loop mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 08/14] qemu: introduce qemu_cpu_kick mtosatti
` (6 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: qemu-vcpu-init --]
[-- Type: text/plain, Size: 4198 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/qemu-common.h
===================================================================
--- trunk.orig/qemu-common.h
+++ trunk/qemu-common.h
@@ -189,6 +189,12 @@ void qemu_service_io(void);
/* Force QEMU to process pending events */
void qemu_notify_event(void);
+#ifdef CONFIG_USER_ONLY
+#define qemu_init_vcpu(env) do { } while (0)
+#else
+void qemu_init_vcpu(void *env);
+#endif
+
typedef struct QEMUIOVector {
struct iovec *iov;
int niov;
Index: trunk/target-alpha/translate.c
===================================================================
--- trunk.orig/target-alpha/translate.c
+++ trunk/target-alpha/translate.c
@@ -2505,6 +2505,7 @@ CPUAlphaState * cpu_alpha_init (const ch
env->ipr[IPR_SISR] = 0;
env->ipr[IPR_VIRBND] = -1ULL;
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/target-arm/helper.c
===================================================================
--- trunk.orig/target-arm/helper.c
+++ trunk/target-arm/helper.c
@@ -267,6 +267,7 @@ CPUARMState *cpu_arm_init(const char *cp
gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
19, "arm-vfp.xml", 0);
}
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/target-cris/translate.c
===================================================================
--- trunk.orig/target-cris/translate.c
+++ trunk/target-cris/translate.c
@@ -3405,6 +3405,7 @@ CPUCRISState *cpu_cris_init (const char
cpu_exec_init(env);
cpu_reset(env);
+ qemu_init_vcpu(env);
if (tcg_initialized)
return env;
Index: trunk/target-i386/helper.c
===================================================================
--- trunk.orig/target-i386/helper.c
+++ trunk/target-i386/helper.c
@@ -1668,7 +1668,8 @@ CPUX86State *cpu_x86_init(const char *cp
#ifdef USE_KQEMU
kqemu_init(env);
#endif
- if (kvm_enabled())
- kvm_init_vcpu(env);
+
+ qemu_init_vcpu(env);
+
return env;
}
Index: trunk/target-m68k/helper.c
===================================================================
--- trunk.orig/target-m68k/helper.c
+++ trunk/target-m68k/helper.c
@@ -180,6 +180,7 @@ CPUM68KState *cpu_m68k_init(const char *
}
cpu_reset(env);
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/target-mips/translate.c
===================================================================
--- trunk.orig/target-mips/translate.c
+++ trunk/target-mips/translate.c
@@ -8551,6 +8551,7 @@ CPUMIPSState *cpu_mips_init (const char
env->cpu_model_str = cpu_model;
mips_tcg_init();
cpu_reset(env);
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/target-ppc/helper.c
===================================================================
--- trunk.orig/target-ppc/helper.c
+++ trunk/target-ppc/helper.c
@@ -2831,8 +2831,7 @@ CPUPPCState *cpu_ppc_init (const char *c
cpu_ppc_register_internal(env, def);
cpu_ppc_reset(env);
- if (kvm_enabled())
- kvm_init_vcpu(env);
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/target-sh4/translate.c
===================================================================
--- trunk.orig/target-sh4/translate.c
+++ trunk/target-sh4/translate.c
@@ -290,6 +290,7 @@ CPUSH4State *cpu_sh4_init(const char *cp
cpu_sh4_reset(env);
cpu_sh4_register(env, def);
tlb_flush(env, 1);
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/target-sparc/helper.c
===================================================================
--- trunk.orig/target-sparc/helper.c
+++ trunk/target-sparc/helper.c
@@ -723,6 +723,7 @@ CPUSPARCState *cpu_sparc_init(const char
return NULL;
}
cpu_reset(env);
+ qemu_init_vcpu(env);
return env;
}
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -3663,6 +3663,15 @@ static void qemu_event_increment(void)
#endif
#endif
+void qemu_init_vcpu(void *_env)
+{
+ CPUState *env = _env;
+
+ if (kvm_enabled())
+ kvm_init_vcpu(env);
+ return;
+}
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 08/14] qemu: introduce qemu_cpu_kick
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (6 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 07/14] qemu: introduce qemu_init_vcpu mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 09/14] qemu: introduce qemu_init_main_loop mtosatti
` (5 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: qemu-vcpu-kick --]
[-- Type: text/plain, Size: 1487 bytes --]
To notify cpu of pending interrupt.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: trunk/exec.c
===================================================================
--- trunk.orig/exec.c
+++ trunk/exec.c
@@ -1541,6 +1541,17 @@ void cpu_interrupt(CPUState *env, int ma
old_mask = env->interrupt_request;
env->interrupt_request |= mask;
+#ifndef CONFIG_USER_ONLY
+ /*
+ * If called from iothread context, wake the target cpu in
+ * case its halted.
+ */
+ if (!qemu_cpu_self(env)) {
+ qemu_cpu_kick(env);
+ return;
+ }
+#endif
+
if (use_icount) {
env->icount_decr.u16.high = 0xffff;
#ifndef CONFIG_USER_ONLY
Index: trunk/qemu-common.h
===================================================================
--- trunk.orig/qemu-common.h
+++ trunk/qemu-common.h
@@ -189,6 +189,10 @@ void qemu_service_io(void);
/* Force QEMU to process pending events */
void qemu_notify_event(void);
+/* Unblock cpu */
+void qemu_cpu_kick(void *env);
+int qemu_cpu_self(void *env);
+
#ifdef CONFIG_USER_ONLY
#define qemu_init_vcpu(env) do { } while (0)
#else
Index: trunk/vl.c
===================================================================
--- trunk.orig/vl.c
+++ trunk/vl.c
@@ -3672,6 +3672,16 @@ void qemu_init_vcpu(void *_env)
return;
}
+int qemu_cpu_self(void *env)
+{
+ return 1;
+}
+
+void qemu_cpu_kick(void *env)
+{
+ return;
+}
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 09/14] qemu: introduce qemu_init_main_loop
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (7 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 08/14] qemu: introduce qemu_cpu_kick mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 10/14] qemu: introduce lock/unlock_iothread mtosatti
` (4 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: qemu-init-main-loop --]
[-- Type: text/plain, Size: 690 bytes --]
Hook to allow iothread initialization.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -3682,6 +3682,10 @@ void qemu_cpu_kick(void *env)
return;
}
+static void qemu_init_main_loop(void)
+{
+}
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
@@ -5106,6 +5110,7 @@ int main(int argc, char **argv, char **e
if (smp_cpus > 1)
kqemu_allowed = 0;
#endif
+ qemu_init_main_loop();
linux_boot = (kernel_filename != NULL);
net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 10/14] qemu: introduce lock/unlock_iothread
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (8 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 09/14] qemu: introduce qemu_init_main_loop mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 11/14] qemu: use debug_requested global instead of cpu_exec return mtosatti
` (3 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: qemu-lock --]
[-- Type: text/plain, Size: 807 bytes --]
Hook to allow iothread to drop the global mutex.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -3686,6 +3686,9 @@ static void qemu_init_main_loop(void)
{
}
+#define qemu_mutex_lock_iothread() do { } while (0)
+#define qemu_mutex_unlock_iothread() do { } while (0)
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
@@ -3778,7 +3781,9 @@ void main_loop_wait(int timeout)
slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
}
#endif
+ qemu_mutex_unlock_iothread();
ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+ qemu_mutex_lock_iothread();
if (ret > 0) {
IOHandlerRecord **pioh;
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 11/14] qemu: use debug_requested global instead of cpu_exec return
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (9 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 10/14] qemu: introduce lock/unlock_iothread mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 12/14] qemu: refactor tcg cpu execution loop mtosatti
` (2 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: refactor-main-loop-2 --]
[-- Type: text/plain, Size: 1704 bytes --]
Necessary for the next refactoring patch.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -3504,6 +3504,7 @@ static QEMUResetEntry *first_reset_entry
static int reset_requested;
static int shutdown_requested;
static int powerdown_requested;
+static int debug_requested;
int qemu_shutdown_requested(void)
{
@@ -3526,6 +3527,13 @@ int qemu_powerdown_requested(void)
return r;
}
+static int qemu_debug_requested(void)
+{
+ int r = debug_requested;
+ debug_requested = 0;
+ return r;
+}
+
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
{
QEMUResetEntry **pre, *re;
@@ -3955,6 +3963,8 @@ static int vm_can_run(void)
return 0;
if (shutdown_requested)
return 0;
+ if (debug_requested)
+ return 0;
return 1;
}
@@ -3981,6 +3991,7 @@ static void main_loop(void)
ret = qemu_cpu_exec(env);
if (ret == EXCP_DEBUG) {
gdb_set_stop_cpu(env);
+ debug_requested = 1;
break;
}
}
@@ -3991,11 +4002,11 @@ static void main_loop(void)
#ifdef CONFIG_PROFILER
dev_time += profile_getclock() - ti;
#endif
- } while (ret != EXCP_DEBUG && vm_can_run());
+ } while (vm_can_run());
- if (ret == EXCP_DEBUG)
- vm_stop(EXCP_DEBUG);
+ if (qemu_debug_requested())
+ vm_stop(EXCP_DEBUG);
if (qemu_shutdown_requested()) {
if (no_shutdown) {
vm_stop(0);
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 12/14] qemu: refactor tcg cpu execution loop
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (10 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 11/14] qemu: use debug_requested global instead of cpu_exec return mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 13/14] qemu: handle stop request in main loop mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 14/14] qemu: introduce iothread mtosatti
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: refactor-main-loop-3 --]
[-- Type: text/plain, Size: 2108 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -3887,6 +3887,30 @@ static int qemu_cpu_exec(CPUState *env)
return ret;
}
+static void tcg_cpu_exec(void)
+{
+ int ret;
+
+ if (next_cpu == NULL)
+ next_cpu = first_cpu;
+ for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
+ CPUState *env = cur_cpu = next_cpu;
+
+ if (!vm_running)
+ break;
+ if (timer_alarm_pending) {
+ timer_alarm_pending = 0;
+ break;
+ }
+ ret = qemu_cpu_exec(env);
+ if (ret == EXCP_DEBUG) {
+ gdb_set_stop_cpu(env);
+ debug_requested = 1;
+ break;
+ }
+ }
+}
+
static int cpu_has_work(CPUState *env)
{
if (!env->halted)
@@ -3970,31 +3994,13 @@ static int vm_can_run(void)
static void main_loop(void)
{
- int ret = 0;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
-
for (;;) {
- do {
- if (next_cpu == NULL)
- next_cpu = first_cpu;
- for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
- CPUState *env = cur_cpu = next_cpu;
- if (!vm_running)
- break;
- if (timer_alarm_pending) {
- timer_alarm_pending = 0;
- break;
- }
- ret = qemu_cpu_exec(env);
- if (ret == EXCP_DEBUG) {
- gdb_set_stop_cpu(env);
- debug_requested = 1;
- break;
- }
- }
+ do {
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
+ tcg_cpu_exec();
#ifdef CONFIG_PROFILER
ti = profile_getclock();
#endif
@@ -4004,7 +4010,6 @@ static void main_loop(void)
#endif
} while (vm_can_run());
-
if (qemu_debug_requested())
vm_stop(EXCP_DEBUG);
if (qemu_shutdown_requested()) {
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 13/14] qemu: handle stop request in main loop
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (11 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 12/14] qemu: refactor tcg cpu execution loop mtosatti
@ 2009-04-22 19:15 ` mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 14/14] qemu: introduce iothread mtosatti
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: vmstop-refactor --]
[-- Type: text/plain, Size: 1899 bytes --]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -3483,15 +3483,6 @@ void vm_start(void)
}
}
-void vm_stop(int reason)
-{
- if (vm_running) {
- cpu_disable_ticks();
- vm_running = 0;
- vm_state_notify(0, reason);
- }
-}
-
/* reset/shutdown handler */
typedef struct QEMUResetEntry {
@@ -3505,6 +3496,7 @@ static int reset_requested;
static int shutdown_requested;
static int powerdown_requested;
static int debug_requested;
+static int vmstop_requested;
int qemu_shutdown_requested(void)
{
@@ -3534,6 +3526,22 @@ static int qemu_debug_requested(void)
return r;
}
+static int qemu_vmstop_requested(void)
+{
+ int r = vmstop_requested;
+ vmstop_requested = 0;
+ return r;
+}
+
+static void do_vm_stop(int reason)
+{
+ if (vm_running) {
+ cpu_disable_ticks();
+ vm_running = 0;
+ vm_state_notify(0, reason);
+ }
+}
+
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
{
QEMUResetEntry **pre, *re;
@@ -3697,6 +3705,11 @@ static void qemu_init_main_loop(void)
#define qemu_mutex_lock_iothread() do { } while (0)
#define qemu_mutex_unlock_iothread() do { } while (0)
+void vm_stop(int reason)
+{
+ do_vm_stop(reason);
+}
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
@@ -3994,8 +4007,9 @@ static int vm_can_run(void)
static void main_loop(void)
{
- for (;;) {
+ int r;
+ for (;;) {
do {
#ifdef CONFIG_PROFILER
int64_t ti;
@@ -4023,6 +4037,8 @@ static void main_loop(void)
qemu_system_reset();
if (qemu_powerdown_requested())
qemu_system_powerdown();
+ if ((r = qemu_vmstop_requested()))
+ vm_stop(r);
}
}
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] [patch 14/14] qemu: introduce iothread
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
` (12 preceding siblings ...)
2009-04-22 19:15 ` [Qemu-devel] [patch 13/14] qemu: handle stop request in main loop mtosatti
@ 2009-04-22 19:15 ` mtosatti
13 siblings, 0 replies; 30+ messages in thread
From: mtosatti @ 2009-04-22 19:15 UTC (permalink / raw)
To: qemu-devel, aliguori; +Cc: Marcelo Tosatti
[-- Attachment #1: iothread-the --]
[-- Type: text/plain, Size: 14618 bytes --]
Fill in the hooks and introduce iothread.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: qemu-iothread-4/vl.c
===================================================================
--- qemu-iothread-4.orig/vl.c
+++ qemu-iothread-4/vl.c
@@ -1337,19 +1337,19 @@ static void host_alarm_handler(int host_
qemu_get_clock(vm_clock))) ||
qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
qemu_get_clock(rt_clock))) {
- CPUState *env = next_cpu;
-
alarm_timer->flags |= ALARM_FLAG_EXPIRED;
- if (env) {
+#ifndef CONFIG_IOTHREAD
+ if (next_cpu) {
/* stop the currently executing cpu because a timer occured */
- cpu_exit(env);
+ cpu_exit(next_cpu);
#ifdef USE_KQEMU
- if (env->kqemu_enabled) {
- kqemu_cpu_interrupt(env);
+ if (next_cpu->kqemu_enabled) {
+ kqemu_cpu_interrupt(next_cpu);
}
#endif
}
+#endif
timer_alarm_pending = 1;
qemu_notify_event();
}
@@ -3473,6 +3473,9 @@ static void vm_state_notify(int running,
}
}
+static void resume_all_vcpus(void);
+static void pause_all_vcpus(void);
+
void vm_start(void)
{
if (!vm_running) {
@@ -3480,6 +3483,7 @@ void vm_start(void)
vm_running = 1;
vm_state_notify(1, 0);
qemu_rearm_alarm_timer(alarm_timer);
+ resume_all_vcpus();
}
}
@@ -3538,6 +3542,7 @@ static void do_vm_stop(int reason)
if (vm_running) {
cpu_disable_ticks();
vm_running = 0;
+ pause_all_vcpus();
vm_state_notify(0, reason);
}
}
@@ -3590,18 +3595,13 @@ void qemu_system_powerdown_request(void)
qemu_notify_event();
}
-void qemu_notify_event(void)
+#ifdef CONFIG_IOTHREAD
+static void qemu_system_vmstop_request(int reason)
{
- CPUState *env = cpu_single_env;
-
- if (env) {
- cpu_exit(env);
-#ifdef USE_KQEMU
- if (env->kqemu_enabled)
- kqemu_cpu_interrupt(env);
-#endif
- }
+ vmstop_requested = reason;
+ qemu_notify_event();
}
+#endif
#ifdef CONFIG_IOTHREAD
#ifndef _WIN32
@@ -3679,6 +3679,17 @@ static void qemu_event_increment(void)
#endif
#endif
+
+static int cpu_can_run(CPUState *env)
+{
+ if (env->stop)
+ return 0;
+ if (env->stopped)
+ return 0;
+ return 1;
+}
+
+#ifndef CONFIG_IOTHREAD
void qemu_init_vcpu(void *_env)
{
CPUState *env = _env;
@@ -3698,10 +3709,31 @@ void qemu_cpu_kick(void *env)
return;
}
+static void resume_all_vcpus(void)
+{
+}
+
+static void pause_all_vcpus(void)
+{
+}
+
static void qemu_init_main_loop(void)
{
}
+void qemu_notify_event(void)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env) {
+ cpu_exit(env);
+#ifdef USE_KQEMU
+ if (env->kqemu_enabled)
+ kqemu_cpu_interrupt(env);
+#endif
+ }
+}
+
#define qemu_mutex_lock_iothread() do { } while (0)
#define qemu_mutex_unlock_iothread() do { } while (0)
@@ -3710,6 +3742,315 @@ void vm_stop(int reason)
do_vm_stop(reason);
}
+#else /* CONFIG_IOTHREAD */
+
+#include "qemu-thread.h"
+
+QemuMutex qemu_global_mutex;
+static QemuMutex qemu_fair_mutex;
+
+static QemuThread io_thread;
+
+static QemuThread *tcg_cpu_thread;
+static QemuCond *tcg_halt_cond;
+
+static int qemu_system_ready;
+/* cpu creation */
+static QemuCond qemu_cpu_cond;
+/* system init */
+static QemuCond qemu_system_cond;
+static QemuCond qemu_pause_cond;
+
+static void block_io_signals(void);
+static void unblock_io_signals(void);
+static int tcg_has_work(void);
+
+static void qemu_init_main_loop(void)
+{
+ qemu_cond_init(&qemu_pause_cond);
+ qemu_mutex_init(&qemu_fair_mutex);
+ qemu_mutex_init(&qemu_global_mutex);
+ qemu_mutex_lock(&qemu_global_mutex);
+
+ qemu_event_init();
+
+ unblock_io_signals();
+ qemu_thread_self(&io_thread);
+}
+
+static void qemu_wait_io_event(CPUState *env)
+{
+ while (!tcg_has_work())
+ qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
+
+ qemu_mutex_unlock(&qemu_global_mutex);
+
+ /*
+ * Users of qemu_global_mutex can be starved, having no chance
+ * to acquire it since this path will get to it first.
+ * So use another lock to provide fairness.
+ */
+ qemu_mutex_lock(&qemu_fair_mutex);
+ qemu_mutex_unlock(&qemu_fair_mutex);
+
+ qemu_mutex_lock(&qemu_global_mutex);
+ if (env->stop) {
+ env->stop = 0;
+ env->stopped = 1;
+ qemu_cond_signal(&qemu_pause_cond);
+ }
+}
+
+static int qemu_cpu_exec(CPUState *env);
+
+static void *kvm_cpu_thread_fn(void *arg)
+{
+ CPUState *env = arg;
+
+ block_io_signals();
+ qemu_thread_self(env->thread);
+
+ /* signal CPU creation */
+ qemu_mutex_lock(&qemu_global_mutex);
+ env->created = 1;
+ qemu_cond_signal(&qemu_cpu_cond);
+
+ /* and wait for machine initialization */
+ while (!qemu_system_ready)
+ qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+
+ while (1) {
+ if (cpu_can_run(env))
+ qemu_cpu_exec(env);
+ qemu_wait_io_event(env);
+ }
+
+ return NULL;
+}
+
+static void tcg_cpu_exec(void);
+
+static void *tcg_cpu_thread_fn(void *arg)
+{
+ CPUState *env = arg;
+
+ block_io_signals();
+ qemu_thread_self(env->thread);
+
+ /* signal CPU creation */
+ qemu_mutex_lock(&qemu_global_mutex);
+ for (env = first_cpu; env != NULL; env = env->next_cpu)
+ env->created = 1;
+ qemu_cond_signal(&qemu_cpu_cond);
+
+ /* and wait for machine initialization */
+ while (!qemu_system_ready)
+ qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
+
+ while (1) {
+ tcg_cpu_exec();
+ qemu_wait_io_event(cur_cpu);
+ }
+
+ return NULL;
+}
+
+void qemu_cpu_kick(void *_env)
+{
+ CPUState *env = _env;
+ qemu_cond_broadcast(env->halt_cond);
+ if (kvm_enabled())
+ qemu_thread_signal(env->thread, SIGUSR1);
+}
+
+int qemu_cpu_self(void *env)
+{
+ return (cpu_single_env != NULL);
+}
+
+static void cpu_signal(int sig)
+{
+ if (cpu_single_env)
+ cpu_exit(cpu_single_env);
+}
+
+static void block_io_signals(void)
+{
+ sigset_t set;
+ struct sigaction sigact;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = cpu_signal;
+ sigaction(SIGUSR1, &sigact, NULL);
+}
+
+static void unblock_io_signals(void)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+}
+
+static void qemu_signal_lock(unsigned int msecs)
+{
+ qemu_mutex_lock(&qemu_fair_mutex);
+
+ while (qemu_mutex_trylock(&qemu_global_mutex)) {
+ qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
+ if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
+ break;
+ }
+ qemu_mutex_unlock(&qemu_fair_mutex);
+}
+
+static void qemu_mutex_lock_iothread(void)
+{
+ if (kvm_enabled()) {
+ qemu_mutex_lock(&qemu_fair_mutex);
+ qemu_mutex_lock(&qemu_global_mutex);
+ qemu_mutex_unlock(&qemu_fair_mutex);
+ } else
+ qemu_signal_lock(100);
+}
+
+static void qemu_mutex_unlock_iothread(void)
+{
+ qemu_mutex_unlock(&qemu_global_mutex);
+}
+
+static int all_vcpus_paused(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ if (!penv->stopped)
+ return 0;
+ penv = (CPUState *)penv->next_cpu;
+ }
+
+ return 1;
+}
+
+static void pause_all_vcpus(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ penv->stop = 1;
+ qemu_thread_signal(penv->thread, SIGUSR1);
+ qemu_cpu_kick(penv);
+ penv = (CPUState *)penv->next_cpu;
+ }
+
+ while (!all_vcpus_paused()) {
+ qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
+ penv = first_cpu;
+ while (penv) {
+ qemu_thread_signal(penv->thread, SIGUSR1);
+ penv = (CPUState *)penv->next_cpu;
+ }
+ }
+}
+
+static void resume_all_vcpus(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ penv->stop = 0;
+ penv->stopped = 0;
+ qemu_thread_signal(penv->thread, SIGUSR1);
+ qemu_cpu_kick(penv);
+ penv = (CPUState *)penv->next_cpu;
+ }
+}
+
+static void tcg_init_vcpu(void *_env)
+{
+ CPUState *env = _env;
+ /* share a single thread for all cpus with TCG */
+ if (!tcg_cpu_thread) {
+ env->thread = qemu_mallocz(sizeof(QemuThread));
+ env->halt_cond = qemu_mallocz(sizeof(QemuCond));
+ qemu_cond_init(env->halt_cond);
+ qemu_thread_create(env->thread, tcg_cpu_thread_fn, env);
+ while (env->created == 0)
+ qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+ tcg_cpu_thread = env->thread;
+ tcg_halt_cond = env->halt_cond;
+ } else {
+ env->thread = tcg_cpu_thread;
+ env->halt_cond = tcg_halt_cond;
+ }
+}
+
+static void kvm_start_vcpu(CPUState *env)
+{
+ kvm_init_vcpu(env);
+ env->thread = qemu_mallocz(sizeof(QemuThread));
+ env->halt_cond = qemu_mallocz(sizeof(QemuCond));
+ qemu_cond_init(env->halt_cond);
+ qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
+ while (env->created == 0)
+ qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
+}
+
+void qemu_init_vcpu(void *_env)
+{
+ CPUState *env = _env;
+
+ if (kvm_enabled())
+ kvm_start_vcpu(env);
+ else
+ tcg_init_vcpu(env);
+}
+
+void qemu_notify_event(void)
+{
+ qemu_event_increment();
+}
+
+void vm_stop(int reason)
+{
+ QemuThread me;
+ qemu_thread_self(&me);
+
+ if (!qemu_thread_equal(&me, &io_thread)) {
+ qemu_system_vmstop_request(reason);
+ /*
+ * FIXME: should not return to device code in case
+ * vm_stop() has been requested.
+ */
+ if (cpu_single_env) {
+ cpu_exit(cpu_single_env);
+ cpu_single_env->stop = 1;
+ }
+ return;
+ }
+ do_vm_stop(reason);
+}
+
+#endif
+
+
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
@@ -3846,9 +4187,11 @@ void main_loop_wait(int timeout)
}
/* vm time timers */
- if (vm_running && likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
- qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
- qemu_get_clock(vm_clock));
+ if (vm_running) {
+ if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
+ qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
+ qemu_get_clock(vm_clock));
+ }
/* real time timers */
qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
@@ -3902,7 +4245,7 @@ static int qemu_cpu_exec(CPUState *env)
static void tcg_cpu_exec(void)
{
- int ret;
+ int ret = 0;
if (next_cpu == NULL)
next_cpu = first_cpu;
@@ -3915,7 +4258,8 @@ static void tcg_cpu_exec(void)
timer_alarm_pending = 0;
break;
}
- ret = qemu_cpu_exec(env);
+ if (cpu_can_run(env))
+ ret = qemu_cpu_exec(env);
if (ret == EXCP_DEBUG) {
gdb_set_stop_cpu(env);
debug_requested = 1;
@@ -3926,6 +4270,10 @@ static void tcg_cpu_exec(void)
static int cpu_has_work(CPUState *env)
{
+ if (env->stop)
+ return 1;
+ if (env->stopped)
+ return 0;
if (!env->halted)
return 1;
if (qemu_cpu_has_work(env))
@@ -4009,16 +4357,27 @@ static void main_loop(void)
{
int r;
+#ifdef CONFIG_IOTHREAD
+ qemu_system_ready = 1;
+ qemu_cond_broadcast(&qemu_system_cond);
+#endif
+
for (;;) {
do {
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
+#ifndef CONFIG_IOTHREAD
tcg_cpu_exec();
+#endif
#ifdef CONFIG_PROFILER
ti = profile_getclock();
#endif
+#ifdef CONFIG_IOTHREAD
+ main_loop_wait(1000);
+#else
main_loop_wait(qemu_calculate_timeout());
+#endif
#ifdef CONFIG_PROFILER
dev_time += profile_getclock() - ti;
#endif
@@ -4033,13 +4392,17 @@ static void main_loop(void)
} else
break;
}
- if (qemu_reset_requested())
+ if (qemu_reset_requested()) {
+ pause_all_vcpus();
qemu_system_reset();
+ resume_all_vcpus();
+ }
if (qemu_powerdown_requested())
qemu_system_powerdown();
if ((r = qemu_vmstop_requested()))
vm_stop(r);
}
+ pause_all_vcpus();
}
static void version(void)
Index: qemu-iothread-4/cpu-defs.h
===================================================================
--- qemu-iothread-4.orig/cpu-defs.h
+++ qemu-iothread-4/cpu-defs.h
@@ -170,6 +170,8 @@ typedef struct CPUWatchpoint {
target_ulong mem_io_vaddr; /* target virtual addr at which the \
memory was accessed */ \
uint32_t halted; /* Nonzero if the CPU is in suspend state */ \
+ uint32_t stop; /* Stop request */ \
+ uint32_t stopped; /* Artificially stopped */ \
uint32_t interrupt_request; \
volatile sig_atomic_t exit_request; \
/* The meaning of the MMU modes is defined in the target code. */ \
@@ -209,6 +211,9 @@ typedef struct CPUWatchpoint {
/* user data */ \
void *opaque; \
\
+ uint32_t created; \
+ struct QemuThread *thread; \
+ struct QemuCond *halt_cond; \
const char *cpu_model_str; \
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \
--
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] Re: [patch 02/14] qemu: mutex/thread/cond wrappers and configure tweaks
2009-04-22 19:15 ` [Qemu-devel] [patch 02/14] qemu: mutex/thread/cond wrappers and configure tweaks mtosatti
@ 2009-04-22 20:33 ` Anthony Liguori
2009-04-23 11:15 ` [Qemu-devel] svn trunk currently borked Martin Mohring
0 siblings, 1 reply; 30+ messages in thread
From: Anthony Liguori @ 2009-04-22 20:33 UTC (permalink / raw)
To: mtosatti; +Cc: qemu-devel
mtosatti@redhat.com wrote:
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> @@ -1302,7 +1315,8 @@ echo "Documentation $build_docs"
> echo "uname -r $uname_release"
> echo "NPTL support $nptl"
> echo "vde support $vde"
> -echo "AIO support $aio"
> +echo "IO support $aio"
>
Oops. Fixed locally, but if you have to resubmit, make sure to get rid
of this.
--
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] [patch 05/14] qemu: factor out special event notification
2009-04-22 19:15 ` [Qemu-devel] [patch 05/14] qemu: factor out special event notification mtosatti
@ 2009-04-22 20:58 ` Anthony Liguori
0 siblings, 0 replies; 30+ messages in thread
From: Anthony Liguori @ 2009-04-22 20:58 UTC (permalink / raw)
To: mtosatti; +Cc: aliguori, qemu-devel
mtosatti@redhat.com wrote:
> Special events that have no particular event descriptor (either fd for UNIX
> or HANDLE for Windows) associated with make use of an artificial one.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: trunk/vl.c
> ===================================================================
> --- trunk.orig/vl.c
> +++ trunk/vl.c
> @@ -921,15 +921,11 @@ static void qemu_rearm_alarm_timer(struc
> #define MIN_TIMER_REARM_US 250
>
> static struct qemu_alarm_timer *alarm_timer;
> -#ifndef _WIN32
> -static int alarm_timer_rfd, alarm_timer_wfd;
> -#endif
>
> #ifdef _WIN32
>
> struct qemu_alarm_win32 {
> MMRESULT timerId;
> - HANDLE host_alarm;
> unsigned int period;
> } alarm_win32_data = {0, NULL, -1};
>
There are a number of spots in vl.c that do
CloseHandle(data->host_alarm) that aren't removed in this patch. For
instance, the error path in win32_start_timer().
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 30+ messages in thread
* [Qemu-devel] svn trunk currently borked
2009-04-22 20:33 ` [Qemu-devel] " Anthony Liguori
@ 2009-04-23 11:15 ` Martin Mohring
2009-04-23 11:58 ` Laurent Desnogues
0 siblings, 1 reply; 30+ messages in thread
From: Martin Mohring @ 2009-04-23 11:15 UTC (permalink / raw)
To: qemu-devel
Hi,
one of the last commits borked the qemu user mode:
CC i386-linux-user/i386-dis.o
AR i386-linux-user/libqemu.a
LINK i386-linux-user/qemu-i386
libqemu.a(op_helper.o): In function `handle_even_inj':
/usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1197:
undefined reference to `ldl_phys'
/usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1207:
undefined reference to `stl_phys'
libqemu.a(op_helper.o): In function `do_interrupt':
/usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1270:
undefined reference to `ldl_phys'
Regards, Martin
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] svn trunk currently borked
2009-04-23 11:15 ` [Qemu-devel] svn trunk currently borked Martin Mohring
@ 2009-04-23 11:58 ` Laurent Desnogues
2009-04-23 13:17 ` Anthony Liguori
2009-04-23 13:21 ` Martin Mohring
0 siblings, 2 replies; 30+ messages in thread
From: Laurent Desnogues @ 2009-04-23 11:58 UTC (permalink / raw)
To: Martin Mohring; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 884 bytes --]
On Thu, Apr 23, 2009 at 1:15 PM, Martin Mohring
<martin.mohring@opensuse.org> wrote:
> Hi,
>
> one of the last commits borked the qemu user mode:
>
> CC i386-linux-user/i386-dis.o
> AR i386-linux-user/libqemu.a
> LINK i386-linux-user/qemu-i386
> libqemu.a(op_helper.o): In function `handle_even_inj':
> /usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1197:
> undefined reference to `ldl_phys'
> /usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1207:
> undefined reference to `stl_phys'
> libqemu.a(op_helper.o): In function `do_interrupt':
> /usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1270:
> undefined reference to `ldl_phys'
This is due to commit 7230.
Could you give the attached patch a try? I just checked it compiled.
Laurent
Signed-off-by: Laurent Desnogues <laurent.desnogues@gmail.com>
[-- Attachment #2: i386-SVMI.patch --]
[-- Type: text/x-patch, Size: 1638 bytes --]
Index: target-i386/op_helper.c
===================================================================
--- target-i386/op_helper.c (revision 7232)
+++ target-i386/op_helper.c (working copy)
@@ -1191,6 +1191,7 @@
EIP = next_eip;
}
+#if !defined(CONFIG_USER_ONLY)
static void handle_even_inj(int intno, int is_int, int error_code,
int is_hw, int rm)
{
@@ -1209,6 +1210,7 @@
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj);
}
}
+#endif
/*
* Begin execution of an interruption. is_int is TRUE if coming from
@@ -1250,8 +1252,10 @@
}
}
if (env->cr[0] & CR0_PE_MASK) {
+#if !defined(CONFIG_USER_ONLY)
if (env->hflags & HF_SVMI_MASK)
handle_even_inj(intno, is_int, error_code, is_hw, 0);
+#endif
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
@@ -1261,15 +1265,19 @@
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
}
} else {
+#if !defined(CONFIG_USER_ONLY)
if (env->hflags & HF_SVMI_MASK)
handle_even_inj(intno, is_int, error_code, is_hw, 1);
+#endif
do_interrupt_real(intno, is_int, error_code, next_eip);
}
+#if !defined(CONFIG_USER_ONLY)
if (env->hflags & HF_SVMI_MASK) {
uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
}
+#endif
}
/* This should come from sysemu.h - if we could include it here... */
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] svn trunk currently borked
2009-04-23 11:58 ` Laurent Desnogues
@ 2009-04-23 13:17 ` Anthony Liguori
2009-04-23 13:21 ` Martin Mohring
1 sibling, 0 replies; 30+ messages in thread
From: Anthony Liguori @ 2009-04-23 13:17 UTC (permalink / raw)
To: Laurent Desnogues; +Cc: Martin Mohring, qemu-devel
Laurent Desnogues wrote:
> On Thu, Apr 23, 2009 at 1:15 PM, Martin Mohring
> <martin.mohring@opensuse.org> wrote:
>
> This is due to commit 7230.
>
> Could you give the attached patch a try? I just checked it compiled.
>
Applied. Thanks.
Regards,
Anthony Liguori
> Laurent
>
> Signed-off-by: Laurent Desnogues <laurent.desnogues@gmail.com>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [Qemu-devel] svn trunk currently borked
2009-04-23 11:58 ` Laurent Desnogues
2009-04-23 13:17 ` Anthony Liguori
@ 2009-04-23 13:21 ` Martin Mohring
1 sibling, 0 replies; 30+ messages in thread
From: Martin Mohring @ 2009-04-23 13:21 UTC (permalink / raw)
To: Laurent Desnogues; +Cc: qemu-devel
Your fix solves the problem.
tnx.
Laurent Desnogues wrote:
> On Thu, Apr 23, 2009 at 1:15 PM, Martin Mohring
> <martin.mohring@opensuse.org> wrote:
>
>> Hi,
>>
>> one of the last commits borked the qemu user mode:
>>
>> CC i386-linux-user/i386-dis.o
>> AR i386-linux-user/libqemu.a
>> LINK i386-linux-user/qemu-i386
>> libqemu.a(op_helper.o): In function `handle_even_inj':
>> /usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1197:
>> undefined reference to `ldl_phys'
>> /usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1207:
>> undefined reference to `stl_phys'
>> libqemu.a(op_helper.o): In function `do_interrupt':
>> /usr/src/packages/BUILD/qemu-0.11svn7232/target-i386/op_helper.c:1270:
>> undefined reference to `ldl_phys'
>>
>
> This is due to commit 7230.
>
> Could you give the attached patch a try? I just checked it compiled.
>
>
> Laurent
>
> Signed-off-by: Laurent Desnogues <laurent.desnogues@gmail.com>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2009-04-23 13:21 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20090407195126.467365249@localhost.localdomain>
[not found] ` <20090407195442.646407971@localhost.localdomain>
2009-04-16 20:53 ` [Qemu-devel] Re: [patch 01/11] qemu: create helper for event notification Anthony Liguori
2009-04-16 20:58 ` Marcelo Tosatti
2009-04-17 17:21 ` Anthony Liguori
[not found] ` <20090407195442.764405844@localhost.localdomain>
2009-04-17 13:53 ` [Qemu-devel] Re: [patch 02/11] qemu: mutex/thread/cond wrappers Anthony Liguori
[not found] ` <20090407195443.004166674@localhost.localdomain>
2009-04-17 13:57 ` [Qemu-devel] Re: [patch 04/11] qemu: introduce main_loop_break Anthony Liguori
[not found] ` <20090407195443.121795529@localhost.localdomain>
2009-04-17 14:05 ` [Qemu-devel] Re: [patch 05/11] qemu: separate thread for io Anthony Liguori
2009-04-18 20:45 ` Marcelo Tosatti
[not found] ` <20090407195443.716079176@localhost.localdomain>
2009-04-17 14:07 ` [Qemu-devel] Re: [patch 10/11] qemu: make iothread selectable at compile time Anthony Liguori
[not found] ` <20090407195443.832269134@localhost.localdomain>
2009-04-17 14:09 ` [Qemu-devel] Re: [patch 11/11] qemu: basic kvm iothread support Anthony Liguori
2009-04-22 19:15 ` [Qemu-devel] [patch 00/14] qemu: introduce iothread (v4) mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 01/14] qemu: create helper for event notification mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 02/14] qemu: mutex/thread/cond wrappers and configure tweaks mtosatti
2009-04-22 20:33 ` [Qemu-devel] " Anthony Liguori
2009-04-23 11:15 ` [Qemu-devel] svn trunk currently borked Martin Mohring
2009-04-23 11:58 ` Laurent Desnogues
2009-04-23 13:17 ` Anthony Liguori
2009-04-23 13:21 ` Martin Mohring
2009-04-22 19:15 ` [Qemu-devel] [patch 03/14] qemu: per-arch cpu_has_work mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 04/14] qemu: explictly rearm alarm timer on main_loop_wait mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 05/14] qemu: factor out special event notification mtosatti
2009-04-22 20:58 ` Anthony Liguori
2009-04-22 19:15 ` [Qemu-devel] [patch 06/14] qemu: refactor main_loop mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 07/14] qemu: introduce qemu_init_vcpu mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 08/14] qemu: introduce qemu_cpu_kick mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 09/14] qemu: introduce qemu_init_main_loop mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 10/14] qemu: introduce lock/unlock_iothread mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 11/14] qemu: use debug_requested global instead of cpu_exec return mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 12/14] qemu: refactor tcg cpu execution loop mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 13/14] qemu: handle stop request in main loop mtosatti
2009-04-22 19:15 ` [Qemu-devel] [patch 14/14] qemu: introduce iothread mtosatti
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.