[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 13/17] coroutine-lock: introduce qemu_co_mutex_lock_
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 13/17] coroutine-lock: introduce qemu_co_mutex_lock_unlock |
Date: |
Thu, 20 Apr 2017 14:00:54 +0200 |
This primitive lets you lock/unlock a CoMutex, guaranteeing neither
blocking nor cacheline bouncing if there is no qemu_co_mutex_lock
critical section.
Signed-off-by: Paolo Bonzini <address@hidden>
---
include/qemu/coroutine.h | 6 ++++++
util/qemu-coroutine-lock.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index a4509bd..8d4416c 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -157,6 +157,12 @@ void qemu_co_mutex_init(CoMutex *mutex);
void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
/**
+ * Locks the mutex and immediately unlock it. This is faster than back-to-back
+ * lock/unlock if the mutex is not taken by anyone.
+ */
+void coroutine_fn qemu_co_mutex_lock_unlock(CoMutex *mutex);
+
+/**
* Unlocks the mutex and schedules the next coroutine that was waiting for this
* lock to be run.
*/
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 6328eed..86f56cd 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -287,6 +287,42 @@ retry_fast_path:
self->locks_held++;
}
+void coroutine_fn qemu_co_mutex_lock_unlock(CoMutex *mutex)
+{
+ AioContext *ctx = qemu_get_current_aio_context();
+ int waiters, i;
+
+retry_fast_path:
+ waiters = atomic_read(&mutex->locked);
+ if (waiters == 0) {
+ /* Provide same memory ordering semantics as mutex lock/unlock. */
+ smp_mb_acquire();
+ smp_mb_release();
+ return;
+ }
+
+ i = 0;
+ while (waiters == 1 && ++i < 1000) {
+ if (atomic_read(&mutex->ctx) == ctx) {
+ break;
+ }
+ waiters = atomic_read(&mutex->locked);
+ if (waiters == 0) {
+ smp_mb_acquire();
+ smp_mb_release();
+ return;
+ }
+ cpu_relax();
+ }
+
+ if (atomic_cmpxchg(&mutex->locked, waiters, waiters + 1) != waiters) {
+ goto retry_fast_path;
+ }
+
+ qemu_co_mutex_lock_slowpath(ctx, mutex);
+ qemu_co_mutex_unlock(mutex);
+}
+
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
{
Coroutine *self = qemu_coroutine_self();
--
2.9.3
- [Qemu-devel] [PATCH for 2.10 00/17] Block layer thread safety, part 1, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 07/17] throttle-groups: do not use qemu_co_enter_next, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 06/17] block: access io_plugged with atomic ops, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 05/17] block: access wakeup with atomic ops, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 11/17] block: access write_gen with atomics, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 01/17] block: access copy_on_read with atomic ops, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 13/17] coroutine-lock: introduce qemu_co_mutex_lock_unlock,
Paolo Bonzini <=
- [Qemu-devel] [PATCH 09/17] util: add stats64 module, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 14/17] block: optimize access to reqs_lock, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 03/17] block: access io_limits_disabled with atomic ops, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 02/17] block: access quiesce_counter with atomic ops, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 04/17] block: access serialising_in_flight with atomic ops, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 10/17] block: use Stat64 for wr_highest_offset, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 15/17] block: introduce dirty_bitmap_mutex, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 17/17] block: make accounting thread-safe, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 08/17] throttle-groups: protect throttled requests with a CoMutex, Paolo Bonzini, 2017/04/20
- [Qemu-devel] [PATCH 12/17] block: protect tracked_requests and flush_queue with reqs_lock, Paolo Bonzini, 2017/04/20