File:  [Qemu by Fabrice Bellard] / qemu / os-win32.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:34:06 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

    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:         ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
  144:         if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
  145:             if (w->func[ret - WAIT_OBJECT_0])
  146:                 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
  147: 
  148:             /* Check for additional signaled events */
  149:             for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
  150: 
  151:                 /* Check if event is signaled */
  152:                 ret2 = WaitForSingleObject(w->events[i], 0);
  153:                 if(ret2 == WAIT_OBJECT_0) {
  154:                     if (w->func[i])
  155:                         w->func[i](w->opaque[i]);
  156:                 } else if (ret2 == WAIT_TIMEOUT) {
  157:                 } else {
  158:                     err = GetLastError();
  159:                     fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
  160:                 }
  161:             }
  162:         } else if (ret == WAIT_TIMEOUT) {
  163:         } else {
  164:             err = GetLastError();
  165:             fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
  166:         }
  167:     }
  168: 
  169:     *timeout = 0;
  170: }
  171: 
  172: static BOOL WINAPI qemu_ctrl_handler(DWORD type)
  173: {
  174:     exit(STATUS_CONTROL_C_EXIT);
  175:     return TRUE;
  176: }
  177: 
  178: void os_setup_early_signal_handling(void)
  179: {
  180:     /* Note: cpu_interrupt() is currently not SMP safe, so we force
  181:        QEMU to run on a single CPU */
  182:     HANDLE h;
  183:     DWORD mask, smask;
  184:     int i;
  185: 
  186:     SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
  187: 
  188:     h = GetCurrentProcess();
  189:     if (GetProcessAffinityMask(h, &mask, &smask)) {
  190:         for(i = 0; i < 32; i++) {
  191:             if (mask & (1 << i))
  192:                 break;
  193:         }
  194:         if (i != 32) {
  195:             mask = 1 << i;
  196:             SetProcessAffinityMask(h, mask);
  197:         }
  198:     }
  199: }
  200: 
  201: /* Look for support files in the same directory as the executable.  */
  202: char *os_find_datadir(const char *argv0)
  203: {
  204:     char *p;
  205:     char buf[MAX_PATH];
  206:     DWORD len;
  207: 
  208:     len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
  209:     if (len == 0) {
  210:         return NULL;
  211:     }
  212: 
  213:     buf[len] = 0;
  214:     p = buf + len - 1;
  215:     while (p != buf && *p != '\\')
  216:         p--;
  217:     *p = 0;
  218:     if (access(buf, R_OK) == 0) {
  219:         return qemu_strdup(buf);
  220:     }
  221:     return NULL;
  222: }
  223: 
  224: void os_set_line_buffering(void)
  225: {
  226:     setbuf(stdout, NULL);
  227:     setbuf(stderr, NULL);
  228: }
  229: 
  230: /*
  231:  * Parse OS specific command line options.
  232:  * return 0 if option handled, -1 otherwise
  233:  */
  234: void os_parse_cmd_args(int index, const char *optarg)
  235: {
  236:     return;
  237: }
  238: 
  239: void os_pidfile_error(void)
  240: {
  241:     fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
  242: }
  243: 
  244: int qemu_create_pidfile(const char *filename)
  245: {
  246:     char buffer[128];
  247:     int len;
  248:     HANDLE file;
  249:     OVERLAPPED overlap;
  250:     BOOL ret;
  251:     memset(&overlap, 0, sizeof(overlap));
  252: 
  253:     file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  254: 		      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  255: 
  256:     if (file == INVALID_HANDLE_VALUE) {
  257:         return -1;
  258:     }
  259:     len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
  260:     ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
  261: 		      &overlap, NULL);
  262:     if (ret == 0) {
  263:         return -1;
  264:     }
  265:     return 0;
  266: }

unix.superglobalmegacorp.com