From c27f813900a3c114562efbb8df1065e94766fc48 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 10 Feb 2009 15:43:59 -0800 Subject: auto import from //branches/cupcake/...@130745 --- osdep.c | 588 +++++++++++++--------------------------------------------------- 1 file changed, 117 insertions(+), 471 deletions(-) (limited to 'osdep.c') diff --git a/osdep.c b/osdep.c index b623e13..49193e9 100644 --- a/osdep.c +++ b/osdep.c @@ -27,256 +27,17 @@ #include #include #include - -#include "cpu.h" -#if defined(USE_KQEMU) -#include "vl.h" -#endif - -#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY) - -#include -#include - -/* When not using soft mmu, libc independant functions are needed for - the CPU core because it needs to use alternates stacks and - libc/thread incompatibles settings */ - -#include - -#define QEMU_SYSCALL0(name) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name)); \ -return __res; \ -} - -#define QEMU_SYSCALL1(name,arg1) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1))); \ -return __res; \ -} - -#define QEMU_SYSCALL2(name,arg1,arg2) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ -return __res; \ -} - -#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3))); \ -return __res; \ -} - -#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4))); \ -return __res; \ -} - -#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \ -{ \ -long __res; \ -__asm__ volatile ("int $0x80" \ - : "=a" (__res) \ - : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ -return __res; \ -} - -#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \ -{ \ -long __res; \ -__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \ - : "=a" (__res) \ - : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ - "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \ - "0" ((long)(arg6))); \ -return __res; \ -} - -int qemu_write(int fd, const void *buf, size_t n) -{ - QEMU_SYSCALL3(write, fd, buf, n); -} - - - -/****************************************************************/ -/* shmat replacement */ - -int qemu_ipc(int call, unsigned long first, - unsigned long second, unsigned long third, - void *ptr, unsigned long fifth) -{ - QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth); -} - -#define SHMAT 21 - -/* we must define shmat so that a specific address will be used when - mapping the X11 ximage */ -void *shmat(int shmid, const void *shmaddr, int shmflg) -{ - void *ptr; - int ret; - /* we give an address in the right memory area */ - if (!shmaddr) - shmaddr = get_mmap_addr(8192 * 1024); - ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0); - if (ret < 0) - return NULL; - return ptr; -} - -/****************************************************************/ -/* sigaction bypassing the threads */ - -static int kernel_sigaction(int signum, const struct qemu_sigaction *act, - struct qemu_sigaction *oldact, - int sigsetsize) -{ - QEMU_SYSCALL4(rt_sigaction, signum, act, oldact, sigsetsize); -} - -int qemu_sigaction(int signum, const struct qemu_sigaction *act, - struct qemu_sigaction *oldact) -{ - return kernel_sigaction(signum, act, oldact, 8); -} - -/****************************************************************/ -/* memory allocation */ - -//#define DEBUG_MALLOC - -#define MALLOC_BASE 0xab000000 -#define PHYS_RAM_BASE 0xac000000 - -#define MALLOC_ALIGN 16 -#define BLOCK_HEADER_SIZE 16 - -typedef struct MemoryBlock { - struct MemoryBlock *next; - unsigned long size; /* size of block, including header */ -} MemoryBlock; - -static MemoryBlock *first_free_block; -static unsigned long malloc_addr = MALLOC_BASE; - -static void *malloc_get_space(size_t size) -{ - void *ptr; - size = TARGET_PAGE_ALIGN(size); - ptr = mmap((void *)malloc_addr, size, - PROT_WRITE | PROT_READ, - MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); - if (ptr == MAP_FAILED) - return NULL; - malloc_addr += size; - return ptr; -} - -void *qemu_malloc(size_t size) -{ - MemoryBlock *mb, *mb1, **pmb; - void *ptr; - size_t size1, area_size; - - if (size == 0) - return NULL; - - size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1); - pmb = &first_free_block; - for(;;) { - mb = *pmb; - if (mb == NULL) - break; - if (size <= mb->size) - goto found; - pmb = &mb->next; - } - /* no big enough blocks found: get new space */ - area_size = TARGET_PAGE_ALIGN(size); - mb = malloc_get_space(area_size); - if (!mb) - return NULL; - size1 = area_size - size; - if (size1 > 0) { - /* create a new free block */ - mb1 = (MemoryBlock *)((uint8_t *)mb + size); - mb1->next = NULL; - mb1->size = size1; - *pmb = mb1; - } - goto the_end; - found: - /* a free block was found: use it */ - size1 = mb->size - size; - if (size1 > 0) { - /* create a new free block */ - mb1 = (MemoryBlock *)((uint8_t *)mb + size); - mb1->next = mb->next; - mb1->size = size1; - *pmb = mb1; - } else { - /* suppress the first block */ - *pmb = mb->next; - } - the_end: - mb->size = size; - mb->next = NULL; - ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE); -#ifdef DEBUG_MALLOC - qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr); +#include +#ifdef HOST_SOLARIS +#include +#include #endif - return ptr; -} - -void qemu_free(void *ptr) -{ - MemoryBlock *mb; - - if (!ptr) - return; - mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE); - mb->next = first_free_block; - first_free_block = mb; -} - -/****************************************************************/ -/* virtual memory allocation */ - -unsigned long mmap_addr = PHYS_RAM_BASE; -void *get_mmap_addr(unsigned long size) -{ - unsigned long addr; - addr = mmap_addr; - mmap_addr += ((size + 4095) & ~4095) + 4096; - return (void *)addr; -} - -#else +#include "qemu-common.h" +#include "sysemu.h" #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN #include #elif defined(_BSD) #include @@ -284,33 +45,13 @@ void *get_mmap_addr(unsigned long size) #include #endif -int qemu_write(int fd, const void *buf, size_t n) -{ - int ret; - ret = write(fd, buf, n); - if (ret < 0) - return -errno; - else - return ret; -} - -void *get_mmap_addr(unsigned long size) -{ - return NULL; -} - -void qemu_free(void *ptr) -{ - free(ptr); -} -void *qemu_malloc(size_t size) +#if defined(_WIN32) +void *qemu_memalign(size_t alignment, size_t size) { - return malloc(size); + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); } -#if defined(_WIN32) - void *qemu_vmalloc(size_t size) { /* FIXME: this is not exactly optimal solution since VirtualAlloc @@ -328,28 +69,48 @@ void qemu_vfree(void *ptr) #if defined(USE_KQEMU) +#ifdef __OpenBSD__ +#include +#include +#include +#else #include +#endif + #include #include -void *kqemu_vmalloc(size_t size) +static void *kqemu_vmalloc(size_t size) { static int phys_ram_fd = -1; static int phys_ram_size = 0; + void *ptr; + +#ifdef __OpenBSD__ /* no need (?) for a dummy file on OpenBSD */ + int map_anon = MAP_ANON; +#else + int map_anon = 0; const char *tmpdir; char phys_ram_file[1024]; - void *ptr; +#ifdef HOST_SOLARIS + struct statvfs stfs; +#else struct statfs stfs; +#endif if (phys_ram_fd < 0) { tmpdir = getenv("QEMU_TMPDIR"); if (!tmpdir) +#ifdef HOST_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; - extern int ram_size; free_space = (int64_t)stfs.f_bavail * stfs.f_bsize; if ((ram_size + 8192 * 1024) >= free_space) { ram_mb = (ram_size / (1024 * 1024)); @@ -358,8 +119,7 @@ void *kqemu_vmalloc(size_t size) 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" - "umount /dev/shm\n" - "mount -t tmpfs -o size=%dm none /dev/shm\n", + "mount -o remount,size=%dm /dev/shm\n", ram_mb + 16); } else { fprintf(stderr, @@ -373,7 +133,8 @@ void *kqemu_vmalloc(size_t size) } snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", tmpdir); - if (mkstemp(phys_ram_file) < 0) { + 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" @@ -381,25 +142,21 @@ void *kqemu_vmalloc(size_t size) tmpdir); snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX", "/tmp"); - if (mkstemp(phys_ram_file) < 0) { + 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); } } - phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0600); - if (phys_ram_fd < 0) { - fprintf(stderr, "Could not open 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__ */ ptr = mmap(NULL, size, - PROT_WRITE | PROT_READ, MAP_SHARED, + 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"); @@ -409,13 +166,29 @@ void *kqemu_vmalloc(size_t size) return ptr; } -void kqemu_vfree(void *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) + int ret; + void *ptr; + ret = posix_memalign(&ptr, alignment, size); + if (ret != 0) + return NULL; + return ptr; +#elif defined(_BSD) + return valloc(size); +#else + return memalign(alignment, size); +#endif +} + /* alloc shared memory pages */ void *qemu_vmalloc(size_t size) { @@ -441,202 +214,75 @@ void qemu_vfree(void *ptr) #endif -#endif - -void *qemu_mallocz(size_t size) +int qemu_create_pidfile(const char *filename) { - void *ptr; - ptr = qemu_malloc(size); - if (!ptr) - return NULL; - memset(ptr, 0, size); - return ptr; -} + char buffer[128]; + int len; +#ifndef _WIN32 + int fd; -char *qemu_strdup(const char *str) -{ - char *ptr; - ptr = qemu_malloc(strlen(str) + 1); - if (!ptr) - return NULL; - strcpy(ptr, str); - return ptr; -} + fd = open(filename, O_RDWR | O_CREAT, 0600); + if (fd == -1) + return -1; -/****************************************************************/ -/* printf support */ + if (lockf(fd, F_TLOCK, 0) == -1) + return -1; -static inline int qemu_isdigit(int c) -{ - return c >= '0' && c <= '9'; + len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); + if (write(fd, buffer, len) != len) + return -1; +#else + HANDLE file; + DWORD flags; + OVERLAPPED overlap; + BOOL ret; + + /* Open for writing with no sharing. */ + file = CreateFile(filename, GENERIC_WRITE, 0, 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); + if (ret == 0) + return -1; +#endif + return 0; } -#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) +#ifdef _WIN32 + +/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ +#define _W32_FT_OFFSET (116444736000000000ULL) -/* from BSD ppp sources */ -int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args) +int qemu_gettimeofday(qemu_timeval *tp) { - int c, i, n; - int width, prec, fillch; - int base, len, neg; - unsigned long val = 0; - const char *f; - char *str, *buf0; - char num[32]; - static const char hexchars[] = "0123456789abcdef"; - - buf0 = buf; - --buflen; - while (buflen > 0) { - for (f = fmt; *f != '%' && *f != 0; ++f) - ; - if (f > fmt) { - len = f - fmt; - if (len > buflen) - len = buflen; - memcpy(buf, fmt, len); - buf += len; - buflen -= len; - fmt = f; - } - if (*fmt == 0) - break; - c = *++fmt; - width = prec = 0; - fillch = ' '; - if (c == '0') { - fillch = '0'; - c = *++fmt; - } - if (c == '*') { - width = va_arg(args, int); - c = *++fmt; - } else { - while (qemu_isdigit(c)) { - width = width * 10 + c - '0'; - c = *++fmt; - } - } - if (c == '.') { - c = *++fmt; - if (c == '*') { - prec = va_arg(args, int); - c = *++fmt; - } else { - while (qemu_isdigit(c)) { - prec = prec * 10 + c - '0'; - c = *++fmt; - } - } - } - /* modifiers */ - switch(c) { - case 'l': - c = *++fmt; - break; - default: - break; - } - str = 0; - base = 0; - neg = 0; - ++fmt; - switch (c) { - case 'd': - i = va_arg(args, int); - if (i < 0) { - neg = 1; - val = -i; - } else - val = i; - base = 10; - break; - case 'o': - val = va_arg(args, unsigned int); - base = 8; - break; - case 'x': - case 'X': - val = va_arg(args, unsigned int); - base = 16; - break; - case 'p': - val = (unsigned long) va_arg(args, void *); - base = 16; - neg = 2; - break; - case 's': - str = va_arg(args, char *); - break; - case 'c': - num[0] = va_arg(args, int); - num[1] = 0; - str = num; - break; - default: - *buf++ = '%'; - if (c != '%') - --fmt; /* so %z outputs %z etc. */ - --buflen; - continue; - } - if (base != 0) { - str = num + sizeof(num); - *--str = 0; - while (str > num + neg) { - *--str = hexchars[val % base]; - val = val / base; - if (--prec <= 0 && val == 0) - break; - } - switch (neg) { - case 1: - *--str = '-'; - break; - case 2: - *--str = 'x'; - *--str = '0'; - break; - } - len = num + sizeof(num) - 1 - str; - } else { - len = strlen(str); - if (prec > 0 && len > prec) - len = prec; - } - if (width > 0) { - if (width > buflen) - width = buflen; - if ((n = width - len) > 0) { - buflen -= n; - for (; n > 0; --n) - *buf++ = fillch; - } - } - if (len > buflen) - len = buflen; - memcpy(buf, str, len); - buf += len; - buflen -= len; + union { + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; + + if(tp) + { + GetSystemTimeAsFileTime (&_now.ft); + tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL ); + tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); } - *buf = 0; - return buf - buf0; + /* Always return 0 as per Open Group Base Specifications Issue 6. + Do not set errno on error. */ + return 0; } +#endif /* _WIN32 */ -void qemu_vprintf(const char *fmt, va_list ap) -{ - char buf[1024]; - int len; - - len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap); - qemu_write(1, buf, len); -} - -void qemu_printf(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - qemu_vprintf(fmt, ap); - va_end(ap); -} -- cgit v1.1