Skip to content

Commit 7d5983e

Browse files
vianplstefanhaRH
authored andcommitted
Introduce event-loop-base abstract class
Introduce the 'event-loop-base' abstract class, it'll hold the properties common to all event loops and provide the necessary hooks for their creation and maintenance. Then have iothread inherit from it. EventLoopBaseClass is defined as user creatable and provides a hook for its children to attach themselves to the user creatable class 'complete' function. It also provides an update_params() callback to propagate property changes onto its children. The new 'event-loop-base' class will live in the root directory. It is built on its own using the 'link_whole' option (there are no direct function dependencies between the class and its children, it all happens trough 'constructor' magic). And also imposes new compilation dependencies: qom <- event-loop-base <- blockdev (iothread.c) And in subsequent patches: qom <- event-loop-base <- qemuutil (util/main-loop.c) All this forced some amount of reordering in meson.build: - Moved qom build definition before qemuutil. Doing it the other way around (i.e. moving qemuutil after qom) isn't possible as a lot of core libraries that live in between the two depend on it. - Process the 'hw' subdir earlier, as it introduces files into the 'qom' source set. No functional changes intended. Signed-off-by: Nicolas Saenz Julienne <[email protected]> Reviewed-by: Stefan Hajnoczi <[email protected]> Acked-by: Markus Armbruster <[email protected]> Message-id: [email protected] Signed-off-by: Stefan Hajnoczi <[email protected]>
1 parent 5546232 commit 7d5983e

File tree

6 files changed

+192
-64
lines changed

6 files changed

+192
-64
lines changed

event-loop-base.c

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* QEMU event-loop base
3+
*
4+
* Copyright (C) 2022 Red Hat Inc
5+
*
6+
* Authors:
7+
* Stefan Hajnoczi <[email protected]>
8+
* Nicolas Saenz Julienne <[email protected]>
9+
*
10+
* This work is licensed under the terms of the GNU GPL, version 2 or later.
11+
* See the COPYING file in the top-level directory.
12+
*/
13+
14+
#include "qemu/osdep.h"
15+
#include "qom/object_interfaces.h"
16+
#include "qapi/error.h"
17+
#include "sysemu/event-loop-base.h"
18+
19+
typedef struct {
20+
const char *name;
21+
ptrdiff_t offset; /* field's byte offset in EventLoopBase struct */
22+
} EventLoopBaseParamInfo;
23+
24+
static EventLoopBaseParamInfo aio_max_batch_info = {
25+
"aio-max-batch", offsetof(EventLoopBase, aio_max_batch),
26+
};
27+
28+
static void event_loop_base_get_param(Object *obj, Visitor *v,
29+
const char *name, void *opaque, Error **errp)
30+
{
31+
EventLoopBase *event_loop_base = EVENT_LOOP_BASE(obj);
32+
EventLoopBaseParamInfo *info = opaque;
33+
int64_t *field = (void *)event_loop_base + info->offset;
34+
35+
visit_type_int64(v, name, field, errp);
36+
}
37+
38+
static void event_loop_base_set_param(Object *obj, Visitor *v,
39+
const char *name, void *opaque, Error **errp)
40+
{
41+
EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(obj);
42+
EventLoopBase *base = EVENT_LOOP_BASE(obj);
43+
EventLoopBaseParamInfo *info = opaque;
44+
int64_t *field = (void *)base + info->offset;
45+
int64_t value;
46+
47+
if (!visit_type_int64(v, name, &value, errp)) {
48+
return;
49+
}
50+
51+
if (value < 0) {
52+
error_setg(errp, "%s value must be in range [0, %" PRId64 "]",
53+
info->name, INT64_MAX);
54+
return;
55+
}
56+
57+
*field = value;
58+
59+
if (bc->update_params) {
60+
bc->update_params(base, errp);
61+
}
62+
63+
return;
64+
}
65+
66+
static void event_loop_base_complete(UserCreatable *uc, Error **errp)
67+
{
68+
EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
69+
EventLoopBase *base = EVENT_LOOP_BASE(uc);
70+
71+
if (bc->init) {
72+
bc->init(base, errp);
73+
}
74+
}
75+
76+
static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
77+
{
78+
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
79+
ucc->complete = event_loop_base_complete;
80+
81+
object_class_property_add(klass, "aio-max-batch", "int",
82+
event_loop_base_get_param,
83+
event_loop_base_set_param,
84+
NULL, &aio_max_batch_info);
85+
}
86+
87+
static const TypeInfo event_loop_base_info = {
88+
.name = TYPE_EVENT_LOOP_BASE,
89+
.parent = TYPE_OBJECT,
90+
.instance_size = sizeof(EventLoopBase),
91+
.class_size = sizeof(EventLoopBaseClass),
92+
.class_init = event_loop_base_class_init,
93+
.abstract = true,
94+
.interfaces = (InterfaceInfo[]) {
95+
{ TYPE_USER_CREATABLE },
96+
{ }
97+
}
98+
};
99+
100+
static void register_types(void)
101+
{
102+
type_register_static(&event_loop_base_info);
103+
}
104+
type_init(register_types);

