* os-win32.c
*
* Copyright (c) 2003-2008 Fabrice Bellard
- * Copyright (c) 2010 Red Hat, Inc.
+ * Copyright (c) 2010-2016 Red Hat, Inc.
*
* QEMU library functions for win32 which are shared between QEMU and
* the QEMU tools.
* this file are based on code from GNOME glib-2 and use a different license,
* see the license comment there.
*/
+#include "qemu/osdep.h"
#include <windows.h>
-#include <glib.h>
-#include <stdlib.h>
-#include "config-host.h"
+#include "qapi/error.h"
#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
#include "trace.h"
#include "qemu/sockets.h"
+#include "qemu/cutils.h"
/* this must come after including "trace.h" */
#include <shlobj.h>
return qemu_oom_check(qemu_try_memalign(alignment, size));
}
-void *qemu_anon_ram_alloc(size_t size, uint64_t *align)
+static int get_allocation_granularity(void)
+{
+ SYSTEM_INFO system_info;
+
+ GetSystemInfo(&system_info);
+ return system_info.dwAllocationGranularity;
+}
+
+void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared)
{
void *ptr;
- /* FIXME: this is not exactly optimal solution since VirtualAlloc
- has 64Kb granularity, but at least it guarantees us that the
- memory is page aligned. */
ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
trace_qemu_anon_ram_alloc(size, ptr);
+
+ if (ptr && align) {
+ *align = MAX(get_allocation_granularity(), getpagesize());
+ }
return ptr;
}
}
}
+#ifndef CONFIG_LOCALTIME_R
/* FIXME: add proper locking */
struct tm *gmtime_r(const time_t *timep, struct tm *result)
{
}
return p;
}
+#endif /* CONFIG_LOCALTIME_R */
void qemu_set_block(int fd)
{
return 0;
}
+
+static int socket_error(void)
+{
+ switch (WSAGetLastError()) {
+ case 0:
+ return 0;
+ case WSAEINTR:
+ return EINTR;
+ case WSAEINVAL:
+ return EINVAL;
+ case WSA_INVALID_HANDLE:
+ return EBADF;
+ case WSA_NOT_ENOUGH_MEMORY:
+ return ENOMEM;
+ case WSA_INVALID_PARAMETER:
+ return EINVAL;
+ case WSAENAMETOOLONG:
+ return ENAMETOOLONG;
+ case WSAENOTEMPTY:
+ return ENOTEMPTY;
+ case WSAEWOULDBLOCK:
+ /* not using EWOULDBLOCK as we don't want code to have
+ * to check both EWOULDBLOCK and EAGAIN */
+ return EAGAIN;
+ case WSAEINPROGRESS:
+ return EINPROGRESS;
+ case WSAEALREADY:
+ return EALREADY;
+ case WSAENOTSOCK:
+ return ENOTSOCK;
+ case WSAEDESTADDRREQ:
+ return EDESTADDRREQ;
+ case WSAEMSGSIZE:
+ return EMSGSIZE;
+ case WSAEPROTOTYPE:
+ return EPROTOTYPE;
+ case WSAENOPROTOOPT:
+ return ENOPROTOOPT;
+ case WSAEPROTONOSUPPORT:
+ return EPROTONOSUPPORT;
+ case WSAEOPNOTSUPP:
+ return EOPNOTSUPP;
+ case WSAEAFNOSUPPORT:
+ return EAFNOSUPPORT;
+ case WSAEADDRINUSE:
+ return EADDRINUSE;
+ case WSAEADDRNOTAVAIL:
+ return EADDRNOTAVAIL;
+ case WSAENETDOWN:
+ return ENETDOWN;
+ case WSAENETUNREACH:
+ return ENETUNREACH;
+ case WSAENETRESET:
+ return ENETRESET;
+ case WSAECONNABORTED:
+ return ECONNABORTED;
+ case WSAECONNRESET:
+ return ECONNRESET;
+ case WSAENOBUFS:
+ return ENOBUFS;
+ case WSAEISCONN:
+ return EISCONN;
+ case WSAENOTCONN:
+ return ENOTCONN;
+ case WSAETIMEDOUT:
+ return ETIMEDOUT;
+ case WSAECONNREFUSED:
+ return ECONNREFUSED;
+ case WSAELOOP:
+ return ELOOP;
+ case WSAEHOSTUNREACH:
+ return EHOSTUNREACH;
+ default:
+ return EIO;
+ }
+}
+
int inet_aton(const char *cp, struct in_addr *ia)
{
uint32_t addr = inet_addr(cp);
return g_strdup(exec_dir);
}
+#if !GLIB_CHECK_VERSION(2, 50, 0)
/*
* The original implementation of g_poll from glib has a problem on Windows
* when using timeouts < 10 ms.
if (timeout == 0 && nhandles > 1) {
/* Remove the handle that fired */
int i;
- if (ready < nhandles - 1) {
- for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
- handles[i-1] = handles[i];
- }
+ for (i = ready - WAIT_OBJECT_0 + 1; i < nhandles; i++) {
+ handles[i-1] = handles[i];
}
nhandles--;
recursed_result = poll_rest(FALSE, handles, nhandles, fds, nfds, 0);
return retval;
}
+#endif
-size_t getpagesize(void)
+int getpagesize(void)
{
SYSTEM_INFO system_info;
return system_info.dwPageSize;
}
-void os_mem_prealloc(int fd, char *area, size_t memory)
+void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
+ Error **errp)
{
int i;
size_t pagesize = getpagesize();
memset(area + pagesize * i, 0, 1);
}
}
+
+
+char *qemu_get_pid_name(pid_t pid)
+{
+ /* XXX Implement me */
+ abort();
+}
+
+
+pid_t qemu_fork(Error **errp)
+{
+ errno = ENOSYS;
+ error_setg_errno(errp, errno,
+ "cannot fork child process");
+ return -1;
+}
+
+
+#undef connect
+int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ int ret;
+ ret = connect(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef listen
+int qemu_listen_wrap(int sockfd, int backlog)
+{
+ int ret;
+ ret = listen(sockfd, backlog);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef bind
+int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ int ret;
+ ret = bind(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef socket
+int qemu_socket_wrap(int domain, int type, int protocol)
+{
+ int ret;
+ ret = socket(domain, type, protocol);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef accept
+int qemu_accept_wrap(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen)
+{
+ int ret;
+ ret = accept(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef shutdown
+int qemu_shutdown_wrap(int sockfd, int how)
+{
+ int ret;
+ ret = shutdown(sockfd, how);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef ioctlsocket
+int qemu_ioctlsocket_wrap(int fd, int req, void *val)
+{
+ int ret;
+ ret = ioctlsocket(fd, req, val);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef closesocket
+int qemu_closesocket_wrap(int fd)
+{
+ int ret;
+ ret = closesocket(fd);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef getsockopt
+int qemu_getsockopt_wrap(int sockfd, int level, int optname,
+ void *optval, socklen_t *optlen)
+{
+ int ret;
+ ret = getsockopt(sockfd, level, optname, optval, optlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef setsockopt
+int qemu_setsockopt_wrap(int sockfd, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ int ret;
+ ret = setsockopt(sockfd, level, optname, optval, optlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef getpeername
+int qemu_getpeername_wrap(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen)
+{
+ int ret;
+ ret = getpeername(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef getsockname
+int qemu_getsockname_wrap(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen)
+{
+ int ret;
+ ret = getsockname(sockfd, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef send
+ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags)
+{
+ int ret;
+ ret = send(sockfd, buf, len, flags);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef sendto
+ssize_t qemu_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *addr, socklen_t addrlen)
+{
+ int ret;
+ ret = sendto(sockfd, buf, len, flags, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef recv
+ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags)
+{
+ int ret;
+ ret = recv(sockfd, buf, len, flags);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+
+#undef recvfrom
+ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *addr, socklen_t *addrlen)
+{
+ int ret;
+ ret = recvfrom(sockfd, buf, len, flags, addr, addrlen);
+ if (ret < 0) {
+ errno = socket_error();
+ }
+ return ret;
+}
+
+bool qemu_write_pidfile(const char *filename, Error **errp)
+{
+ char buffer[128];
+ int len;
+ HANDLE file;
+ OVERLAPPED overlap;
+ BOOL ret;
+ memset(&overlap, 0, sizeof(overlap));
+
+ file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (file == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "Failed to create PID file");
+ return false;
+ }
+ len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", (pid_t)getpid());
+ ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len,
+ NULL, &overlap);
+ CloseHandle(file);
+ if (ret == 0) {
+ error_setg(errp, "Failed to write PID file");
+ return false;
+ }
+ return true;
+}