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" 3459a5264bSJes Sorensen #include "qemu-options.h" 3519113504SJes Sorensen 3619113504SJes Sorensen /***********************************************************/ 370a1574bbSStefan Weil /* Functions missing in mingw */ 380a1574bbSStefan Weil 390a1574bbSStefan Weil int setenv(const char *name, const char *value, int overwrite) 400a1574bbSStefan Weil { 410a1574bbSStefan Weil int result = 0; 420a1574bbSStefan Weil if (overwrite || !getenv(name)) { 430a1574bbSStefan Weil size_t length = strlen(name) + strlen(value) + 2; 440a1574bbSStefan Weil char *string = qemu_malloc(length); 450a1574bbSStefan Weil snprintf(string, length, "%s=%s", name, value); 460a1574bbSStefan Weil result = putenv(string); 470a1574bbSStefan Weil } 480a1574bbSStefan Weil return result; 490a1574bbSStefan Weil } 500a1574bbSStefan Weil 510a1574bbSStefan Weil /***********************************************************/ 5219113504SJes Sorensen /* Polling handling */ 5319113504SJes Sorensen 5419113504SJes Sorensen typedef struct PollingEntry { 5519113504SJes Sorensen PollingFunc *func; 5619113504SJes Sorensen void *opaque; 5719113504SJes Sorensen struct PollingEntry *next; 5819113504SJes Sorensen } PollingEntry; 5919113504SJes Sorensen 6019113504SJes Sorensen static PollingEntry *first_polling_entry; 6119113504SJes Sorensen 6219113504SJes Sorensen int qemu_add_polling_cb(PollingFunc *func, void *opaque) 6319113504SJes Sorensen { 6419113504SJes Sorensen PollingEntry **ppe, *pe; 6519113504SJes Sorensen pe = qemu_mallocz(sizeof(PollingEntry)); 6619113504SJes Sorensen pe->func = func; 6719113504SJes Sorensen pe->opaque = opaque; 6819113504SJes Sorensen for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next); 6919113504SJes Sorensen *ppe = pe; 7019113504SJes Sorensen return 0; 7119113504SJes Sorensen } 7219113504SJes Sorensen 7319113504SJes Sorensen void qemu_del_polling_cb(PollingFunc *func, void *opaque) 7419113504SJes Sorensen { 7519113504SJes Sorensen PollingEntry **ppe, *pe; 7619113504SJes Sorensen for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) { 7719113504SJes Sorensen pe = *ppe; 7819113504SJes Sorensen if (pe->func == func && pe->opaque == opaque) { 7919113504SJes Sorensen *ppe = pe->next; 8019113504SJes Sorensen qemu_free(pe); 8119113504SJes Sorensen break; 8219113504SJes Sorensen } 8319113504SJes Sorensen } 8419113504SJes Sorensen } 8519113504SJes Sorensen 8619113504SJes Sorensen /***********************************************************/ 8719113504SJes Sorensen /* Wait objects support */ 8819113504SJes Sorensen typedef struct WaitObjects { 8919113504SJes Sorensen int num; 9019113504SJes Sorensen HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; 9119113504SJes Sorensen WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1]; 9219113504SJes Sorensen void *opaque[MAXIMUM_WAIT_OBJECTS + 1]; 9319113504SJes Sorensen } WaitObjects; 9419113504SJes Sorensen 9519113504SJes Sorensen static WaitObjects wait_objects = {0}; 9619113504SJes Sorensen 9719113504SJes Sorensen int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) 9819113504SJes Sorensen { 9919113504SJes Sorensen WaitObjects *w = &wait_objects; 10019113504SJes Sorensen 10119113504SJes Sorensen if (w->num >= MAXIMUM_WAIT_OBJECTS) 10219113504SJes Sorensen return -1; 10319113504SJes Sorensen w->events[w->num] = handle; 10419113504SJes Sorensen w->func[w->num] = func; 10519113504SJes Sorensen w->opaque[w->num] = opaque; 10619113504SJes Sorensen w->num++; 10719113504SJes Sorensen return 0; 10819113504SJes Sorensen } 10919113504SJes Sorensen 11019113504SJes Sorensen void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) 11119113504SJes Sorensen { 11219113504SJes Sorensen int i, found; 11319113504SJes Sorensen WaitObjects *w = &wait_objects; 11419113504SJes Sorensen 11519113504SJes Sorensen found = 0; 11619113504SJes Sorensen for (i = 0; i < w->num; i++) { 11719113504SJes Sorensen if (w->events[i] == handle) 11819113504SJes Sorensen found = 1; 11919113504SJes Sorensen if (found) { 12019113504SJes Sorensen w->events[i] = w->events[i + 1]; 12119113504SJes Sorensen w->func[i] = w->func[i + 1]; 12219113504SJes Sorensen w->opaque[i] = w->opaque[i + 1]; 12319113504SJes Sorensen } 12419113504SJes Sorensen } 12519113504SJes Sorensen if (found) 12619113504SJes Sorensen w->num--; 12719113504SJes Sorensen } 1280d93ca7cSJes Sorensen 1290d93ca7cSJes Sorensen void os_host_main_loop_wait(int *timeout) 1300d93ca7cSJes Sorensen { 1310d93ca7cSJes Sorensen int ret, ret2, i; 1320d93ca7cSJes Sorensen PollingEntry *pe; 1330d93ca7cSJes Sorensen 1340d93ca7cSJes Sorensen /* XXX: need to suppress polling by better using win32 events */ 1350d93ca7cSJes Sorensen ret = 0; 1360d93ca7cSJes Sorensen for(pe = first_polling_entry; pe != NULL; pe = pe->next) { 1370d93ca7cSJes Sorensen ret |= pe->func(pe->opaque); 1380d93ca7cSJes Sorensen } 1390d93ca7cSJes Sorensen if (ret == 0) { 1400d93ca7cSJes Sorensen int err; 1410d93ca7cSJes Sorensen WaitObjects *w = &wait_objects; 1420d93ca7cSJes Sorensen 1430d93ca7cSJes Sorensen ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout); 1440d93ca7cSJes Sorensen if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) { 1450d93ca7cSJes Sorensen if (w->func[ret - WAIT_OBJECT_0]) 1460d93ca7cSJes Sorensen w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]); 1470d93ca7cSJes Sorensen 1480d93ca7cSJes Sorensen /* Check for additional signaled events */ 1490d93ca7cSJes Sorensen for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) { 1500d93ca7cSJes Sorensen 1510d93ca7cSJes Sorensen /* Check if event is signaled */ 1520d93ca7cSJes Sorensen ret2 = WaitForSingleObject(w->events[i], 0); 1530d93ca7cSJes Sorensen if(ret2 == WAIT_OBJECT_0) { 1540d93ca7cSJes Sorensen if (w->func[i]) 1550d93ca7cSJes Sorensen w->func[i](w->opaque[i]); 1560d93ca7cSJes Sorensen } else if (ret2 == WAIT_TIMEOUT) { 1570d93ca7cSJes Sorensen } else { 1580d93ca7cSJes Sorensen err = GetLastError(); 1590d93ca7cSJes Sorensen fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); 1600d93ca7cSJes Sorensen } 1610d93ca7cSJes Sorensen } 1620d93ca7cSJes Sorensen } else if (ret == WAIT_TIMEOUT) { 1630d93ca7cSJes Sorensen } else { 1640d93ca7cSJes Sorensen err = GetLastError(); 1650d93ca7cSJes Sorensen fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err); 1660d93ca7cSJes Sorensen } 1670d93ca7cSJes Sorensen } 1680d93ca7cSJes Sorensen 1690d93ca7cSJes Sorensen *timeout = 0; 1700d93ca7cSJes Sorensen } 17169bd73b1SJes Sorensen 17269bd73b1SJes Sorensen static BOOL WINAPI qemu_ctrl_handler(DWORD type) 17369bd73b1SJes Sorensen { 17469bd73b1SJes Sorensen exit(STATUS_CONTROL_C_EXIT); 17569bd73b1SJes Sorensen return TRUE; 17669bd73b1SJes Sorensen } 17769bd73b1SJes Sorensen 178fe98ac14SJes Sorensen void os_setup_early_signal_handling(void) 17969bd73b1SJes Sorensen { 18069bd73b1SJes Sorensen /* Note: cpu_interrupt() is currently not SMP safe, so we force 18169bd73b1SJes Sorensen QEMU to run on a single CPU */ 18269bd73b1SJes Sorensen HANDLE h; 18369bd73b1SJes Sorensen DWORD mask, smask; 18469bd73b1SJes Sorensen int i; 18569bd73b1SJes Sorensen 18669bd73b1SJes Sorensen SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE); 18769bd73b1SJes Sorensen 18869bd73b1SJes Sorensen h = GetCurrentProcess(); 18969bd73b1SJes Sorensen if (GetProcessAffinityMask(h, &mask, &smask)) { 19069bd73b1SJes Sorensen for(i = 0; i < 32; i++) { 19169bd73b1SJes Sorensen if (mask & (1 << i)) 19269bd73b1SJes Sorensen break; 19369bd73b1SJes Sorensen } 19469bd73b1SJes Sorensen if (i != 32) { 19569bd73b1SJes Sorensen mask = 1 << i; 19669bd73b1SJes Sorensen SetProcessAffinityMask(h, mask); 19769bd73b1SJes Sorensen } 19869bd73b1SJes Sorensen } 19969bd73b1SJes Sorensen } 2006170540bSJes Sorensen 2016170540bSJes Sorensen /* Look for support files in the same directory as the executable. */ 2026170540bSJes Sorensen char *os_find_datadir(const char *argv0) 2036170540bSJes Sorensen { 2046170540bSJes Sorensen char *p; 2056170540bSJes Sorensen char buf[MAX_PATH]; 2066170540bSJes Sorensen DWORD len; 2076170540bSJes Sorensen 2086170540bSJes Sorensen len = GetModuleFileName(NULL, buf, sizeof(buf) - 1); 2096170540bSJes Sorensen if (len == 0) { 2106170540bSJes Sorensen return NULL; 2116170540bSJes Sorensen } 2126170540bSJes Sorensen 2136170540bSJes Sorensen buf[len] = 0; 2146170540bSJes Sorensen p = buf + len - 1; 2156170540bSJes Sorensen while (p != buf && *p != '\\') 2166170540bSJes Sorensen p--; 2176170540bSJes Sorensen *p = 0; 2186170540bSJes Sorensen if (access(buf, R_OK) == 0) { 2196170540bSJes Sorensen return qemu_strdup(buf); 2206170540bSJes Sorensen } 2216170540bSJes Sorensen return NULL; 2226170540bSJes Sorensen } 22359a5264bSJes Sorensen 224*6650b710SStefan Weil void os_set_line_buffering(void) 225*6650b710SStefan Weil { 226*6650b710SStefan Weil setbuf(stdout, NULL); 227*6650b710SStefan Weil setbuf(stderr, NULL); 228*6650b710SStefan Weil } 229*6650b710SStefan Weil 23059a5264bSJes Sorensen /* 23159a5264bSJes Sorensen * Parse OS specific command line options. 23259a5264bSJes Sorensen * return 0 if option handled, -1 otherwise 23359a5264bSJes Sorensen */ 23459a5264bSJes Sorensen void os_parse_cmd_args(int index, const char *optarg) 23559a5264bSJes Sorensen { 23659a5264bSJes Sorensen return; 23759a5264bSJes Sorensen } 238eb505be1SJes Sorensen 239eb505be1SJes Sorensen void os_pidfile_error(void) 240eb505be1SJes Sorensen { 241eb505be1SJes Sorensen fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); 242eb505be1SJes Sorensen } 243