ia64/xen-unstable

changeset 8588:cc2f35c83b4c

Add a new timer operation kill_timer(). Effectively the
'opposite' of init_timer(), it marks the end of a timer's
lifetime. After this call the timer will not be pending,
its callback handler will not be running, and future calls
to set_timer() will silently fail.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Jan 13 01:03:44 2006 +0100 (2006-01-13)
parents d32797209632
children ec4ef8c5f04d
files xen/arch/x86/vmx.c xen/common/sched_bvt.c xen/common/schedule.c xen/common/timer.c xen/include/xen/timer.h
line diff
     1.1 --- a/xen/arch/x86/vmx.c	Fri Jan 13 00:16:07 2006 +0100
     1.2 +++ b/xen/arch/x86/vmx.c	Fri Jan 13 01:03:44 2006 +0100
     1.3 @@ -105,13 +105,11 @@ void vmx_relinquish_resources(struct vcp
     1.4      destroy_vmcs(&v->arch.arch_vmx);
     1.5      free_monitor_pagetable(v);
     1.6      vpit = &v->domain->arch.vmx_platform.vmx_pit;
     1.7 -    if ( active_timer(&(vpit->pit_timer)) )
     1.8 -        stop_timer(&vpit->pit_timer);
     1.9 -    if ( active_timer(&v->arch.arch_vmx.hlt_timer) )
    1.10 -        stop_timer(&v->arch.arch_vmx.hlt_timer);
    1.11 +    kill_timer(&vpit->pit_timer);
    1.12 +    kill_timer(&v->arch.arch_vmx.hlt_timer);
    1.13      if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) )
    1.14      {
    1.15 -        stop_timer(&VLAPIC(v)->vlapic_timer);
    1.16 +        kill_timer(&VLAPIC(v)->vlapic_timer);
    1.17          xfree(VLAPIC(v));
    1.18      }
    1.19  }
     2.1 --- a/xen/common/sched_bvt.c	Fri Jan 13 00:16:07 2006 +0100
     2.2 +++ b/xen/common/sched_bvt.c	Fri Jan 13 01:03:44 2006 +0100
     2.3 @@ -45,9 +45,9 @@ struct bvt_dom_info
     2.4                                               limits*/
     2.5      s32                 warp_value;       /* virtual time warp */
     2.6      s_time_t            warpl;            /* warp limit */
     2.7 -    struct timer     warp_timer;       /* deals with warpl */
     2.8 +    struct timer        warp_timer;       /* deals with warpl */
     2.9      s_time_t            warpu;            /* unwarp time requirement */
    2.10 -    struct timer     unwarp_timer;     /* deals with warpu */
    2.11 +    struct timer        unwarp_timer;     /* deals with warpu */
    2.12  
    2.13      struct bvt_vcpu_info vcpu_inf[MAX_VIRT_CPUS];
    2.14  };
    2.15 @@ -168,6 +168,7 @@ static inline u32 calc_evt(struct vcpu *
    2.16  static int bvt_alloc_task(struct vcpu *v)
    2.17  {
    2.18      struct domain *d = v->domain;
    2.19 +    struct bvt_dom_info *inf;
    2.20  
    2.21      if ( (d->sched_priv == NULL) )
    2.22      {
    2.23 @@ -176,32 +177,12 @@ static int bvt_alloc_task(struct vcpu *v
    2.24          memset(d->sched_priv, 0, sizeof(struct bvt_dom_info));
    2.25      }
    2.26  
    2.27 -    v->sched_priv = &BVT_INFO(d)->vcpu_inf[v->vcpu_id];
    2.28 -
    2.29 -    BVT_INFO(d)->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d);
    2.30 -    BVT_INFO(d)->vcpu_inf[v->vcpu_id].vcpu = v;
    2.31 -
    2.32 -    return 0;
    2.33 -}
    2.34 +    inf = BVT_INFO(d);
    2.35  
    2.36 -/*
    2.37 - * Add and remove a domain
    2.38 - */
    2.39 -static void bvt_add_task(struct vcpu *v) 
    2.40 -{
    2.41 -    struct bvt_dom_info *inf = BVT_INFO(v->domain);
    2.42 -    struct bvt_vcpu_info *einf = EBVT_INFO(v);
    2.43 -    ASSERT(inf != NULL);
    2.44 -    ASSERT(v   != NULL);
    2.45 +    v->sched_priv = &inf->vcpu_inf[v->vcpu_id];
    2.46  
    2.47 -    /* Allocate per-CPU context if this is the first domain to be added. */
    2.48 -    if ( CPU_INFO(v->processor) == NULL )
    2.49 -    {
    2.50 -        schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info);
    2.51 -        BUG_ON(CPU_INFO(v->processor) == NULL);
    2.52 -        INIT_LIST_HEAD(RUNQUEUE(v->processor));
    2.53 -        CPU_SVT(v->processor) = 0;
    2.54 -    }
    2.55 +    inf->vcpu_inf[v->vcpu_id].inf  = BVT_INFO(d);
    2.56 +    inf->vcpu_inf[v->vcpu_id].vcpu = v;
    2.57  
    2.58      if ( v->vcpu_id == 0 )
    2.59      {
    2.60 @@ -218,7 +199,28 @@ static void bvt_add_task(struct vcpu *v)
    2.61          init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor);
    2.62      }
    2.63  
    2.64 -    einf->vcpu = v;
    2.65 +    return 0;
    2.66 +}
    2.67 +
    2.68 +/*
    2.69 + * Add and remove a domain
    2.70 + */
    2.71 +static void bvt_add_task(struct vcpu *v) 
    2.72 +{
    2.73 +    struct bvt_dom_info *inf = BVT_INFO(v->domain);
    2.74 +    struct bvt_vcpu_info *einf = EBVT_INFO(v);
    2.75 +
    2.76 +    ASSERT(inf != NULL);
    2.77 +    ASSERT(v   != NULL);
    2.78 +
    2.79 +    /* Allocate per-CPU context if this is the first domain to be added. */
    2.80 +    if ( CPU_INFO(v->processor) == NULL )
    2.81 +    {
    2.82 +        schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info);
    2.83 +        BUG_ON(CPU_INFO(v->processor) == NULL);
    2.84 +        INIT_LIST_HEAD(RUNQUEUE(v->processor));
    2.85 +        CPU_SVT(v->processor) = 0;
    2.86 +    }
    2.87  
    2.88      if ( is_idle_vcpu(v) )
    2.89      {
    2.90 @@ -305,8 +307,14 @@ static int bvt_set_affinity(struct vcpu 
    2.91   */
    2.92  static void bvt_free_task(struct domain *d)
    2.93  {
    2.94 -    ASSERT(d->sched_priv != NULL);
    2.95 -    xfree(d->sched_priv);
    2.96 +    struct bvt_dom_info *inf = BVT_INFO(d);
    2.97 +
    2.98 +    ASSERT(inf != NULL);
    2.99 +
   2.100 +    kill_timer(&inf->warp_timer);
   2.101 +    kill_timer(&inf->unwarp_timer);
   2.102 +
   2.103 +    xfree(inf);
   2.104  }
   2.105  
   2.106  /* Control the scheduler. */
     3.1 --- a/xen/common/schedule.c	Fri Jan 13 00:16:07 2006 +0100
     3.2 +++ b/xen/common/schedule.c	Fri Jan 13 01:03:44 2006 +0100
     3.3 @@ -156,7 +156,7 @@ void sched_add_domain(struct vcpu *v)
     3.4  
     3.5  void sched_rem_domain(struct vcpu *v) 
     3.6  {
     3.7 -    stop_timer(&v->timer);
     3.8 +    kill_timer(&v->timer);
     3.9      SCHED_OP(rem_task, v);
    3.10      TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
    3.11  }
    3.12 @@ -462,7 +462,7 @@ static void s_timer_fn(void *unused)
    3.13  /* Periodic tick timer: send timer event to current domain */
    3.14  static void t_timer_fn(void *unused)
    3.15  {
    3.16 -    struct vcpu  *v  = current;
    3.17 +    struct vcpu  *v   = current;
    3.18      unsigned int  cpu = smp_processor_id();
    3.19  
    3.20      schedule_data[cpu].tick++;
     4.1 --- a/xen/common/timer.c	Fri Jan 13 00:16:07 2006 +0100
     4.2 +++ b/xen/common/timer.c	Fri Jan 13 01:03:44 2006 +0100
     4.3 @@ -29,6 +29,7 @@
     4.4  struct timers {
     4.5      spinlock_t     lock;
     4.6      struct timer **heap;
     4.7 +    struct timer  *running;
     4.8  } __cacheline_aligned;
     4.9  
    4.10  struct timers timers[NR_CPUS];
    4.11 @@ -167,11 +168,11 @@ void set_timer(struct timer *timer, s_ti
    4.12      unsigned long flags;
    4.13  
    4.14      spin_lock_irqsave(&timers[cpu].lock, flags);
    4.15 -    ASSERT(timer != NULL);
    4.16      if ( active_timer(timer) )
    4.17          __stop_timer(timer);
    4.18      timer->expires = expires;
    4.19 -    __add_timer(timer);
    4.20 +    if ( likely(!timer->killed) )
    4.21 +        __add_timer(timer);
    4.22      spin_unlock_irqrestore(&timers[cpu].lock, flags);
    4.23  }
    4.24  
    4.25 @@ -182,13 +183,31 @@ void stop_timer(struct timer *timer)
    4.26      unsigned long flags;
    4.27  
    4.28      spin_lock_irqsave(&timers[cpu].lock, flags);
    4.29 -    ASSERT(timer != NULL);
    4.30      if ( active_timer(timer) )
    4.31          __stop_timer(timer);
    4.32      spin_unlock_irqrestore(&timers[cpu].lock, flags);
    4.33  }
    4.34  
    4.35  
    4.36 +void kill_timer(struct timer *timer)
    4.37 +{
    4.38 +    int           cpu = timer->cpu;
    4.39 +    unsigned long flags;
    4.40 +
    4.41 +    BUG_ON(timers[cpu].running == timer);
    4.42 +
    4.43 +    spin_lock_irqsave(&timers[cpu].lock, flags);
    4.44 +    if ( active_timer(timer) )
    4.45 +        __stop_timer(timer);
    4.46 +    timer->killed = 1;
    4.47 +    spin_unlock_irqrestore(&timers[cpu].lock, flags);
    4.48 +
    4.49 +    for_each_online_cpu ( cpu )
    4.50 +        while ( timers[cpu].running == timer )
    4.51 +            cpu_relax();
    4.52 +}
    4.53 +
    4.54 +
    4.55  static void timer_softirq_action(void)
    4.56  {
    4.57      int           cpu = smp_processor_id();
    4.58 @@ -208,19 +227,20 @@ static void timer_softirq_action(void)
    4.59          {
    4.60              remove_entry(heap, t);
    4.61  
    4.62 +            timers[cpu].running = t;
    4.63 +
    4.64              fn   = t->function;
    4.65              data = t->data;
    4.66  
    4.67 -            if ( fn != NULL )
    4.68 -            {
    4.69 -                spin_unlock_irq(&timers[cpu].lock);
    4.70 -                (*fn)(data);
    4.71 -                spin_lock_irq(&timers[cpu].lock);
    4.72 -            }
    4.73 +            spin_unlock_irq(&timers[cpu].lock);
    4.74 +            (*fn)(data);
    4.75 +            spin_lock_irq(&timers[cpu].lock);
    4.76  
    4.77              /* Heap may have grown while the lock was released. */
    4.78              heap = timers[cpu].heap;
    4.79          }
    4.80 +
    4.81 +        timers[cpu].running = NULL;
    4.82      }
    4.83      while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) );
    4.84  
     5.1 --- a/xen/include/xen/timer.h	Fri Jan 13 00:16:07 2006 +0100
     5.2 +++ b/xen/include/xen/timer.h	Fri Jan 13 01:03:44 2006 +0100
     5.3 @@ -22,6 +22,8 @@ struct timer {
     5.4      void         *data;
     5.5      /* Timer-heap offset. */
     5.6      unsigned int  heap_offset;
     5.7 +    /* Has this timer been killed (cannot be activated)? */
     5.8 +    int           killed;
     5.9  };
    5.10  
    5.11  /*
    5.12 @@ -64,6 +66,13 @@ extern void set_timer(struct timer *time
    5.13  extern void stop_timer(struct timer *timer);
    5.14  
    5.15  /*
    5.16 + * Deactivate a timer and prevent it from being re-set (future calls to
    5.17 + * set_timer will silently fail). When this function returns it is guaranteed
    5.18 + * that the timer callback handler is not running on any CPU.
    5.19 + */
    5.20 +extern void kill_timer(struct timer *timer);
    5.21 +
    5.22 +/*
    5.23   * Initialisation. Must be called before any other timer function.
    5.24   */
    5.25  extern void timer_init(void);