ia64/xen-unstable

changeset 936:464dff9c4e15

bitkeeper revision 1.596 (3fb247cfmIy4Y7E2SLnZRhjvUWmjXw)

schedule.c:
Fix a race when calling update_dom_time.
author kaf24@scramble.cl.cam.ac.uk
date Wed Nov 12 14:46:39 2003 +0000 (2003-11-12)
parents 87d895822ab8
children eaaf88bbc222 cfd9961afd8b
files xen/common/schedule.c
line diff
     1.1 --- a/xen/common/schedule.c	Wed Nov 12 13:22:54 2003 +0000
     1.2 +++ b/xen/common/schedule.c	Wed Nov 12 14:46:39 2003 +0000
     1.3 @@ -53,9 +53,17 @@ typedef struct schedule_data_st
     1.4      u32                 hist[BUCKETS];  /* for scheduler latency histogram */
     1.5  #endif
     1.6  } __cacheline_aligned schedule_data_t;
     1.7 -schedule_data_t schedule_data[NR_CPUS];
     1.8 +static schedule_data_t schedule_data[NR_CPUS];
     1.9  
    1.10 -struct ac_timer v_timer;        /* scheduling timer  */
    1.11 +/* Skanky periodic event to all guests. This must die in the next release! */
    1.12 +static struct ac_timer v_timer; 
    1.13 +
    1.14 +/*
    1.15 + * Per-CPU timer to ensure that even guests with very long quantums get
    1.16 + * their time-of-day state updated often enough to avoid wrapping.
    1.17 + */
    1.18 +static struct ac_timer fallback_timer[NR_CPUS];
    1.19 +
    1.20  static void virt_timer(unsigned long foo);
    1.21  static void dump_rqueue(struct list_head *queue, char *name);
    1.22  
    1.23 @@ -544,10 +552,8 @@ int idle_cpu(int cpu)
    1.24  }
    1.25  
    1.26  
    1.27 -/*
    1.28 - * The scheduler timer.
    1.29 - */
    1.30 -static void sched_timer(unsigned long foo)
    1.31 +/* The scheduler timer. */
    1.32 +static void sched_timer(unsigned long unused)
    1.33  {
    1.34      int                 cpu  = smp_processor_id();
    1.35      struct task_struct *curr = schedule_data[cpu].curr;
    1.36 @@ -556,33 +562,42 @@ static void sched_timer(unsigned long fo
    1.37      perfc_incrc(sched_irq);
    1.38  }
    1.39  
    1.40 -/*
    1.41 - * The Domain virtual time timer
    1.42 - */
    1.43 -static void virt_timer(unsigned long foo)
    1.44 +/* The Domain virtual time timer */
    1.45 +static void virt_timer(unsigned long unused)
    1.46  {
    1.47 -    unsigned long cpu_mask = 0;
    1.48 +    unsigned long flags, cpu_mask = 0;
    1.49      struct task_struct *p;
    1.50      s_time_t now;
    1.51  
    1.52      /* send virtual timer interrupt */
    1.53 -    read_lock(&tasklist_lock);
    1.54 +    read_lock_irqsave(&tasklist_lock, flags);
    1.55      p = &idle0_task;
    1.56      do {
    1.57          if ( is_idle_task(p) ) continue;
    1.58          cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
    1.59 -        if ( p->has_cpu ) 
    1.60 -            update_dom_time(p->shared_info);
    1.61      }
    1.62      while ( (p = p->next_task) != &idle0_task );
    1.63 -    read_unlock(&tasklist_lock);
    1.64 +    read_unlock_irqrestore(&tasklist_lock, flags);
    1.65      guest_event_notify(cpu_mask);
    1.66  
    1.67      now = NOW();
    1.68 -    v_timer.expires  = now + MILLISECS(20);
    1.69 +    v_timer.expires = now + MILLISECS(20);
    1.70      add_ac_timer(&v_timer);
    1.71  }
    1.72  
    1.73 +/* Fallback timer to ensure guests get time updated 'often enough'. */
    1.74 +static void fallback_timer_fn(unsigned long unused)
    1.75 +{
    1.76 +    struct task_struct *p = current;
    1.77 +    unsigned int cpu = p->processor;
    1.78 +
    1.79 +    if ( !is_idle_task(p) )
    1.80 +        update_dom_time(p->shared_info);
    1.81 +
    1.82 +    fallback_timer[cpu].expires = NOW() + MILLISECS(500);
    1.83 +    add_ac_timer(&fallback_timer[cpu]);
    1.84 +}
    1.85 +
    1.86  /*
    1.87   * Initialise the data structures
    1.88   */
    1.89 @@ -598,15 +613,19 @@ void __init scheduler_init(void)
    1.90          spin_lock_init(&schedule_data[i].lock);
    1.91          schedule_data[i].curr = &idle0_task;
    1.92          
    1.93 -        /* a timer for each CPU  */
    1.94          init_ac_timer(&schedule_data[i].s_timer, i);
    1.95 -        schedule_data[i].s_timer.data = 2;
    1.96 +        schedule_data[i].s_timer.data     = 2;
    1.97          schedule_data[i].s_timer.function = &sched_timer;
    1.98  
    1.99 +        init_ac_timer(&fallback_timer[i], i);
   1.100 +        fallback_timer[i].data     = 0;
   1.101 +        fallback_timer[i].function = &fallback_timer_fn;
   1.102      }
   1.103 -    schedule_data[0].idle = &idle0_task; /* idle on CPU 0 is special */
   1.104 +
   1.105 +    schedule_data[0].idle = &idle0_task;
   1.106 +
   1.107      init_ac_timer(&v_timer, 0);
   1.108 -    v_timer.data = 3;
   1.109 +    v_timer.data     = 0;
   1.110      v_timer.function = &virt_timer;
   1.111  }
   1.112  
   1.113 @@ -617,9 +636,14 @@ void __init scheduler_init(void)
   1.114  void schedulers_start(void) 
   1.115  {   
   1.116      printk("Start schedulers\n");
   1.117 +
   1.118 +    virt_timer(0);
   1.119 +
   1.120      sched_timer(0);
   1.121 -    virt_timer(0);
   1.122      smp_call_function((void *)sched_timer, NULL, 1, 1);
   1.123 +
   1.124 +    fallback_timer_fn(0);
   1.125 +    smp_call_function((void *)fallback_timer_fn, NULL, 1, 1);
   1.126  }
   1.127  
   1.128