|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
* Wrappers around Linux futex syscall |
|
|
|
* Wrappers around Linux futex syscall and similar |
|
|
|
* |
|
|
|
* Copyright Red Hat, Inc. 2017 |
|
|
|
* |
|
|
|
@ -11,28 +11,37 @@ |
|
|
|
* |
|
|
|
*/ |
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that a wake-up can also be caused by common futex usage patterns in |
|
|
|
* unrelated code that happened to have previously used the futex word's |
|
|
|
* memory location (e.g., typical futex-based implementations of Pthreads |
|
|
|
* mutexes can cause this under some conditions). Therefore, qemu_futex_wait() |
|
|
|
* callers should always conservatively assume that it is a spurious wake-up, |
|
|
|
* and use the futex word's value (i.e., the user-space synchronization scheme) |
|
|
|
* to decide whether to continue to block or not. |
|
|
|
*/ |
|
|
|
|
|
|
|
#ifndef QEMU_FUTEX_H |
|
|
|
#define QEMU_FUTEX_H |
|
|
|
|
|
|
|
#define HAVE_FUTEX |
|
|
|
|
|
|
|
#ifdef CONFIG_LINUX |
|
|
|
#include <sys/syscall.h> |
|
|
|
#include <linux/futex.h> |
|
|
|
|
|
|
|
#define qemu_futex(...) syscall(__NR_futex, __VA_ARGS__) |
|
|
|
|
|
|
|
static inline void qemu_futex_wake(void *f, int n) |
|
|
|
static inline void qemu_futex_wake_all(void *f) |
|
|
|
{ |
|
|
|
qemu_futex(f, FUTEX_WAKE, n, NULL, NULL, 0); |
|
|
|
qemu_futex(f, FUTEX_WAKE, INT_MAX, NULL, NULL, 0); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void qemu_futex_wake_single(void *f) |
|
|
|
{ |
|
|
|
qemu_futex(f, FUTEX_WAKE, 1, NULL, NULL, 0); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that a wake-up can also be caused by common futex usage patterns in |
|
|
|
* unrelated code that happened to have previously used the futex word's |
|
|
|
* memory location (e.g., typical futex-based implementations of Pthreads |
|
|
|
* mutexes can cause this under some conditions). Therefore, callers should |
|
|
|
* always conservatively assume that it is a spurious wake-up, and use the futex |
|
|
|
* word's value (i.e., the user-space synchronization scheme) to decide whether |
|
|
|
* to continue to block or not. |
|
|
|
*/ |
|
|
|
static inline void qemu_futex_wait(void *f, unsigned val) |
|
|
|
{ |
|
|
|
while (qemu_futex(f, FUTEX_WAIT, (int) val, NULL, NULL, 0)) { |
|
|
|
@ -46,5 +55,25 @@ static inline void qemu_futex_wait(void *f, unsigned val) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#elif defined(CONFIG_WIN32) |
|
|
|
#include <synchapi.h> |
|
|
|
|
|
|
|
static inline void qemu_futex_wake_all(void *f) |
|
|
|
{ |
|
|
|
WakeByAddressAll(f); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void qemu_futex_wake_single(void *f) |
|
|
|
{ |
|
|
|
WakeByAddressSingle(f); |
|
|
|
} |
|
|
|
|
|
|
|
static inline void qemu_futex_wait(void *f, unsigned val) |
|
|
|
{ |
|
|
|
WaitOnAddress(f, &val, sizeof(val), INFINITE); |
|
|
|
} |
|
|
|
#else |
|
|
|
#undef HAVE_FUTEX |
|
|
|
#endif |
|
|
|
|
|
|
|
#endif /* QEMU_FUTEX_H */ |
|
|
|
|