include/sysemu/event-loop-base.h

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* QEMU event-loop backend
3+
*
4+
* Copyright (C) 2022 Red Hat Inc
5+
*
6+
* Authors:
7+
* Nicolas Saenz Julienne <[email protected]>
8+
*
9+
* This work is licensed under the terms of the GNU GPL, version 2 or later.
10+
* See the COPYING file in the top-level directory.
11+
*/
12+
#ifndef QEMU_EVENT_LOOP_BASE_H
13+
#define QEMU_EVENT_LOOP_BASE_H
14+
15+
#include "qom/object.h"
16+
#include "block/aio.h"
17+
#include "qemu/typedefs.h"
18+
19+
#define TYPE_EVENT_LOOP_BASE "event-loop-base"
20+
OBJECT_DECLARE_TYPE(EventLoopBase, EventLoopBaseClass,
21+
EVENT_LOOP_BASE)
22+
23+
struct EventLoopBaseClass {
24+
ObjectClass parent_class;
25+
26+
void (*init)(EventLoopBase *base, Error **errp);
27+
void (*update_params)(EventLoopBase *base, Error **errp);
28+
};
29+
30+
struct EventLoopBase {
31+
Object parent;
32+
33+
/* AioContext AIO engine parameters */
34+
int64_t aio_max_batch;
35+
};
36+
#endif

include/sysemu/iothread.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
#include "block/aio.h"
1818
#include "qemu/thread.h"
1919
#include "qom/object.h"
20+
#include "sysemu/event-loop-base.h"
2021

2122
#define TYPE_IOTHREAD "iothread"
2223

2324
struct IOThread {
24-
Object parent_obj;
25+
EventLoopBase parent_obj;
2526

2627
QemuThread thread;
2728
AioContext *ctx;
@@ -37,9 +38,6 @@ struct IOThread {
3738
int64_t poll_max_ns;
3839
int64_t poll_grow;
3940
int64_t poll_shrink;
40-
41-
/* AioContext AIO engine parameters */
42-
int64_t aio_max_batch;
4341
};
4442
typedef struct IOThread IOThread;
4543

iothread.c

+19-46
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "qemu/module.h"
1818
#include "block/aio.h"
1919
#include "block/block.h"
20+
#include "sysemu/event-loop-base.h"
2021
#include "sysemu/iothread.h"
2122
#include "qapi/error.h"
2223
#include "qapi/qapi-commands-misc.h"
@@ -152,10 +153,15 @@ static void iothread_init_gcontext(IOThread *iothread)
152153
iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
153154
}
154155

