aboutsummaryrefslogtreecommitdiff
path: root/util/qemu-coroutine-lock.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2016-08-11 17:51:59 +0200
committerKevin Wolf <kwolf@redhat.com>2016-09-05 19:06:48 +0200
commit1b7f01d966f97b7820f3cdd471461cf0799a93cc (patch)
treeaaf94f449ee10f7eb018b5f9987e6f1205036c68 /util/qemu-coroutine-lock.c
parent0e438cdc932a785de72166af4641aafa103a6670 (diff)
coroutine: Assert that no locks are held on termination
A coroutine that takes a lock must also release it again. If the coroutine terminates without having released all its locks, it's buggy and we'll probably run into a deadlock sooner or later. Make sure that we don't get such cases. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'util/qemu-coroutine-lock.c')
-rw-r--r--util/qemu-coroutine-lock.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index f30ee8184d..14cf9ce458 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -130,6 +130,7 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
mutex->locked = true;
mutex->holder = self;
+ self->locks_held++;
trace_qemu_co_mutex_lock_return(mutex, self);
}
@@ -146,6 +147,7 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
mutex->locked = false;
mutex->holder = NULL;
+ self->locks_held--;
qemu_co_queue_next(&mutex->queue);
trace_qemu_co_mutex_unlock_return(mutex, self);
@@ -159,14 +161,19 @@ void qemu_co_rwlock_init(CoRwlock *lock)
void qemu_co_rwlock_rdlock(CoRwlock *lock)
{
+ Coroutine *self = qemu_coroutine_self();
+
while (lock->writer) {
qemu_co_queue_wait(&lock->queue);
}
lock->reader++;
+ self->locks_held++;
}
void qemu_co_rwlock_unlock(CoRwlock *lock)
{
+ Coroutine *self = qemu_coroutine_self();
+
assert(qemu_in_coroutine());
if (lock->writer) {
lock->writer = false;
@@ -179,12 +186,16 @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
qemu_co_queue_next(&lock->queue);
}
}
+ self->locks_held--;
}
void qemu_co_rwlock_wrlock(CoRwlock *lock)
{
+ Coroutine *self = qemu_coroutine_self();
+
while (lock->writer || lock->reader) {
qemu_co_queue_wait(&lock->queue);
}
lock->writer = true;
+ self->locks_held++;
}