119113504SJes Sorensen /* 219113504SJes Sorensen * os-win32.c 319113504SJes Sorensen * 419113504SJes Sorensen * Copyright (c) 2003-2008 Fabrice Bellard 519113504SJes Sorensen * Copyright (c) 2010 Red Hat, Inc. 619113504SJes Sorensen * 719113504SJes Sorensen * Permission is hereby granted, free of charge, to any person obtaining a copy 819113504SJes Sorensen * of this software and associated documentation files (the "Software"), to deal 919113504SJes Sorensen * in the Software without restriction, including without limitation the rights 1019113504SJes Sorensen * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1119113504SJes Sorensen * copies of the Software, and to permit persons to whom the Software is 1219113504SJes Sorensen * furnished to do so, subject to the following conditions: 1319113504SJes Sorensen * 1419113504SJes Sorensen * The above copyright notice and this permission notice shall be included in 1519113504SJes Sorensen * all copies or substantial portions of the Software. 1619113504SJes Sorensen * 1719113504SJes Sorensen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1819113504SJes Sorensen * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1919113504SJes Sorensen * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2019113504SJes Sorensen * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2119113504SJes Sorensen * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2219113504SJes Sorensen * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2319113504SJes Sorensen * THE SOFTWARE. 2419113504SJes Sorensen */ 2519113504SJes Sorensen #include <windows.h> 2619113504SJes Sorensen #include <unistd.h> 2719113504SJes Sorensen #include <fcntl.h> 2819113504SJes Sorensen #include <signal.h> 2919113504SJes Sorensen #include <time.h> 3019113504SJes Sorensen #include <errno.h> 3119113504SJes Sorensen #include <sys/time.h> 3219113504SJes Sorensen #include "config-host.h" 3319113504SJes Sorensen #include "sysemu.h" 3419113504SJes Sorensen 3519113504SJes Sorensen /***********************************************************/ 3619113504SJes Sorensen /* Polling handling */ 3719113504SJes Sorensen 3819113504SJes Sorensen typedef struct PollingEntry { 3919113504SJes Sorensen PollingFunc *func; 4019113504SJes Sorensen void *opaque; 4119113504SJes Sorensen struct PollingEntry *next; 4219113504SJes Sorensen } PollingEntry; 4319113504SJes Sorensen 4419113504SJes Sorensen static PollingEntry *first_polling_entry; 4519113504SJes Sorensen 4619113504SJes Sorensen int qemu_add_polling_cb(PollingFunc *func, void *opaque) 4719113504SJes Sorensen { 4819113504SJes Sorensen PollingEntry **ppe, *pe; 4919113504SJes Sorensen pe = qemu_mallocz(sizeof(PollingEntry)); 5019113504SJes Sorensen pe->func = func; 5119113504SJes Sorensen pe->opaque = opaque; 5219113504SJes Sorensen for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next); 5319113504SJes Sorensen *ppe = pe; 5419113504SJes Sorensen return 0; 5519113504SJes Sorensen } 5619113504SJes Sorensen 5719113504SJes Sorensen void qemu_del_polling_cb(PollingFunc *func, void *opaque) 5819113504SJes Sorensen { 5919113504SJes Sorensen PollingEntry **ppe, *pe; 6019113504SJes Sorensen for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) { 6119113504SJes Sorensen pe = *ppe; 6219113504SJes Sorensen if (pe->func == func && pe->opaque == opaque) { 6319113504SJes Sorensen *ppe = pe->next; 6419113504SJes Sorensen qemu_free(pe); 6519113504SJes Sorensen break; 6619113504SJes Sorensen } 6719113504SJes Sorensen } 6819113504SJes Sorensen } 6919113504SJes Sorensen 7019113504SJes Sorensen /***********************************************************/ 7119113504SJes Sorensen /* Wait objects support */ 7219113504SJes Sorensen typedef struct WaitObjects { 7319113504SJes Sorensen int num; 7419113504SJes Sorensen HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; 7519113504SJes Sorensen WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1]; 7619113504SJes Sorensen void *opaque[MAXIMUM_WAIT_OBJECTS + 1]; 7719113504SJes Sorensen } WaitObjects; 7819113504SJes Sorensen 7919113504SJes Sorensen static WaitObjects wait_objects = {0}; 8019113504SJes Sorensen 8119113504SJes Sorensen int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) 8219113504SJes Sorensen { 8319113504SJes Sorensen WaitObjects *w = &wait_objects; 8419113504SJes Sorensen 8519113504SJes Sorensen if (w->num >= MAXIMUM_WAIT_OBJECTS) 8619113504SJes Sorensen return -1; 8719113504SJes Sorensen w->events[w->num] = handle; 8819113504SJes Sorensen w->func[w->num] = func; 8919113504SJes Sorensen w->opaque[w->num] = opaque; 9019113504SJes Sorensen w->num++; 9119113504SJes Sorensen return 0; 9219113504SJes Sorensen } 9319113504SJes Sorensen 9419113504SJes Sorensen void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) 9519113504SJes Sorensen { 9619113504SJes Sorensen int i, found; 9719113504SJes Sorensen WaitObjects *w = &wait_objects; 9819113504SJes Sorensen 9919113504SJes Sorensen found = 0; 10019113504SJes Sorensen for (i = 0; i < w->num; i++) { 10119113504SJes Sorensen if (w->events[i] == handle) 10219113504SJes Sorensen found = 1; 10319113504SJes Sorensen if (found) { 10419113504SJes Sorensen w->events[i] = w->events[i + 1]; 10519113504SJes Sorensen w->func[i] = w->func[i + 1]; 10619113504SJes Sorensen w->opaque[i] = w->opaque[i + 1]; 10719113504SJes Sorensen } 10819113504SJes Sorensen } 10919113504SJes Sorensen if (found) 11019113504SJes Sorensen w->num--; 11119113504SJes Sorensen } 1120d93ca7cSJes Sorensen 1130d93ca7cSJes Sorensen void os_host_main_loop_wait(int *timeout) 1140d93ca7cSJes Sorensen { 1150d93ca7cSJes Sorensen int ret, ret2, i; 1160d93ca7cSJes Sorensen PollingEntry *pe; 1170d93ca7cSJes Sorensen 1180d93ca7cSJes Sorensen /* XXX: need to suppress polling by better using win32 events */ 1190d93ca7cSJes Sorensen ret = 0; 1200d93ca7cSJes Sorensen for(pe = first_polling_entry; pe != NULL; pe = pe->next) { 1210d93ca7cSJes Sorensen ret |= pe->func(pe->opaque); 1220d93ca7cSJes Sorensen } 1230d93ca7cSJes Sorensen if (ret == 0) { 1240d93ca7cSJes Sorensen int err; 1250d93ca7cSJes Sorensen WaitObjects *w = &wait_objects; 1260d93ca7cSJes Sorensen 1270d93ca7cSJes Sorensen ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout); 1280d93ca7cSJes Sorensen if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) { 1290d93ca7cSJes Sorensen if (w->func[ret - WAIT_OBJECT_0]) 1300d93ca7cSJes Sorensen w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]); 1310d93ca7cSJes Sorensen 1320d93ca7cSJes Sorensen /* Check for additional signaled events */ 1330d93ca7cSJes Sorensen for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) { 1340d93ca7cSJes Sorensen 1350d93ca7cSJes Sorensen /* Check if event is signaled */ 1360d93ca7cSJes Sorensen ret2 = WaitForSingleObject(w->events[i], 0); 1370d93ca7cSJes Sorensen if(ret2 == WAIT_OBJECT_0) { 1380d93ca7cSJes Sorensen if (w->func[i]) 1390d93ca7cSJes Sorensen w->func[i](w->opaque[i]); 1400d93ca7cSJes Sorensen } else if (ret2 == WAIT_TIMEOUT) { 1410d93ca7cSJes Sorensen } else { 1420d93ca7cSJes Sorensen err = GetLastError(); 1430d93ca7cSJes Sorensen fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); 1440d93ca7cSJes Sorensen } 1450d93ca7cSJes Sorensen } 1460d93ca7cSJes Sorensen } else if (ret == WAIT_TIMEOUT) { 1470d93ca7cSJes Sorensen } else { 1480d93ca7cSJes Sorensen err = GetLastError(); 1490d93ca7cSJes Sorensen fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err); 1500d93ca7cSJes Sorensen } 1510d93ca7cSJes Sorensen } 1520d93ca7cSJes Sorensen 1530d93ca7cSJes Sorensen *timeout = 0; 1540d93ca7cSJes Sorensen } 15569bd73b1SJes Sorensen 15669bd73b1SJes Sorensen static BOOL WINAPI qemu_ctrl_handler(DWORD type) 15769bd73b1SJes Sorensen { 15869bd73b1SJes Sorensen exit(STATUS_CONTROL_C_EXIT); 15969bd73b1SJes Sorensen return TRUE; 16069bd73b1SJes Sorensen } 16169bd73b1SJes Sorensen 162fe98ac14SJes Sorensen void os_setup_early_signal_handling(void) 16369bd73b1SJes Sorensen { 16469bd73b1SJes Sorensen /* Note: cpu_interrupt() is currently not SMP safe, so we force 16569bd73b1SJes Sorensen QEMU to run on a single CPU */ 16669bd73b1SJes Sorensen HANDLE h; 16769bd73b1SJes Sorensen DWORD mask, smask; 16869bd73b1SJes Sorensen int i; 16969bd73b1SJes Sorensen 17069bd73b1SJes Sorensen SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE); 17169bd73b1SJes Sorensen 17269bd73b1SJes Sorensen h = GetCurrentProcess(); 17369bd73b1SJes Sorensen if (GetProcessAffinityMask(h, &mask, &smask)) { 17469bd73b1SJes Sorensen for(i = 0; i < 32; i++) { 17569bd73b1SJes Sorensen if (mask & (1 << i)) 17669bd73b1SJes Sorensen break; 17769bd73b1SJes Sorensen } 17869bd73b1SJes Sorensen if (i != 32) { 17969bd73b1SJes Sorensen mask = 1 << i; 18069bd73b1SJes Sorensen SetProcessAffinityMask(h, mask); 18169bd73b1SJes Sorensen } 18269bd73b1SJes Sorensen } 18369bd73b1SJes Sorensen } 184*6170540bSJes Sorensen 185*6170540bSJes Sorensen /* Look for support files in the same directory as the executable. */ 186*6170540bSJes Sorensen char *os_find_datadir(const char *argv0) 187*6170540bSJes Sorensen { 188*6170540bSJes Sorensen char *p; 189*6170540bSJes Sorensen char buf[MAX_PATH]; 190*6170540bSJes Sorensen DWORD len; 191*6170540bSJes Sorensen 192*6170540bSJes Sorensen len = GetModuleFileName(NULL, buf, sizeof(buf) - 1); 193*6170540bSJes Sorensen if (len == 0) { 194*6170540bSJes Sorensen return NULL; 195*6170540bSJes Sorensen } 196*6170540bSJes Sorensen 197*6170540bSJes Sorensen buf[len] = 0; 198*6170540bSJes Sorensen p = buf + len - 1; 199*6170540bSJes Sorensen while (p != buf && *p != '\\') 200*6170540bSJes Sorensen p--; 201*6170540bSJes Sorensen *p = 0; 202*6170540bSJes Sorensen if (access(buf, R_OK) == 0) { 203*6170540bSJes Sorensen return qemu_strdup(buf); 204*6170540bSJes Sorensen } 205*6170540bSJes Sorensen return NULL; 206*6170540bSJes Sorensen } 207