xref: /qemu/os-win32.c (revision 6650b710)
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