]> Git Repo - qemu.git/blob - io/task.c
colo: Consolidate the duplicate code chunk into a routine
[qemu.git] / io / task.c
1 /*
2  * QEMU I/O task
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "qemu/osdep.h"
22 #include "io/task.h"
23 #include "qapi/error.h"
24 #include "qemu/thread.h"
25 #include "trace.h"
26
27 struct QIOTask {
28     Object *source;
29     QIOTaskFunc func;
30     gpointer opaque;
31     GDestroyNotify destroy;
32     Error *err;
33     gpointer result;
34     GDestroyNotify destroyResult;
35 };
36
37
38 QIOTask *qio_task_new(Object *source,
39                       QIOTaskFunc func,
40                       gpointer opaque,
41                       GDestroyNotify destroy)
42 {
43     QIOTask *task;
44
45     task = g_new0(QIOTask, 1);
46
47     task->source = source;
48     object_ref(source);
49     task->func = func;
50     task->opaque = opaque;
51     task->destroy = destroy;
52
53     trace_qio_task_new(task, source, func, opaque);
54
55     return task;
56 }
57
58 static void qio_task_free(QIOTask *task)
59 {
60     if (task->destroy) {
61         task->destroy(task->opaque);
62     }
63     if (task->destroyResult) {
64         task->destroyResult(task->result);
65     }
66     if (task->err) {
67         error_free(task->err);
68     }
69     object_unref(task->source);
70
71     g_free(task);
72 }
73
74
75 struct QIOTaskThreadData {
76     QIOTask *task;
77     QIOTaskWorker worker;
78     gpointer opaque;
79     GDestroyNotify destroy;
80 };
81
82
83 static gboolean gio_task_thread_result(gpointer opaque)
84 {
85     struct QIOTaskThreadData *data = opaque;
86
87     trace_qio_task_thread_result(data->task);
88     qio_task_complete(data->task);
89
90     if (data->destroy) {
91         data->destroy(data->opaque);
92     }
93
94     g_free(data);
95
96     return FALSE;
97 }
98
99
100 static gpointer qio_task_thread_worker(gpointer opaque)
101 {
102     struct QIOTaskThreadData *data = opaque;
103
104     trace_qio_task_thread_run(data->task);
105     data->worker(data->task, data->opaque);
106
107     /* We're running in the background thread, and must only
108      * ever report the task results in the main event loop
109      * thread. So we schedule an idle callback to report
110      * the worker results
111      */
112     trace_qio_task_thread_exit(data->task);
113     g_idle_add(gio_task_thread_result, data);
114     return NULL;
115 }
116
117
118 void qio_task_run_in_thread(QIOTask *task,
119                             QIOTaskWorker worker,
120                             gpointer opaque,
121                             GDestroyNotify destroy)
122 {
123     struct QIOTaskThreadData *data = g_new0(struct QIOTaskThreadData, 1);
124     QemuThread thread;
125
126     data->task = task;
127     data->worker = worker;
128     data->opaque = opaque;
129     data->destroy = destroy;
130
131     trace_qio_task_thread_start(task, worker, opaque);
132     qemu_thread_create(&thread,
133                        "io-task-worker",
134                        qio_task_thread_worker,
135                        data,
136                        QEMU_THREAD_DETACHED);
137 }
138
139
140 void qio_task_complete(QIOTask *task)
141 {
142     task->func(task, task->opaque);
143     trace_qio_task_complete(task);
144     qio_task_free(task);
145 }
146
147
148 void qio_task_set_error(QIOTask *task,
149                         Error *err)
150 {
151     error_propagate(&task->err, err);
152 }
153
154
155 bool qio_task_propagate_error(QIOTask *task,
156                               Error **errp)
157 {
158     if (task->err) {
159         error_propagate(errp, task->err);
160         task->err = NULL;
161         return true;
162     }
163
164     return false;
165 }
166
167
168 void qio_task_set_result_pointer(QIOTask *task,
169                                  gpointer result,
170                                  GDestroyNotify destroy)
171 {
172     task->result = result;
173     task->destroyResult = destroy;
174 }
175
176
177 gpointer qio_task_get_result_pointer(QIOTask *task)
178 {
179     return task->result;
180 }
181
182
183 Object *qio_task_get_source(QIOTask *task)
184 {
185     return task->source;
186 }
This page took 0.033251 seconds and 4 git commands to generate.