qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] slow down qemu - brake


From: Miroslav Novak
Subject: [Qemu-devel] [PATCH] slow down qemu - brake
Date: Mon, 27 Nov 2006 18:16:44 -0000
User-agent: Thunderbird 1.5.0.8 (X11/20061123)

This patch adds support for slowing down Qemu and saving cpu load.
The '-brake' command line parameter or monitor command 'brake' determines how long to wait in the main_loop with respect to duration of time that qemu used for the emulation itself. Thus e.g. zero value runs at full speed, 1 at 1/2 speed, 10 at 1/11 speed, etc.

A drawback of this approach is that the PIC interrupt can be missed if PIC raises them too often. This happens if the loop_main divided by (1+brake) is less than the frequency of PIC interrupts.
In such case the time of emulated system runs slowly.
This problem occurs mainly for Linux emulation where kernel parameter HZ is usually of several hundreds.

For DOS emulation, where PIC interrupts are raised usually at 18Hz, this approach works nice. And one can play old DOS games at reasonable speed and save batteries.

Mirek

diff -aur ../../orig/qemu-0.8.2/monitor.c ./monitor.c
--- ../../orig/qemu-0.8.2/monitor.c     2006-07-22 19:23:34.000000000 +0200
+++ ./monitor.c 2006-11-27 18:11:34.000000000 +0100
@@ -276,6 +276,14 @@
         term_printf("Invalid CPU index\n");
 }
 
+static void do_brake_set(int multiplier)
+{
+    if (multiplier < 0)
+        term_printf("Current brake multiplier %d\n", brake_mult);
+    else
+        brake_mult = multiplier;
+}
+
 static void do_info_jit(void)
 {
     dump_exec_info(NULL, monitor_fprintf);
@@ -1198,6 +1206,8 @@
 #endif
      { "stopcapture", "i", do_stop_capture,
        "capture index", "stop capture" },
+    { "brake", "i", do_brake_set, 
+      "multiplier", "set brake multiplier (non-negative integer), negative 
value prints actual setting" },
     { NULL, NULL, }, 
 };
 
diff -aur ../../orig/qemu-0.8.2/vl.c ./vl.c
--- ../../orig/qemu-0.8.2/vl.c  2006-07-22 19:23:34.000000000 +0200
+++ ./vl.c      2006-11-27 18:25:22.000000000 +0100
@@ -156,6 +156,7 @@
 #endif
 int acpi_enabled = 1;
 int fd_bootchk = 1;
+int brake_mult = 0;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -5045,8 +5046,39 @@
 
 static CPUState *cur_cpu;
 
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval 
*y) {
+       /* Perform the carry for the later subtraction by updating y. */
+       if (x->tv_usec < y->tv_usec) {
+               int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+               y->tv_usec -= 1000000 * nsec;
+               y->tv_sec += nsec;
+       }
+       if (x->tv_usec - y->tv_usec > 1000000) {
+               int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+               y->tv_usec += 1000000 * nsec;
+               y->tv_sec -= nsec;
+       }
+
+       /* Compute the time remaining to wait.
+        *      tv_usec is certainly positive. */
+       result->tv_sec = x->tv_sec - y->tv_sec;
+       result->tv_usec = x->tv_usec - y->tv_usec;
+
+       /* Return 1 if result is negative. */
+       return x->tv_sec < y->tv_sec;
+}
+
+
 int main_loop(void)
 {
+    struct timeval tti, tti2, tti3, ttix;
+//#define BRAKE_DEBUG
+#ifdef BRAKE_DEBUG
+    int64_t mti, mti1, mti2, mti3;
+    int prcnt=0;
+#endif
+
     int ret, timeout;
 #ifdef CONFIG_PROFILER
     int64_t ti;
@@ -5055,6 +5087,11 @@
 
     cur_cpu = first_cpu;
     for(;;) {
+
+        gettimeofday(&tti, NULL);
+#ifdef BRAKE_DEBUG
+        mti = profile_getclock();
+#endif
         if (vm_running) {
 
             env = cur_cpu;
@@ -5113,6 +5150,41 @@
 #ifdef CONFIG_PROFILER
         dev_time += profile_getclock() - ti;
 #endif
+
+        gettimeofday(&tti2, NULL);
+#ifdef BRAKE_DEBUG
+        mti2 = profile_getclock();
+#endif
+
+        {
+            struct timespec ts;
+            int delus, delunc=0;
+            sigset_t sis, osis;
+
+            timeval_subtract(&ttix, &tti2, &tti);
+            delus = ttix.tv_usec*brake_mult - delunc;
+            ts.tv_sec=0;
+            ts.tv_nsec=delus*1000;
+
+            sigfillset(&sis);
+            sigprocmask(SIG_BLOCK, &sis, &osis);
+            if (delus>0) while (nanosleep(&ts, &ts));
+            sigprocmask(SIG_SETMASK, &osis, NULL);
+#ifdef BRAKE_DEBUG
+            mti3 = profile_getclock();
+#endif
+            gettimeofday(&tti3, NULL);
+
+            timeval_subtract(&ttix, &tti3, &tti2);
+            delunc = ttix.tv_usec-delus; 
+#ifdef BRAKE_DEBUG
+            if (!((++prcnt)%128)) {
+                printf("cycles %qd, \t%qd, \t%qd, \t%qd \%\n", (mti1 - mti), 
(mti2 - mti1), (mti3 - mti2), (100*(mti1 - mti))/(mti3-mti) );
+                //printf("del[us] %d, \t%d\n", delus, delunc);
+                //printf("ts[ns] = %d\n", ts.tv_nsec);
+            }
+#endif
+        }
     }
     cpu_disable_ticks();
     return ret;
@@ -5224,6 +5296,7 @@
 #endif
            "-loadvm file    start right away with a saved state (loadvm in 
monitor)\n"
           "-vnc display    start a VNC server on display\n"
+           "-brake multiplier    enables brake system which slows down qemu 
`multiplier'-times\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -5302,6 +5375,7 @@
     QEMU_OPTION_smp,
     QEMU_OPTION_vnc,
     QEMU_OPTION_no_acpi,
+    QEMU_OPTION_brake,
 };
 
 typedef struct QEMUOption {
@@ -5378,6 +5452,7 @@
     { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
     { "no-acpi", 0, QEMU_OPTION_no_acpi },
+    { "brake", 1, QEMU_OPTION_brake },
     { NULL },
 };
 
@@ -6021,6 +6096,9 @@
             case QEMU_OPTION_no_acpi:
                 acpi_enabled = 0;
                 break;
+           case QEMU_OPTION_brake:
+               brake_mult = atoi(optarg);
+               break;
             }
         }
     }
diff -aur ../../orig/qemu-0.8.2/vl.h ./vl.h
--- ../../orig/qemu-0.8.2/vl.h  2006-07-22 19:23:34.000000000 +0200
+++ ./vl.h      2006-11-27 18:09:41.000000000 +0100
@@ -1177,4 +1177,6 @@
 
 void kqemu_record_dump(void);
 
+extern int brake_mult;
+
 #endif /* VL_H */

reply via email to

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