qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 11/19] use a bottom half to run timers


From: Marcelo Tosatti
Subject: Re: [Qemu-devel] [PATCH 11/19] use a bottom half to run timers
Date: Wed, 23 Dec 2009 16:37:14 -0200
User-agent: Mutt/1.5.19 (2009-01-05)

On Mon, Dec 21, 2009 at 09:09:22AM +0100, Paolo Bonzini wrote:
> Make the timer subsystem register its own bottom half instead of
> placing the bottom half code in the heart of the main loop.  To
> test if an alarm timer is pending, just check if the bottom half is
> scheduled.
> 
> Signed-off-by: Paolo Bonzini <address@hidden>
> ---
>  vl.c |   68 ++++++++++++++++++++++++++++++++++++-----------------------------
>  1 files changed, 38 insertions(+), 30 deletions(-)
> 
> diff --git a/vl.c b/vl.c
> index 78807f5..289aadc 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -573,10 +573,17 @@ struct qemu_alarm_timer {
>      void (*rearm)(struct qemu_alarm_timer *t);
>      void *priv;
>  
> +    QEMUBH *bh;
>      char expired;
> -    char pending;
>  };
>  
> +static struct qemu_alarm_timer *alarm_timer;
> +
> +static inline int qemu_alarm_pending(void)
> +{
> +    return qemu_bh_scheduled(alarm_timer->bh);
> +}
> +
>  static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
>  {
>      return !!t->rearm;
> @@ -593,8 +600,6 @@ static void qemu_rearm_alarm_timer(struct 
> qemu_alarm_timer *t)
>  /* TODO: MIN_TIMER_REARM_US should be optimized */
>  #define MIN_TIMER_REARM_US 250
>  
> -static struct qemu_alarm_timer *alarm_timer;
> -
>  #ifdef _WIN32
>  
>  struct qemu_alarm_win32 {
> @@ -874,7 +879,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
>  
>      /* Rearm if necessary  */
>      if (pt == &active_timers[ts->clock->type]) {
> -        if (!alarm_timer->pending) {
> +        if (!qemu_alarm_pending()) {
>              qemu_rearm_alarm_timer(alarm_timer);
>          }
>          /* Interrupt execution to force deadline recalculation.  */
> @@ -1001,6 +1006,31 @@ static const VMStateDescription vmstate_timers = {
>  
>  static void qemu_event_increment(void);
>  
> +static void qemu_timer_bh(void *opaque)
> +{
> +    struct qemu_alarm_timer *t = opaque;
> +
> +    /* rearm timer, if not periodic */
> +    if (t->expired) {
> +        t->expired = 0;
> +        qemu_rearm_alarm_timer(t);
> +    }
> +
> +    /* vm time timers */
> +    if (vm_running) {
> +        if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & 
> SSTEP_NOTIMER)))
> +            qemu_run_timers(&active_timers[QEMU_CLOCK_VIRTUAL],
> +                            qemu_get_clock(vm_clock));
> +    }
> +
> +    /* real time timers */
> +    qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME],
> +                    qemu_get_clock(rt_clock));
> +
> +    qemu_run_timers(&active_timers[QEMU_CLOCK_HOST],
> +                    qemu_get_clock(host_clock));
> +}
> +
>  #ifdef _WIN32
>  static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
>                                          DWORD_PTR dwUser, DWORD_PTR dw1,
> @@ -1059,8 +1089,7 @@ static void host_alarm_handler(int host_signum)
>              cpu_exit(next_cpu);
>          }
>  #endif
> -        t->pending = 1;
> -        qemu_notify_event();
> +        qemu_bh_schedule(t->bh);
>      }
>  }
>  
> @@ -1446,7 +1475,8 @@ static int init_timer_alarm(void)
>      }
>  
>      /* first event is at time 0 */
> -    t->pending = 1;
> +    t->bh = qemu_bh_new(qemu_timer_bh, t);
> +    qemu_bh_schedule(t->bh);
>      alarm_timer = t;

You should probably make sure the bh handling is signal safe. Perhaps
use atomic test-and-set for bh->schedule on qemu_bh_poll, etc...

Also there's a similar problem with the expired flag

> +    /* rearm timer, if not periodic */
> +    if (t->expired) {
> +        t->expired = 0;
> +        qemu_rearm_alarm_timer(t);
> +    }

(it was there before your patch).

BTW, if host_alarm_handler runs after is t->expired is cleared,
but before qemu_run_timers->callback->qemu_mod_timer, subsequent
qemu_mod_timer callbacks fail to rearm the alarm timer, in case
timer in question expires earlier?

Nice patchset!

>      qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
>  
> @@ -3811,28 +3841,6 @@ void main_loop_wait(int timeout)
>  
>      slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
>  
> -    /* rearm timer, if not periodic */
> -    if (alarm_timer->expired) {
> -        alarm_timer->expired = 0;
> -        qemu_rearm_alarm_timer(alarm_timer);
> -    }
> -
> -    alarm_timer->pending = 0;
> -
> -    /* vm time timers */
> -    if (vm_running) {
> -        if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & 
> SSTEP_NOTIMER)))
> -            qemu_run_timers(&active_timers[QEMU_CLOCK_VIRTUAL],
> -                            qemu_get_clock(vm_clock));
> -    }
> -
> -    /* real time timers */
> -    qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME],
> -                    qemu_get_clock(rt_clock));
> -
> -    qemu_run_timers(&active_timers[QEMU_CLOCK_HOST],
> -                    qemu_get_clock(host_clock));
> -
>      /* Check bottom-halves last in case any of the earlier events triggered
>         them.  */
>      qemu_bh_poll();
> @@ -3888,7 +3896,7 @@ static void tcg_cpu_exec(void)
>  
>          if (!vm_running)
>              break;
> -        if (alarm_timer->pending)
> +        if (qemu_alarm_pending())
>              break;
>          if (cpu_can_run(env))
>              ret = qemu_cpu_exec(env);
> -- 
> 1.6.5.2
> 
> 
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]