mirror of https://gitee.com/openkylin/qemu.git
threadpool: do not take lock in event_notifier_ready
The ordering is: worker thread consumer thread ------------------------------------------------------------------- write ret event_notifier_test_and_clear wmb() read state write state rmb() event_notifier_set read ret Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
d354c7eccf
commit
19d092cf9b
|
@ -39,6 +39,11 @@ struct ThreadPoolElement {
|
||||||
BlockDriverAIOCB common;
|
BlockDriverAIOCB common;
|
||||||
ThreadPoolFunc *func;
|
ThreadPoolFunc *func;
|
||||||
void *arg;
|
void *arg;
|
||||||
|
|
||||||
|
/* Moving state out of THREAD_QUEUED is protected by lock. After
|
||||||
|
* that, only the worker thread can write to it. Reads and writes
|
||||||
|
* of state and ret are ordered with memory barriers.
|
||||||
|
*/
|
||||||
enum ThreadState state;
|
enum ThreadState state;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -95,9 +100,12 @@ static void *worker_thread(void *unused)
|
||||||
|
|
||||||
ret = req->func(req->arg);
|
ret = req->func(req->arg);
|
||||||
|
|
||||||
qemu_mutex_lock(&lock);
|
|
||||||
req->state = THREAD_DONE;
|
|
||||||
req->ret = ret;
|
req->ret = ret;
|
||||||
|
/* Write ret before state. */
|
||||||
|
smp_wmb();
|
||||||
|
req->state = THREAD_DONE;
|
||||||
|
|
||||||
|
qemu_mutex_lock(&lock);
|
||||||
if (pending_cancellations) {
|
if (pending_cancellations) {
|
||||||
qemu_cond_broadcast(&check_cancel);
|
qemu_cond_broadcast(&check_cancel);
|
||||||
}
|
}
|
||||||
|
@ -162,11 +170,10 @@ restart:
|
||||||
trace_thread_pool_complete(elem, elem->common.opaque, elem->ret);
|
trace_thread_pool_complete(elem, elem->common.opaque, elem->ret);
|
||||||
}
|
}
|
||||||
if (elem->state == THREAD_DONE && elem->common.cb) {
|
if (elem->state == THREAD_DONE && elem->common.cb) {
|
||||||
qemu_mutex_lock(&lock);
|
|
||||||
int ret = elem->ret;
|
|
||||||
qemu_mutex_unlock(&lock);
|
|
||||||
QLIST_REMOVE(elem, all);
|
QLIST_REMOVE(elem, all);
|
||||||
elem->common.cb(elem->common.opaque, ret);
|
/* Read state before ret. */
|
||||||
|
smp_rmb();
|
||||||
|
elem->common.cb(elem->common.opaque, elem->ret);
|
||||||
qemu_aio_release(elem);
|
qemu_aio_release(elem);
|
||||||
goto restart;
|
goto restart;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue