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:
Paolo Bonzini 2012-10-31 10:09:11 +01:00
parent d354c7eccf
commit 19d092cf9b
1 changed files with 13 additions and 6 deletions

View File

@ -39,6 +39,11 @@ struct ThreadPoolElement {
BlockDriverAIOCB common;
ThreadPoolFunc *func;
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;
int ret;
@ -95,9 +100,12 @@ static void *worker_thread(void *unused)
ret = req->func(req->arg);
qemu_mutex_lock(&lock);
req->state = THREAD_DONE;
req->ret = ret;
/* Write ret before state. */
smp_wmb();
req->state = THREAD_DONE;
qemu_mutex_lock(&lock);
if (pending_cancellations) {
qemu_cond_broadcast(&check_cancel);
}
@ -162,11 +170,10 @@ restart:
trace_thread_pool_complete(elem, elem->common.opaque, elem->ret);
}
if (elem->state == THREAD_DONE && elem->common.cb) {
qemu_mutex_lock(&lock);
int ret = elem->ret;
qemu_mutex_unlock(&lock);
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);
goto restart;
} else {