| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QEMU I/O task | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2015 Red Hat, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-29 17:50:03 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | #include "io/task.h"
 | 
					
						
							| 
									
										
											  
											
												include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef.  Since then, we've moved to include qemu/osdep.h
everywhere.  Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h.  That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h.  Include qapi/error.h in .c files that need it and don't
get it now.  Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly.  Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h.  Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third.  Unfortunately, the number depending on
qapi-types.h shrinks only a little.  More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
											
										 
											2016-03-14 09:01:28 +01:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | #include "qemu/thread.h"
 | 
					
						
							|  |  |  | #include "trace.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct QIOTask { | 
					
						
							|  |  |  |     Object *source; | 
					
						
							|  |  |  |     QIOTaskFunc func; | 
					
						
							|  |  |  |     gpointer opaque; | 
					
						
							|  |  |  |     GDestroyNotify destroy; | 
					
						
							| 
									
										
										
										
											2016-08-11 14:40:44 +01:00
										 |  |  |     Error *err; | 
					
						
							| 
									
										
										
										
											2016-08-11 14:36:21 +01:00
										 |  |  |     gpointer result; | 
					
						
							|  |  |  |     GDestroyNotify destroyResult; | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QIOTask *qio_task_new(Object *source, | 
					
						
							|  |  |  |                       QIOTaskFunc func, | 
					
						
							|  |  |  |                       gpointer opaque, | 
					
						
							|  |  |  |                       GDestroyNotify destroy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QIOTask *task; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     task = g_new0(QIOTask, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     task->source = source; | 
					
						
							|  |  |  |     object_ref(source); | 
					
						
							|  |  |  |     task->func = func; | 
					
						
							|  |  |  |     task->opaque = opaque; | 
					
						
							|  |  |  |     task->destroy = destroy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_qio_task_new(task, source, func, opaque); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return task; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void qio_task_free(QIOTask *task) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (task->destroy) { | 
					
						
							|  |  |  |         task->destroy(task->opaque); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-11 14:36:21 +01:00
										 |  |  |     if (task->destroyResult) { | 
					
						
							|  |  |  |         task->destroyResult(task->result); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-11 14:40:44 +01:00
										 |  |  |     if (task->err) { | 
					
						
							|  |  |  |         error_free(task->err); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  |     object_unref(task->source); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_free(task); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct QIOTaskThreadData { | 
					
						
							|  |  |  |     QIOTask *task; | 
					
						
							|  |  |  |     QIOTaskWorker worker; | 
					
						
							|  |  |  |     gpointer opaque; | 
					
						
							|  |  |  |     GDestroyNotify destroy; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean gio_task_thread_result(gpointer opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct QIOTaskThreadData *data = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_qio_task_thread_result(data->task); | 
					
						
							| 
									
										
										
										
											2016-08-11 15:20:58 +01:00
										 |  |  |     qio_task_complete(data->task); | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (data->destroy) { | 
					
						
							|  |  |  |         data->destroy(data->opaque); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_free(data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gpointer qio_task_thread_worker(gpointer opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct QIOTaskThreadData *data = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_qio_task_thread_run(data->task); | 
					
						
							| 
									
										
										
										
											2016-08-11 17:38:07 +01:00
										 |  |  |     data->worker(data->task, data->opaque); | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* We're running in the background thread, and must only
 | 
					
						
							|  |  |  |      * ever report the task results in the main event loop | 
					
						
							|  |  |  |      * thread. So we schedule an idle callback to report | 
					
						
							|  |  |  |      * the worker results | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     trace_qio_task_thread_exit(data->task); | 
					
						
							|  |  |  |     g_idle_add(gio_task_thread_result, data); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qio_task_run_in_thread(QIOTask *task, | 
					
						
							|  |  |  |                             QIOTaskWorker worker, | 
					
						
							|  |  |  |                             gpointer opaque, | 
					
						
							|  |  |  |                             GDestroyNotify destroy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct QIOTaskThreadData *data = g_new0(struct QIOTaskThreadData, 1); | 
					
						
							|  |  |  |     QemuThread thread; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data->task = task; | 
					
						
							|  |  |  |     data->worker = worker; | 
					
						
							|  |  |  |     data->opaque = opaque; | 
					
						
							|  |  |  |     data->destroy = destroy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace_qio_task_thread_start(task, worker, opaque); | 
					
						
							|  |  |  |     qemu_thread_create(&thread, | 
					
						
							|  |  |  |                        "io-task-worker", | 
					
						
							|  |  |  |                        qio_task_thread_worker, | 
					
						
							|  |  |  |                        data, | 
					
						
							|  |  |  |                        QEMU_THREAD_DETACHED); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qio_task_complete(QIOTask *task) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-11 15:20:58 +01:00
										 |  |  |     task->func(task, task->opaque); | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  |     trace_qio_task_complete(task); | 
					
						
							|  |  |  |     qio_task_free(task); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 14:40:44 +01:00
										 |  |  | void qio_task_set_error(QIOTask *task, | 
					
						
							|  |  |  |                         Error *err) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     error_propagate(&task->err, err); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool qio_task_propagate_error(QIOTask *task, | 
					
						
							|  |  |  |                               Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (task->err) { | 
					
						
							|  |  |  |         error_propagate(errp, task->err); | 
					
						
							| 
									
										
										
										
											2017-01-25 11:10:53 +00:00
										 |  |  |         task->err = NULL; | 
					
						
							| 
									
										
										
										
											2016-08-11 14:40:44 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 14:36:21 +01:00
										 |  |  | void qio_task_set_result_pointer(QIOTask *task, | 
					
						
							|  |  |  |                                  gpointer result, | 
					
						
							|  |  |  |                                  GDestroyNotify destroy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     task->result = result; | 
					
						
							|  |  |  |     task->destroyResult = destroy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gpointer qio_task_get_result_pointer(QIOTask *task) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return task->result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 17:25:45 +00:00
										 |  |  | Object *qio_task_get_source(QIOTask *task) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return task->source; | 
					
						
							|  |  |  | } |