]> git.proxmox.com Git - qemu.git/blobdiff - qemu-timer.c
Introduce a 'client_add' monitor command accepting an open FD
[qemu.git] / qemu-timer.c
index 72066c7c50551db216783b9c1b02a57130b177ff..67c2974959891ff022f47307671afb46127a81cf 100644 (file)
@@ -218,6 +218,7 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t);
 
 static int unix_start_timer(struct qemu_alarm_timer *t);
 static void unix_stop_timer(struct qemu_alarm_timer *t);
+static void unix_rearm_timer(struct qemu_alarm_timer *t);
 
 #ifdef __linux__
 
@@ -290,7 +291,7 @@ static struct qemu_alarm_timer alarm_timers[] = {
     {"dynticks", dynticks_start_timer,
      dynticks_stop_timer, dynticks_rearm_timer},
 #endif
-    {"unix", unix_start_timer, unix_stop_timer, NULL},
+    {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
 #else
     {"mmtimer", mm_start_timer, mm_stop_timer, NULL},
     {"mmtimer2", mm_start_timer, mm_stop_timer, mm_rearm_timer},
@@ -890,8 +891,6 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
 static int unix_start_timer(struct qemu_alarm_timer *t)
 {
     struct sigaction act;
-    struct itimerval itv;
-    int err;
 
     /* timer signal */
     sigfillset(&act.sa_mask);
@@ -899,18 +898,35 @@ static int unix_start_timer(struct qemu_alarm_timer *t)
     act.sa_handler = host_alarm_handler;
 
     sigaction(SIGALRM, &act, NULL);
+    return 0;
+}
 
-    itv.it_interval.tv_sec = 0;
-    /* for i386 kernel 2.6 to get 1 ms */
-    itv.it_interval.tv_usec = 999;
-    itv.it_value.tv_sec = 0;
-    itv.it_value.tv_usec = 10 * 1000;
+static void unix_rearm_timer(struct qemu_alarm_timer *t)
+{
+    struct itimerval itv;
+    int64_t nearest_delta_ns = INT64_MAX;
+    int err;
 
-    err = setitimer(ITIMER_REAL, &itv, NULL);
-    if (err)
-        return -1;
+    assert(alarm_has_dynticks(t));
+    if (!active_timers[QEMU_CLOCK_REALTIME] &&
+        !active_timers[QEMU_CLOCK_VIRTUAL] &&
+        !active_timers[QEMU_CLOCK_HOST])
+        return;
 
-    return 0;
+    nearest_delta_ns = qemu_next_alarm_deadline();
+    if (nearest_delta_ns < MIN_TIMER_REARM_NS)
+        nearest_delta_ns = MIN_TIMER_REARM_NS;
+
+    itv.it_interval.tv_sec = 0;
+    itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
+    itv.it_value.tv_sec =  nearest_delta_ns / 1000000000;
+    itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
+    err = setitimer(ITIMER_REAL, &itv, NULL);
+    if (err) {
+        perror("setitimer");
+        fprintf(stderr, "Internal timer error: aborting\n");
+        exit(1);
+    }
 }
 
 static void unix_stop_timer(struct qemu_alarm_timer *t)