Hi Ethan,
On 5/6/25 08:18, Ethan Chen via wrote:
This change introduces a configurable round-robin kick period, giving users the
flexibility to balance SMP simulation accuracy and performance according to
their specific needs.
The round-robin kick period is the time one vCPU can run before scheduler
switches to another vCPU when using a single thread TCG. The default value of
0.1 seconds may allow one vCPU to run for too long before the scheduler
switches to another. This behavior may not be suitable for workloads with
strict timing requirements.
Reducing the period can improve the fidelity of SMP simulation by allowing
more frequent vCPU switching, though it may negatively impact overall
simulation performance.
Signed-off-by: Ethan Chen <etha...@andestech.com>
---
accel/tcg/tcg-accel-ops-rr.c | 2 +-
accel/tcg/tcg-accel-ops-rr.h | 2 +-
accel/tcg/tcg-all.c | 35 +++++++++++++++++++++++++++++++++++
qemu-options.hx | 9 ++++++++-
4 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/accel/tcg/tcg-accel-ops-rr.h b/accel/tcg/tcg-accel-ops-rr.h
index 2a76a29612..324bb772cb 100644
--- a/accel/tcg/tcg-accel-ops-rr.h
+++ b/accel/tcg/tcg-accel-ops-rr.h
@@ -10,7 +10,7 @@
#ifndef TCG_ACCEL_OPS_RR_H
#define TCG_ACCEL_OPS_RR_H
-#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
+extern uint64_t rr_kick_period;
No need for another extern, pass it as argument:
-- >8 --
diff --git a/accel/tcg/tcg-accel-ops-rr.c b/accel/tcg/tcg-accel-ops-rr.c
index f62cf24e1d4..551864b5509 100644
--- a/accel/tcg/tcg-accel-ops-rr.c
+++ b/accel/tcg/tcg-accel-ops-rr.c
@@ -62,9 +62,9 @@ void rr_kick_vcpu_thread(CPUState *unused)
static QEMUTimer *rr_kick_vcpu_timer;
static CPUState *rr_current_cpu;
-static inline int64_t rr_next_kick_time(void)
+static inline int64_t rr_next_kick_time(uint64_t kick_delay_ns)
{
- return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + kick_delay_ns;
}
/* Kick the currently round-robin scheduled vCPU to next */
@@ -83,15 +83,20 @@ static void rr_kick_next_cpu(void)
static void rr_kick_thread(void *opaque)
{
- timer_mod(rr_kick_vcpu_timer, rr_next_kick_time());
+ CPUState *cpu = opaque;
+
+ // here use rr_next_kick_time(cpu->accel->rr_kick_delay_ns):
+ timer_mod(rr_kick_vcpu_timer, rr_next_kick_time(TCG_KICK_PERIOD));
rr_kick_next_cpu();
}
static void rr_start_kick_timer(void)
{
- if (!rr_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
+ CPUState *next_cpu = CPU_NEXT(first_cpu);
+
+ if (!rr_kick_vcpu_timer && next_cpu) {
rr_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- rr_kick_thread, NULL);
+ rr_kick_thread, next_cpu);
}
if (rr_kick_vcpu_timer && !timer_pending(rr_kick_vcpu_timer)) {
timer_mod(rr_kick_vcpu_timer, rr_next_kick_time());
---
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index 6e5dc333d5..69390020aa 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -36,6 +36,7 @@
#include "qapi/qapi-builtin-visit.h"
#include "qemu/units.h"
#include "qemu/target-info.h"
+#include "qemu/timer.h"
#ifndef CONFIG_USER_ONLY
#include "hw/boards.h"
#endif
@@ -50,6 +51,7 @@ struct TCGState {
bool one_insn_per_tb;
int splitwx_enabled;
unsigned long tb_size;
+ uint64_t rr_kick_period;
'rr_kick_delay_ns' seems more accurate.
};
typedef struct TCGState TCGState;
@@ -76,9 +78,11 @@ static void tcg_accel_instance_init(Object *obj)
#else
s->splitwx_enabled = 0;
#endif
+ s->rr_kick_period = NANOSECONDS_PER_SECOND / 10;
}
bool one_insn_per_tb;
+uint64_t rr_kick_period;
(Drop)
static int tcg_init_machine(MachineState *ms)
{
@@ -125,6 +129,7 @@ static int tcg_init_machine(MachineState *ms)
#endif
tcg_allowed = true;
+ rr_kick_period = s->rr_kick_period;
(Drop)
page_init();
tb_htable_init();
@@ -234,6 +239,30 @@ static int tcg_gdbstub_supported_sstep_flags(void)
}
}
Patch LGTM otherwise.
Regards,
Phil.