Revision efe75411

b/vl.c
784 784

  
785 785
struct qemu_alarm_timer {
786 786
    char const *name;
787
    unsigned int flags;
787 788

  
788 789
    int (*start)(struct qemu_alarm_timer *t);
789 790
    void (*stop)(struct qemu_alarm_timer *t);
791
    void (*rearm)(struct qemu_alarm_timer *t);
790 792
    void *priv;
791 793
};
792 794

  
795
#define ALARM_FLAG_DYNTICKS  0x1
796

  
797
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
798
{
799
    return t->flags & ALARM_FLAG_DYNTICKS;
800
}
801

  
802
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
803
{
804
    if (!alarm_has_dynticks(t))
805
        return;
806

  
807
    t->rearm(t);
808
}
809

  
810
/* TODO: MIN_TIMER_REARM_US should be optimized */
811
#define MIN_TIMER_REARM_US 250
812

  
793 813
static struct qemu_alarm_timer *alarm_timer;
794 814

  
795 815
#ifdef _WIN32
......
802 822

  
803 823
static int win32_start_timer(struct qemu_alarm_timer *t);
804 824
static void win32_stop_timer(struct qemu_alarm_timer *t);
825
static void win32_rearm_timer(struct qemu_alarm_timer *t);
805 826

  
806 827
#else
807 828

  
808 829
static int unix_start_timer(struct qemu_alarm_timer *t);
809 830
static void unix_stop_timer(struct qemu_alarm_timer *t);
810 831

  
832
static int dynticks_start_timer(struct qemu_alarm_timer *t);
833
static void dynticks_stop_timer(struct qemu_alarm_timer *t);
834
static void dynticks_rearm_timer(struct qemu_alarm_timer *t);
835

  
811 836
#ifdef __linux__
812 837

  
813 838
static int hpet_start_timer(struct qemu_alarm_timer *t);
......
816 841
static int rtc_start_timer(struct qemu_alarm_timer *t);
817 842
static void rtc_stop_timer(struct qemu_alarm_timer *t);
818 843

  
819
#endif
844
#endif /* __linux__ */
820 845

  
821 846
#endif /* _WIN32 */
822 847

  
823 848
static struct qemu_alarm_timer alarm_timers[] = {
849
#ifndef _WIN32
850
    {"dynticks", ALARM_FLAG_DYNTICKS, dynticks_start_timer,
851
     dynticks_stop_timer, dynticks_rearm_timer, NULL},
824 852
#ifdef __linux__
825 853
    /* HPET - if available - is preferred */
826
    {"hpet", hpet_start_timer, hpet_stop_timer, NULL},
854
    {"hpet", 0, hpet_start_timer, hpet_stop_timer, NULL, NULL},
827 855
    /* ...otherwise try RTC */
828
    {"rtc", rtc_start_timer, rtc_stop_timer, NULL},
856
    {"rtc", 0, rtc_start_timer, rtc_stop_timer, NULL, NULL},
829 857
#endif
830
#ifndef _WIN32
831
    {"unix", unix_start_timer, unix_stop_timer, NULL},
858
    {"unix", 0, unix_start_timer, unix_stop_timer, NULL, NULL},
832 859
#else
833
    {"win32", win32_start_timer, win32_stop_timer, &alarm_win32_data},
860
    {"dynticks", ALARM_FLAG_DYNTICKS, win32_start_timer,
861
     win32_stop_timer, win32_rearm_timer, &alarm_win32_data},
862
    {"win32", 0, win32_start_timer,
863
     win32_stop_timer, NULL, &alarm_win32_data},
834 864
#endif
835 865
    {NULL, }
836 866
};
......
949 979
        }
950 980
        pt = &t->next;
951 981
    }
982

  
983
    qemu_rearm_alarm_timer(alarm_timer);
952 984
}
953 985

  
954 986
/* modify the current timer so that it will be fired when current_time
......
1008 1040
        /* run the callback (the timer list can be modified) */
1009 1041
        ts->cb(ts->opaque);
1010 1042
    }
1043
    qemu_rearm_alarm_timer(alarm_timer);
1011 1044
}
1012 1045

  
1013 1046
int64_t qemu_get_clock(QEMUClock *clock)
......
1115 1148
        last_clock = ti;
1116 1149
    }
1117 1150
#endif
1118
    if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
1151
    if (alarm_has_dynticks(alarm_timer) ||
1152
        qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
1119 1153
                           qemu_get_clock(vm_clock)) ||
1120 1154
        qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
1121 1155
                           qemu_get_clock(rt_clock))) {
......
1136 1170
    }
