mirror of https://github.com/xemu-project/xemu.git
qemu-thread: Assert locks are initialized before using
Not all platforms check whether a lock is initialized before used. In particular Linux seems to be more permissive than OSX. Check initialization state explicitly in our code to catch such bugs earlier. Signed-off-by: Fam Zheng <famz@redhat.com> Message-Id: <20170704122325.25634-1-famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
025bdeab3c
commit
c096358e74
|
@ -12,10 +12,12 @@ typedef QemuMutex QemuRecMutex;
|
||||||
|
|
||||||
struct QemuMutex {
|
struct QemuMutex {
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QemuCond {
|
struct QemuCond {
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QemuSemaphore {
|
struct QemuSemaphore {
|
||||||
|
@ -26,6 +28,7 @@ struct QemuSemaphore {
|
||||||
#else
|
#else
|
||||||
sem_t sem;
|
sem_t sem;
|
||||||
#endif
|
#endif
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QemuEvent {
|
struct QemuEvent {
|
||||||
|
@ -34,6 +37,7 @@ struct QemuEvent {
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
#endif
|
#endif
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QemuThread {
|
struct QemuThread {
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
|
|
||||||
struct QemuMutex {
|
struct QemuMutex {
|
||||||
SRWLOCK lock;
|
SRWLOCK lock;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct QemuRecMutex QemuRecMutex;
|
typedef struct QemuRecMutex QemuRecMutex;
|
||||||
struct QemuRecMutex {
|
struct QemuRecMutex {
|
||||||
CRITICAL_SECTION lock;
|
CRITICAL_SECTION lock;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
void qemu_rec_mutex_destroy(QemuRecMutex *mutex);
|
void qemu_rec_mutex_destroy(QemuRecMutex *mutex);
|
||||||
|
@ -19,15 +21,18 @@ void qemu_rec_mutex_unlock(QemuRecMutex *mutex);
|
||||||
|
|
||||||
struct QemuCond {
|
struct QemuCond {
|
||||||
CONDITION_VARIABLE var;
|
CONDITION_VARIABLE var;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QemuSemaphore {
|
struct QemuSemaphore {
|
||||||
HANDLE sema;
|
HANDLE sema;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QemuEvent {
|
struct QemuEvent {
|
||||||
int value;
|
int value;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
|
bool initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct QemuThreadData QemuThreadData;
|
typedef struct QemuThreadData QemuThreadData;
|
||||||
|
|
|
@ -43,12 +43,15 @@ void qemu_mutex_init(QemuMutex *mutex)
|
||||||
err = pthread_mutex_init(&mutex->lock, NULL);
|
err = pthread_mutex_init(&mutex->lock, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
mutex->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_mutex_destroy(QemuMutex *mutex)
|
void qemu_mutex_destroy(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(mutex->initialized);
|
||||||
|
mutex->initialized = false;
|
||||||
err = pthread_mutex_destroy(&mutex->lock);
|
err = pthread_mutex_destroy(&mutex->lock);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
@ -58,6 +61,7 @@ void qemu_mutex_lock(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(mutex->initialized);
|
||||||
err = pthread_mutex_lock(&mutex->lock);
|
err = pthread_mutex_lock(&mutex->lock);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
@ -69,6 +73,7 @@ int qemu_mutex_trylock(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(mutex->initialized);
|
||||||
err = pthread_mutex_trylock(&mutex->lock);
|
err = pthread_mutex_trylock(&mutex->lock);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
trace_qemu_mutex_locked(mutex);
|
trace_qemu_mutex_locked(mutex);
|
||||||
|
@ -84,6 +89,7 @@ void qemu_mutex_unlock(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(mutex->initialized);
|
||||||
trace_qemu_mutex_unlocked(mutex);
|
trace_qemu_mutex_unlocked(mutex);
|
||||||
err = pthread_mutex_unlock(&mutex->lock);
|
err = pthread_mutex_unlock(&mutex->lock);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -102,6 +108,7 @@ void qemu_rec_mutex_init(QemuRecMutex *mutex)
|
||||||
if (err) {
|
if (err) {
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
}
|
}
|
||||||
|
mutex->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_cond_init(QemuCond *cond)
|
void qemu_cond_init(QemuCond *cond)
|
||||||
|
@ -111,12 +118,15 @@ void qemu_cond_init(QemuCond *cond)
|
||||||
err = pthread_cond_init(&cond->cond, NULL);
|
err = pthread_cond_init(&cond->cond, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
cond->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_cond_destroy(QemuCond *cond)
|
void qemu_cond_destroy(QemuCond *cond)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(cond->initialized);
|
||||||
|
cond->initialized = false;
|
||||||
err = pthread_cond_destroy(&cond->cond);
|
err = pthread_cond_destroy(&cond->cond);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
@ -126,6 +136,7 @@ void qemu_cond_signal(QemuCond *cond)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(cond->initialized);
|
||||||
err = pthread_cond_signal(&cond->cond);
|
err = pthread_cond_signal(&cond->cond);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
@ -135,6 +146,7 @@ void qemu_cond_broadcast(QemuCond *cond)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(cond->initialized);
|
||||||
err = pthread_cond_broadcast(&cond->cond);
|
err = pthread_cond_broadcast(&cond->cond);
|
||||||
if (err)
|
if (err)
|
||||||
error_exit(err, __func__);
|
error_exit(err, __func__);
|
||||||
|
@ -144,6 +156,7 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
assert(cond->initialized);
|
||||||
trace_qemu_mutex_unlocked(mutex);
|
trace_qemu_mutex_unlocked(mutex);
|
||||||
err = pthread_cond_wait(&cond->cond, &mutex->lock);
|
err = pthread_cond_wait(&cond->cond, &mutex->lock);
|
||||||
trace_qemu_mutex_locked(mutex);
|
trace_qemu_mutex_locked(mutex);
|
||||||
|
@ -174,12 +187,15 @@ void qemu_sem_init(QemuSemaphore *sem, int init)
|
||||||
error_exit(errno, __func__);
|
error_exit(errno, __func__);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
sem->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_sem_destroy(QemuSemaphore *sem)
|
void qemu_sem_destroy(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(sem->initialized);
|
||||||
|
sem->initialized = false;
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
rc = pthread_cond_destroy(&sem->cond);
|
rc = pthread_cond_destroy(&sem->cond);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -201,6 +217,7 @@ void qemu_sem_post(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(sem->initialized);
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
pthread_mutex_lock(&sem->lock);
|
pthread_mutex_lock(&sem->lock);
|
||||||
if (sem->count == UINT_MAX) {
|
if (sem->count == UINT_MAX) {
|
||||||
|
@ -238,6 +255,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
|
||||||
int rc;
|
int rc;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
|
assert(sem->initialized);
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
compute_abs_deadline(&ts, ms);
|
compute_abs_deadline(&ts, ms);
|
||||||
|
@ -285,6 +303,7 @@ void qemu_sem_wait(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(sem->initialized);
|
||||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||||
pthread_mutex_lock(&sem->lock);
|
pthread_mutex_lock(&sem->lock);
|
||||||
while (sem->count == 0) {
|
while (sem->count == 0) {
|
||||||
|
@ -310,6 +329,7 @@ void qemu_sem_wait(QemuSemaphore *sem)
|
||||||
#else
|
#else
|
||||||
static inline void qemu_futex_wake(QemuEvent *ev, int n)
|
static inline void qemu_futex_wake(QemuEvent *ev, int n)
|
||||||
{
|
{
|
||||||
|
assert(ev->initialized);
|
||||||
pthread_mutex_lock(&ev->lock);
|
pthread_mutex_lock(&ev->lock);
|
||||||
if (n == 1) {
|
if (n == 1) {
|
||||||
pthread_cond_signal(&ev->cond);
|
pthread_cond_signal(&ev->cond);
|
||||||
|
@ -321,6 +341,7 @@ static inline void qemu_futex_wake(QemuEvent *ev, int n)
|
||||||
|
|
||||||
static inline void qemu_futex_wait(QemuEvent *ev, unsigned val)
|
static inline void qemu_futex_wait(QemuEvent *ev, unsigned val)
|
||||||
{
|
{
|
||||||
|
assert(ev->initialized);
|
||||||
pthread_mutex_lock(&ev->lock);
|
pthread_mutex_lock(&ev->lock);
|
||||||
if (ev->value == val) {
|
if (ev->value == val) {
|
||||||
pthread_cond_wait(&ev->cond, &ev->lock);
|
pthread_cond_wait(&ev->cond, &ev->lock);
|
||||||
|
@ -355,10 +376,13 @@ void qemu_event_init(QemuEvent *ev, bool init)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ev->value = (init ? EV_SET : EV_FREE);
|
ev->value = (init ? EV_SET : EV_FREE);
|
||||||
|
ev->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_event_destroy(QemuEvent *ev)
|
void qemu_event_destroy(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
|
assert(ev->initialized);
|
||||||
|
ev->initialized = false;
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
pthread_mutex_destroy(&ev->lock);
|
pthread_mutex_destroy(&ev->lock);
|
||||||
pthread_cond_destroy(&ev->cond);
|
pthread_cond_destroy(&ev->cond);
|
||||||
|
@ -370,6 +394,7 @@ void qemu_event_set(QemuEvent *ev)
|
||||||
/* qemu_event_set has release semantics, but because it *loads*
|
/* qemu_event_set has release semantics, but because it *loads*
|
||||||
* ev->value we need a full memory barrier here.
|
* ev->value we need a full memory barrier here.
|
||||||
*/
|
*/
|
||||||
|
assert(ev->initialized);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
if (atomic_read(&ev->value) != EV_SET) {
|
if (atomic_read(&ev->value) != EV_SET) {
|
||||||
if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
|
if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
|
||||||
|
@ -383,6 +408,7 @@ void qemu_event_reset(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
|
||||||
|
assert(ev->initialized);
|
||||||
value = atomic_read(&ev->value);
|
value = atomic_read(&ev->value);
|
||||||
smp_mb_acquire();
|
smp_mb_acquire();
|
||||||
if (value == EV_SET) {
|
if (value == EV_SET) {
|
||||||
|
@ -398,6 +424,7 @@ void qemu_event_wait(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
|
||||||
|
assert(ev->initialized);
|
||||||
value = atomic_read(&ev->value);
|
value = atomic_read(&ev->value);
|
||||||
smp_mb_acquire();
|
smp_mb_acquire();
|
||||||
if (value != EV_SET) {
|
if (value != EV_SET) {
|
||||||
|
|
|
@ -46,15 +46,19 @@ static void error_exit(int err, const char *msg)
|
||||||
void qemu_mutex_init(QemuMutex *mutex)
|
void qemu_mutex_init(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
InitializeSRWLock(&mutex->lock);
|
InitializeSRWLock(&mutex->lock);
|
||||||
|
mutex->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_mutex_destroy(QemuMutex *mutex)
|
void qemu_mutex_destroy(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
|
mutex->initialized = false;
|
||||||
InitializeSRWLock(&mutex->lock);
|
InitializeSRWLock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_mutex_lock(QemuMutex *mutex)
|
void qemu_mutex_lock(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
AcquireSRWLockExclusive(&mutex->lock);
|
AcquireSRWLockExclusive(&mutex->lock);
|
||||||
trace_qemu_mutex_locked(mutex);
|
trace_qemu_mutex_locked(mutex);
|
||||||
}
|
}
|
||||||
|
@ -63,6 +67,7 @@ int qemu_mutex_trylock(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
int owned;
|
int owned;
|
||||||
|
|
||||||
|
assert(mutex->initialized);
|
||||||
owned = TryAcquireSRWLockExclusive(&mutex->lock);
|
owned = TryAcquireSRWLockExclusive(&mutex->lock);
|
||||||
if (owned) {
|
if (owned) {
|
||||||
trace_qemu_mutex_locked(mutex);
|
trace_qemu_mutex_locked(mutex);
|
||||||
|
@ -73,6 +78,7 @@ int qemu_mutex_trylock(QemuMutex *mutex)
|
||||||
|
|
||||||
void qemu_mutex_unlock(QemuMutex *mutex)
|
void qemu_mutex_unlock(QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
trace_qemu_mutex_unlocked(mutex);
|
trace_qemu_mutex_unlocked(mutex);
|
||||||
ReleaseSRWLockExclusive(&mutex->lock);
|
ReleaseSRWLockExclusive(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
@ -80,25 +86,31 @@ void qemu_mutex_unlock(QemuMutex *mutex)
|
||||||
void qemu_rec_mutex_init(QemuRecMutex *mutex)
|
void qemu_rec_mutex_init(QemuRecMutex *mutex)
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&mutex->lock);
|
InitializeCriticalSection(&mutex->lock);
|
||||||
|
mutex->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_rec_mutex_destroy(QemuRecMutex *mutex)
|
void qemu_rec_mutex_destroy(QemuRecMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
|
mutex->initialized = false;
|
||||||
DeleteCriticalSection(&mutex->lock);
|
DeleteCriticalSection(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_rec_mutex_lock(QemuRecMutex *mutex)
|
void qemu_rec_mutex_lock(QemuRecMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
EnterCriticalSection(&mutex->lock);
|
EnterCriticalSection(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_rec_mutex_trylock(QemuRecMutex *mutex)
|
int qemu_rec_mutex_trylock(QemuRecMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
return !TryEnterCriticalSection(&mutex->lock);
|
return !TryEnterCriticalSection(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_rec_mutex_unlock(QemuRecMutex *mutex)
|
void qemu_rec_mutex_unlock(QemuRecMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(mutex->initialized);
|
||||||
LeaveCriticalSection(&mutex->lock);
|
LeaveCriticalSection(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,25 +118,31 @@ void qemu_cond_init(QemuCond *cond)
|
||||||
{
|
{
|
||||||
memset(cond, 0, sizeof(*cond));
|
memset(cond, 0, sizeof(*cond));
|
||||||
InitializeConditionVariable(&cond->var);
|
InitializeConditionVariable(&cond->var);
|
||||||
|
cond->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_cond_destroy(QemuCond *cond)
|
void qemu_cond_destroy(QemuCond *cond)
|
||||||
{
|
{
|
||||||
|
assert(cond->initialized);
|
||||||
|
cond->initialized = false;
|
||||||
InitializeConditionVariable(&cond->var);
|
InitializeConditionVariable(&cond->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_cond_signal(QemuCond *cond)
|
void qemu_cond_signal(QemuCond *cond)
|
||||||
{
|
{
|
||||||
|
assert(cond->initialized);
|
||||||
WakeConditionVariable(&cond->var);
|
WakeConditionVariable(&cond->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_cond_broadcast(QemuCond *cond)
|
void qemu_cond_broadcast(QemuCond *cond)
|
||||||
{
|
{
|
||||||
|
assert(cond->initialized);
|
||||||
WakeAllConditionVariable(&cond->var);
|
WakeAllConditionVariable(&cond->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
|
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
|
||||||
{
|
{
|
||||||
|
assert(cond->initialized);
|
||||||
trace_qemu_mutex_unlocked(mutex);
|
trace_qemu_mutex_unlocked(mutex);
|
||||||
SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0);
|
SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0);
|
||||||
trace_qemu_mutex_locked(mutex);
|
trace_qemu_mutex_locked(mutex);
|
||||||
|
@ -134,21 +152,28 @@ void qemu_sem_init(QemuSemaphore *sem, int init)
|
||||||
{
|
{
|
||||||
/* Manual reset. */
|
/* Manual reset. */
|
||||||
sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
|
sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
|
||||||
|
sem->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_sem_destroy(QemuSemaphore *sem)
|
void qemu_sem_destroy(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
|
assert(sem->initialized);
|
||||||
|
sem->initialized = false;
|
||||||
CloseHandle(sem->sema);
|
CloseHandle(sem->sema);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_sem_post(QemuSemaphore *sem)
|
void qemu_sem_post(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
|
assert(sem->initialized);
|
||||||
ReleaseSemaphore(sem->sema, 1, NULL);
|
ReleaseSemaphore(sem->sema, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
|
int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
|
||||||
{
|
{
|
||||||
int rc = WaitForSingleObject(sem->sema, ms);
|
int rc;
|
||||||
|
|
||||||
|
assert(sem->initialized);
|
||||||
|
rc = WaitForSingleObject(sem->sema, ms);
|
||||||
if (rc == WAIT_OBJECT_0) {
|
if (rc == WAIT_OBJECT_0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +185,7 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
|
||||||
|
|
||||||
void qemu_sem_wait(QemuSemaphore *sem)
|
void qemu_sem_wait(QemuSemaphore *sem)
|
||||||
{
|
{
|
||||||
|
assert(sem->initialized);
|
||||||
if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
|
if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
|
||||||
error_exit(GetLastError(), __func__);
|
error_exit(GetLastError(), __func__);
|
||||||
}
|
}
|
||||||
|
@ -193,15 +219,19 @@ void qemu_event_init(QemuEvent *ev, bool init)
|
||||||
/* Manual reset. */
|
/* Manual reset. */
|
||||||
ev->event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
ev->event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||||
ev->value = (init ? EV_SET : EV_FREE);
|
ev->value = (init ? EV_SET : EV_FREE);
|
||||||
|
ev->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_event_destroy(QemuEvent *ev)
|
void qemu_event_destroy(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
|
assert(ev->initialized);
|
||||||
|
ev->initialized = false;
|
||||||
CloseHandle(ev->event);
|
CloseHandle(ev->event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_event_set(QemuEvent *ev)
|
void qemu_event_set(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
|
assert(ev->initialized);
|
||||||
/* qemu_event_set has release semantics, but because it *loads*
|
/* qemu_event_set has release semantics, but because it *loads*
|
||||||
* ev->value we need a full memory barrier here.
|
* ev->value we need a full memory barrier here.
|
||||||
*/
|
*/
|
||||||
|
@ -218,6 +248,7 @@ void qemu_event_reset(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
|
||||||
|
assert(ev->initialized);
|
||||||
value = atomic_read(&ev->value);
|
value = atomic_read(&ev->value);
|
||||||
smp_mb_acquire();
|
smp_mb_acquire();
|
||||||
if (value == EV_SET) {
|
if (value == EV_SET) {
|
||||||
|
@ -232,6 +263,7 @@ void qemu_event_wait(QemuEvent *ev)
|
||||||
{
|
{
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
|
||||||
|
assert(ev->initialized);
|
||||||
value = atomic_read(&ev->value);
|
value = atomic_read(&ev->value);
|
||||||
smp_mb_acquire();
|
smp_mb_acquire();
|
||||||
if (value != EV_SET) {
|
if (value != EV_SET) {
|
||||||
|
|
Loading…
Reference in New Issue