util/main-loop: Introduce the main loop into QOM
'event-loop-base' provides basic property handling for all 'AioContext'
based event loops. So let's define a new 'MainLoopClass' that inherits
from it. This will permit tweaking the main loop's properties through
qapi as well as through the command line using the '-object' keyword[1].
Only one instance of 'MainLoopClass' might be created at any time.
'EventLoopBaseClass' learns a new callback, 'can_be_deleted()' so as to
mark 'MainLoop' as non-deletable.
[1] For example:
      -object main-loop,id=main-loop,aio-max-batch=<value>
Signed-off-by: Nicolas Saenz Julienne <nsaenzju@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Message-id: 20220425075723.20019-3-nsaenzju@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
			
			
This commit is contained in:
		
				
					committed by
					
						
						Stefan Hajnoczi
					
				
			
			
				
	
			
			
			
						parent
						
							7d5983e3c8
						
					
				
				
					commit
					70ac26b9e5
				
			@@ -73,10 +73,23 @@ static void event_loop_base_complete(UserCreatable *uc, Error **errp)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool event_loop_base_can_be_deleted(UserCreatable *uc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EventLoopBaseClass *bc = EVENT_LOOP_BASE_GET_CLASS(uc);
 | 
				
			||||||
 | 
					    EventLoopBase *backend = EVENT_LOOP_BASE(uc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bc->can_be_deleted) {
 | 
				
			||||||
 | 
					        return bc->can_be_deleted(backend);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
 | 
					static void event_loop_base_class_init(ObjectClass *klass, void *class_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
 | 
					    UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
 | 
				
			||||||
    ucc->complete = event_loop_base_complete;
 | 
					    ucc->complete = event_loop_base_complete;
 | 
				
			||||||
 | 
					    ucc->can_be_deleted = event_loop_base_can_be_deleted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object_class_property_add(klass, "aio-max-batch", "int",
 | 
					    object_class_property_add(klass, "aio-max-batch", "int",
 | 
				
			||||||
                              event_loop_base_get_param,
 | 
					                              event_loop_base_get_param,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,9 +26,19 @@
 | 
				
			|||||||
#define QEMU_MAIN_LOOP_H
 | 
					#define QEMU_MAIN_LOOP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "block/aio.h"
 | 
					#include "block/aio.h"
 | 
				
			||||||
 | 
					#include "qom/object.h"
 | 
				
			||||||
 | 
					#include "sysemu/event-loop-base.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SIG_IPI SIGUSR1
 | 
					#define SIG_IPI SIGUSR1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TYPE_MAIN_LOOP  "main-loop"
 | 
				
			||||||
 | 
					OBJECT_DECLARE_TYPE(MainLoop, MainLoopClass, MAIN_LOOP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct MainLoop {
 | 
				
			||||||
 | 
					    EventLoopBase parent_obj;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef struct MainLoop MainLoop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * qemu_init_main_loop: Set up the process so that it can run the main loop.
 | 
					 * qemu_init_main_loop: Set up the process so that it can run the main loop.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ struct EventLoopBaseClass {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void (*init)(EventLoopBase *base, Error **errp);
 | 
					    void (*init)(EventLoopBase *base, Error **errp);
 | 
				
			||||||
    void (*update_params)(EventLoopBase *base, Error **errp);
 | 
					    void (*update_params)(EventLoopBase *base, Error **errp);
 | 
				
			||||||
 | 
					    bool (*can_be_deleted)(EventLoopBase *base);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct EventLoopBase {
 | 
					struct EventLoopBase {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3053,7 +3053,8 @@ libqemuutil = static_library('qemuutil',
 | 
				
			|||||||
                             sources: util_ss.sources() + stub_ss.sources() + genh,
 | 
					                             sources: util_ss.sources() + stub_ss.sources() + genh,
 | 
				
			||||||
                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
 | 
					                             dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman])
 | 
				
			||||||
qemuutil = declare_dependency(link_with: libqemuutil,
 | 
					qemuutil = declare_dependency(link_with: libqemuutil,
 | 
				
			||||||
                              sources: genh + version_res)
 | 
					                              sources: genh + version_res,
 | 
				
			||||||
 | 
					                              dependencies: [event_loop_base])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if have_system or have_user
 | 
					if have_system or have_user
 | 
				
			||||||
  decodetree = generator(find_program('scripts/decodetree.py'),
 | 
					  decodetree = generator(find_program('scripts/decodetree.py'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -540,6 +540,17 @@
 | 
				
			|||||||
            '*poll-grow': 'int',
 | 
					            '*poll-grow': 'int',
 | 
				
			||||||
            '*poll-shrink': 'int' } }
 | 
					            '*poll-shrink': 'int' } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					# @MainLoopProperties:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Properties for the main-loop object.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Since: 7.1
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					{ 'struct': 'MainLoopProperties',
 | 
				
			||||||
 | 
					  'base': 'EventLoopBaseProperties',
 | 
				
			||||||
 | 
					  'data': {} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# @MemoryBackendProperties:
 | 
					# @MemoryBackendProperties:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@@ -830,6 +841,7 @@
 | 
				
			|||||||
    { 'name': 'input-linux',
 | 
					    { 'name': 'input-linux',
 | 
				
			||||||
      'if': 'CONFIG_LINUX' },
 | 
					      'if': 'CONFIG_LINUX' },
 | 
				
			||||||
    'iothread',
 | 
					    'iothread',
 | 
				
			||||||
 | 
					    'main-loop',
 | 
				
			||||||
    { 'name': 'memory-backend-epc',
 | 
					    { 'name': 'memory-backend-epc',
 | 
				
			||||||
      'if': 'CONFIG_LINUX' },
 | 
					      'if': 'CONFIG_LINUX' },
 | 
				
			||||||
    'memory-backend-file',
 | 
					    'memory-backend-file',
 | 
				
			||||||
@@ -895,6 +907,7 @@
 | 
				
			|||||||
      'input-linux':                { 'type': 'InputLinuxProperties',
 | 
					      'input-linux':                { 'type': 'InputLinuxProperties',
 | 
				
			||||||
                                      'if': 'CONFIG_LINUX' },
 | 
					                                      'if': 'CONFIG_LINUX' },
 | 
				
			||||||
      'iothread':                   'IothreadProperties',
 | 
					      'iothread':                   'IothreadProperties',
 | 
				
			||||||
 | 
					      'main-loop':                  'MainLoopProperties',
 | 
				
			||||||
      'memory-backend-epc':         { 'type': 'MemoryBackendEpcProperties',
 | 
					      'memory-backend-epc':         { 'type': 'MemoryBackendEpcProperties',
 | 
				
			||||||
                                      'if': 'CONFIG_LINUX' },
 | 
					                                      'if': 'CONFIG_LINUX' },
 | 
				
			||||||
      'memory-backend-file':        'MemoryBackendFileProperties',
 | 
					      'memory-backend-file':        'MemoryBackendFileProperties',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,7 @@
 | 
				
			|||||||
#include "qemu/error-report.h"
 | 
					#include "qemu/error-report.h"
 | 
				
			||||||
#include "qemu/queue.h"
 | 
					#include "qemu/queue.h"
 | 
				
			||||||
#include "qemu/compiler.h"
 | 
					#include "qemu/compiler.h"
 | 
				
			||||||
 | 
					#include "qom/object.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _WIN32
 | 
					#ifndef _WIN32
 | 
				
			||||||
#include <sys/wait.h>
 | 
					#include <sys/wait.h>
 | 
				
			||||||
@@ -184,6 +185,61 @@ int qemu_init_main_loop(Error **errp)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void main_loop_update_params(EventLoopBase *base, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!qemu_aio_context) {
 | 
				
			||||||
 | 
					        error_setg(errp, "qemu aio context not ready");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aio_context_set_aio_params(qemu_aio_context, base->aio_max_batch, errp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MainLoop *mloop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void main_loop_init(EventLoopBase *base, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    MainLoop *m = MAIN_LOOP(base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mloop) {
 | 
				
			||||||
 | 
					        error_setg(errp, "only one main-loop instance allowed");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    main_loop_update_params(base, errp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mloop = m;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool main_loop_can_be_deleted(EventLoopBase *base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void main_loop_class_init(ObjectClass *oc, void *class_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EventLoopBaseClass *bc = EVENT_LOOP_BASE_CLASS(oc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bc->init = main_loop_init;
 | 
				
			||||||
 | 
					    bc->update_params = main_loop_update_params;
 | 
				
			||||||
 | 
					    bc->can_be_deleted = main_loop_can_be_deleted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const TypeInfo main_loop_info = {
 | 
				
			||||||
 | 
					    .name = TYPE_MAIN_LOOP,
 | 
				
			||||||
 | 
					    .parent = TYPE_EVENT_LOOP_BASE,
 | 
				
			||||||
 | 
					    .class_init = main_loop_class_init,
 | 
				
			||||||
 | 
					    .instance_size = sizeof(MainLoop),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void main_loop_register_types(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    type_register_static(&main_loop_info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type_init(main_loop_register_types)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int max_priority;
 | 
					static int max_priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _WIN32
 | 
					#ifndef _WIN32
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user