qemu-timer.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /*
  2. * QEMU System Emulator
  3. *
  4. * Copyright (c) 2003-2008 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "sysemu.h"
  25. #include "monitor/monitor.h"
  26. #include "ui/console.h"
  27. #include "hw/hw.h"
  28. #include "qemu-timer.h"
  29. #ifdef CONFIG_POSIX
  30. #include <pthread.h>
  31. #endif
  32. #ifdef _WIN32
  33. #include <mmsystem.h>
  34. #endif
  35. /***********************************************************/
  36. /* timers */
  37. #define QEMU_CLOCK_REALTIME 0
  38. #define QEMU_CLOCK_VIRTUAL 1
  39. #define QEMU_CLOCK_HOST 2
  40. struct QEMUClock {
  41. QEMUTimer *active_timers;
  42. NotifierList reset_notifiers;
  43. int64_t last;
  44. int type;
  45. bool enabled;
  46. };
  47. struct QEMUTimer {
  48. int64_t expire_time; /* in nanoseconds */
  49. QEMUClock *clock;
  50. QEMUTimerCB *cb;
  51. void *opaque;
  52. QEMUTimer *next;
  53. int scale;
  54. };
  55. struct qemu_alarm_timer {
  56. char const *name;
  57. int (*start)(struct qemu_alarm_timer *t);
  58. void (*stop)(struct qemu_alarm_timer *t);
  59. void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
  60. #if defined(__linux__)
  61. timer_t timer;
  62. int fd;
  63. #elif defined(_WIN32)
  64. HANDLE timer;
  65. #endif
  66. bool expired;
  67. bool pending;
  68. };
  69. static struct qemu_alarm_timer *alarm_timer;
  70. static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
  71. {
  72. return timer_head && (timer_head->expire_time <= current_time);
  73. }
  74. static int64_t qemu_next_alarm_deadline(void)
  75. {
  76. int64_t delta = INT64_MAX;
  77. int64_t rtdelta;
  78. if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
  79. delta = vm_clock->active_timers->expire_time -
  80. qemu_get_clock_ns(vm_clock);
  81. }
  82. if (host_clock->enabled && host_clock->active_timers) {
  83. int64_t hdelta = host_clock->active_timers->expire_time -
  84. qemu_get_clock_ns(host_clock);
  85. if (hdelta < delta) {
  86. delta = hdelta;
  87. }
  88. }
  89. if (rt_clock->enabled && rt_clock->active_timers) {
  90. rtdelta = (rt_clock->active_timers->expire_time -
  91. qemu_get_clock_ns(rt_clock));
  92. if (rtdelta < delta) {
  93. delta = rtdelta;
  94. }
  95. }
  96. return delta;
  97. }
  98. static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
  99. {
  100. int64_t nearest_delta_ns = qemu_next_alarm_deadline();
  101. if (nearest_delta_ns < INT64_MAX) {
  102. t->rearm(t, nearest_delta_ns);
  103. }
  104. }
  105. /* TODO: MIN_TIMER_REARM_NS should be optimized */
  106. #define MIN_TIMER_REARM_NS 250000
  107. #ifdef _WIN32
  108. static int mm_start_timer(struct qemu_alarm_timer *t);
  109. static void mm_stop_timer(struct qemu_alarm_timer *t);
  110. static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
  111. static int win32_start_timer(struct qemu_alarm_timer *t);
  112. static void win32_stop_timer(struct qemu_alarm_timer *t);
  113. static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
  114. #else
  115. static int unix_start_timer(struct qemu_alarm_timer *t);
  116. static void unix_stop_timer(struct qemu_alarm_timer *t);
  117. static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
  118. #ifdef __linux__
  119. static int dynticks_start_timer(struct qemu_alarm_timer *t);
  120. static void dynticks_stop_timer(struct qemu_alarm_timer *t);
  121. static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
  122. #endif /* __linux__ */
  123. #endif /* _WIN32 */
  124. static struct qemu_alarm_timer alarm_timers[] = {
  125. #ifndef _WIN32
  126. #ifdef __linux__
  127. {"dynticks", dynticks_start_timer,
  128. dynticks_stop_timer, dynticks_rearm_timer},
  129. #endif
  130. {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
  131. #else
  132. {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
  133. {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
  134. #endif
  135. {NULL, }
  136. };
  137. static void show_available_alarms(void)
  138. {
  139. int i;
  140. printf("Available alarm timers, in order of precedence:\n");
  141. for (i = 0; alarm_timers[i].name; i++)
  142. printf("%s\n", alarm_timers[i].name);
  143. }
  144. void configure_alarms(char const *opt)
  145. {
  146. int i;
  147. int cur = 0;
  148. int count = ARRAY_SIZE(alarm_timers) - 1;
  149. char *arg;
  150. char *name;
  151. struct qemu_alarm_timer tmp;
  152. if (is_help_option(opt)) {
  153. show_available_alarms();
  154. exit(0);
  155. }
  156. arg = g_strdup(opt);
  157. /* Reorder the array */
  158. name = strtok(arg, ",");
  159. while (name) {
  160. for (i = 0; i < count && alarm_timers[i].name; i++) {
  161. if (!strcmp(alarm_timers[i].name, name))
  162. break;
  163. }
  164. if (i == count) {
  165. fprintf(stderr, "Unknown clock %s\n", name);
  166. goto next;
  167. }
  168. if (i < cur)
  169. /* Ignore */
  170. goto next;
  171. /* Swap */
  172. tmp = alarm_timers[i];
  173. alarm_timers[i] = alarm_timers[cur];
  174. alarm_timers[cur] = tmp;
  175. cur++;
  176. next:
  177. name = strtok(NULL, ",");
  178. }
  179. g_free(arg);
  180. if (cur) {
  181. /* Disable remaining timers */
  182. for (i = cur; i < count; i++)
  183. alarm_timers[i].name = NULL;
  184. } else {
  185. show_available_alarms();
  186. exit(1);
  187. }
  188. }
  189. QEMUClock *rt_clock;
  190. QEMUClock *vm_clock;
  191. QEMUClock *host_clock;
  192. static QEMUClock *qemu_new_clock(int type)
  193. {
  194. QEMUClock *clock;
  195. clock = g_malloc0(sizeof(QEMUClock));
  196. clock->type = type;
  197. clock->enabled = true;
  198. clock->last = INT64_MIN;
  199. notifier_list_init(&clock->reset_notifiers);
  200. return clock;
  201. }
  202. void qemu_clock_enable(QEMUClock *clock, bool enabled)
  203. {
  204. bool old = clock->enabled;
  205. clock->enabled = enabled;
  206. if (enabled && !old) {
  207. qemu_rearm_alarm_timer(alarm_timer);
  208. }
  209. }
  210. int64_t qemu_clock_has_timers(QEMUClock *clock)
  211. {
  212. return !!clock->active_timers;
  213. }
  214. int64_t qemu_clock_expired(QEMUClock *clock)
  215. {
  216. return (clock->active_timers &&
  217. clock->active_timers->expire_time < qemu_get_clock_ns(clock));
  218. }
  219. int64_t qemu_clock_deadline(QEMUClock *clock)
  220. {
  221. /* To avoid problems with overflow limit this to 2^32. */
  222. int64_t delta = INT32_MAX;
  223. if (clock->active_timers) {
  224. delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
  225. }
  226. if (delta < 0) {
  227. delta = 0;
  228. }
  229. return delta;
  230. }
  231. QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
  232. QEMUTimerCB *cb, void *opaque)
  233. {
  234. QEMUTimer *ts;
  235. ts = g_malloc0(sizeof(QEMUTimer));
  236. ts->clock = clock;
  237. ts->cb = cb;
  238. ts->opaque = opaque;
  239. ts->scale = scale;
  240. return ts;
  241. }
  242. void qemu_free_timer(QEMUTimer *ts)
  243. {
  244. g_free(ts);
  245. }
  246. /* stop a timer, but do not dealloc it */
  247. void qemu_del_timer(QEMUTimer *ts)
  248. {
  249. QEMUTimer **pt, *t;
  250. /* NOTE: this code must be signal safe because
  251. qemu_timer_expired() can be called from a signal. */
  252. pt = &ts->clock->active_timers;
  253. for(;;) {
  254. t = *pt;
  255. if (!t)
  256. break;
  257. if (t == ts) {
  258. *pt = t->next;
  259. break;
  260. }
  261. pt = &t->next;
  262. }
  263. }
  264. /* modify the current timer so that it will be fired when current_time
  265. >= expire_time. The corresponding callback will be called. */
  266. void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
  267. {
  268. QEMUTimer **pt, *t;
  269. qemu_del_timer(ts);
  270. /* add the timer in the sorted list */
  271. /* NOTE: this code must be signal safe because
  272. qemu_timer_expired() can be called from a signal. */
  273. pt = &ts->clock->active_timers;
  274. for(;;) {
  275. t = *pt;
  276. if (!qemu_timer_expired_ns(t, expire_time)) {
  277. break;
  278. }
  279. pt = &t->next;
  280. }
  281. ts->expire_time = expire_time;
  282. ts->next = *pt;
  283. *pt = ts;
  284. /* Rearm if necessary */
  285. if (pt == &ts->clock->active_timers) {
  286. if (!alarm_timer->pending) {
  287. qemu_rearm_alarm_timer(alarm_timer);
  288. }
  289. /* Interrupt execution to force deadline recalculation. */
  290. qemu_clock_warp(ts->clock);
  291. if (use_icount) {
  292. qemu_notify_event();
  293. }
  294. }
  295. }
  296. void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
  297. {
  298. qemu_mod_timer_ns(ts, expire_time * ts->scale);
  299. }
  300. bool qemu_timer_pending(QEMUTimer *ts)
  301. {
  302. QEMUTimer *t;
  303. for (t = ts->clock->active_timers; t != NULL; t = t->next) {
  304. if (t == ts) {
  305. return true;
  306. }
  307. }
  308. return false;
  309. }
  310. bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
  311. {
  312. return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
  313. }
  314. void qemu_run_timers(QEMUClock *clock)
  315. {
  316. QEMUTimer *ts;
  317. int64_t current_time;
  318. if (!clock->enabled)
  319. return;
  320. current_time = qemu_get_clock_ns(clock);
  321. for(;;) {
  322. ts = clock->active_timers;
  323. if (!qemu_timer_expired_ns(ts, current_time)) {
  324. break;
  325. }
  326. /* remove timer from the list before calling the callback */
  327. clock->active_timers = ts->next;
  328. ts->next = NULL;
  329. /* run the callback (the timer list can be modified) */
  330. ts->cb(ts->opaque);
  331. }
  332. }
  333. int64_t qemu_get_clock_ns(QEMUClock *clock)
  334. {
  335. int64_t now, last;
  336. switch(clock->type) {
  337. case QEMU_CLOCK_REALTIME:
  338. return get_clock();
  339. default:
  340. case QEMU_CLOCK_VIRTUAL:
  341. if (use_icount) {
  342. return cpu_get_icount();
  343. } else {
  344. return cpu_get_clock();
  345. }
  346. case QEMU_CLOCK_HOST:
  347. now = get_clock_realtime();
  348. last = clock->last;
  349. clock->last = now;
  350. if (now < last) {
  351. notifier_list_notify(&clock->reset_notifiers, &now);
  352. }
  353. return now;
  354. }
  355. }
  356. void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
  357. {
  358. notifier_list_add(&clock->reset_notifiers, notifier);
  359. }
  360. void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
  361. {
  362. notifier_remove(notifier);
  363. }
  364. void init_clocks(void)
  365. {
  366. if (!rt_clock) {
  367. rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
  368. vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
  369. host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
  370. }
  371. }
  372. uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
  373. {
  374. return qemu_timer_pending(ts) ? ts->expire_time : -1;
  375. }
  376. void qemu_run_all_timers(void)
  377. {
  378. alarm_timer->pending = false;
  379. /* vm time timers */
  380. qemu_run_timers(vm_clock);
  381. qemu_run_timers(rt_clock);
  382. qemu_run_timers(host_clock);
  383. /* rearm timer, if not periodic */
  384. if (alarm_timer->expired) {
  385. alarm_timer->expired = false;
  386. qemu_rearm_alarm_timer(alarm_timer);
  387. }
  388. }
  389. #ifdef _WIN32
  390. static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
  391. #else
  392. static void host_alarm_handler(int host_signum)
  393. #endif
  394. {
  395. struct qemu_alarm_timer *t = alarm_timer;
  396. if (!t)
  397. return;
  398. t->expired = true;
  399. t->pending = true;
  400. qemu_notify_event();
  401. }
  402. #if defined(__linux__)
  403. #include "compatfd.h"
  404. static int dynticks_start_timer(struct qemu_alarm_timer *t)
  405. {
  406. struct sigevent ev;
  407. timer_t host_timer;
  408. struct sigaction act;
  409. sigfillset(&act.sa_mask);
  410. act.sa_flags = 0;
  411. act.sa_handler = host_alarm_handler;
  412. sigaction(SIGALRM, &act, NULL);
  413. /*
  414. * Initialize ev struct to 0 to avoid valgrind complaining
  415. * about uninitialized data in timer_create call
  416. */
  417. memset(&ev, 0, sizeof(ev));
  418. ev.sigev_value.sival_int = 0;
  419. ev.sigev_notify = SIGEV_SIGNAL;
  420. #ifdef CONFIG_SIGEV_THREAD_ID
  421. if (qemu_signalfd_available()) {
  422. ev.sigev_notify = SIGEV_THREAD_ID;
  423. ev._sigev_un._tid = qemu_get_thread_id();
  424. }
  425. #endif /* CONFIG_SIGEV_THREAD_ID */
  426. ev.sigev_signo = SIGALRM;
  427. if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
  428. perror("timer_create");
  429. return -1;
  430. }
  431. t->timer = host_timer;
  432. return 0;
  433. }
  434. static void dynticks_stop_timer(struct qemu_alarm_timer *t)
  435. {
  436. timer_t host_timer = t->timer;
  437. timer_delete(host_timer);
  438. }
  439. static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
  440. int64_t nearest_delta_ns)
  441. {
  442. timer_t host_timer = t->timer;
  443. struct itimerspec timeout;
  444. int64_t current_ns;
  445. if (nearest_delta_ns < MIN_TIMER_REARM_NS)
  446. nearest_delta_ns = MIN_TIMER_REARM_NS;
  447. /* check whether a timer is already running */
  448. if (timer_gettime(host_timer, &timeout)) {
  449. perror("gettime");
  450. fprintf(stderr, "Internal timer error: aborting\n");
  451. exit(1);
  452. }
  453. current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
  454. if (current_ns && current_ns <= nearest_delta_ns)
  455. return;
  456. timeout.it_interval.tv_sec = 0;
  457. timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
  458. timeout.it_value.tv_sec = nearest_delta_ns / 1000000000;
  459. timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
  460. if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
  461. perror("settime");
  462. fprintf(stderr, "Internal timer error: aborting\n");
  463. exit(1);
  464. }
  465. }
  466. #endif /* defined(__linux__) */
  467. #if !defined(_WIN32)
  468. static int unix_start_timer(struct qemu_alarm_timer *t)
  469. {
  470. struct sigaction act;
  471. /* timer signal */
  472. sigfillset(&act.sa_mask);
  473. act.sa_flags = 0;
  474. act.sa_handler = host_alarm_handler;
  475. sigaction(SIGALRM, &act, NULL);
  476. return 0;
  477. }
  478. static void unix_rearm_timer(struct qemu_alarm_timer *t,
  479. int64_t nearest_delta_ns)
  480. {
  481. struct itimerval itv;
  482. int err;
  483. if (nearest_delta_ns < MIN_TIMER_REARM_NS)
  484. nearest_delta_ns = MIN_TIMER_REARM_NS;
  485. itv.it_interval.tv_sec = 0;
  486. itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
  487. itv.it_value.tv_sec = nearest_delta_ns / 1000000000;
  488. itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
  489. err = setitimer(ITIMER_REAL, &itv, NULL);
  490. if (err) {
  491. perror("setitimer");
  492. fprintf(stderr, "Internal timer error: aborting\n");
  493. exit(1);
  494. }
  495. }
  496. static void unix_stop_timer(struct qemu_alarm_timer *t)
  497. {
  498. struct itimerval itv;
  499. memset(&itv, 0, sizeof(itv));
  500. setitimer(ITIMER_REAL, &itv, NULL);
  501. }
  502. #endif /* !defined(_WIN32) */
  503. #ifdef _WIN32
  504. static MMRESULT mm_timer;
  505. static TIMECAPS mm_tc;
  506. static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
  507. DWORD_PTR dwUser, DWORD_PTR dw1,
  508. DWORD_PTR dw2)
  509. {
  510. struct qemu_alarm_timer *t = alarm_timer;
  511. if (!t) {
  512. return;
  513. }
  514. t->expired = true;
  515. t->pending = true;
  516. qemu_notify_event();
  517. }
  518. static int mm_start_timer(struct qemu_alarm_timer *t)
  519. {
  520. timeGetDevCaps(&mm_tc, sizeof(mm_tc));
  521. timeBeginPeriod(mm_tc.wPeriodMin);
  522. mm_timer = timeSetEvent(mm_tc.wPeriodMin, /* interval (ms) */
  523. mm_tc.wPeriodMin, /* resolution */
  524. mm_alarm_handler, /* function */
  525. (DWORD_PTR)t, /* parameter */
  526. TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
  527. if (!mm_timer) {
  528. fprintf(stderr, "Failed to initialize win32 alarm timer\n");
  529. timeEndPeriod(mm_tc.wPeriodMin);
  530. return -1;
  531. }
  532. return 0;
  533. }
  534. static void mm_stop_timer(struct qemu_alarm_timer *t)
  535. {
  536. timeKillEvent(mm_timer);
  537. timeEndPeriod(mm_tc.wPeriodMin);
  538. }
  539. static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
  540. {
  541. int64_t nearest_delta_ms = delta / 1000000;
  542. if (nearest_delta_ms < mm_tc.wPeriodMin) {
  543. nearest_delta_ms = mm_tc.wPeriodMin;
  544. } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
  545. nearest_delta_ms = mm_tc.wPeriodMax;
  546. }
  547. timeKillEvent(mm_timer);
  548. mm_timer = timeSetEvent((UINT)nearest_delta_ms,
  549. mm_tc.wPeriodMin,
  550. mm_alarm_handler,
  551. (DWORD_PTR)t,
  552. TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
  553. if (!mm_timer) {
  554. fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
  555. timeEndPeriod(mm_tc.wPeriodMin);
  556. exit(1);
  557. }
  558. }
  559. static int win32_start_timer(struct qemu_alarm_timer *t)
  560. {
  561. HANDLE hTimer;
  562. BOOLEAN success;
  563. /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
  564. is zero) that has already expired, the timer is not updated. Since
  565. creating a new timer is relatively expensive, set a bogus one-hour
  566. interval in the dynticks case. */
  567. success = CreateTimerQueueTimer(&hTimer,
  568. NULL,
  569. host_alarm_handler,
  570. t,
  571. 1,
  572. 3600000,
  573. WT_EXECUTEINTIMERTHREAD);
  574. if (!success) {
  575. fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
  576. GetLastError());
  577. return -1;
  578. }
  579. t->timer = hTimer;
  580. return 0;
  581. }
  582. static void win32_stop_timer(struct qemu_alarm_timer *t)
  583. {
  584. HANDLE hTimer = t->timer;
  585. if (hTimer) {
  586. DeleteTimerQueueTimer(NULL, hTimer, NULL);
  587. }
  588. }
  589. static void win32_rearm_timer(struct qemu_alarm_timer *t,
  590. int64_t nearest_delta_ns)
  591. {
  592. HANDLE hTimer = t->timer;
  593. int64_t nearest_delta_ms;
  594. BOOLEAN success;
  595. nearest_delta_ms = nearest_delta_ns / 1000000;
  596. if (nearest_delta_ms < 1) {
  597. nearest_delta_ms = 1;
  598. }
  599. /* ULONG_MAX can be 32 bit */
  600. if (nearest_delta_ms > ULONG_MAX) {
  601. nearest_delta_ms = ULONG_MAX;
  602. }
  603. success = ChangeTimerQueueTimer(NULL,
  604. hTimer,
  605. (unsigned long) nearest_delta_ms,
  606. 3600000);
  607. if (!success) {
  608. fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
  609. GetLastError());
  610. exit(-1);
  611. }
  612. }
  613. #endif /* _WIN32 */
  614. static void quit_timers(void)
  615. {
  616. struct qemu_alarm_timer *t = alarm_timer;
  617. alarm_timer = NULL;
  618. t->stop(t);
  619. }
  620. #ifdef CONFIG_POSIX
  621. static void reinit_timers(void)
  622. {
  623. struct qemu_alarm_timer *t = alarm_timer;
  624. t->stop(t);
  625. if (t->start(t)) {
  626. fprintf(stderr, "Internal timer error: aborting\n");
  627. exit(1);
  628. }
  629. qemu_rearm_alarm_timer(t);
  630. }
  631. #endif /* CONFIG_POSIX */
  632. int init_timer_alarm(void)
  633. {
  634. struct qemu_alarm_timer *t = NULL;
  635. int i, err = -1;
  636. if (alarm_timer) {
  637. return 0;
  638. }
  639. for (i = 0; alarm_timers[i].name; i++) {
  640. t = &alarm_timers[i];
  641. err = t->start(t);
  642. if (!err)
  643. break;
  644. }
  645. if (err) {
  646. err = -ENOENT;
  647. goto fail;
  648. }
  649. atexit(quit_timers);
  650. #ifdef CONFIG_POSIX
  651. pthread_atfork(NULL, NULL, reinit_timers);
  652. #endif
  653. alarm_timer = t;
  654. return 0;
  655. fail:
  656. return err;
  657. }