1137 1171
}
1138 1172

  
1173
static uint64_t qemu_next_deadline(void)
1174
{
1175
    int64_t nearest_delta_us = ULLONG_MAX;
1176
    int64_t vmdelta_us;
1177

  
1178
    if (active_timers[QEMU_TIMER_REALTIME])
1179
        nearest_delta_us = (active_timers[QEMU_TIMER_REALTIME]->expire_time -
1180
                            qemu_get_clock(rt_clock))*1000;
1181

  
1182
    if (active_timers[QEMU_TIMER_VIRTUAL]) {
1183
        /* round up */
1184
        vmdelta_us = (active_timers[QEMU_TIMER_VIRTUAL]->expire_time -
1185
                      qemu_get_clock(vm_clock)+999)/1000;
1186
        if (vmdelta_us < nearest_delta_us)
1187
            nearest_delta_us = vmdelta_us;
1188
    }
1189

  
1190
    /* Avoid arming the timer to negative, zero, or too low values */
1191
    if (nearest_delta_us <= MIN_TIMER_REARM_US)
1192
        nearest_delta_us = MIN_TIMER_REARM_US;
1193

  
1194
    return nearest_delta_us;
1195
}
1196

  
1139 1197
#ifndef _WIN32
1140 1198

  
1141 1199
#if defined(__linux__)
......
1243 1301

  
1244 1302
#endif /* !defined(__linux__) */
1245 1303

  
1304
static int dynticks_start_timer(struct qemu_alarm_timer *t)
1305
{
1306
    struct sigevent ev;
1307
    timer_t host_timer;
1308
    struct sigaction act;
1309

  
1310
    sigfillset(&act.sa_mask);
1311
    act.sa_flags = 0;
1312
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1313
    act.sa_flags |= SA_ONSTACK;
1314
#endif
1315
    act.sa_handler = host_alarm_handler;
1316

  
1317
    sigaction(SIGALRM, &act, NULL);
1318

  
1319
    ev.sigev_value.sival_int = 0;
1320
    ev.sigev_notify = SIGEV_SIGNAL;
1321
    ev.sigev_signo = SIGALRM;
1322

  
1323
    if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
1324
        perror("timer_create");
1325

  
1326
        /* disable dynticks */
1327
        fprintf(stderr, "Dynamic Ticks disabled\n");
1328

  
1329
        return -1;
1330
    }
1331

  
1332
    t->priv = (void *)host_timer;
1333

  
1334
    return 0;
1335
}
1336

  
1337
static void dynticks_stop_timer(struct qemu_alarm_timer *t)
1338
{
1339
    timer_t host_timer = (timer_t)t->priv;
1340

  
1341
    timer_delete(host_timer);
1342
}
1343

  
1344
static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
1345
{
1346
    timer_t host_timer = (timer_t)t->priv;
1347
    struct itimerspec timeout;
1348
    int64_t nearest_delta_us = INT64_MAX;
1349
    int64_t current_us;
1350

  
1351
    if (!active_timers[QEMU_TIMER_REALTIME] &&
1352
                !active_timers[QEMU_TIMER_VIRTUAL])
1353
            return;
1354

  
1355
    nearest_delta_us = qemu_next_deadline();
1356

  
1357
    /* check whether a timer is already running */
1358
    if (timer_gettime(host_timer, &timeout)) {
1359
        perror("gettime");
1360
        fprintf(stderr, "Internal timer error: aborting\n");
1361
        exit(1);
1362
    }
1363
    current_us = timeout.it_value.tv_sec * 1000000 + timeout.it_value.tv_nsec/1000;
1364
    if (current_us && current_us <= nearest_delta_us)
1365
        return;
1366

  
1367
    timeout.it_interval.tv_sec = 0;
1368
    timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
1369
    timeout.it_value.tv_sec =  nearest_delta_us / 1000000;
1370
    timeout.it_value.tv_nsec = (nearest_delta_us % 1000000) * 1000;
1371
    if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
1372
        perror("settime");
1373
        fprintf(stderr, "Internal timer error: aborting\n");
1374
        exit(1);
1375
    }
1376
}
1377

  
1246 1378
static int unix_start_timer(struct qemu_alarm_timer *t)
1247 1379
{
1248 1380
    struct sigaction act;
......
1288 1420
{
1289 1421
    TIMECAPS tc;
1290 1422
    struct qemu_alarm_win32 *data = t->priv;
1423
    UINT flags;
1291 1424

  
1292 1425
    data->host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
1293 1426
    if (!data->host_alarm) {
......
1303 1436

  
1304 1437
    timeBeginPeriod(data->period);
1305 1438

  
1439
    flags = TIME_CALLBACK_FUNCTION;
1440
    if (alarm_has_dynticks(t))
1441
        flags |= TIME_ONESHOT;
1442
    else
1443
        flags |= TIME_PERIODIC;
1444

  
1306 1445
    data->timerId = timeSetEvent(1,         // interval (ms)
1307 1446
                        data->period,       // resolution
1308 1447
                        host_alarm_handler, // function
1309 1448
                        (DWORD)t,           // parameter
1310
                        TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1449
                        flags);
1311 1450

  
1312 1451
    if (!data->timerId) {
1313 1452
        perror("Failed to initialize win32 alarm timer");
......
1332 1471
    CloseHandle(data->host_alarm);
1333 1472
}
1334 1473

  
1474
static void win32_rearm_timer(struct qemu_alarm_timer *t)
1475
{
1476
    struct qemu_alarm_win32 *data = t->priv;
1477
    uint64_t nearest_delta_us;
1478

  
1479
    if (!active_timers[QEMU_TIMER_REALTIME] &&
1480
                !active_timers[QEMU_TIMER_VIRTUAL])
1481
            return;
1482

  
1483
    nearest_delta_us = qemu_next_deadline();
1484
    nearest_delta_us /= 1000;
1485

  
1486
    timeKillEvent(data->timerId);
1487

  
1488
    data->timerId = timeSetEvent(1,
1489
                        data->period,
1490
                        host_alarm_handler,
1491
                        (DWORD)t,
1492
                        TIME_ONESHOT | TIME_PERIODIC);
1493

  
1494
    if (!data->timerId) {
1495
        perror("Failed to re-arm win32 alarm timer");
1496

  
1497
        timeEndPeriod(data->period);
1498
        CloseHandle(data->host_alarm);
1499
        exit(1);
1500
    }
1501
}
1502

  
1335 1503
#endif /* _WIN32 */
1336 1504

  
1337 1505
static void init_timer_alarm(void)
......
6490 6658
        cpu_enable_ticks();
6491 6659
        vm_running = 1;
6492 6660
        vm_state_notify(1);
6661
        qemu_rearm_alarm_timer(alarm_timer);
6493 6662
    }
6494 6663
}
6495 6664

  

Also available in: Unified diff