io: store reference to thread information in the QIOTask struct

Currently the struct QIOTaskThreadData is only needed by the worker
thread, but a subsequent patch will need to access it from another
context.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20190211182442.8542-2-berrange@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-02-11 18:24:27 +00:00 committed by Marc-André Lureau
parent 68cf36a7ea
commit 52d6cfeca2
1 changed files with 34 additions and 30 deletions

View File

@ -24,6 +24,14 @@
#include "qemu/thread.h" #include "qemu/thread.h"
#include "trace.h" #include "trace.h"
struct QIOTaskThreadData {
QIOTaskWorker worker;
gpointer opaque;
GDestroyNotify destroy;
GMainContext *context;
};
struct QIOTask { struct QIOTask {
Object *source; Object *source;
QIOTaskFunc func; QIOTaskFunc func;
@ -32,6 +40,7 @@ struct QIOTask {
Error *err; Error *err;
gpointer result; gpointer result;
GDestroyNotify destroyResult; GDestroyNotify destroyResult;
struct QIOTaskThreadData *thread;
}; };
@ -57,6 +66,18 @@ QIOTask *qio_task_new(Object *source,
static void qio_task_free(QIOTask *task) static void qio_task_free(QIOTask *task)
{ {
if (task->thread) {
if (task->thread->destroy) {
task->thread->destroy(task->thread->opaque);
}
if (task->thread->context) {
g_main_context_unref(task->thread->context);
}
g_free(task->thread);
}
if (task->destroy) { if (task->destroy) {
task->destroy(task->opaque); task->destroy(task->opaque);
} }
@ -72,31 +93,12 @@ static void qio_task_free(QIOTask *task)
} }
struct QIOTaskThreadData {
QIOTask *task;
QIOTaskWorker worker;
gpointer opaque;
GDestroyNotify destroy;
GMainContext *context;
};
static gboolean qio_task_thread_result(gpointer opaque) static gboolean qio_task_thread_result(gpointer opaque)
{ {
struct QIOTaskThreadData *data = opaque; QIOTask *task = opaque;
trace_qio_task_thread_result(data->task); trace_qio_task_thread_result(task);
qio_task_complete(data->task); qio_task_complete(task);
if (data->destroy) {
data->destroy(data->opaque);
}
if (data->context) {
g_main_context_unref(data->context);
}
g_free(data);
return FALSE; return FALSE;
} }
@ -104,22 +106,23 @@ static gboolean qio_task_thread_result(gpointer opaque)
static gpointer qio_task_thread_worker(gpointer opaque) static gpointer qio_task_thread_worker(gpointer opaque)
{ {
struct QIOTaskThreadData *data = opaque; QIOTask *task = opaque;
GSource *idle; GSource *idle;
trace_qio_task_thread_run(data->task); trace_qio_task_thread_run(task);
data->worker(data->task, data->opaque);
task->thread->worker(task, task->thread->opaque);
/* We're running in the background thread, and must only /* We're running in the background thread, and must only
* ever report the task results in the main event loop * ever report the task results in the main event loop
* thread. So we schedule an idle callback to report * thread. So we schedule an idle callback to report
* the worker results * the worker results
*/ */
trace_qio_task_thread_exit(data->task); trace_qio_task_thread_exit(task);
idle = g_idle_source_new(); idle = g_idle_source_new();
g_source_set_callback(idle, qio_task_thread_result, data, NULL); g_source_set_callback(idle, qio_task_thread_result, task, NULL);
g_source_attach(idle, data->context); g_source_attach(idle, task->thread->context);
return NULL; return NULL;
} }
@ -138,17 +141,18 @@ void qio_task_run_in_thread(QIOTask *task,
g_main_context_ref(context); g_main_context_ref(context);
} }
data->task = task;
data->worker = worker; data->worker = worker;
data->opaque = opaque; data->opaque = opaque;
data->destroy = destroy; data->destroy = destroy;
data->context = context; data->context = context;
task->thread = data;
trace_qio_task_thread_start(task, worker, opaque); trace_qio_task_thread_start(task, worker, opaque);
qemu_thread_create(&thread, qemu_thread_create(&thread,
"io-task-worker", "io-task-worker",
qio_task_thread_worker, qio_task_thread_worker,
data, task,
QEMU_THREAD_DETACHED); QEMU_THREAD_DETACHED);
} }