mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
121 lines
2.8 KiB
C
121 lines
2.8 KiB
C
|
/*
|
||
|
* Event loop thread
|
||
|
*
|
||
|
* Copyright Red Hat Inc., 2013
|
||
|
*
|
||
|
* Authors:
|
||
|
* Stefan Hajnoczi <stefanha@redhat.com>
|
||
|
*
|
||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||
|
* See the COPYING file in the top-level directory.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "qom/object.h"
|
||
|
#include "qom/object_interfaces.h"
|
||
|
#include "qemu/module.h"
|
||
|
#include "qemu/thread.h"
|
||
|
#include "block/aio.h"
|
||
|
#include "sysemu/iothread.h"
|
||
|
|
||
|
#define IOTHREADS_PATH "/objects"
|
||
|
|
||
|
typedef ObjectClass IOThreadClass;
|
||
|
struct IOThread {
|
||
|
Object parent_obj;
|
||
|
|
||
|
QemuThread thread;
|
||
|
AioContext *ctx;
|
||
|
bool stopping;
|
||
|
};
|
||
|
|
||
|
#define IOTHREAD_GET_CLASS(obj) \
|
||
|
OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
|
||
|
#define IOTHREAD_CLASS(klass) \
|
||
|
OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD)
|
||
|
|
||
|
static void *iothread_run(void *opaque)
|
||
|
{
|
||
|
IOThread *iothread = opaque;
|
||
|
|
||
|
while (!iothread->stopping) {
|
||
|
aio_context_acquire(iothread->ctx);
|
||
|
while (!iothread->stopping && aio_poll(iothread->ctx, true)) {
|
||
|
/* Progress was made, keep going */
|
||
|
}
|
||
|
aio_context_release(iothread->ctx);
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static void iothread_instance_finalize(Object *obj)
|
||
|
{
|
||
|
IOThread *iothread = IOTHREAD(obj);
|
||
|
|
||
|
iothread->stopping = true;
|
||
|
aio_notify(iothread->ctx);
|
||
|
qemu_thread_join(&iothread->thread);
|
||
|
aio_context_unref(iothread->ctx);
|
||
|
}
|
||
|
|
||
|
static void iothread_complete(UserCreatable *obj, Error **errp)
|
||
|
{
|
||
|
IOThread *iothread = IOTHREAD(obj);
|
||
|
|
||
|
iothread->stopping = false;
|
||
|
iothread->ctx = aio_context_new();
|
||
|
|
||
|
/* This assumes we are called from a thread with useful CPU affinity for us
|
||
|
* to inherit.
|
||
|
*/
|
||
|
qemu_thread_create(&iothread->thread, "iothread", iothread_run,
|
||
|
iothread, QEMU_THREAD_JOINABLE);
|
||
|
}
|
||
|
|
||
|
static void iothread_class_init(ObjectClass *klass, void *class_data)
|
||
|
{
|
||
|
UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
|
||
|
ucc->complete = iothread_complete;
|
||
|
}
|
||
|
|
||
|
static const TypeInfo iothread_info = {
|
||
|
.name = TYPE_IOTHREAD,
|
||
|
.parent = TYPE_OBJECT,
|
||
|
.class_init = iothread_class_init,
|
||
|
.instance_size = sizeof(IOThread),
|
||
|
.instance_finalize = iothread_instance_finalize,
|
||
|
.interfaces = (InterfaceInfo[]) {
|
||
|
{TYPE_USER_CREATABLE},
|
||
|
{}
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static void iothread_register_types(void)
|
||
|
{
|
||
|
type_register_static(&iothread_info);
|
||
|
}
|
||
|
|
||
|
type_init(iothread_register_types)
|
||
|
|
||
|
IOThread *iothread_find(const char *id)
|
||
|
{
|
||
|
Object *container = container_get(object_get_root(), IOTHREADS_PATH);
|
||
|
Object *child;
|
||
|
|
||
|
child = object_property_get_link(container, id, NULL);
|
||
|
if (!child) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return (IOThread *)object_dynamic_cast(child, TYPE_IOTHREAD);
|
||
|
}
|
||
|
|
||
|
char *iothread_get_id(IOThread *iothread)
|
||
|
{
|
||
|
return object_get_canonical_path_component(OBJECT(iothread));
|
||
|
}
|
||
|
|
||
|
AioContext *iothread_get_aio_context(IOThread *iothread)
|
||
|
{
|
||
|
return iothread->ctx;
|
||
|
}
|