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