fixed refresh logic (initial patch by Igor Kovalenko)
[qemu] / vl.c
diff --git a/vl.c b/vl.c
index c9992d8..b31b239 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -517,6 +517,8 @@ static int64_t clock_freq;
 
 static void init_get_clock(void)
 {
+    LARGE_INTEGER freq;
+    int ret;
     ret = QueryPerformanceFrequency(&freq);
     if (ret == 0) {
         fprintf(stderr, "Could not calibrate ticks\n");
@@ -3779,6 +3781,7 @@ static int usb_device_del(const char *devname)
 {
     USBPort *port;
     USBPort **lastp;
+    USBDevice *dev;
     int bus_num, addr;
     const char *p;
 
@@ -3803,8 +3806,10 @@ static int usb_device_del(const char *devname)
     if (!port)
         return -1;
 
+    dev = port->dev;
     *lastp = port->next;
     usb_attach(port, NULL);
+    dev->handle_destroy(dev);
     port->next = free_usb_ports;
     free_usb_ports = port;
     return 0;
@@ -4767,6 +4772,77 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 /***********************************************************/
+/* bottom halves (can be seen as timers which expire ASAP) */
+
+struct QEMUBH {
+    QEMUBHFunc *cb;
+    void *opaque;
+    int scheduled;
+    QEMUBH *next;
+};
+
+static QEMUBH *first_bh = NULL;
+
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
+{
+    QEMUBH *bh;
+    bh = qemu_mallocz(sizeof(QEMUBH));
+    if (!bh)
+        return NULL;
+    bh->cb = cb;
+    bh->opaque = opaque;
+    return bh;
+}
+
+void qemu_bh_poll(void)
+{
+    QEMUBH *bh, **pbh;
+
+    for(;;) {
+        pbh = &first_bh;
+        bh = *pbh;
+        if (!bh)
+            break;
+        *pbh = bh->next;
+        bh->scheduled = 0;
+        bh->cb(bh->opaque);
+    }
+}
+
+void qemu_bh_schedule(QEMUBH *bh)
+{
+    CPUState *env = cpu_single_env;
+    if (bh->scheduled)
+        return;
+    bh->scheduled = 1;
+    bh->next = first_bh;
+    first_bh = bh;
+
+    /* stop the currently executing CPU to execute the BH ASAP */
+    if (env) {
+        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+    }
+}
+
+void qemu_bh_cancel(QEMUBH *bh)
+{
+    QEMUBH **pbh;
+    if (bh->scheduled) {
+        pbh = &first_bh;
+        while (*pbh != bh)
+            pbh = &(*pbh)->next;
+        *pbh = bh->next;
+        bh->scheduled = 0;
+    }
+}
+
+void qemu_bh_delete(QEMUBH *bh)
+{
+    qemu_bh_cancel(bh);
+    qemu_free(bh);
+}
+
+/***********************************************************/
 /* machine registration */
 
 QEMUMachine *first_machine = NULL;
@@ -5025,6 +5101,8 @@ void main_loop_wait(int timeout)
 #ifdef _WIN32
     tap_win32_poll();
 #endif
+    qemu_aio_poll();
+    qemu_bh_poll();
 
     if (vm_running) {
         qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
@@ -5614,9 +5692,25 @@ int main(int argc, char **argv)
     }
 #else
     SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
+    /* Note: cpu_interrupt() is currently not SMP safe, so we force
+       QEMU to run on a single CPU */
+    {
+        HANDLE h;
+        DWORD mask, smask;
+        int i;
+        h = GetCurrentProcess();
+        if (GetProcessAffinityMask(h, &mask, &smask)) {
+            for(i = 0; i < 32; i++) {
+                if (mask & (1 << i))
+                    break;
+            }
+            if (i != 32) {
+                mask = 1 << i;
+                SetProcessAffinityMask(h, mask);
+            }
+        }
+    }
 #endif
-    init_timers();
-    init_timer_alarm();
 
     register_machines();
     machine = first_machine;
@@ -6026,6 +6120,10 @@ int main(int argc, char **argv)
 
     setvbuf(stdout, NULL, _IOLBF, 0);
     
+    init_timers();
+    init_timer_alarm();
+    qemu_aio_init();
+
 #ifdef _WIN32
     socket_init();
 #endif
@@ -6069,7 +6167,7 @@ int main(int argc, char **argv)
                 snprintf(buf, sizeof(buf), "hd%c", i + 'a');
                 bs_table[i] = bdrv_new(buf);
             }
-            if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
+            if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
                 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
                         hd_filename[i]);
                 exit(1);
@@ -6094,7 +6192,8 @@ int main(int argc, char **argv)
                 bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
             }
             if (fd_filename[i] != '\0') {
-                if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
+                if (bdrv_open(fd_table[i], fd_filename[i],
+                              snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
                     fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
                             fd_filename[i]);
                     exit(1);
@@ -6139,7 +6238,7 @@ int main(int argc, char **argv)
                 exit(1);
             }
             if (!strcmp(serial_devices[i], "vc"))
-                qemu_chr_printf(serial_hds[i], "serial%d console\n", i);
+                qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
         }
     }
 
@@ -6152,7 +6251,7 @@ int main(int argc, char **argv)
                 exit(1);
             }
             if (!strcmp(parallel_devices[i], "vc"))
-                qemu_chr_printf(parallel_hds[i], "parallel%d console\n", i);
+                qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
         }
     }