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