1/* 2 * os-win32.c 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * Copyright (c) 2010 Red Hat, Inc. 6 * 7 * QEMU library functions for win32 which are shared between QEMU and 8 * the QEMU tools. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a copy 11 * of this software and associated documentation files (the "Software"), to deal 12 * in the Software without restriction, including without limitation the rights 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 * copies of the Software, and to permit persons to whom the Software is 15 * furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included in 18 * all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 */ 28#include <windows.h> 29#include <glib.h> 30#include <stdlib.h> 31#include "config-host.h" 32#include "sysemu/sysemu.h" 33#include "trace.h" 34#include "qemu/sockets.h" 35 36/* this must come after including "trace.h" */ 37#include <shlobj.h> 38 39void *qemu_oom_check(void *ptr) 40{ 41 if (ptr == NULL) { 42 fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); 43 abort(); 44 } 45 return ptr; 46} 47 48void *qemu_memalign(size_t alignment, size_t size) 49{ 50 void *ptr; 51 52 if (!size) { 53 abort(); 54 } 55 ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); 56 //trace_qemu_memalign(alignment, size, ptr); 57 return ptr; 58} 59 60void *qemu_vmalloc(size_t size) 61{ 62 void *ptr; 63 64 /* FIXME: this is not exactly optimal solution since VirtualAlloc 65 has 64Kb granularity, but at least it guarantees us that the 66 memory is page aligned. */ 67 if (!size) { 68 abort(); 69 } 70 ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); 71 //trace_qemu_vmalloc(size, ptr); 72 return ptr; 73} 74 75void *qemu_anon_ram_alloc(size_t size) 76{ 77 void *ptr; 78 79 /* FIXME: this is not exactly optimal solution since VirtualAlloc 80 has 64Kb granularity, but at least it guarantees us that the 81 memory is page aligned. */ 82 ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); 83 //trace_qemu_anon_ram_alloc(size, ptr); 84 return ptr; 85} 86 87void qemu_vfree(void *ptr) 88{ 89 //trace_qemu_vfree(ptr); 90 if (ptr) { 91 VirtualFree(ptr, 0, MEM_RELEASE); 92 } 93} 94 95void qemu_anon_ram_free(void *ptr, size_t size) 96{ 97 //trace_qemu_anon_ram_free(ptr, size); 98 if (ptr) { 99 VirtualFree(ptr, 0, MEM_RELEASE); 100 } 101} 102 103/* FIXME: add proper locking */ 104struct tm *gmtime_r(const time_t *timep, struct tm *result) 105{ 106 struct tm *p = gmtime(timep); 107 memset(result, 0, sizeof(*result)); 108 if (p) { 109 *result = *p; 110 p = result; 111 } 112 return p; 113} 114 115/* FIXME: add proper locking */ 116struct tm *localtime_r(const time_t *timep, struct tm *result) 117{ 118 struct tm *p = localtime(timep); 119 memset(result, 0, sizeof(*result)); 120 if (p) { 121 *result = *p; 122 p = result; 123 } 124 return p; 125} 126 127void qemu_set_block(int fd) 128{ 129 unsigned long opt = 0; 130 WSAEventSelect(fd, NULL, 0); 131 ioctlsocket(fd, FIONBIO, &opt); 132} 133 134void qemu_set_nonblock(int fd) 135{ 136 unsigned long opt = 1; 137 ioctlsocket(fd, FIONBIO, &opt); 138#ifndef CONFIG_ANDROID 139 qemu_fd_register(fd); 140#endif 141} 142 143int socket_set_fast_reuse(int fd) 144{ 145 /* Enabling the reuse of an endpoint that was used by a socket still in 146 * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows 147 * fast reuse is the default and SO_REUSEADDR does strange things. So we 148 * don't have to do anything here. More info can be found at: 149 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ 150 return 0; 151} 152 153int inet_aton(const char *cp, struct in_addr *ia) 154{ 155 uint32_t addr = inet_addr(cp); 156 if (addr == 0xffffffff) { 157 return 0; 158 } 159 ia->s_addr = addr; 160 return 1; 161} 162 163void qemu_set_cloexec(int fd) 164{ 165} 166 167/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ 168#define _W32_FT_OFFSET (116444736000000000ULL) 169 170int qemu_gettimeofday(qemu_timeval *tp) 171{ 172 union { 173 unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ 174 FILETIME ft; 175 } _now; 176 177 if(tp) { 178 GetSystemTimeAsFileTime (&_now.ft); 179 tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL ); 180 tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); 181 } 182 /* Always return 0 as per Open Group Base Specifications Issue 6. 183 Do not set errno on error. */ 184 return 0; 185} 186 187int qemu_get_thread_id(void) 188{ 189 return GetCurrentThreadId(); 190} 191 192char * 193qemu_get_local_state_pathname(const char *relative_pathname) 194{ 195 HRESULT result; 196 char base_path[MAX_PATH+1] = ""; 197 198 result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 199 /* SHGFP_TYPE_CURRENT */ 0, base_path); 200 if (result != S_OK) { 201 /* misconfigured environment */ 202 g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result); 203 abort(); 204 } 205 return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path, 206 relative_pathname); 207} 208 209#ifdef CONFIG_ANDROID 210int ffs(int x) { 211 int result = 0; 212 unsigned ux = (unsigned)x; 213 while (ux) { 214 if (ux & 1) 215 return result + 1; 216 ux >>= 1; 217 } 218 return 0; 219} 220#endif 221