qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qio: non-default context for threaded qtask

qio_task_run_in_thread() allows main thread to run blocking operations
in the background. However it has an assumption on that it's always
working with the default context. This patch tries to allow the threaded
QIO task framework to run with non-default gcontext.

Currently no functional change so far, so the QIOTasks are still always
running on main context.

Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

authored by

Peter Xu and committed by
Daniel P. Berrangé
a17536c5 938c8b79

+33 -8
+5 -2
include/io/task.h
··· 227 227 * @worker: the function to invoke in a thread 228 228 * @opaque: opaque data to pass to @worker 229 229 * @destroy: function to free @opaque 230 + * @context: the context to run the complete hook. If %NULL, the 231 + * default context will be used. 230 232 * 231 233 * Run a task in a background thread. When @worker 232 234 * returns it will call qio_task_complete() in 233 - * the main event thread context. 235 + * the event thread context that provided. 234 236 */ 235 237 void qio_task_run_in_thread(QIOTask *task, 236 238 QIOTaskWorker worker, 237 239 gpointer opaque, 238 - GDestroyNotify destroy); 240 + GDestroyNotify destroy, 241 + GMainContext *context); 239 242 240 243 /** 241 244 * qio_task_complete:
+6 -3
io/channel-socket.c
··· 188 188 qio_task_run_in_thread(task, 189 189 qio_channel_socket_connect_worker, 190 190 addrCopy, 191 - (GDestroyNotify)qapi_free_SocketAddress); 191 + (GDestroyNotify)qapi_free_SocketAddress, 192 + NULL); 192 193 } 193 194 194 195 ··· 246 247 qio_task_run_in_thread(task, 247 248 qio_channel_socket_listen_worker, 248 249 addrCopy, 249 - (GDestroyNotify)qapi_free_SocketAddress); 250 + (GDestroyNotify)qapi_free_SocketAddress, 251 + NULL); 250 252 } 251 253 252 254 ··· 322 324 qio_task_run_in_thread(task, 323 325 qio_channel_socket_dgram_worker, 324 326 data, 325 - qio_channel_socket_dgram_worker_free); 327 + qio_channel_socket_dgram_worker_free, 328 + NULL); 326 329 } 327 330 328 331
+2 -1
io/dns-resolver.c
··· 234 234 qio_task_run_in_thread(task, 235 235 qio_dns_resolver_lookup_worker, 236 236 data, 237 - qio_dns_resolver_lookup_data_free); 237 + qio_dns_resolver_lookup_data_free, 238 + NULL); 238 239 } 239 240 240 241
+18 -2
io/task.c
··· 77 77 QIOTaskWorker worker; 78 78 gpointer opaque; 79 79 GDestroyNotify destroy; 80 + GMainContext *context; 80 81 }; 81 82 82 83 ··· 89 90 90 91 if (data->destroy) { 91 92 data->destroy(data->opaque); 93 + } 94 + 95 + if (data->context) { 96 + g_main_context_unref(data->context); 92 97 } 93 98 94 99 g_free(data); ··· 100 105 static gpointer qio_task_thread_worker(gpointer opaque) 101 106 { 102 107 struct QIOTaskThreadData *data = opaque; 108 + GSource *idle; 103 109 104 110 trace_qio_task_thread_run(data->task); 105 111 data->worker(data->task, data->opaque); ··· 110 116 * the worker results 111 117 */ 112 118 trace_qio_task_thread_exit(data->task); 113 - g_idle_add(qio_task_thread_result, data); 119 + 120 + idle = g_idle_source_new(); 121 + g_source_set_callback(idle, qio_task_thread_result, data, NULL); 122 + g_source_attach(idle, data->context); 123 + 114 124 return NULL; 115 125 } 116 126 ··· 118 128 void qio_task_run_in_thread(QIOTask *task, 119 129 QIOTaskWorker worker, 120 130 gpointer opaque, 121 - GDestroyNotify destroy) 131 + GDestroyNotify destroy, 132 + GMainContext *context) 122 133 { 123 134 struct QIOTaskThreadData *data = g_new0(struct QIOTaskThreadData, 1); 124 135 QemuThread thread; 125 136 137 + if (context) { 138 + g_main_context_ref(context); 139 + } 140 + 126 141 data->task = task; 127 142 data->worker = worker; 128 143 data->opaque = opaque; 129 144 data->destroy = destroy; 145 + data->context = context; 130 146 131 147 trace_qio_task_thread_start(task, worker, opaque); 132 148 qemu_thread_create(&thread,
+2
tests/test-io-task.c
··· 187 187 qio_task_run_in_thread(task, 188 188 test_task_thread_worker, 189 189 &data, 190 + NULL, 190 191 NULL); 191 192 192 193 g_main_loop_run(data.loop); ··· 228 229 qio_task_run_in_thread(task, 229 230 test_task_thread_worker, 230 231 &data, 232 + NULL, 231 233 NULL); 232 234 233 235 g_main_loop_run(data.loop);