File:  [Qemu by Fabrice Bellard] / qemu / os-win32.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:56:23 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.1

    1: /*
    2:  * os-win32.c
    3:  *
    4:  * Copyright (c) 2003-2008 Fabrice Bellard
    5:  * Copyright (c) 2010 Red Hat, Inc.
    6:  *
    7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    8:  * of this software and associated documentation files (the "Software"), to deal
    9:  * in the Software without restriction, including without limitation the rights
   10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   11:  * copies of the Software, and to permit persons to whom the Software is
   12:  * furnished to do so, subject to the following conditions:
   13:  *
   14:  * The above copyright notice and this permission notice shall be included in
   15:  * all copies or substantial portions of the Software.
   16:  *
   17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   23:  * THE SOFTWARE.
   24:  */
   25: #include <windows.h>
   26: #include <unistd.h>
   27: #include <fcntl.h>
   28: #include <signal.h>
   29: #include <time.h>
   30: #include <errno.h>
   31: #include <sys/time.h>
   32: #include "config-host.h"
   33: #include "sysemu.h"
   34: #include "qemu-options.h"
   35: 
   36: /***********************************************************/
   37: /* Functions missing in mingw */
   38: 
   39: int setenv(const char *name, const char *value, int overwrite)
   40: {
   41:     int result = 0;
   42:     if (overwrite || !getenv(name)) {
   43:         size_t length = strlen(name) + strlen(value) + 2;
   44:         char *string = qemu_malloc(length);
   45:         snprintf(string, length, "%s=%s", name, value);
   46:         result = putenv(string);
   47:     }
   48:     return result;
   49: }
   50: 
   51: /***********************************************************/
   52: /* Polling handling */
   53: 
   54: typedef struct PollingEntry {
   55:     PollingFunc *func;
   56:     void *opaque;
   57:     struct PollingEntry *next;
   58: } PollingEntry;
   59: 
   60: static PollingEntry *first_polling_entry;
   61: 
   62: int qemu_add_polling_cb(PollingFunc *func, void *opaque)
   63: {
   64:     PollingEntry **ppe, *pe;
   65:     pe = qemu_mallocz(sizeof(PollingEntry));
   66:     pe->func = func;
   67:     pe->opaque = opaque;
   68:     for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
   69:     *ppe = pe;
   70:     return 0;
   71: }
   72: 
   73: void qemu_del_polling_cb(PollingFunc *func, void *opaque)
   74: {
   75:     PollingEntry **ppe, *pe;
   76:     for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
   77:         pe = *ppe;
   78:         if (pe->func == func && pe->opaque == opaque) {
   79:             *ppe = pe->next;
   80:             qemu_free(pe);
   81:             break;
   82:         }
   83:     }
   84: }
   85: 
   86: /***********************************************************/
   87: /* Wait objects support */
   88: typedef struct WaitObjects {
   89:     int num;
   90:     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
   91:     WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
   92:     void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
   93: } WaitObjects;
   94: 
   95: static WaitObjects wait_objects = {0};
   96: 
   97: int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
   98: {
   99:     WaitObjects *w = &wait_objects;
  100: 
  101:     if (w->num >= MAXIMUM_WAIT_OBJECTS)
  102:         return -1;
  103:     w->events[w->num] = handle;
  104:     w->func[w->num] = func;
  105:     w->opaque[w->num] = opaque;
  106:     w->num++;
  107:     return 0;
  108: }
  109: 
  110: void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
  111: {
  112:     int i, found;
  113:     WaitObjects *w = &wait_objects;
  114: 
  115:     found = 0;
  116:     for (i = 0; i < w->num; i++) {
  117:         if (w->events[i] == handle)
  118:             found = 1;
  119:         if (found) {
  120:             w->events[i] = w->events[i + 1];
  121:             w->func[i] = w->func[i + 1];
  122:             w->opaque[i] = w->opaque[i + 1];
  123:         }
  124:     }
  125:     if (found)
  126:         w->num--;
  127: }
  128: 
  129: void os_host_main_loop_wait(int *timeout)
  130: {
  131:     int ret, ret2, i;
  132:     PollingEntry *pe;
  133: 
  134:     /* XXX: need to suppress polling by better using win32 events */
  135:     ret = 0;
  136:     for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
  137:         ret |= pe->func(pe->opaque);
  138:     }
  139:     if (ret == 0) {
  140:         int err;
  141:         WaitObjects *w = &wait_objects;
  142: 
  143:         qemu_mutex_unlock_iothread();
  144:         ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
  145:         qemu_mutex_lock_iothread();
  146:         if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
  147:             if (w->func[ret - WAIT_OBJECT_0])
  148:                 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
  149: 
  150:             /* Check for additional signaled events */
  151:             for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
  152: 
  153:                 /* Check if event is signaled */
  154:                 ret2 = WaitForSingleObject(w->events[i], 0);
  155:                 if(ret2 == WAIT_OBJECT_0) {
  156:                     if (w->func[i])
  157:                         w->func[i](w->opaque[i]);
  158:                 } else if (ret2 == WAIT_TIMEOUT) {
  159:                 } else {
  160:                     err = GetLastError();
  161:                     fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
  162:                 }
  163:             }
  164:         } else if (ret == WAIT_TIMEOUT) {
  165:         } else {
  166:             err = GetLastError();
  167:             fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
  168:         }
  169:     }
  170: 
  171:     *timeout = 0;
  172: }
  173: 
  174: static BOOL WINAPI qemu_ctrl_handler(DWORD type)
  175: {
  176:     exit(STATUS_CONTROL_C_EXIT);
  177:     return TRUE;
  178: }
  179: 
  180: void os_setup_early_signal_handling(void)
  181: {
  182:     /* Note: cpu_interrupt() is currently not SMP safe, so we force
  183:        QEMU to run on a single CPU */
  184:     HANDLE h;
  185:     DWORD_PTR mask, smask;
  186:     int i;
  187: 
  188:     SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
  189: 
  190:     h = GetCurrentProcess();
  191:     if (GetProcessAffinityMask(h, &mask, &smask)) {
  192:         for(i = 0; i < 32; i++) {
  193:             if (mask & (1 << i))
  194:                 break;
  195:         }
  196:         if (i != 32) {
  197:             mask = 1 << i;
  198:             SetProcessAffinityMask(h, mask);
  199:         }
  200:     }
  201: }
  202: 
  203: /* Look for support files in the same directory as the executable.  */
  204: char *os_find_datadir(const char *argv0)
  205: {
  206:     char *p;
  207:     char buf[MAX_PATH];
  208:     DWORD len;
  209: 
  210:     len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
  211:     if (len == 0) {
  212:         return NULL;
  213:     }
  214: 
  215:     buf[len] = 0;
  216:     p = buf + len - 1;
  217:     while (p != buf && *p != '\\')
  218:         p--;
  219:     *p = 0;
  220:     if (access(buf, R_OK) == 0) {
  221:         return qemu_strdup(buf);
  222:     }
  223:     return NULL;
  224: }
  225: 
  226: void os_set_line_buffering(void)
  227: {
  228:     setbuf(stdout, NULL);
  229:     setbuf(stderr, NULL);
  230: }
  231: 
  232: /*
  233:  * Parse OS specific command line options.
  234:  * return 0 if option handled, -1 otherwise
  235:  */
  236: void os_parse_cmd_args(int index, const char *optarg)
  237: {
  238:     return;
  239: }
  240: 
  241: void os_pidfile_error(void)
  242: {
  243:     fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
  244: }
  245: 
  246: int qemu_create_pidfile(const char *filename)
  247: {
  248:     char buffer[128];
  249:     int len;
  250:     HANDLE file;
  251:     OVERLAPPED overlap;
  252:     BOOL ret;
  253:     memset(&overlap, 0, sizeof(overlap));
  254: 
  255:     file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  256: 		      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  257: 
  258:     if (file == INVALID_HANDLE_VALUE) {
  259:         return -1;
  260:     }
  261:     len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid());
  262:     ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
  263: 		      &overlap, NULL);
  264:     if (ret == 0) {
  265:         return -1;
  266:     }
  267:     return 0;
  268: }
  269: 
  270: int qemu_get_thread_id(void)
  271: {
  272:     return GetCurrentThreadId();
  273: }

unix.superglobalmegacorp.com