155-
static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
156+
static void iothread_set_aio_context_params(EventLoopBase *base, Error **errp)
156157
{
158+
IOThread *iothread = IOTHREAD(base);
157159
ERRP_GUARD();
158160

161+
if (!iothread->ctx) {
162+
return;
163+
}
164+
159165
aio_context_set_poll_params(iothread->ctx,
160166
iothread->poll_max_ns,
161167
iothread->poll_grow,
@@ -166,14 +172,15 @@ static void iothread_set_aio_context_params(IOThread *iothread, Error **errp)
166172
}
167173

168174
aio_context_set_aio_params(iothread->ctx,
169-
iothread->aio_max_batch,
175+
iothread->parent_obj.aio_max_batch,
170176
errp);
171177
}
172178

173-
static void iothread_complete(UserCreatable *obj, Error **errp)
179+
180+
static void iothread_init(EventLoopBase *base, Error **errp)
174181
{
175182
Error *local_error = NULL;
176-
IOThread *iothread = IOTHREAD(obj);
183+
IOThread *iothread = IOTHREAD(base);
177184
char *thread_name;
178185

179186
iothread->stopping = false;
@@ -189,7 +196,7 @@ static void iothread_complete(UserCreatable *obj, Error **errp)
189196
*/
190197
iothread_init_gcontext(iothread);
191198

192-
iothread_set_aio_context_params(iothread, &local_error);
199+
iothread_set_aio_context_params(base, &local_error);
193200
if (local_error) {
194201
error_propagate(errp, local_error);
195202
aio_context_unref(iothread->ctx);
@@ -201,7 +208,7 @@ static void iothread_complete(UserCreatable *obj, Error **errp)
201208
* to inherit.
202209
*/
203210
thread_name = g_strdup_printf("IO %s",
204-
object_get_canonical_path_component(OBJECT(obj)));
211+
object_get_canonical_path_component(OBJECT(base)));
205212
qemu_thread_create(&iothread->thread, thread_name, iothread_run,
206213
iothread, QEMU_THREAD_JOINABLE);
207214
g_free(thread_name);
@@ -226,9 +233,6 @@ static IOThreadParamInfo poll_grow_info = {
226233
static IOThreadParamInfo poll_shrink_info = {
227234
"poll-shrink", offsetof(IOThread, poll_shrink),
228235
};
229-
static IOThreadParamInfo aio_max_batch_info = {
230-
"aio-max-batch", offsetof(IOThread, aio_max_batch),
231-
};
232236

233237
static void iothread_get_param(Object *obj, Visitor *v,
234238
const char *name, IOThreadParamInfo *info, Error **errp)
@@ -288,35 +292,12 @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
288292
}
289293
}
290294

291-
static void iothread_get_aio_param(Object *obj, Visitor *v,
292-
const char *name, void *opaque, Error **errp)
293-
{
294-
IOThreadParamInfo *info = opaque;
295-
296-
iothread_get_param(obj, v, name, info, errp);
297-
}
298-
299-
static void iothread_set_aio_param(Object *obj, Visitor *v,
300-
const char *name, void *opaque, Error **errp)
301-
{
302-
IOThread *iothread = IOTHREAD(obj);
303-
IOThreadParamInfo *info = opaque;
304-
305-
if (!iothread_set_param(obj, v, name, info, errp)) {
306-
return;
307-
}
308-
309-
if (iothread->ctx) {
310-
aio_context_set_aio_params(iothread->ctx,
311-
iothread->aio_max_batch,
312-
errp);
313-
}
314-
}
315-
316295
static void iothread_class_init(ObjectClass *klass, void *class_data)
317296
{
318-
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
319-
ucc->complete = iothread_complete;
297+
EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(klass);
298+
299+
bc->init = iothread_init;
300+
bc->update_params = iothread_set_aio_context_params;
320301

321302
object_class_property_add(klass, "poll-max-ns", "int",
322303
iothread_get_poll_param,
@@ -330,23 +311,15 @@ static void iothread_class_init(ObjectClass *klass, void *class_data)
330311
iothread_get_poll_param,
331312
iothread_set_poll_param,
332313
NULL, &poll_shrink_info);
333-
object_class_property_add(klass, "aio-max-batch", "int",
334-
iothread_get_aio_param,
335-
iothread_set_aio_param,
336-
NULL, &aio_max_batch_info);
337314
}
338315

