qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC] Ensure SIGALRM causes a cpu_loop_exit


From: andrzej zaborowski
Subject: [Qemu-devel] [RFC] Ensure SIGALRM causes a cpu_loop_exit
Date: Fri, 23 Nov 2007 23:50:45 +0100

Hi,
  There is a chance that when using "unix" or "dynticks" clock, the
signal arrives when no cpu is executing. The probability is high when
using dynticks and a timer is scheduled to expire very soon so that a
signal is delivered very soon after a previous signal. When that
happens cpu_single_env is zero and the signal handler does nothing.
This is not much problem with "unix" clocks or when not using
-nographic or when the guest OS uses interrupts, because a another
cpu_loop_exit will happen in not too long. If none of these conditions
is true the cpu loop starts spinning without a chance to exit and
process events. I used the following patch to prevent this but there's
probably a better way:

diff --git a/cpu-all.h b/cpu-all.h
index f4db592..c095e9c 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -706,6 +706,7 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
     __attribute__ ((__noreturn__));
 extern CPUState *first_cpu;
 extern CPUState *cpu_single_env;
+extern int env_pending_request;
 extern int code_copy_enabled;

 #define CPU_INTERRUPT_EXIT   0x01 /* wants exit from main loop */
diff --git a/cpu-exec.c b/cpu-exec.c
index 1c7356a..af75731 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -258,6 +258,11 @@ int cpu_exec(CPUState *env1)

     cpu_single_env = env1;

+    if (env_pending_request) {
+        cpu_interrupt(env1, env_pending_request);
+        env_pending_request = 0;
+    }
+
     /* first we save global registers */
 #define SAVE_HOST_REGS 1
 #include "hostregs_helper.h"
diff --git a/exec.c b/exec.c
index 6384df2..a649d8f 100644
--- a/exec.c
+++ b/exec.c
@@ -96,6 +96,7 @@ CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
    cpu_exec() */
 CPUState *cpu_single_env;
+int env_pending_request;

 typedef struct PageDesc {
     /* list of TBs intersecting this ram page */
@@ -1194,6 +1195,12 @@ void cpu_interrupt(CPUState *env, int mask)
     TranslationBlock *tb;
     static int interrupt_lock;

+    /* cause an interrupt in the first cpu that tries to start running */
+    if (!env) {
+        env_pending_request |= mask;
+        return;
+    }
+
     env->interrupt_request |= mask;
     /* if the cpu is currently executing code, we must unlink it and
        all the potentially executing TB */
diff --git a/vl.c b/vl.c
index 864a044..ec2aa84 100644
--- a/vl.c
+++ b/vl.c
@@ -1184,15 +1184,14 @@ static void host_alarm_handler(int host_signum)
         SetEvent(data->host_alarm);
 #endif
         CPUState *env = cpu_single_env;
-        if (env) {
-            /* stop the currently executing cpu because a timer occured */
-            cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+
+        /* stop the currently executing cpu because a timer occured */
+        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
 #ifdef USE_KQEMU
-            if (env->kqemu_enabled) {
-                kqemu_cpu_interrupt(env);
-            }
-#endif
+        if (env && env->kqemu_enabled) {
+            kqemu_cpu_interrupt(env);
         }
+#endif
     }
 }

Regards




reply via email to

[Prev in Thread] Current Thread [Next in Thread]