summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/cutils.c150
-rw-r--r--util/qemu-thread-posix.c11
-rw-r--r--util/rcu.c7
3 files changed, 166 insertions, 2 deletions
diff --git a/util/cutils.c b/util/cutils.c
index 9234452..ae35198 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -354,6 +354,156 @@ int64_t strtosz(const char *nptr, char **end)
}
/**
+ * Helper function for qemu_strto*l() functions.
+ */
+static int check_strtox_error(const char *p, char *endptr, const char **next,
+ int err)
+{
+ /* If no conversion was performed, prefer BSD behavior over glibc
+ * behavior.
+ */
+ if (err == 0 && endptr == p) {
+ err = EINVAL;
+ }
+ if (!next && *endptr) {
+ return -EINVAL;
+ }
+ if (next) {
+ *next = endptr;
+ }
+ return -err;
+}
+
+/**
+ * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions.
+ *
+ * Convert ASCII string @nptr to a long integer value
+ * from the given @base. Parameters @nptr, @endptr, @base
+ * follows same semantics as strtol() C function.
+ *
+ * Unlike from strtol() function, if @endptr is not NULL, this
+ * function will return -EINVAL whenever it cannot fully convert
+ * the string in @nptr with given @base to a long. This function returns
+ * the result of the conversion only through the @result parameter.
+ *
+ * If NULL is passed in @endptr, then the whole string in @ntpr
+ * is a number otherwise it returns -EINVAL.
+ *
+ * RETURN VALUE
+ * Unlike from strtol() function, this wrapper returns either
+ * -EINVAL or the errno set by strtol() function (e.g -ERANGE).
+ * If the conversion overflows, -ERANGE is returned, and @result
+ * is set to the max value of the desired type
+ * (e.g. LONG_MAX, LLONG_MAX, ULONG_MAX, ULLONG_MAX). If the case
+ * of underflow, -ERANGE is returned, and @result is set to the min
+ * value of the desired type. For strtol(), strtoll(), @result is set to
+ * LONG_MIN, LLONG_MIN, respectively, and for strtoul(), strtoull() it
+ * is set to 0.
+ */
+int qemu_strtol(const char *nptr, const char **endptr, int base,
+ long *result)
+{
+ char *p;
+ int err = 0;
+ if (!nptr) {
+ if (endptr) {
+ *endptr = nptr;
+ }
+ err = -EINVAL;
+ } else {
+ errno = 0;
+ *result = strtol(nptr, &p, base);
+ err = check_strtox_error(nptr, p, endptr, errno);
+ }
+ return err;
+}
+
+/**
+ * Converts ASCII string to an unsigned long integer.
+ *
+ * If string contains a negative number, value will be converted to
+ * the unsigned representation of the signed value, unless the original
+ * (nonnegated) value would overflow, in this case, it will set @result
+ * to ULONG_MAX, and return ERANGE.
+ *
+ * The same behavior holds, for qemu_strtoull() but sets @result to
+ * ULLONG_MAX instead of ULONG_MAX.
+ *
+ * See qemu_strtol() documentation for more info.
+ */
+int qemu_strtoul(const char *nptr, const char **endptr, int base,
+ unsigned long *result)
+{
+ char *p;
+ int err = 0;
+ if (!nptr) {
+ if (endptr) {
+ *endptr = nptr;
+ }
+ err = -EINVAL;
+ } else {
+ errno = 0;
+ *result = strtoul(nptr, &p, base);
+ /* Windows returns 1 for negative out-of-range values. */
+ if (errno == ERANGE) {
+ *result = -1;
+ }
+ err = check_strtox_error(nptr, p, endptr, errno);
+ }
+ return err;
+}
+
+/**
+ * Converts ASCII string to a long long integer.
+ *
+ * See qemu_strtol() documentation for more info.
+ */
+int qemu_strtoll(const char *nptr, const char **endptr, int base,
+ int64_t *result)
+{
+ char *p;
+ int err = 0;
+ if (!nptr) {
+ if (endptr) {
+ *endptr = nptr;
+ }
+ err = -EINVAL;
+ } else {
+ errno = 0;
+ *result = strtoll(nptr, &p, base);
+ err = check_strtox_error(nptr, p, endptr, errno);
+ }
+ return err;
+}
+
+/**
+ * Converts ASCII string to an unsigned long long integer.
+ *
+ * See qemu_strtol() documentation for more info.
+ */
+int qemu_strtoull(const char *nptr, const char **endptr, int base,
+ uint64_t *result)
+{
+ char *p;
+ int err = 0;
+ if (!nptr) {
+ if (endptr) {
+ *endptr = nptr;
+ }
+ err = -EINVAL;
+ } else {
+ errno = 0;
+ *result = strtoull(nptr, &p, base);
+ /* Windows returns 1 for negative out-of-range values. */
+ if (errno == ERANGE) {
+ *result = -1;
+ }
+ err = check_strtox_error(nptr, p, endptr, errno);
+ }
+ return err;
+}
+
+/**
* parse_uint:
*
* @s: String to parse
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index b1abe97..dbd8094 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -298,7 +298,16 @@ static inline void futex_wake(QemuEvent *ev, int n)
static inline void futex_wait(QemuEvent *ev, unsigned val)
{
- futex(ev, FUTEX_WAIT, (int) val, NULL, NULL, 0);
+ while (futex(ev, FUTEX_WAIT, (int) val, NULL, NULL, 0)) {
+ switch (errno) {
+ case EWOULDBLOCK:
+ return;
+ case EINTR:
+ break; /* get out of switch and retry */
+ default:
+ abort();
+ }
+ }
}
#else
static inline void futex_wake(QemuEvent *ev, int n)
diff --git a/util/rcu.c b/util/rcu.c
index 8ba304d..47c2bce 100644
--- a/util/rcu.c
+++ b/util/rcu.c
@@ -335,6 +335,11 @@ static void rcu_init_unlock(void)
qemu_mutex_unlock(&rcu_registry_lock);
qemu_mutex_unlock(&rcu_sync_lock);
}
+
+static void rcu_init_child(void)
+{
+ qemu_mutex_init(&rcu_registry_lock);
+}
#endif
void rcu_after_fork(void)
@@ -346,7 +351,7 @@ void rcu_after_fork(void)
static void __attribute__((__constructor__)) rcu_init(void)
{
#ifdef CONFIG_POSIX
- pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_unlock);
+ pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_child);
#endif
rcu_init_complete();
}
OpenPOWER on IntegriCloud