As of v7.0.0-877-g70ac26b9e5 QEMU exposes its main event loop as an QMP object. In the very next commit (v7.0.0-878-g71ad4713cc) it was extended for thread-pool-min and thread-pool-max attributes. Expose them under new <mainloop/> element. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- docs/formatdomain.rst | 5 ++ src/conf/domain_conf.c | 57 +++++++++++++++++++ src/conf/domain_conf.h | 8 +++ src/conf/schemas/domaincommon.rng | 15 +++++ src/conf/virconftypes.h | 2 + .../iothreads-ids-pool-sizes.xml | 1 + 6 files changed, 88 insertions(+) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index de085f616a..5e0019c574 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -677,6 +677,7 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)` <iothread id="6"/> <iothread id="8" pool_min="2" pool_max="32"/> </iothreadids> + <mainloop pool_min="8" pool_max="16"/> ... </domain> @@ -699,6 +700,10 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)` The element has two optional attributes ``pool_min`` and ``pool_max`` which allow setting lower and upper boundary for number of worker threads for given IOThread. :since:`Since 8.4.0` +``mainloop`` + The optional ``mainloop`` element contains two optional attributes + ``pool_min`` and ``pool_max`` which allow setting lower and upper boundary + for number of worker threads for the main event loop. :since:`Since 8.4.0` diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7572e62db1..866270160e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3824,6 +3824,8 @@ void virDomainDefFree(virDomainDef *def) virDomainIOThreadIDDefArrayFree(def->iothreadids, def->niothreadids); + g_free(def->mainLoop); + virBitmapFree(def->cputune.emulatorpin); g_free(def->cputune.emulatorsched); @@ -17085,6 +17087,32 @@ virDomainDefParseIOThreads(virDomainDef *def, } +static int +virDomainDefParseMainLoop(virDomainDef *def, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr node = NULL; + g_autofree virDomainMainLoopDef *ml = NULL; + + node = virXPathNode("./mainloop", ctxt); + if (!node) + return 0; + + ml = g_new0(virDomainMainLoopDef, 1); + + if (virXMLPropLongLong(node, "pool_min", 10, + VIR_XML_PROP_NONNEGATIVE, &ml->pool_min, -1) < 0) + return -1; + + if (virXMLPropLongLong(node, "pool_max", 10, + VIR_XML_PROP_NONNEGATIVE, &ml->pool_max, -1) < 0) + return -1; + + def->mainLoop = g_steal_pointer(&ml); + return 0; +} + + /* Parse the XML definition for a vcpupin * * vcpupin has the form of @@ -19259,6 +19287,9 @@ virDomainDefTunablesParse(virDomainDef *def, if (virDomainDefParseIOThreads(def, ctxt) < 0) return -1; + if (virDomainDefParseMainLoop(def, ctxt) < 0) + return -1; + /* Extract cpu tunables. */ if ((n = virXPathULongLong("string(./cputune/shares[1])", ctxt, &def->cputune.shares)) < -1) { @@ -27641,6 +27672,30 @@ virDomainDefIOThreadsFormat(virBuffer *buf, } +static void +virDomainDefMainLoopFormat(virBuffer *buf, + const virDomainDef *def) +{ + virBuffer attrBuf = VIR_BUFFER_INITIALIZER; + + if (!def->mainLoop) + return; + + if (def->mainLoop->pool_min >= 0) { + virBufferAsprintf(&attrBuf, " pool_min='%lld'", + def->mainLoop->pool_min); + } + + if (def->mainLoop->pool_max >= 0) { + virBufferAsprintf(&attrBuf, " pool_max='%lld'", + def->mainLoop->pool_max); + } + + + virXMLFormatElement(buf, "mainloop", &attrBuf, NULL); +} + + static void virDomainIOMMUDefFormat(virBuffer *buf, const virDomainIOMMUDef *iommu) @@ -28288,6 +28343,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, virDomainDefIOThreadsFormat(buf, def); + virDomainDefMainLoopFormat(buf, def); + if (virDomainCputuneDefFormat(buf, def, flags) < 0) return -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c502100d45..3184d36d54 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2655,6 +2655,12 @@ void virDomainIOThreadIDDefFree(virDomainIOThreadIDDef *def); G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainIOThreadIDDef, virDomainIOThreadIDDefFree); +struct _virDomainMainLoopDef { + long long pool_min; + long long pool_max; +}; + + struct _virDomainCputune { unsigned long long shares; bool sharesSpecified; @@ -2863,6 +2869,8 @@ struct _virDomainDef { size_t niothreadids; virDomainIOThreadIDDef **iothreadids; + virDomainMainLoopDef *mainLoop; + virDomainCputune cputune; virDomainResctrlDef **resctrls; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 94035c38e7..57c3f390f5 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -844,6 +844,21 @@ </element> </optional> + <optional> + <element name="mainloop"> + <optional> + <attribute name="pool_min"> + <ref name="unsignedLong"/> + </attribute> + </optional> + <optional> + <attribute name="pool_max"> + <ref name="unsignedLong"/> + </attribute> + </optional> + </element> + </optional> + <optional> <ref name="blkiotune"/> </optional> diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 21420ba8ea..f462642cbe 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -142,6 +142,8 @@ typedef struct _virDomainIOMMUDef virDomainIOMMUDef; typedef struct _virDomainIOThreadIDDef virDomainIOThreadIDDef; +typedef struct _virDomainMainLoopDef virDomainMainLoopDef; + typedef struct _virDomainIdMapDef virDomainIdMapDef; typedef struct _virDomainIdMapEntry virDomainIdMapEntry; diff --git a/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml b/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml index 5ff3b4b18e..087564171b 100644 --- a/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml +++ b/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml @@ -12,6 +12,7 @@ <iothread id='3'/> <iothread id='5'/> </iothreadids> + <mainloop pool_min='10' pool_max='120'/> <os> <type arch='x86_64' machine='q35'>hvm</type> <boot dev='hd'/> -- 2.35.1