<qemu-common.h>, <osdep.h>: upstream integration.
Change-Id: I418ead66b929af81bd158114afe56387c9939a97
diff --git a/bt-host.c b/bt-host.c
index f80e685..26cb22c 100644
--- a/bt-host.c
+++ b/bt-host.c
@@ -171,7 +171,7 @@
hci_filter_all_ptypes(&flt);
hci_filter_all_events(&flt);
- if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+ if (qemu_setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
fprintf(stderr, "qemu: Can't set HCI filter on socket (%i)\n", errno);
return 0;
}
diff --git a/gdbstub.c b/gdbstub.c
index bed1b52..2078f11 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2253,7 +2253,7 @@
/* set short latency */
val = 1;
- setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+ qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
s = g_malloc0(sizeof(GDBState));
s->c_cpu = first_cpu;
@@ -2279,7 +2279,7 @@
/* allow fast reuse */
val = 1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+ qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
diff --git a/include/android/sockets.h b/include/android/sockets.h
index 6ce3041..47d6c91 100644
--- a/include/android/sockets.h
+++ b/include/android/sockets.h
@@ -339,6 +339,9 @@
/* set socket in blocking mode */
int socket_set_blocking(int fd);
+/* set cork mode on Linux (if set, don't send partial frames). */
+int socket_set_cork(int fd, int value);
+
/* disable the TCP Nagle algorithm for lower latency */
int socket_set_nodelay(int fd);
diff --git a/include/qemu-common.h b/include/qemu-common.h
index cfbe415..48c3324 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -75,20 +75,6 @@
#define TIME_MAX LONG_MAX
#endif
-#ifndef CONFIG_IOVEC
-#define CONFIG_IOVEC
-struct iovec {
- void *iov_base;
- size_t iov_len;
-};
-/*
- * Use the same value as Linux for now.
- */
-#define IOV_MAX 1024
-#else
-#include <sys/uio.h>
-#endif
-
typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
@@ -240,6 +226,10 @@
int qemu_open(const char *name, int flags, ...);
ssize_t qemu_write_full(int fd, const void *buf, size_t count)
QEMU_WARN_UNUSED_RESULT;
+ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
+ QEMU_WARN_UNUSED_RESULT;
+ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
+ QEMU_WARN_UNUSED_RESULT;
void qemu_set_cloexec(int fd);
#ifndef _WIN32
@@ -248,6 +238,36 @@
int qemu_pipe(int pipefd[2]);
#endif
+#ifdef CONFIG_ANDROID
+int qemu_recv(int sock, void* buf, size_t len, int flags);
+
+int qemu_getsockopt(int sockfd, int level, int optname,
+ void* optval, size_t* optlen);
+
+int qemu_setsockopt(int sockfd, int level, int optname,
+ const void* optval, size_t optlen);
+
+#else // !CONFIG_ANDROID
+#ifdef _WIN32
+/* MinGW needs type casts for the 'buf' and 'optval' arguments. */
+#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \
+ getsockopt(sockfd, level, optname, optval, optlen);
+#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \
+ setsockopt(sockfd, level, optname, (const void *)optval, optlen)
+#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags)
+#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \
+ sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen)
+#else
+#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \
+ getsockopt(sockfd, level, optname, optval, optlen)
+#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \
+ setsockopt(sockfd, level, optname, optval, optlen)
+#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
+#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \
+ sendto(sockfd, buf, len, flags, destaddr, addrlen)
+#endif
+#endif // !CONFIG_ANDROID
+
void *get_mmap_addr(unsigned long size);
@@ -334,12 +354,19 @@
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
-void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t offset, size_t size);
+void qemu_iovec_concat(QEMUIOVector *dst,
+ QEMUIOVector *src, size_t soffset, size_t sbytes);
+void qemu_iovec_concat_iov(QEMUIOVector *dst,
+ struct iovec *src_iov, unsigned int src_cnt,
+ size_t soffset, size_t sbytes);
void qemu_iovec_destroy(QEMUIOVector *qiov);
void qemu_iovec_reset(QEMUIOVector *qiov);
-size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, void *buf, size_t count);
-size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, const void *buf, size_t count);
-size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, int c, size_t count);
+size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
+ void *buf, size_t bytes);
+size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
+ const void *buf, size_t bytes);
+size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
+ int fillc, size_t bytes);
bool buffer_is_zero(const void *buf, size_t len);
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 7ff1617..0f688c1 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -22,41 +22,46 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#ifndef HOST_UTILS_H
+#define HOST_UTILS_H 1
-#include "qemu/osdep.h"
+#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */
+#include <limits.h>
-#if defined(__x86_64__)
-#define __HAVE_FAST_MULU64__
+#ifdef CONFIG_INT128
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
uint64_t a, uint64_t b)
{
- __asm__ ("mul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b));
+ __uint128_t r = (__uint128_t)a * b;
+ *plow = r;
+ *phigh = r >> 64;
}
-#define __HAVE_FAST_MULS64__
+
static inline void muls64(uint64_t *plow, uint64_t *phigh,
int64_t a, int64_t b)
{
- __asm__ ("imul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b));
+ __int128_t r = (__int128_t)a * b;
+ *plow = r;
+ *phigh = r >> 64;
}
#else
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
#endif
-/* Binary search for leading zeros. */
-
+/**
+ * clz32 - count leading zeros in a 32-bit value.
+ * @val: The value to search
+ *
+ * Returns 32 if the value is zero. Note that the GCC builtin is
+ * undefined if the value is zero.
+ */
static inline int clz32(uint32_t val)
{
#if QEMU_GNUC_PREREQ(3, 4)
- if (val)
- return __builtin_clz(val);
- else
- return 32;
+ return val ? __builtin_clz(val) : 32;
#else
+ /* Binary search for the leading one bit. */
int cnt = 0;
if (!(val & 0xFFFF0000U)) {
@@ -86,18 +91,28 @@
#endif
}
+/**
+ * clo32 - count leading ones in a 32-bit value.
+ * @val: The value to search
+ *
+ * Returns 32 if the value is -1.
+ */
static inline int clo32(uint32_t val)
{
return clz32(~val);
}
+/**
+ * clz64 - count leading zeros in a 64-bit value.
+ * @val: The value to search
+ *
+ * Returns 64 if the value is zero. Note that the GCC builtin is
+ * undefined if the value is zero.
+ */
static inline int clz64(uint64_t val)
{
#if QEMU_GNUC_PREREQ(3, 4)
- if (val)
- return __builtin_clzll(val);
- else
- return 64;
+ return val ? __builtin_clzll(val) : 64;
#else
int cnt = 0;
@@ -111,19 +126,30 @@
#endif
}
+/**
+ * clo64 - count leading ones in a 64-bit value.
+ * @val: The value to search
+ *
+ * Returns 64 if the value is -1.
+ */
static inline int clo64(uint64_t val)
{
return clz64(~val);
}
+/**
+ * ctz32 - count trailing zeros in a 32-bit value.
+ * @val: The value to search
+ *
+ * Returns 32 if the value is zero. Note that the GCC builtin is
+ * undefined if the value is zero.
+ */
static inline int ctz32(uint32_t val)
{
#if QEMU_GNUC_PREREQ(3, 4)
- if (val)
- return __builtin_ctz(val);
- else
- return 32;
+ return val ? __builtin_ctz(val) : 32;
#else
+ /* Binary search for the trailing one bit. */
int cnt;
cnt = 0;
@@ -155,18 +181,28 @@
#endif
}
+/**
+ * cto32 - count trailing ones in a 32-bit value.
+ * @val: The value to search
+ *
+ * Returns 32 if the value is -1.
+ */
static inline int cto32(uint32_t val)
{
return ctz32(~val);
}
+/**
+ * ctz64 - count trailing zeros in a 64-bit value.
+ * @val: The value to search
+ *
+ * Returns 64 if the value is zero. Note that the GCC builtin is
+ * undefined if the value is zero.
+ */
static inline int ctz64(uint64_t val)
{
#if QEMU_GNUC_PREREQ(3, 4)
- if (val)
- return __builtin_ctzll(val);
- else
- return 64;
+ return val ? __builtin_ctzll(val) : 64;
#else
int cnt;
@@ -180,30 +216,56 @@
#endif
}
+/**
+ * ctz64 - count trailing ones in a 64-bit value.
+ * @val: The value to search
+ *
+ * Returns 64 if the value is -1.
+ */
static inline int cto64(uint64_t val)
{
return ctz64(~val);
}
+/**
+ * ctpop8 - count the population of one bits in an 8-bit value.
+ * @val: The value to search
+ */
static inline int ctpop8(uint8_t val)
{
+#if QEMU_GNUC_PREREQ(3, 4)
+ return __builtin_popcount(val);
+#else
val = (val & 0x55) + ((val >> 1) & 0x55);
val = (val & 0x33) + ((val >> 2) & 0x33);
val = (val & 0x0f) + ((val >> 4) & 0x0f);
return val;
+#endif
}
+/**
+ * ctpop16 - count the population of one bits in a 16-bit value.
+ * @val: The value to search
+ */
static inline int ctpop16(uint16_t val)
{
+#if QEMU_GNUC_PREREQ(3, 4)
+ return __builtin_popcount(val);
+#else
val = (val & 0x5555) + ((val >> 1) & 0x5555);
val = (val & 0x3333) + ((val >> 2) & 0x3333);
val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
return val;
+#endif
}
+/**
+ * ctpop32 - count the population of one bits in a 32-bit value.
+ * @val: The value to search
+ */
static inline int ctpop32(uint32_t val)
{
#if QEMU_GNUC_PREREQ(3, 4)
@@ -219,6 +281,10 @@
#endif
}
+/**
+ * ctpop64 - count the population of one bits in a 64-bit value.
+ * @val: The value to search
+ */
static inline int ctpop64(uint64_t val)
{
#if QEMU_GNUC_PREREQ(3, 4)
@@ -234,3 +300,23 @@
return val;
#endif
}
+
+/* Host type specific sizes of these routines. */
+
+#if ULONG_MAX == UINT32_MAX
+# define clzl clz32
+# define ctzl ctz32
+# define clol clo32
+# define ctol cto32
+# define ctpopl ctpop32
+#elif ULONG_MAX == UINT64_MAX
+# define clzl clz64
+# define ctzl ctz64
+# define clol clo64
+# define ctol cto64
+# define ctpopl ctpop64
+#else
+# error Unknown sizeof long
+#endif
+
+#endif
diff --git a/include/qemu/int128.h b/include/qemu/int128.h
new file mode 100644
index 0000000..9ed47aa
--- /dev/null
+++ b/include/qemu/int128.h
@@ -0,0 +1,144 @@
+#ifndef INT128_H
+#define INT128_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct Int128 Int128;
+
+struct Int128 {
+ uint64_t lo;
+ int64_t hi;
+};
+
+static inline Int128 int128_make64(uint64_t a)
+{
+ return (Int128) { a, 0 };
+}
+
+static inline uint64_t int128_get64(Int128 a)
+{
+ assert(!a.hi);
+ return a.lo;
+}
+
+static inline Int128 int128_zero(void)
+{
+ return int128_make64(0);
+}
+
+static inline Int128 int128_one(void)
+{
+ return int128_make64(1);
+}
+
+static inline Int128 int128_2_64(void)
+{
+ return (Int128) { 0, 1 };
+}
+
+static inline Int128 int128_and(Int128 a, Int128 b)
+{
+ return (Int128) { a.lo & b.lo, a.hi & b.hi };
+}
+
+static inline Int128 int128_rshift(Int128 a, int n)
+{
+ int64_t h;
+ if (!n) {
+ return a;
+ }
+ h = a.hi >> (n & 63);
+ if (n >= 64) {
+ return (Int128) { h, h >> 63 };
+ } else {
+ return (Int128) { (a.lo >> n) | (a.hi << (64 - n)), h };
+ }
+}
+
+static inline Int128 int128_add(Int128 a, Int128 b)
+{
+ uint64_t lo = a.lo + b.lo;
+
+ /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence,
+ * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
+ * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
+ *
+ * So the carry is lo < a.lo.
+ */
+ return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
+}
+
+static inline Int128 int128_neg(Int128 a)
+{
+ uint64_t lo = -a.lo;
+ return (Int128) { lo, ~(uint64_t)a.hi + !lo };
+}
+
+static inline Int128 int128_sub(Int128 a, Int128 b)
+{
+ return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
+}
+
+static inline bool int128_nonneg(Int128 a)
+{
+ return a.hi >= 0;
+}
+
+static inline bool int128_eq(Int128 a, Int128 b)
+{
+ return a.lo == b.lo && a.hi == b.hi;
+}
+
+static inline bool int128_ne(Int128 a, Int128 b)
+{
+ return !int128_eq(a, b);
+}
+
+static inline bool int128_ge(Int128 a, Int128 b)
+{
+ return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
+}
+
+static inline bool int128_lt(Int128 a, Int128 b)
+{
+ return !int128_ge(a, b);
+}
+
+static inline bool int128_le(Int128 a, Int128 b)
+{
+ return int128_ge(b, a);
+}
+
+static inline bool int128_gt(Int128 a, Int128 b)
+{
+ return !int128_le(a, b);
+}
+
+static inline bool int128_nz(Int128 a)
+{
+ return a.lo || a.hi;
+}
+
+static inline Int128 int128_min(Int128 a, Int128 b)
+{
+ return int128_le(a, b) ? a : b;
+}
+
+static inline Int128 int128_max(Int128 a, Int128 b)
+{
+ return int128_ge(a, b) ? a : b;
+}
+
+static inline void int128_addto(Int128 *a, Int128 b)
+{
+ *a = int128_add(*a, b);
+}
+
+static inline void int128_subfrom(Int128 *a, Int128 b)
+{
+ *a = int128_sub(*a, b);
+}
+
+#endif
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 3fe88fe..ba44d1e 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -1,15 +1,31 @@
#ifndef QEMU_OSDEP_H
#define QEMU_OSDEP_H
+#include "config-host.h"
#include <stdarg.h>
#include <stddef.h>
-#ifdef __OpenBSD__
+#include <stdbool.h>
#include <sys/types.h>
+#ifdef __OpenBSD__
#include <sys/signal.h>
#endif
+#ifndef _WIN32
+#include <sys/wait.h>
+#else
+#define WIFEXITED(x) 1
+#define WEXITSTATUS(x) (x)
+#endif
+
#include <sys/time.h>
+#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
+/* [u]int_fast*_t not in <sys/int_types.h> */
+typedef unsigned char uint_fast8_t;
+typedef unsigned int uint_fast16_t;
+typedef signed int int_fast16_t;
+#endif
+
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
@@ -26,9 +42,6 @@
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
-#ifdef CONFIG_NEED_OFFSETOF
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
-#endif
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof(((type *) 0)->member) *__mptr = (ptr); \
@@ -55,6 +68,10 @@
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
+#ifndef ROUND_UP
+#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d))
+#endif
+
#ifndef DIV_ROUND_UP
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#endif
@@ -66,10 +83,12 @@
#ifndef always_inline
#if !((__GNUC__ < 3) || defined(__APPLE__))
#ifdef __OPTIMIZE__
+#undef inline
#define inline __attribute__ (( always_inline )) __inline__
#endif
#endif
#else
+#undef inline
#define inline always_inline
#endif
@@ -88,9 +107,12 @@
# define QEMU_GNUC_PREREQ(maj, min) 0
#endif
+int qemu_daemon(int nochdir, int noclose);
void *qemu_memalign(size_t alignment, size_t size);
void *qemu_vmalloc(size_t size);
+void *qemu_anon_ram_alloc(size_t size);
void qemu_vfree(void *ptr);
+void qemu_anon_ram_free(void *ptr, size_t size);
#define QEMU_MADV_INVALID -1
@@ -108,6 +130,16 @@
#else
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
#endif
+#ifdef MADV_DONTDUMP
+#define QEMU_MADV_DONTDUMP MADV_DONTDUMP
+#else
+#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
+#endif
+#ifdef MADV_HUGEPAGE
+#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE
+#else
+#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
+#endif
#elif defined(CONFIG_POSIX_MADVISE)
@@ -115,6 +147,8 @@
#define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
+#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
+#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
#else /* no-op */
@@ -122,14 +156,43 @@
#define QEMU_MADV_DONTNEED QEMU_MADV_INVALID
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
+#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
+#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
#endif
int qemu_madvise(void *addr, size_t len, int advice);
+int qemu_open(const char *name, int flags, ...);
+int qemu_close(int fd);
+
+#if defined(__HAIKU__) && defined(__i386__)
+#define FMT_pid "%ld"
+#elif defined(WIN64)
+#define FMT_pid "%" PRId64
+#else
+#define FMT_pid "%d"
+#endif
+
int qemu_create_pidfile(const char *filename);
int qemu_get_thread_id(void);
+#ifndef CONFIG_IOVEC
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+/*
+ * Use the same value as Linux for now.
+ */
+#define IOV_MAX 1024
+
+ssize_t readv(int fd, const struct iovec *iov, int iov_cnt);
+ssize_t writev(int fd, const struct iovec *iov, int iov_cnt);
+#else
+#include <sys/uio.h>
+#endif
+
#ifdef _WIN32
static inline void qemu_timersub(const struct timeval *val1,
const struct timeval *val2,
@@ -148,9 +211,48 @@
#define ffs __builtin_ffs
#endif
-/* in osdep.c */
-#ifdef _WIN32
-int asprintf(char**, const char*, ...);
+void qemu_set_cloexec(int fd);
+
+void qemu_set_version(const char *);
+const char *qemu_get_version(void);
+
+void fips_set_state(bool requested);
+bool fips_get_state(void);
+
+/* Return a dynamically allocated pathname denoting a file or directory that is
+ * appropriate for storing local state.
+ *
+ * @relative_pathname need not start with a directory separator; one will be
+ * added automatically.
+ *
+ * The caller is responsible for releasing the value returned with g_free()
+ * after use.
+ */
+char *qemu_get_local_state_pathname(const char *relative_pathname);
+
+/**
+ * qemu_getauxval:
+ * @type: the auxiliary vector key to lookup
+ *
+ * Search the auxiliary vector for @type, returning the value
+ * or 0 if @type is not present.
+ */
+#if defined(CONFIG_GETAUXVAL) || defined(__linux__)
+unsigned long qemu_getauxval(unsigned long type);
+#else
+static inline unsigned long qemu_getauxval(unsigned long type) { return 0; }
+#endif
+
+/**
+ * qemu_init_auxval:
+ * @envp: the third argument to main
+ *
+ * If supported and required, locate the auxiliary vector at program startup.
+ */
+#if defined(CONFIG_GETAUXVAL) || !defined(__linux__)
+static inline void qemu_init_auxval(char **envp) { }
+#else
+void qemu_init_auxval(char **envp);
#endif
#endif
diff --git a/include/qemu/range.h b/include/qemu/range.h
new file mode 100644
index 0000000..aae9720
--- /dev/null
+++ b/include/qemu/range.h
@@ -0,0 +1,63 @@
+#ifndef QEMU_RANGE_H
+#define QEMU_RANGE_H
+
+#include <inttypes.h>
+#include <qemu/typedefs.h>
+
+/*
+ * Operations on 64 bit address ranges.
+ * Notes:
+ * - ranges must not wrap around 0, but can include the last byte ~0x0LL.
+ * - this can not represent a full 0 to ~0x0LL range.
+ */
+
+/* A structure representing a range of addresses. */
+struct Range {
+ uint64_t begin; /* First byte of the range, or 0 if empty. */
+ uint64_t end; /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
+};
+
+static inline void range_extend(Range *range, Range *extend_by)
+{
+ if (!extend_by->begin && !extend_by->end) {
+ return;
+ }
+ if (!range->begin && !range->end) {
+ *range = *extend_by;
+ return;
+ }
+ if (range->begin > extend_by->begin) {
+ range->begin = extend_by->begin;
+ }
+ /* Compare last byte in case region ends at ~0x0LL */
+ if (range->end - 1 < extend_by->end - 1) {
+ range->end = extend_by->end;
+ }
+}
+
+/* Get last byte of a range from offset + length.
+ * Undefined for ranges that wrap around 0. */
+static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
+{
+ return offset + len - 1;
+}
+
+/* Check whether a given range covers a given byte. */
+static inline int range_covers_byte(uint64_t offset, uint64_t len,
+ uint64_t byte)
+{
+ return offset <= byte && byte <= range_get_last(offset, len);
+}
+
+/* Check whether 2 given ranges overlap.
+ * Undefined if ranges that wrap around 0. */
+static inline int ranges_overlap(uint64_t first1, uint64_t len1,
+ uint64_t first2, uint64_t len2)
+{
+ uint64_t last1 = range_get_last(first1, len1);
+ uint64_t last2 = range_get_last(first2, len2);
+
+ return !(last2 < first1 || last1 < first2);
+}
+
+#endif
diff --git a/migration-tcp.c b/migration-tcp.c
index 46354c3..9dbd261 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -192,7 +192,7 @@
return -socket_error();
val = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+ qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
goto err;
diff --git a/net/net.c b/net/net.c
index b05181d..56bea18 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1611,7 +1611,7 @@
}
val = 1;
- ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ ret=qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(const char *)&val, sizeof(val));
if (ret < 0) {
perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
@@ -1628,7 +1628,7 @@
imr.imr_multiaddr = mcastaddr->sin_addr;
imr.imr_interface.s_addr = htonl(INADDR_ANY);
- ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const char *)&imr, sizeof(struct ip_mreq));
if (ret < 0) {
perror("setsockopt(IP_ADD_MEMBERSHIP)");
@@ -1637,7 +1637,7 @@
/* Force mcast msgs to loopback (eg. several QEMUs in same host */
val = 1;
- ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+ ret=qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
(const char *)&val, sizeof(val));
if (ret < 0) {
perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
@@ -1818,7 +1818,7 @@
/* allow fast reuse */
val = 1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+ qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret < 0) {
diff --git a/os-posix.c b/os-posix.c
index 75d68b5..b46d4dd 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -387,12 +387,3 @@
return 0;
}
-
-int qemu_get_thread_id(void)
-{
-#if defined (__linux__)
- return syscall(SYS_gettid);
-#else
- return getpid();
-#endif
-}
diff --git a/os-win32.c b/os-win32.c
index 0acbaf9..404b941 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -266,8 +266,3 @@
}
return 0;
}
-
-int qemu_get_thread_id(void)
-{
- return GetCurrentThreadId();
-}
diff --git a/util/host-utils.c b/util/host-utils.c
index 5e3915a..f0784d6 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -27,79 +27,63 @@
#include <stdint.h>
#include "qemu/host-utils.h"
-//#define DEBUG_MULDIV
-
/* Long integer helpers */
-#if !defined(__x86_64__)
-static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+#ifndef CONFIG_INT128
+static inline void mul64(uint64_t *plow, uint64_t *phigh,
+ uint64_t a, uint64_t b)
{
- *plow += a;
- /* carry test */
- if (*plow < a)
- (*phigh)++;
- *phigh += b;
-}
+ typedef union {
+ uint64_t ll;
+ struct {
+#ifdef HOST_WORDS_BIGENDIAN
+ uint32_t high, low;
+#else
+ uint32_t low, high;
+#endif
+ } l;
+ } LL;
+ LL rl, rm, rn, rh, a0, b0;
+ uint64_t c;
-static void neg128 (uint64_t *plow, uint64_t *phigh)
-{
- *plow = ~*plow;
- *phigh = ~*phigh;
- add128(plow, phigh, 1, 0);
-}
+ a0.ll = a;
+ b0.ll = b;
-static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
-{
- uint32_t a0, a1, b0, b1;
- uint64_t v;
+ rl.ll = (uint64_t)a0.l.low * b0.l.low;
+ rm.ll = (uint64_t)a0.l.low * b0.l.high;
+ rn.ll = (uint64_t)a0.l.high * b0.l.low;
+ rh.ll = (uint64_t)a0.l.high * b0.l.high;
- a0 = a;
- a1 = a >> 32;
+ c = (uint64_t)rl.l.high + rm.l.low + rn.l.low;
+ rl.l.high = c;
+ c >>= 32;
+ c = c + rm.l.high + rn.l.high + rh.l.low;
+ rh.l.low = c;
+ rh.l.high += (uint32_t)(c >> 32);
- b0 = b;
- b1 = b >> 32;
-
- v = (uint64_t)a0 * (uint64_t)b0;
- *plow = v;
- *phigh = 0;
-
- v = (uint64_t)a0 * (uint64_t)b1;
- add128(plow, phigh, v << 32, v >> 32);
-
- v = (uint64_t)a1 * (uint64_t)b0;
- add128(plow, phigh, v << 32, v >> 32);
-
- v = (uint64_t)a1 * (uint64_t)b1;
- *phigh += v;
+ *plow = rl.ll;
+ *phigh = rh.ll;
}
/* Unsigned 64x64 -> 128 multiplication */
void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
{
mul64(plow, phigh, a, b);
-#if defined(DEBUG_MULDIV)
- printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
- a, b, *phigh, *plow);
-#endif
}
/* Signed 64x64 -> 128 multiplication */
void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
{
- int sa, sb;
+ uint64_t rh;
- sa = (a < 0);
- if (sa)
- a = -a;
- sb = (b < 0);
- if (sb)
- b = -b;
- mul64(plow, phigh, a, b);
- if (sa ^ sb) {
- neg128(plow, phigh);
+ mul64(plow, &rh, a, b);
+
+ /* Adjust for signs. */
+ if (b < 0) {
+ rh -= a;
}
-#if defined(DEBUG_MULDIV)
- printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
- a, b, *phigh, *plow);
-#endif
+ if (a < 0) {
+ rh -= b;
+ }
+ *phigh = rh;
}
-#endif /* !defined(__x86_64__) */
+#endif /* !CONFIG_INT128 */
diff --git a/util/module.c b/util/module.c
index 89c082b..7acc33d 100644
--- a/util/module.c
+++ b/util/module.c
@@ -9,6 +9,8 @@
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
*/
#include "qemu-common.h"
@@ -17,7 +19,6 @@
typedef struct ModuleEntry
{
- module_init_type type;
void (*init)(void);
QTAILQ_ENTRY(ModuleEntry) node;
} ModuleEntry;
diff --git a/util/osdep.c b/util/osdep.c
index a4e5098..a02858a 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
@@ -44,27 +45,31 @@
extern int madvise(caddr_t, size_t, int);
#endif
-#ifdef _WIN32
-#include <windows.h>
-#elif defined(CONFIG_BSD)
-#include <stdlib.h>
-#else
-#include <malloc.h>
-#endif
-
-#ifdef CONFIG_ANDROID
-#ifdef WIN32
-#include <winsock2.h>
-#include <stdint.h>
-typedef int32_t socklen_t;
-#else
-#include <sys/socket.h>
-#endif
-#endif /* CONFIG_ANDROID */
-
#include "qemu-common.h"
-#include "sysemu/sysemu.h"
+#include "trace.h"
#include "qemu/sockets.h"
+#include "monitor/monitor.h"
+
+static bool fips_enabled = false;
+
+static const char *qemu_version = QEMU_VERSION;
+
+#ifndef CONFIG_ANDROID // See android/sockets.c instead.
+int socket_set_cork(int fd, int v)
+{
+#if defined(SOL_TCP) && defined(TCP_CORK)
+ return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
+#else
+ return 0;
+#endif
+}
+
+int socket_set_nodelay(int fd)
+{
+ int v = 1;
+ return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+}
+#endif // !CONFIG_ANDROID
int qemu_madvise(void *addr, size_t len, int advice)
{
@@ -82,6 +87,69 @@
#endif
}
+#ifndef CONFIG_ANDROID
+#ifndef _WIN32
+/*
+ * Dups an fd and sets the flags
+ */
+static int qemu_dup_flags(int fd, int flags)
+{
+ int ret;
+ int serrno;
+ int dup_flags;
+
+#ifdef F_DUPFD_CLOEXEC
+ ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+#else
+ ret = dup(fd);
+ if (ret != -1) {
+ qemu_set_cloexec(ret);
+ }
+#endif
+ if (ret == -1) {
+ goto fail;
+ }
+
+ dup_flags = fcntl(ret, F_GETFL);
+ if (dup_flags == -1) {
+ goto fail;
+ }
+
+ if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
+ errno = EINVAL;
+ goto fail;
+ }
+
+ /* Set/unset flags that we can with fcntl */
+ if (fcntl(ret, F_SETFL, flags) == -1) {
+ goto fail;
+ }
+
+ /* Truncate the file in the cases that open() would truncate it */
+ if (flags & O_TRUNC ||
+ ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
+ if (ftruncate(ret, 0) == -1) {
+ goto fail;
+ }
+ }
+
+ return ret;
+
+fail:
+ serrno = errno;
+ if (ret != -1) {
+ close(ret);
+ }
+ errno = serrno;
+ return -1;
+}
+
+static int qemu_parse_fdset(const char *param)
+{
+ return qemu_parse_fd(param);
+}
+#endif
+#endif // !CONFIG_ANDROID
/*
* Opens a file with FD_CLOEXEC set
@@ -91,6 +159,42 @@
int ret;
int mode = 0;
+#ifndef CONFIG_ANDROID
+#ifndef _WIN32
+ const char *fdset_id_str;
+
+ /* Attempt dup of fd from fd set */
+ if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
+ int64_t fdset_id;
+ int fd, dupfd;
+
+ fdset_id = qemu_parse_fdset(fdset_id_str);
+ if (fdset_id == -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fd = monitor_fdset_get_fd(fdset_id, flags);
+ if (fd == -1) {
+ return -1;
+ }
+
+ dupfd = qemu_dup_flags(fd, flags);
+ if (dupfd == -1) {
+ return -1;
+ }
+
+ ret = monitor_fdset_dup_fd_add(fdset_id, dupfd);
+ if (ret == -1) {
+ close(dupfd);
+ errno = EINVAL;
+ return -1;
+ }
+ return dupfd;
+ }
+#endif
+#endif // !CONFIG_ANDROID
+
if (flags & O_CREAT) {
va_list ap;
@@ -108,9 +212,37 @@
}
#endif
+#ifdef O_DIRECT
+ if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
+ error_report("file system may not support O_DIRECT");
+ errno = EINVAL; /* in case it was clobbered */
+ }
+#endif /* O_DIRECT */
+
return ret;
}
+int qemu_close(int fd)
+{
+#ifndef CONFIG_ANDROID
+ int64_t fdset_id;
+
+ /* Close fd that was dup'd from an fdset */
+ fdset_id = monitor_fdset_dup_fd_find(fd);
+ if (fdset_id != -1) {
+ int ret;
+
+ ret = close(fd);
+ if (ret == 0) {
+ monitor_fdset_dup_fd_remove(fd);
+ }
+
+ return ret;
+ }
+#endif
+ return close(fd);
+}
+
/*
* A variant of write(2) which handles partial write.
*
@@ -164,6 +296,7 @@
return ret;
}
+#ifndef CONFIG_ANDROID
/*
* Accept a connection and set FD_CLOEXEC
*/
@@ -184,6 +317,178 @@
return ret;
}
+#endif
+
+/*
+ * A variant of send(2) which handles partial write.
+ *
+ * Return the number of bytes transferred, which is only
+ * smaller than `count' if there is an error.
+ *
+ * This function won'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_send_full(int fd, const void *buf, size_t count, int flags)
+{
+ ssize_t ret = 0;
+ ssize_t total = 0;
+
+ while (count) {
+ ret = send(fd, buf, count, flags);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+
+ count -= ret;
+ buf += ret;
+ total += ret;
+ }
+
+ return total;
+}
+
+/*
+ * A variant of recv(2) which handles partial write.
+ *
+ * Return the number of bytes transferred, which is only
+ * smaller than `count' if there is an error.
+ *
+ * This function won'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_recv_full(int fd, void *buf, size_t count, int flags)
+{
+ ssize_t ret = 0;
+ ssize_t total = 0;
+
+ while (count) {
+ ret = qemu_recv(fd, buf, count, flags);
+ if (ret <= 0) {
+ if (ret < 0 && errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+
+ count -= ret;
+ buf += ret;
+ total += ret;
+ }
+
+ return total;
+}
+
+void qemu_set_version(const char *version)
+{
+ qemu_version = version;
+}
+
+const char *qemu_get_version(void)
+{
+ return qemu_version;
+}
+
+void fips_set_state(bool requested)
+{
+#ifdef __linux__
+ if (requested) {
+ FILE *fds = fopen("/proc/sys/crypto/fips_enabled", "r");
+ if (fds != NULL) {
+ fips_enabled = (fgetc(fds) == '1');
+ fclose(fds);
+ }
+ }
+#else
+ fips_enabled = false;
+#endif /* __linux__ */
+
+#ifdef _FIPS_DEBUG
+ fprintf(stderr, "FIPS mode %s (requested %s)\n",
+ (fips_enabled ? "enabled" : "disabled"),
+ (requested ? "enabled" : "disabled"));
+#endif
+}
+
+bool fips_get_state(void)
+{
+ return fips_enabled;
+}
+
+#ifndef CONFIG_ANDROID
+#ifdef _WIN32
+static void socket_cleanup(void)
+{
+ WSACleanup();
+}
+#endif
+
+int socket_init(void)
+{
+#ifdef _WIN32
+ WSADATA Data;
+ int ret, err;
+
+ ret = WSAStartup(MAKEWORD(2, 2), &Data);
+ if (ret != 0) {
+ err = WSAGetLastError();
+ fprintf(stderr, "WSAStartup: %d\n", err);
+ return -1;
+ }
+ atexit(socket_cleanup);
+#endif
+ return 0;
+}
+#endif // !CONFIG_ANDROID
+
+#ifndef CONFIG_IOVEC
+/* helper function for iov_send_recv() */
+static ssize_t
+readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
+{
+ unsigned i = 0;
+ ssize_t ret = 0;
+ while (i < iov_cnt) {
+ ssize_t r = do_write
+ ? write(fd, iov[i].iov_base, iov[i].iov_len)
+ : read(fd, iov[i].iov_base, iov[i].iov_len);
+ if (r > 0) {
+ ret += r;
+ } else if (!r) {
+ break;
+ } else if (errno == EINTR) {
+ continue;
+ } else {
+ /* else it is some "other" error,
+ * only return if there was no data processed. */
+ if (ret == 0) {
+ ret = -1;
+ }
+ break;
+ }
+ i++;
+ }
+ return ret;
+}
+
+ssize_t
+readv(int fd, const struct iovec *iov, int iov_cnt)
+{
+ return readv_writev(fd, iov, iov_cnt, false);
+}
+
+ssize_t
+writev(int fd, const struct iovec *iov, int iov_cnt)
+{
+ return readv_writev(fd, iov, iov_cnt, true);
+}
+#endif
#ifdef WIN32
int asprintf( char **, const char *, ... );
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index b5e6886..a2f3439 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -26,10 +26,55 @@
* THE SOFTWARE.
*/
+/* The following block of code temporarily renames the daemon() function so the
+ compiler does not see the warning associated with it in stdlib.h on OSX */
+#ifdef __APPLE__
+#define daemon qemu_fake_daemon_function
+#include <stdlib.h>
+#undef daemon
+extern int daemon(int, int);
+#endif
+
+#if defined(__linux__) && (defined(__x86_64__) || defined(__arm__))
+ /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
+ Valgrind does not support alignments larger than 1 MiB,
+ therefore we need special code which handles running on Valgrind. */
+# define QEMU_VMALLOC_ALIGN (512 * 4096)
+#elif defined(__linux__) && defined(__s390x__)
+ /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */
+# define QEMU_VMALLOC_ALIGN (256 * 4096)
+#else
+# define QEMU_VMALLOC_ALIGN getpagesize()
+#endif
+
+#include "config-host.h"
+#ifndef CONFIG_ANDROID
+#include <glib/gprintf.h>
+#endif
+
#include "config-host.h"
#include "sysemu/sysemu.h"
#include "trace.h"
#include "qemu/sockets.h"
+#include <sys/mman.h>
+
+#ifdef CONFIG_LINUX
+#include <sys/syscall.h>
+#endif
+
+int qemu_get_thread_id(void)
+{
+#if defined(__linux__)
+ return syscall(SYS_gettid);
+#else
+ return getpid();
+#endif
+}
+
+int qemu_daemon(int nochdir, int noclose)
+{
+ return daemon(nochdir, noclose);
+}
void *qemu_oom_check(void *ptr)
{
@@ -66,20 +111,76 @@
return qemu_memalign(getpagesize(), size);
}
+/* alloc shared memory pages */
+void *qemu_anon_ram_alloc(size_t size)
+{
+ size_t align = QEMU_VMALLOC_ALIGN;
+ size_t total = size + align - getpagesize();
+ void *ptr = mmap(0, total, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr;
+
+ if (ptr == MAP_FAILED) {
+ return NULL;
+ }
+
+ ptr += offset;
+ total -= offset;
+
+ if (offset > 0) {
+ munmap(ptr - offset, offset);
+ }
+ if (total > size) {
+ munmap(ptr + size, total - size);
+ }
+
+ //trace_qemu_anon_ram_alloc(size, ptr);
+ return ptr;
+}
+
void qemu_vfree(void *ptr)
{
//trace_qemu_vfree(ptr);
free(ptr);
}
-#if 0 /* in sockets.c */
-void socket_set_nonblock(int fd)
+void qemu_anon_ram_free(void *ptr, size_t size)
+{
+ //trace_qemu_anon_ram_free(ptr, size);
+ if (ptr) {
+ munmap(ptr, size);
+ }
+}
+
+void qemu_set_block(int fd)
+{
+ int f;
+ f = fcntl(fd, F_GETFL);
+ fcntl(fd, F_SETFL, f & ~O_NONBLOCK);
+}
+
+void qemu_set_nonblock(int fd)
{
int f;
f = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, f | O_NONBLOCK);
}
+
+int socket_set_fast_reuse(int fd)
+{
+#ifdef CONFIG_ANDROID
+ return socket_set_xreuseaddr(fd);
+#else
+ int val = 1, ret;
+
+ ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *)&val, sizeof(val));
+
+ assert(ret == 0);
+
+ return ret;
#endif
+}
void qemu_set_cloexec(int fd)
{
@@ -110,8 +211,7 @@
return ret;
}
-int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
- int flags)
+int qemu_utimens(const char *path, const struct timespec *times)
{
struct timeval tv[2], tv_now;
struct stat st;
@@ -119,7 +219,7 @@
#ifdef CONFIG_UTIMENSAT
int ret;
- ret = utimensat(dirfd, path, times, flags);
+ ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
if (ret != -1 || errno != ENOSYS) {
return ret;
}
@@ -157,3 +257,14 @@
return utimes(path, &tv[0]);
}
+
+char *
+qemu_get_local_state_pathname(const char *relative_pathname)
+{
+#ifdef CONFIG_ANDROID
+ return NULL;
+#else
+ return g_strdup_printf("%s/%s", CONFIG_QEMU_LOCALSTATEDIR,
+ relative_pathname);
+#endif
+}
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index d5455da..b2489c9 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -26,11 +26,16 @@
* THE SOFTWARE.
*/
#include <windows.h>
+#include <glib.h>
+#include <stdlib.h>
#include "config-host.h"
#include "sysemu/sysemu.h"
#include "trace.h"
#include "qemu/sockets.h"
+/* this must come after including "trace.h" */
+#include <shlobj.h>
+
void *qemu_oom_check(void *ptr)
{
if (ptr == NULL) {
@@ -67,19 +72,83 @@
return ptr;
}
+void *qemu_anon_ram_alloc(size_t size)
+{
+ 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);
+ return ptr;
+}
+
void qemu_vfree(void *ptr)
{
//trace_qemu_vfree(ptr);
- VirtualFree(ptr, 0, MEM_RELEASE);
+ if (ptr) {
+ VirtualFree(ptr, 0, MEM_RELEASE);
+ }
}
-#if 0 /* in sockets.c */
-void socket_set_nonblock(int fd)
+void qemu_anon_ram_free(void *ptr, size_t size)
+{
+ //trace_qemu_anon_ram_free(ptr, size);
+ if (ptr) {
+ VirtualFree(ptr, 0, MEM_RELEASE);
+ }
+}
+
+/* FIXME: add proper locking */
+struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+ struct tm *p = gmtime(timep);
+ memset(result, 0, sizeof(*result));
+ if (p) {
+ *result = *p;
+ p = result;
+ }
+ return p;
+}
+
+/* FIXME: add proper locking */
+struct tm *localtime_r(const time_t *timep, struct tm *result)
+{
+ struct tm *p = localtime(timep);
+ memset(result, 0, sizeof(*result));
+ if (p) {
+ *result = *p;
+ p = result;
+ }
+ return p;
+}
+
+void qemu_set_block(int fd)
+{
+ unsigned long opt = 0;
+ WSAEventSelect(fd, NULL, 0);
+ ioctlsocket(fd, FIONBIO, &opt);
+}
+
+void qemu_set_nonblock(int fd)
{
unsigned long opt = 1;
ioctlsocket(fd, FIONBIO, &opt);
-}
+#ifndef CONFIG_ANDROID
+ qemu_fd_register(fd);
#endif
+}
+
+int socket_set_fast_reuse(int fd)
+{
+ /* Enabling the reuse of an endpoint that was used by a socket still in
+ * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows
+ * fast reuse is the default and SO_REUSEADDR does strange things. So we
+ * don't have to do anything here. More info can be found at:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */
+ return 0;
+}
int inet_aton(const char *cp, struct in_addr *ia)
{
@@ -114,3 +183,25 @@
Do not set errno on error. */
return 0;
}
+
+int qemu_get_thread_id(void)
+{
+ return GetCurrentThreadId();
+}
+
+char *
+qemu_get_local_state_pathname(const char *relative_pathname)
+{
+ HRESULT result;
+ char base_path[MAX_PATH+1] = "";
+
+ result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
+ /* SHGFP_TYPE_CURRENT */ 0, base_path);
+ if (result != S_OK) {
+ /* misconfigured environment */
+ g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result);
+ abort();
+ }
+ return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
+ relative_pathname);
+}
diff --git a/util/path.c b/util/path.c
index f0d703f..2868d15 100644
--- a/util/path.c
+++ b/util/path.c
@@ -42,7 +42,7 @@
}
static struct pathelem *add_entry(struct pathelem *root, const char *name,
- unsigned char type);
+ unsigned type);
static struct pathelem *new_entry(const char *root,
struct pathelem *parent,
@@ -50,10 +50,7 @@
{
struct pathelem *new = malloc(sizeof(*new));
new->name = strdup(name);
- if (asprintf(&new->pathname, "%s/%s", root, name) == -1) {
- printf("Cannot allocate memory\n");
- exit(1);
- }
+ new->pathname = g_strdup_printf("%s/%s", root, name);
new->num_entries = 0;
return new;
}
@@ -61,9 +58,10 @@
#define streq(a,b) (strcmp((a), (b)) == 0)
/* Not all systems provide this feature */
-#if defined(DT_DIR) && defined(DT_UNKNOWN)
+#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
# define dirent_type(dirent) ((dirent)->d_type)
-# define is_dir_maybe(type) ((type) == DT_DIR || (type) == DT_UNKNOWN)
+# define is_dir_maybe(type) \
+ ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
#else
# define dirent_type(dirent) (1)
# define is_dir_maybe(type) (type)
@@ -87,7 +85,7 @@
}
static struct pathelem *add_entry(struct pathelem *root, const char *name,
- unsigned char type)
+ unsigned type)
{
struct pathelem **e;
diff --git a/util/qemu-error.c b/util/qemu-error.c
index 642bff9..55bad09 100644
--- a/util/qemu-error.c
+++ b/util/qemu-error.c
@@ -157,6 +157,11 @@
progname = p ? p + 1 : argv0;
}
+const char *error_get_progname(void)
+{
+ return progname;
+}
+
/*
* Print current location to current monitor if we have one, else to stderr.
*/
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 16e0c44..a3103eb 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -180,11 +180,11 @@
continue;
}
- setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+ qemu_setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
#ifdef IPV6_V6ONLY
if (e->ai_family == PF_INET6) {
/* listen on both ipv4 and ipv6 */
- setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
+ qemu_setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
sizeof(off));
}
#endif
@@ -284,7 +284,7 @@
inet_strfamily(e->ai_family), strerror(errno));
continue;
}
- setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+ qemu_setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
/* connect to peer */
if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
@@ -377,7 +377,7 @@
inet_strfamily(peer->ai_family), strerror(errno));
goto err;
}
- setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+ qemu_setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
/* bind socket */
if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen,