From f7dd220a26b2c2153e3b331b06826934cac292fb Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 10 Sep 2010 10:59:22 +0200 Subject: upstream: osdep updates. + add CONFIG_ANDROID to config-host.h --- osdep.c | 388 +++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 236 insertions(+), 152 deletions(-) (limited to 'osdep.c') diff --git a/osdep.c b/osdep.c index e4ad738..37d3001 100644 --- a/osdep.c +++ b/osdep.c @@ -28,13 +28,18 @@ #include #include #include + +/* Needed early for CONFIG_BSD etc. */ +#include "config-host.h" + #ifdef CONFIG_SOLARIS #include #include #endif -/* Needed early for CONFIG_BSD etc. */ -#include "config-host.h" +#ifdef CONFIG_EVENTFD +#include +#endif #ifdef _WIN32 #include @@ -46,21 +51,30 @@ #include "qemu-common.h" #include "sysemu.h" +#include "qemu_socket.h" -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#elif defined(CONFIG_BSD) -#include +#if !defined(_POSIX_C_SOURCE) || defined(_WIN32) || defined(__sun__) +static void *oom_check(void *ptr) +{ + if (ptr == NULL) { +#if defined(_WIN32) + fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); #else -#include + fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); +#endif + abort(); + } + return ptr; +} #endif - #if defined(_WIN32) void *qemu_memalign(size_t alignment, size_t size) { - return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); + if (!size) { + abort(); + } + return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); } void *qemu_vmalloc(size_t size) @@ -68,7 +82,10 @@ void *qemu_vmalloc(size_t size) /* FIXME: this is not exactly optimal solution since VirtualAlloc has 64Kb granularity, but at least it guarantees us that the memory is page aligned. */ - return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); + if (!size) { + abort(); + } + return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); } void qemu_vfree(void *ptr) @@ -78,147 +95,33 @@ void qemu_vfree(void *ptr) #else -#if defined(CONFIG_KQEMU) - -#ifdef __OpenBSD__ -#include -#include -#include -#else -#ifndef __FreeBSD__ -#include -#endif -#endif - -#include -#include - -static void *kqemu_vmalloc(size_t size) -{ - static int phys_ram_fd = -1; - static int phys_ram_size = 0; - void *ptr; - -/* no need (?) for a dummy file on OpenBSD/FreeBSD */ -#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) - int map_anon = MAP_ANON; -#else - int map_anon = 0; - const char *tmpdir; - char phys_ram_file[1024]; -#ifdef CONFIG_SOLARIS - struct statvfs stfs; -#else - struct statfs stfs; -#endif - - if (phys_ram_fd < 0) { - tmpdir = getenv("QEMU_TMPDIR"); - if (!tmpdir) -#ifdef CONFIG_SOLARIS - tmpdir = "/tmp"; - if (statvfs(tmpdir, &stfs) == 0) { -#else - tmpdir = "/dev/shm"; - if (statfs(tmpdir, &stfs) == 0) { -#endif - int64_t free_space; - int ram_mb; - - free_space = (int64_t)stfs.f_bavail * stfs.f_bsize; - if ((ram_size + 8192 * 1024) >= free_space) { - ram_mb = (ram_size / (1024 * 1024)); - fprintf(stderr, - "You do not have enough space in '%s' for the %d MB of QEMU virtual RAM.\n", - tmpdir, ram_mb); - if (strcmp(tmpdir, "/dev/shm") == 0) { - fprintf(stderr, "To have more space available provided you have enough RAM and swap, do as root:\n" - "mount -o remount,size=%dm /dev/shm\n", - ram_mb + 16); - } else { - fprintf(stderr, - "Use the '-m' option of QEMU to diminish the amount of virtual RAM or use the\n" - "QEMU_TMPDIR environment variable to set another directory where the QEMU\n" - "temporary RAM file will be opened.\n"); - } - fprintf(stderr, "Or disable the accelerator module with -no-kqemu\n"); - exit(1); - } - } - snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", - tmpdir); - phys_ram_fd = mkstemp(phys_ram_file); - if (phys_ram_fd < 0) { - fprintf(stderr, - "warning: could not create temporary file in '%s'.\n" - "Use QEMU_TMPDIR to select a directory in a tmpfs filesystem.\n" - "Using '/tmp' as fallback.\n", - tmpdir); - snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", - "/tmp"); - phys_ram_fd = mkstemp(phys_ram_file); - if (phys_ram_fd < 0) { - fprintf(stderr, "Could not create temporary memory file '%s'\n", - phys_ram_file); - exit(1); - } - } - unlink(phys_ram_file); - } - size = (size + 4095) & ~4095; - ftruncate(phys_ram_fd, phys_ram_size + size); -#endif /* !(__OpenBSD__ || __FreeBSD__ || __DragonFly__) */ - ptr = mmap(NULL, - size, - PROT_WRITE | PROT_READ, map_anon | MAP_SHARED, - phys_ram_fd, phys_ram_size); - if (ptr == MAP_FAILED) { - fprintf(stderr, "Could not map physical memory\n"); - exit(1); - } - phys_ram_size += size; - return ptr; -} - -static void kqemu_vfree(void *ptr) -{ - /* may be useful some day, but currently we do not need to free */ -} - -#endif - void *qemu_memalign(size_t alignment, size_t size) { -#if defined(_POSIX_C_SOURCE) +#if defined(_POSIX_C_SOURCE) && !defined(__sun__) int ret; void *ptr; ret = posix_memalign(&ptr, alignment, size); - if (ret != 0) - return NULL; + if (ret != 0) { + fprintf(stderr, "Failed to allocate %zu B: %s\n", + size, strerror(ret)); + abort(); + } return ptr; #elif defined(CONFIG_BSD) - return valloc(size); + return oom_check(valloc(size)); #else - return memalign(alignment, size); + return oom_check(memalign(alignment, size)); #endif } /* alloc shared memory pages */ void *qemu_vmalloc(size_t size) { -#if defined(CONFIG_KQEMU) - if (kqemu_allowed) - return kqemu_vmalloc(size); -#endif return qemu_memalign(getpagesize(), size); } void qemu_vfree(void *ptr) { -#if defined(CONFIG_KQEMU) - if (kqemu_allowed) - kqemu_vfree(ptr); -#endif free(ptr); } @@ -231,7 +134,7 @@ int qemu_create_pidfile(const char *filename) #ifndef _WIN32 int fd; - fd = open(filename, O_RDWR | O_CREAT, 0600); + fd = qemu_open(filename, O_RDWR | O_CREAT, 0600); if (fd == -1) return -1; @@ -243,25 +146,16 @@ int qemu_create_pidfile(const char *filename) return -1; #else HANDLE file; - DWORD flags; OVERLAPPED overlap; BOOL ret; + memset(&overlap, 0, sizeof(overlap)); - /* Open for writing with no sharing. */ - file = CreateFile(filename, GENERIC_WRITE, 0, NULL, + file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) return -1; - flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY; - overlap.hEvent = 0; - /* Lock 1 byte. */ - ret = LockFileEx(file, flags, 0, 0, 1, &overlap); - if (ret == 0) - return -1; - - /* Write PID to file. */ len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len, &overlap, NULL); @@ -273,6 +167,13 @@ int qemu_create_pidfile(const char *filename) #ifdef _WIN32 +/* mingw32 needs ffs for compilations without optimization. */ +int ffs(int i) +{ + /* Use gcc's builtin ffs. */ + return __builtin_ffs(i); +} + /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ #define _W32_FT_OFFSET (116444736000000000ULL) @@ -293,18 +194,201 @@ int qemu_gettimeofday(qemu_timeval *tp) Do not set errno on error. */ return 0; } +#endif /* _WIN32 */ + -int ffs(int val) +#ifdef _WIN32 +#ifndef CONFIG_ANDROID +void socket_set_nonblock(int fd) { - int nn; - - for (nn = 0; nn < sizeof(int)*8; nn++) - if (val & (1 << nn)) - return nn+1; + unsigned long opt = 1; + ioctlsocket(fd, FIONBIO, &opt); +} +#endif +int inet_aton(const char *cp, struct in_addr *ia) +{ + uint32_t addr = inet_addr(cp); + if (addr == 0xffffffff) return 0; + ia->s_addr = addr; + return 1; } -#endif /* _WIN32 */ +void qemu_set_cloexec(int fd) +{ +} +#else +#ifndef CONFIG_ANDROID +void socket_set_nonblock(int fd) +{ + int f; + f = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, f | O_NONBLOCK); +} +#endif + +void qemu_set_cloexec(int fd) +{ + int f; + f = fcntl(fd, F_GETFD); + fcntl(fd, F_SETFD, f | FD_CLOEXEC); +} + +#endif + +/* + * Opens a file with FD_CLOEXEC set + */ +int qemu_open(const char *name, int flags, ...) +{ + int ret; + int mode = 0; + + if (flags & O_CREAT) { + va_list ap; + + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + +#ifdef O_CLOEXEC + ret = open(name, flags | O_CLOEXEC, mode); +#else + ret = open(name, flags, mode); + if (ret >= 0) { + qemu_set_cloexec(ret); + } +#endif + + return ret; +} + +/* + * A variant of write(2) which handles partial write. + * + * Return the number of bytes transferred. + * Set errno if fewer than `count' bytes are written. + * + * This function don't work with non-blocking fd's. + * Any of the possibilities with non-bloking fd's is bad: + * - return a short write (then name is wrong) + * - busy wait adding (errno == EAGAIN) to the loop + */ +ssize_t qemu_write_full(int fd, const void *buf, size_t count) +{ + ssize_t ret = 0; + ssize_t total = 0; + + while (count) { + ret = write(fd, buf, count); + if (ret < 0) { + if (errno == EINTR) + continue; + break; + } + + count -= ret; + buf += ret; + total += ret; + } + + return total; +} + +#ifndef _WIN32 +/* + * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set. + */ +int qemu_eventfd(int fds[2]) +{ +#ifdef CONFIG_EVENTFD + int ret; + + ret = eventfd(0, 0); + if (ret >= 0) { + fds[0] = ret; + qemu_set_cloexec(ret); + if ((fds[1] = dup(ret)) == -1) { + close(ret); + return -1; + } + qemu_set_cloexec(fds[1]); + return 0; + } + + if (errno != ENOSYS) { + return -1; + } +#endif + + return qemu_pipe(fds); +} + +/* + * Creates a pipe with FD_CLOEXEC set on both file descriptors + */ +int qemu_pipe(int pipefd[2]) +{ + int ret; + +#ifdef CONFIG_PIPE2 + ret = pipe2(pipefd, O_CLOEXEC); + if (ret != -1 || errno != ENOSYS) { + return ret; + } +#endif + ret = pipe(pipefd); + if (ret == 0) { + qemu_set_cloexec(pipefd[0]); + qemu_set_cloexec(pipefd[1]); + } + + return ret; +} +#endif + +/* + * Opens a socket with FD_CLOEXEC set + */ +int qemu_socket(int domain, int type, int protocol) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socket(domain, type | SOCK_CLOEXEC, protocol); + if (ret != -1 || errno != EINVAL) { + return ret; + } +#endif + ret = socket(domain, type, protocol); + if (ret >= 0) { + qemu_set_cloexec(ret); + } + + return ret; +} + +/* + * Accept a connection and set FD_CLOEXEC + */ +int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int ret; + +#ifdef CONFIG_ACCEPT4 + ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); + if (ret != -1 || errno != ENOSYS) { + return ret; + } +#endif + ret = accept(s, addr, addrlen); + if (ret >= 0) { + qemu_set_cloexec(ret); + } + + return ret; +} -- cgit v1.1