339316
static const TypeInfo iothread_info = {
340317
.name = TYPE_IOTHREAD,
341-
.parent = TYPE_OBJECT,
318+
.parent = TYPE_EVENT_LOOP_BASE,
342319
.class_init = iothread_class_init,
343320
.instance_size = sizeof(IOThread),
344321
.instance_init = iothread_instance_init,
345322
.instance_finalize = iothread_instance_finalize,
346-
.interfaces = (InterfaceInfo[]) {
347-
{TYPE_USER_CREATABLE},
348-
{}
349-
},
350323
};
351324

352325
static void iothread_register_types(void)
@@ -383,7 +356,7 @@ static int query_one_iothread(Object *object, void *opaque)
383356
info->poll_max_ns = iothread->poll_max_ns;
384357
info->poll_grow = iothread->poll_grow;
385358
info->poll_shrink = iothread->poll_shrink;
386-
info->aio_max_batch = iothread->aio_max_batch;
359+
info->aio_max_batch = iothread->parent_obj.aio_max_batch;
387360

388361
QAPI_LIST_APPEND(*tail, info);
389362
return 0;

meson.build

+14-9
Original file line numberDiff line numberDiff line change
@@ -3025,13 +3025,26 @@ subdir('qom')
30253025
subdir('authz')
30263026
subdir('crypto')
30273027
subdir('ui')
3028+
subdir('hw')
30283029

30293030

30303031
if enable_modules
30313032
libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO')
30323033
modulecommon = declare_dependency(link_whole: libmodulecommon, compile_args: '-DBUILD_DSO')
30333034
endif
30343035

3036+
qom_ss = qom_ss.apply(config_host, strict: false)
3037+
libqom = static_library('qom', qom_ss.sources() + genh,
3038+
dependencies: [qom_ss.dependencies()],
3039+
name_suffix: 'fa')
3040+
qom = declare_dependency(link_whole: libqom)
3041+
3042+
event_loop_base = files('event-loop-base.c')
3043+
event_loop_base = static_library('event-loop-base', sources: event_loop_base + genh,
3044+
build_by_default: true)
3045+
event_loop_base = declare_dependency(link_whole: event_loop_base,
3046+
dependencies: [qom])
3047+
30353048
stub_ss = stub_ss.apply(config_all, strict: false)
30363049

30373050
util_ss.add_all(trace_ss)
@@ -3118,7 +3131,6 @@ subdir('monitor')
31183131
subdir('net')
31193132
subdir('replay')
31203133
subdir('semihosting')
3121-
subdir('hw')
31223134
subdir('tcg')
31233135
subdir('fpu')
31243136
subdir('accel')
@@ -3243,13 +3255,6 @@ qemu_syms = custom_target('qemu.syms', output: 'qemu.syms',
32433255
capture: true,
32443256
command: [undefsym, nm, '@INPUT@'])
32453257

3246-
qom_ss = qom_ss.apply(config_host, strict: false)
3247-
libqom = static_library('qom', qom_ss.sources() + genh,
3248-
dependencies: [qom_ss.dependencies()],
3249-
name_suffix: 'fa')
3250-
3251-
qom = declare_dependency(link_whole: libqom)
3252-
32533258
authz_ss = authz_ss.apply(config_host, strict: false)
32543259
libauthz = static_library('authz', authz_ss.sources() + genh,
32553260
dependencies: [authz_ss.dependencies()],
@@ -3302,7 +3307,7 @@ libblockdev = static_library('blockdev', blockdev_ss.sources() + genh,
33023307
build_by_default: false)
33033308

33043309
blockdev = declare_dependency(link_whole: [libblockdev],
3305-
dependencies: [block])
3310+
dependencies: [block, event_loop_base])
33063311

33073312
qmp_ss = qmp_ss.apply(config_host, strict: false)
33083313
libqmp = static_library('qmp', qmp_ss.sources() + genh,

0 commit comments

Comments
 (0)