1f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/*
2f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * QEMU System Emulator
3f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner *
4f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard
5f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner *
6f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
7f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal
8f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * in the Software without restriction, including without limitation the rights
9f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is
11f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * furnished to do so, subject to the following conditions:
12f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner *
13f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * The above copyright notice and this permission notice shall be included in
14f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * all copies or substantial portions of the Software.
15f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner *
16f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner * THE SOFTWARE.
23f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner */
24f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
25f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "android/charpipe.h"
26f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "android/log-rotate.h"
27f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "android/snaphost-android.h"
28f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "block/aio.h"
29f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "exec/hax.h"
30f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "hw/hw.h"
31f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "monitor/monitor.h"
32f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "net/net.h"
33f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "qemu-common.h"
34f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "qemu/sockets.h"
35f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "qemu/timer.h"
36f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "slirp-android/libslirp.h"
37f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "sysemu/cpus.h"
38f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include "sysemu/sysemu.h"
39f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
40f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef __linux__
41f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include <sys/ioctl.h>
42f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
43f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
44f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef _WIN32
45f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include <windows.h>
46f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#include <mmsystem.h>
47f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
48f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
49dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnerint qemu_calculate_timeout(void);
50f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
51dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#ifndef CONFIG_ANDROID
52f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/* Conversion factor from emulated instructions to virtual clock ticks.  */
53f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint icount_time_shift;
54f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
55f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#define MAX_ICOUNT_SHIFT 10
56f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/* Compensate for varying guest execution speed.  */
57f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint64_t qemu_icount_bias;
58f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic QEMUTimer *icount_rt_timer;
59f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic QEMUTimer *icount_vm_timer;
60dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner#endif  // !CONFIG_ANDROID
61f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
62f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifndef _WIN32
63f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int io_thread_fd = -1;
64f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
65f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void qemu_event_read(void *opaque)
66f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
67f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int fd = (unsigned long)opaque;
68f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    ssize_t len;
69f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
70f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* Drain the notify pipe */
71f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    do {
72f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        char buffer[512];
73f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        len = read(fd, buffer, sizeof(buffer));
74f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    } while ((len == -1 && errno == EINTR) || len > 0);
75f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
76f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
770e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic int qemu_main_loop_event_init(void)
78f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
79f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int err;
80f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int fds[2];
81f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
82f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    err = pipe(fds);
83f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (err == -1)
84f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -errno;
85f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
86f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    err = fcntl_setfl(fds[0], O_NONBLOCK);
87f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (err < 0)
88f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        goto fail;
89f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
90f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    err = fcntl_setfl(fds[1], O_NONBLOCK);
91f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (err < 0)
92f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        goto fail;
93f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
94f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
95f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                         (void *)(unsigned long)fds[0]);
96f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
97f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    io_thread_fd = fds[1];
98f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
99f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
100f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerfail:
101f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    close(fds[0]);
102f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    close(fds[1]);
103f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return err;
104f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
105f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#else
106f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' TurnerHANDLE qemu_event_handle;
107f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
108f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void dummy_event_handler(void *opaque)
109f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
110f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
111f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
1120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic int qemu_main_loop_event_init(void)
113f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
114f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
115f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!qemu_event_handle) {
116f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        perror("Failed CreateEvent");
117f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -1;
118f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
119f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
120f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
121f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
122f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
123f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
124f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint qemu_init_main_loop(void)
125f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
1260e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return qemu_main_loop_event_init();
127f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
128f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
129f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifndef _WIN32
130f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
131f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic inline void os_host_main_loop_wait(int *timeout)
132f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
133f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
134f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
135f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#else  // _WIN32
136f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
137f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/***********************************************************/
138f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/* Polling handling */
139f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
140f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnertypedef struct PollingEntry {
141f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    PollingFunc *func;
142f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    void *opaque;
143f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct PollingEntry *next;
144f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner} PollingEntry;
145f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
146f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic PollingEntry *first_polling_entry;
147f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
148f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint qemu_add_polling_cb(PollingFunc *func, void *opaque)
149f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
150f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    PollingEntry **ppe, *pe;
151f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    pe = g_malloc0(sizeof(PollingEntry));
152f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    pe->func = func;
153f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    pe->opaque = opaque;
154f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
155f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    *ppe = pe;
156f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
157f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
158f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
159f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid qemu_del_polling_cb(PollingFunc *func, void *opaque)
160f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
161f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    PollingEntry **ppe, *pe;
162f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
163f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        pe = *ppe;
164f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (pe->func == func && pe->opaque == opaque) {
165f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            *ppe = pe->next;
166f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            g_free(pe);
167f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            break;
168f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
169f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
170f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
171f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
172f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/***********************************************************/
173f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/* Wait objects support */
174f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnertypedef struct WaitObjects {
175f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int num;
176f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
177f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
178f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
179f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner} WaitObjects;
180f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
181f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic WaitObjects wait_objects = {0};
182f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
183f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
184f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
185f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    WaitObjects *w = &wait_objects;
186f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
187f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (w->num >= MAXIMUM_WAIT_OBJECTS)
188f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -1;
189f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    w->events[w->num] = handle;
190f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    w->func[w->num] = func;
191f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    w->opaque[w->num] = opaque;
192f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    w->num++;
193f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
194f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
195f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
196f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
197f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
198f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int i, found;
199f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    WaitObjects *w = &wait_objects;
200f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
201f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    found = 0;
202f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for (i = 0; i < w->num; i++) {
203f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (w->events[i] == handle)
204f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            found = 1;
205f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (found) {
206f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            w->events[i] = w->events[i + 1];
207f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            w->func[i] = w->func[i + 1];
208f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            w->opaque[i] = w->opaque[i + 1];
209f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
210f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
211f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (found)
212f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        w->num--;
213f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
214f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
215f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid os_host_main_loop_wait(int *timeout)
216f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
217f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int ret, ret2, i;
218f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    PollingEntry *pe;
219f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
220f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* XXX: need to suppress polling by better using win32 events */
221f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    ret = 0;
222f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
223f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        ret |= pe->func(pe->opaque);
224f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
225f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (ret == 0) {
226f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        int err;
227f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        WaitObjects *w = &wait_objects;
228f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
229f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        qemu_mutex_unlock_iothread();
230f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
231f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        qemu_mutex_lock_iothread();
232f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
233f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            if (w->func[ret - WAIT_OBJECT_0])
234f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
235f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
236f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            /* Check for additional signaled events */
237f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
238f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
239f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                /* Check if event is signaled */
240f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                ret2 = WaitForSingleObject(w->events[i], 0);
241f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                if(ret2 == WAIT_OBJECT_0) {
242f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                    if (w->func[i])
243f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                        w->func[i](w->opaque[i]);
244f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                } else if (ret2 == WAIT_TIMEOUT) {
245f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                } else {
246f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                    err = GetLastError();
247f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
248f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                }
249f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            }
250f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        } else if (ret == WAIT_TIMEOUT) {
251f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        } else {
252f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            err = GetLastError();
253f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
254f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
255f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
256f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
257f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    *timeout = 0;
258f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
259f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
260f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif  // _WIN32
261f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
262821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turnerstatic void qemu_run_alarm_timer(void);  // forward
263821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner
264f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid main_loop_wait(int timeout)
265f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
266f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    fd_set rfds, wfds, xfds;
267f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int ret, nfds;
268f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct timeval tv;
269f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
270f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_bh_update_timeout(&timeout);
271f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
272f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    os_host_main_loop_wait(&timeout);
273f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
274f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    tv.tv_sec = timeout / 1000;
275f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    tv.tv_usec = (timeout % 1000) * 1000;
276f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
277f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* poll any events */
278f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
279f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* XXX: separate device handlers from system ones */
280f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    nfds = -1;
281f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    FD_ZERO(&rfds);
282f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    FD_ZERO(&wfds);
283f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    FD_ZERO(&xfds);
284f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
285f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (slirp_is_inited()) {
286f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
287f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
288f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
289f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_mutex_unlock_iothread();
290f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
291f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_mutex_lock_iothread();
292f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
293f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (slirp_is_inited()) {
294f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (ret < 0) {
295f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            FD_ZERO(&rfds);
296f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            FD_ZERO(&wfds);
297f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            FD_ZERO(&xfds);
298f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
299f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        slirp_select_poll(&rfds, &wfds, &xfds);
300f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
301f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    charpipe_poll();
302f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
303dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_clock_run_all_timers();
304f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
305821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    qemu_run_alarm_timer();
306821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner
307f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* Check bottom-halves last in case any of the earlier events triggered
308f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner       them.  */
309f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_bh_poll();
310f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
311f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
312f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
313f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid main_loop(void)
314f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
315f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int r;
316f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
317f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef CONFIG_HAX
318f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (hax_enabled())
319f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        hax_sync_vcpus();
320f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
321f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
322f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for (;;) {
323f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        do {
324f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef CONFIG_PROFILER
325f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            int64_t ti;
326f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
327f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            tcg_cpu_exec();
328f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef CONFIG_PROFILER
329f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            ti = profile_getclock();
330f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
331f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            main_loop_wait(qemu_calculate_timeout());
332f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef CONFIG_PROFILER
333f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            dev_time += profile_getclock() - ti;
334f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
335f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
336f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            qemu_log_rotation_poll();
337f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
338f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        } while (vm_can_run());
339f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
340f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (qemu_debug_requested())
341f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            vm_stop(EXCP_DEBUG);
342f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (qemu_shutdown_requested()) {
343f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            if (no_shutdown) {
344f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                vm_stop(0);
345f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                no_shutdown = 0;
346f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            } else {
347f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                if (savevm_on_exit != NULL) {
348f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                  /* Prior to saving VM to the snapshot file, save HW config
349f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                   * settings for that VM, so we can match them when VM gets
350f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                   * loaded from the snapshot. */
351f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                  snaphost_save_config(savevm_on_exit);
352f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                  do_savevm(cur_mon, savevm_on_exit);
353f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                }
354f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                break;
355f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            }
356f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
357f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (qemu_reset_requested()) {
358f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            pause_all_vcpus();
359f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            qemu_system_reset();
360f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            resume_all_vcpus();
361f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
362f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (qemu_powerdown_requested())
363f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            qemu_system_powerdown();
364f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if ((r = qemu_vmstop_requested()))
365f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            vm_stop(r);
366f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
367f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    pause_all_vcpus();
368f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
369f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
370821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// TODO(digit): Re-enable icount handling int he future.
371dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid configure_icount(const char* opts) {
372dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
373f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
374f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstruct qemu_alarm_timer {
375f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    char const *name;
376f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int (*start)(struct qemu_alarm_timer *t);
377f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    void (*stop)(struct qemu_alarm_timer *t);
378f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    void (*rearm)(struct qemu_alarm_timer *t);
379f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#if defined(__linux__)
380f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int fd;
381f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timer_t timer;
382f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#elif defined(_WIN32)
383f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    HANDLE timer;
384f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
385f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    char expired;
386f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner};
387f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
388f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic struct qemu_alarm_timer *alarm_timer;
389f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
390f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
391f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
392821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    return t->rearm != NULL;
393f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
394f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
395f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
396f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
397821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    if (t->rearm) {
398821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        t->rearm(t);
399821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    }
400821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner}
401f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
402821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turnerstatic void qemu_run_alarm_timer(void) {
403821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    /* rearm timer, if not periodic */
404821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    if (alarm_timer->expired) {
405821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        alarm_timer->expired = 0;
406821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        qemu_rearm_alarm_timer(alarm_timer);
407821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    }
408f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
409f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
410f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner/* TODO: MIN_TIMER_REARM_NS should be optimized */
411f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#define MIN_TIMER_REARM_NS 250000
412f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
413f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef _WIN32
414f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
415f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int mm_start_timer(struct qemu_alarm_timer *t);
416f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void mm_stop_timer(struct qemu_alarm_timer *t);
417f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void mm_rearm_timer(struct qemu_alarm_timer *t);
418f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
419f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int win32_start_timer(struct qemu_alarm_timer *t);
420f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void win32_stop_timer(struct qemu_alarm_timer *t);
421f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void win32_rearm_timer(struct qemu_alarm_timer *t);
422f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
423f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#else
424f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
425f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int unix_start_timer(struct qemu_alarm_timer *t);
426f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void unix_stop_timer(struct qemu_alarm_timer *t);
427f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
428f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef __linux__
429f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
430f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int dynticks_start_timer(struct qemu_alarm_timer *t);
431f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void dynticks_stop_timer(struct qemu_alarm_timer *t);
432f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void dynticks_rearm_timer(struct qemu_alarm_timer *t);
433f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
434f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif /* __linux__ */
435f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
436f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif /* _WIN32 */
437f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
438f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint64_t qemu_icount_round(int64_t count)
439f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
440f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
441f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
442f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
443f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic struct qemu_alarm_timer alarm_timers[] = {
444f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifndef _WIN32
445f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {"unix", unix_start_timer, unix_stop_timer, NULL},
446f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef __linux__
447f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* on Linux, the 'dynticks' clock sometimes doesn't work
448f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     * properly. this results in the UI freezing while emulation
449f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     * continues, for several seconds... So move it to the end
450f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     * of the list. */
451f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {"dynticks", dynticks_start_timer,
452f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     dynticks_stop_timer, dynticks_rearm_timer},
453f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
454f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#else
455f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {"mmtimer", mm_start_timer, mm_stop_timer, NULL},
456f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {"mmtimer2", mm_start_timer, mm_stop_timer, mm_rearm_timer},
457f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
458f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {"win32", win32_start_timer, win32_stop_timer, NULL},
459f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
460f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    {NULL, }
461f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner};
462f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
463f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void show_available_alarms(void)
464f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
465f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int i;
466f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
467f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    printf("Available alarm timers, in order of precedence:\n");
468f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for (i = 0; alarm_timers[i].name; i++)
469f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        printf("%s\n", alarm_timers[i].name);
470f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
471f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
472f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid configure_alarms(char const *opt)
473f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
474f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int i;
475f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int cur = 0;
476f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int count = ARRAY_SIZE(alarm_timers) - 1;
477f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    char *arg;
478f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    char *name;
479f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct qemu_alarm_timer tmp;
480f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
481f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!strcmp(opt, "?")) {
482f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        show_available_alarms();
483f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        exit(0);
484f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
485f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
486f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    arg = g_strdup(opt);
487f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
488f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* Reorder the array */
489f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    name = strtok(arg, ",");
490f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    while (name) {
491f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        for (i = 0; i < count && alarm_timers[i].name; i++) {
492f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            if (!strcmp(alarm_timers[i].name, name))
493f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                break;
494f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
495f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
496f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (i == count) {
497f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            fprintf(stderr, "Unknown clock %s\n", name);
498f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            goto next;
499f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        }
500f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
501f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (i < cur)
502f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            /* Ignore */
503f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            goto next;
504f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
505f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        /* Swap */
506f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        tmp = alarm_timers[i];
507f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        alarm_timers[i] = alarm_timers[cur];
508f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        alarm_timers[cur] = tmp;
509f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
510f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        cur++;
511f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnernext:
512f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        name = strtok(NULL, ",");
513f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
514f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
515f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    g_free(arg);
516f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
517f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (cur) {
518f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        /* Disable remaining timers */
519f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        for (i = cur; i < count; i++)
520f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            alarm_timers[i].name = NULL;
521f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    } else {
522f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        show_available_alarms();
523f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        exit(1);
524f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
525f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
526f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
527821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// This variable is used to notify the qemu_timer_alarm_pending() caller
528821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// (really tcg_cpu_exec()) that an alarm has expired. It is set in the
529821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// timer callback, which can be a signal handler on non-Windows platforms.
530821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turnerstatic volatile sig_atomic_t timer_alarm_pending = 1;
531f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
532f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint qemu_timer_alarm_pending(void)
533f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
534f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int ret = timer_alarm_pending;
535f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timer_alarm_pending = 0;
536f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return ret;
537f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
538f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
539821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// Compute the next alarm deadline, return a timeout in nanoseconds.
540821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// NOTE: This function cannot be called from a signal handler since
541821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner// it calls qemu-timer.c functions that acquire/release global mutexes.
542f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int64_t qemu_next_alarm_deadline(void)
543f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
544f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int64_t delta = INT32_MAX;
545f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!use_icount) {
546dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        delta = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
547f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
548dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t hdelta = qemu_clock_deadline_ns_all(QEMU_CLOCK_HOST);
549f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (hdelta < delta) {
550f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        delta = hdelta;
551f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
552dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    int64_t rtdelta = qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME);
553f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (rtdelta < delta) {
554f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        delta = rtdelta;
555f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
556f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return delta;
557f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
558f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
559821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner#ifdef _WIN32
560821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turnerstatic void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
561821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner#else
562821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turnerstatic void host_alarm_handler(int host_signum)
563821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner#endif
564f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
565821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    struct qemu_alarm_timer *t = alarm_timer;
566821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    if (!t)
567821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        return;
568f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
569821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // It's not possible to call qemu_next_alarm_deadline() to know
570821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // if a timer has really expired, in the case of non-dynamic alarms,
571821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // so just signal and let the main loop thread do the checks instead.
572821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    timer_alarm_pending = 1;
573f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
574821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // Ensure a dynamic alarm will be properly rescheduled.
575821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    if (alarm_has_dynticks(t))
576821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        t->expired = 1;
577f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
578821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // This forces a cpu_exit() call that will end the current CPU
579821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // execution ASAP.
580821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    qemu_notify_event();
581f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
582f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
583821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner#if defined(__linux__)
584f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
585f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int dynticks_start_timer(struct qemu_alarm_timer *t)
586f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
587f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct sigevent ev;
588f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timer_t host_timer;
589f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct sigaction act;
590f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
591f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    sigfillset(&act.sa_mask);
592f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    act.sa_flags = 0;
593f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    act.sa_handler = host_alarm_handler;
594f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
595f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    sigaction(SIGALRM, &act, NULL);
596f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
597f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /*
598f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     * Initialize ev struct to 0 to avoid valgrind complaining
599f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     * about uninitialized data in timer_create call
600f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner     */
601f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    memset(&ev, 0, sizeof(ev));
602f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    ev.sigev_value.sival_int = 0;
603f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    ev.sigev_notify = SIGEV_SIGNAL;
604f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    ev.sigev_signo = SIGALRM;
605f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
606f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
607f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        perror("timer_create");
608f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
609f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        /* disable dynticks */
610f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Dynamic Ticks disabled\n");
611f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
612f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -1;
613f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
614f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
615f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    t->timer = host_timer;
616f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
617f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
618f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
619f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
620f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void dynticks_stop_timer(struct qemu_alarm_timer *t)
621f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
622f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timer_t host_timer = t->timer;
623f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
624f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timer_delete(host_timer);
625f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
626f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
627f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void dynticks_rearm_timer(struct qemu_alarm_timer *t)
628f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
629f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timer_t host_timer = t->timer;
630f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct itimerspec timeout;
631f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int64_t nearest_delta_ns = INT64_MAX;
632f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int64_t current_ns;
633f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
634f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    assert(alarm_has_dynticks(t));
635dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!qemu_clock_has_timers(QEMU_CLOCK_REALTIME) &&
636dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        !qemu_clock_has_timers(QEMU_CLOCK_VIRTUAL) &&
637dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        !qemu_clock_has_timers(QEMU_CLOCK_HOST))
638f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return;
639f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
640f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    nearest_delta_ns = qemu_next_alarm_deadline();
641f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (nearest_delta_ns < MIN_TIMER_REARM_NS)
642f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        nearest_delta_ns = MIN_TIMER_REARM_NS;
643f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
644f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* check whether a timer is already running */
645f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (timer_gettime(host_timer, &timeout)) {
646f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        perror("gettime");
647f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Internal timer error: aborting\n");
648f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        exit(1);
649f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
650f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
651f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (current_ns && current_ns <= nearest_delta_ns)
652f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return;
653f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
654f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeout.it_interval.tv_sec = 0;
655f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
656f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeout.it_value.tv_sec =  nearest_delta_ns / 1000000000;
657f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
658f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
659f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        perror("settime");
660f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Internal timer error: aborting\n");
661f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        exit(1);
662f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
663f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
664f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
665f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif /* defined(__linux__) */
666f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
667f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#if !defined(_WIN32)
668f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
669f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int unix_start_timer(struct qemu_alarm_timer *t)
670f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
671f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct sigaction act;
672f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct itimerval itv;
673f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int err;
674f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
675f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* timer signal */
676f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    sigfillset(&act.sa_mask);
677f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    act.sa_flags = 0;
678f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    act.sa_handler = host_alarm_handler;
679f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
680f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    sigaction(SIGALRM, &act, NULL);
681f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
682f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    itv.it_interval.tv_sec = 0;
683f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* for i386 kernel 2.6 to get 1 ms */
684f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    itv.it_interval.tv_usec = 999;
685f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    itv.it_value.tv_sec = 0;
686f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    itv.it_value.tv_usec = 10 * 1000;
687f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
688f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    err = setitimer(ITIMER_REAL, &itv, NULL);
689f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (err)
690f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -1;
691f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
692f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
693f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
694f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
695f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void unix_stop_timer(struct qemu_alarm_timer *t)
696f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
697f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct itimerval itv;
698f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
699f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    memset(&itv, 0, sizeof(itv));
700f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    setitimer(ITIMER_REAL, &itv, NULL);
701f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
702f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
703f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif /* !defined(_WIN32) */
704f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
705f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
706f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef _WIN32
707f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
708f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic MMRESULT mm_timer;
709f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic unsigned mm_period;
710f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
711f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
712f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                                      DWORD_PTR dwUser, DWORD_PTR dw1,
713f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                                      DWORD_PTR dw2)
714f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
715f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct qemu_alarm_timer *t = alarm_timer;
716f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!t) {
717f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return;
718f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
719821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // We can actually call qemu_next_alarm_deadline() here since this
720821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    // doesn't run in a signal handler, but a different thread.
721f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {
722821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        t->expired = 1;
723821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        timer_alarm_pending = 1;
724f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        qemu_notify_event();
725f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
726f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
727f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
728f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int mm_start_timer(struct qemu_alarm_timer *t)
729f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
730f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    TIMECAPS tc;
731f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    UINT flags;
732f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
733f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    memset(&tc, 0, sizeof(tc));
734f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeGetDevCaps(&tc, sizeof(tc));
735f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
736f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    mm_period = tc.wPeriodMin;
737f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeBeginPeriod(mm_period);
738f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
739f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    flags = TIME_CALLBACK_FUNCTION;
740f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (alarm_has_dynticks(t)) {
741f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        flags |= TIME_ONESHOT;
742f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    } else {
743f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        flags |= TIME_PERIODIC;
744f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
745f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
746f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    mm_timer = timeSetEvent(1,                  /* interval (ms) */
747f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            mm_period,          /* resolution */
748f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            mm_alarm_handler,   /* function */
749f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            (DWORD_PTR)t,       /* parameter */
750f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                        flags);
751f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
752f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!mm_timer) {
753f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
754f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                GetLastError());
755f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        timeEndPeriod(mm_period);
756f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -1;
757f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
758f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
759f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
760f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
761f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
762f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void mm_stop_timer(struct qemu_alarm_timer *t)
763f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
764f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeKillEvent(mm_timer);
765f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeEndPeriod(mm_period);
766f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
767f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
768f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void mm_rearm_timer(struct qemu_alarm_timer *t)
769f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
770f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int nearest_delta_ms;
771f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
772f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    assert(alarm_has_dynticks(t));
773dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!qemu_clock_has_timers(QEMU_CLOCK_REALTIME) &&
774dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        !qemu_clock_has_timers(QEMU_CLOCK_VIRTUAL) &&
775dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        !qemu_clock_has_timers(QEMU_CLOCK_HOST)) {
776f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return;
777f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
778f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
779f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    timeKillEvent(mm_timer);
780f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
781f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
782f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (nearest_delta_ms < 1) {
783f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        nearest_delta_ms = 1;
784f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
785f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    mm_timer = timeSetEvent(nearest_delta_ms,
786f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            mm_period,
787f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            mm_alarm_handler,
788f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            (DWORD_PTR)t,
789f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                            TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
790f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
791f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!mm_timer) {
792f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",
793f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                GetLastError());
794f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
795f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        timeEndPeriod(mm_period);
796f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        exit(1);
797f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
798f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
799f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
800f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic int win32_start_timer(struct qemu_alarm_timer *t)
801f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
802f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    HANDLE hTimer;
803f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    BOOLEAN success;
804f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
805f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
806f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner       is zero) that has already expired, the timer is not updated.  Since
807f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner       creating a new timer is relatively expensive, set a bogus one-hour
808f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner       interval in the dynticks case.  */
809f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    success = CreateTimerQueueTimer(&hTimer,
810f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                          NULL,
811f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                          host_alarm_handler,
812f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                          t,
813f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                          1,
814f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                          alarm_has_dynticks(t) ? 3600000 : 1,
815f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                          WT_EXECUTEINTIMERTHREAD);
816f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
817f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!success) {
818f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
819f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                GetLastError());
820f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return -1;
821f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
822f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
823f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    t->timer = hTimer;
824f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
825f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
826f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
827f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void win32_stop_timer(struct qemu_alarm_timer *t)
828f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
829f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    HANDLE hTimer = t->timer;
830f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
831f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (hTimer) {
832f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        DeleteTimerQueueTimer(NULL, hTimer, NULL);
833f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
834f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
835f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
836f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerstatic void win32_rearm_timer(struct qemu_alarm_timer *t)
837f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
838f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    HANDLE hTimer = t->timer;
839f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int nearest_delta_ms;
840f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    BOOLEAN success;
841f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
842f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    assert(alarm_has_dynticks(t));
843dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (!qemu_clock_has_timers(QEMU_CLOCK_REALTIME) &&
844dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        !qemu_clock_has_timers(QEMU_CLOCK_VIRTUAL) &&
845dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        !qemu_clock_has_timers(QEMU_CLOCK_HOST)) {
846f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        return;
847dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
848f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
849f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (nearest_delta_ms < 1) {
850f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        nearest_delta_ms = 1;
851f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
852f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    success = ChangeTimerQueueTimer(NULL,
853f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                                    hTimer,
854f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                                    nearest_delta_ms,
855f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                                    3600000);
856f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
857f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!success) {
858f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
859f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                GetLastError());
860f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        exit(-1);
861f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
862f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
863f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
864f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif /* _WIN32 */
865f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
866c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turnerstatic void alarm_timer_on_change_state_rearm(void *opaque,
867c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner                                              int running,
868f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner                                              int reason)
869f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
870f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (running)
871f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque);
872f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
873f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
874f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint init_timer_alarm(void)
875f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
876f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct qemu_alarm_timer *t = NULL;
877f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int i, err = -1;
878f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
879f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    for (i = 0; alarm_timers[i].name; i++) {
880f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        t = &alarm_timers[i];
881f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
882f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        err = t->start(t);
883f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        if (!err)
884f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner            break;
885f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
886f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
887f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (err) {
888f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        err = -ENOENT;
889f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        goto fail;
890f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
891f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
892f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    /* first event is at time 0 */
893f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    alarm_timer = t;
894821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    timer_alarm_pending = 1;
895f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
896f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
897f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return 0;
898f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
899f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerfail:
900f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return err;
901f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
902f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
903f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnervoid quit_timers(void)
904f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
905f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    struct qemu_alarm_timer *t = alarm_timer;
906f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    alarm_timer = NULL;
907f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    t->stop(t);
908f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
909f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
910f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turnerint qemu_calculate_timeout(void)
911f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner{
912f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    int timeout;
913f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
914f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    if (!vm_running)
915f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        timeout = 5000;
916f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    else if (tcg_has_work())
917f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        timeout = 0;
918821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner    else {
919f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#ifdef WIN32
920f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        /* This corresponds to the case where the emulated system is
921f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         * totally idle and waiting for i/o. The problem is that on
922f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         * Windows, the default value will prevent Windows user events
923f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         * to be delivered in less than 5 seconds.
924f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         *
925f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         * Upstream contains a different way to handle this, for now
926f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         * this hack should be sufficient until we integrate it into
927f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         * our tree.
928f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner         */
929f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        timeout = 1000/15;  /* deliver user events every 15/th of second */
930f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#else
931f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner        timeout = 5000;
932f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner#endif
933821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        int64_t timeout_ns = (int64_t)timeout * 1000000LL;
934821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        timeout_ns = qemu_soonest_timeout(
935821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner                timeout_ns, timerlistgroup_deadline_ns(&main_loop_tlg));
936821f2bc9cc9601032715c1ef7e1a74a7fd036749David 'Digit' Turner        timeout = (int)((timeout_ns + 999999LL) / 1000000LL);
937f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    }
938f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner
939f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner    return timeout;
940f9077a88a0b9edca081b0810dde73d108db087a6David 'Digit' Turner}
941