mirror of https://github.com/xemu-project/xemu.git
cpus: introduce cpu_update_icount helper
By holding off updates to timer_state.qemu_icount we can run into trouble when the non-vCPU thread needs to know the time. This helper ensures we atomically update timers_state.qemu_icount based on what has been currently executed. Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
This commit is contained in:
parent
e4cd96571f
commit
512d3c8071
23
cpus.c
23
cpus.c
|
@ -232,12 +232,31 @@ static int64_t cpu_get_icount_executed(CPUState *cpu)
|
||||||
return cpu->icount_budget - (cpu->icount_decr.u16.low + cpu->icount_extra);
|
return cpu->icount_budget - (cpu->icount_decr.u16.low + cpu->icount_extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the global shared timer_state.qemu_icount to take into
|
||||||
|
* account executed instructions. This is done by the TCG vCPU
|
||||||
|
* thread so the main-loop can see time has moved forward.
|
||||||
|
*/
|
||||||
|
void cpu_update_icount(CPUState *cpu)
|
||||||
|
{
|
||||||
|
int64_t executed = cpu_get_icount_executed(cpu);
|
||||||
|
cpu->icount_budget -= executed;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ATOMIC64
|
||||||
|
atomic_set__nocheck(&timers_state.qemu_icount,
|
||||||
|
atomic_read__nocheck(&timers_state.qemu_icount) +
|
||||||
|
executed);
|
||||||
|
#else /* FIXME: we need 64bit atomics to do this safely */
|
||||||
|
timers_state.qemu_icount += executed;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int64_t cpu_get_icount_raw(void)
|
int64_t cpu_get_icount_raw(void)
|
||||||
{
|
{
|
||||||
int64_t icount;
|
int64_t icount;
|
||||||
CPUState *cpu = current_cpu;
|
CPUState *cpu = current_cpu;
|
||||||
|
|
||||||
icount = timers_state.qemu_icount;
|
icount = atomic_read(&timers_state.qemu_icount);
|
||||||
if (cpu && cpu->running) {
|
if (cpu && cpu->running) {
|
||||||
if (!cpu->can_do_io) {
|
if (!cpu->can_do_io) {
|
||||||
fprintf(stderr, "Bad icount read\n");
|
fprintf(stderr, "Bad icount read\n");
|
||||||
|
@ -1220,7 +1239,7 @@ static void process_icount_data(CPUState *cpu)
|
||||||
{
|
{
|
||||||
if (use_icount) {
|
if (use_icount) {
|
||||||
/* Account for executed instructions */
|
/* Account for executed instructions */
|
||||||
timers_state.qemu_icount += cpu_get_icount_executed(cpu);
|
cpu_update_icount(cpu);
|
||||||
|
|
||||||
/* Reset the counters */
|
/* Reset the counters */
|
||||||
cpu->icount_decr.u16.low = 0;
|
cpu->icount_decr.u16.low = 0;
|
||||||
|
|
|
@ -869,6 +869,7 @@ int64_t cpu_get_icount_raw(void);
|
||||||
int64_t cpu_get_icount(void);
|
int64_t cpu_get_icount(void);
|
||||||
int64_t cpu_get_clock(void);
|
int64_t cpu_get_clock(void);
|
||||||
int64_t cpu_icount_to_ns(int64_t icount);
|
int64_t cpu_icount_to_ns(int64_t icount);
|
||||||
|
void cpu_update_icount(CPUState *cpu);
|
||||||
|
|
||||||
/*******************************************/
|
/*******************************************/
|
||||||
/* host CPU ticks (if available) */
|
/* host CPU ticks (if available) */
|
||||||
|
|
Loading…
Reference in New Issue