ia64/xen-unstable

changeset 4294:46155de3064d

bitkeeper revision 1.1236.43.1 (4242f75e6Zk-5XZxY7UL-J_Qi8D43g)

Fix VIRQ_TIMER holdoff for SMP guests.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Mar 24 17:22:38 2005 +0000 (2005-03-24)
parents 0c7d16e71835
children 7e0520c972fb
files linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c xen/arch/ia64/patch/linux-2.6.7/time.c xen/arch/x86/time.c xen/common/sched_atropos.c xen/common/sched_bvt.c xen/common/sched_rrobin.c xen/common/schedule.c xen/include/xen/sched-if.h xen/include/xen/sched.h xen/include/xen/time.h
line diff
     1.1 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c	Thu Mar 24 11:04:24 2005 +0000
     1.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c	Thu Mar 24 17:22:38 2005 +0000
     1.3 @@ -672,6 +672,7 @@ int set_timeout_timer(void)
     1.4  {
     1.5  	u64 alarm = 0;
     1.6  	int ret = 0;
     1.7 +	unsigned long j;
     1.8  #ifdef CONFIG_SMP
     1.9  	unsigned long seq;
    1.10  #endif
    1.11 @@ -685,13 +686,14 @@ int set_timeout_timer(void)
    1.12  #ifdef CONFIG_SMP
    1.13  	do {
    1.14  		seq = read_seqbegin(&xtime_lock);
    1.15 -		if (smp_processor_id())
    1.16 -			alarm = __jiffies_to_st(jiffies + 1);
    1.17 -		else
    1.18 -			alarm = __jiffies_to_st(jiffies + 1);
    1.19 +		j = jiffies + 1;
    1.20 +		alarm = __jiffies_to_st(j);
    1.21  	} while (read_seqretry(&xtime_lock, seq));
    1.22  #else
    1.23 -	alarm = __jiffies_to_st(next_timer_interrupt());
    1.24 +	j = next_timer_interrupt();
    1.25 +	if (j < (jiffies + 1))
    1.26 +		j = jiffies + 1;
    1.27 +	alarm = __jiffies_to_st(j);
    1.28  #endif
    1.29  
    1.30  	/* Failure is pretty bad, but we'd best soldier on. */
    1.31 @@ -726,7 +728,6 @@ void time_resume(void)
    1.32  }
    1.33  
    1.34  #ifdef CONFIG_SMP
    1.35 -#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
    1.36  
    1.37  static irqreturn_t local_timer_interrupt(int irq, void *dev_id,
    1.38  					 struct pt_regs *regs)
    1.39 @@ -764,11 +765,6 @@ static irqreturn_t local_timer_interrupt
    1.40  #endif
    1.41  	}
    1.42  
    1.43 -	if (smp_processor_id() == 0) {
    1.44 -	    xxprint("bug bug\n");
    1.45 -	    BUG();
    1.46 -	}
    1.47 -
    1.48  	return IRQ_HANDLED;
    1.49  }
    1.50  
     2.1 --- a/xen/arch/ia64/patch/linux-2.6.7/time.c	Thu Mar 24 11:04:24 2005 +0000
     2.2 +++ b/xen/arch/ia64/patch/linux-2.6.7/time.c	Thu Mar 24 17:22:38 2005 +0000
     2.3 @@ -70,11 +70,11 @@
     2.4  +    return now; 
     2.5  +}
     2.6  +
     2.7 -+int update_dom_time(struct exec_domain *ed)
     2.8 ++void update_dom_time(struct exec_domain *ed)
     2.9  +{
    2.10  +// FIXME: implement this?
    2.11  +//	printf("update_dom_time: called, not implemented, skipping\n");
    2.12 -+	return 0;
    2.13 ++	return;
    2.14  +}
    2.15  +
    2.16  +/* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
     3.1 --- a/xen/arch/x86/time.c	Thu Mar 24 11:04:24 2005 +0000
     3.2 +++ b/xen/arch/x86/time.c	Thu Mar 24 17:22:38 2005 +0000
     3.3 @@ -296,18 +296,16 @@ static inline void __update_dom_time(str
     3.4      spin_unlock(&d->time_lock);
     3.5  }
     3.6  
     3.7 -int update_dom_time(struct exec_domain *ed)
     3.8 +void update_dom_time(struct exec_domain *ed)
     3.9  {
    3.10      unsigned long flags;
    3.11  
    3.12 -    if ( ed->domain->shared_info->tsc_timestamp == full_tsc_irq )
    3.13 -        return 0;
    3.14 -
    3.15 -    read_lock_irqsave(&time_lock, flags);
    3.16 -    __update_dom_time(ed);
    3.17 -    read_unlock_irqrestore(&time_lock, flags);
    3.18 -
    3.19 -    return 1;
    3.20 +    if ( ed->domain->shared_info->tsc_timestamp != full_tsc_irq )
    3.21 +    {
    3.22 +        read_lock_irqsave(&time_lock, flags);
    3.23 +        __update_dom_time(ed);
    3.24 +        read_unlock_irqrestore(&time_lock, flags);
    3.25 +    }
    3.26  }
    3.27  
    3.28  /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
     4.1 --- a/xen/common/sched_atropos.c	Thu Mar 24 11:04:24 2005 +0000
     4.2 +++ b/xen/common/sched_atropos.c	Thu Mar 24 17:22:38 2005 +0000
     4.3 @@ -325,7 +325,7 @@ static void block(struct domain* sdom)
     4.4  /**
     4.5   * ATROPOS - main scheduler function
     4.6   */
     4.7 -task_slice_t ksched_scheduler(s_time_t time)
     4.8 +struct task_slice ksched_scheduler(s_time_t time)
     4.9  {
    4.10      struct domain *cur_sdom = current;  /* Current sdom           */
    4.11      s_time_t       newtime;
    4.12 @@ -335,7 +335,7 @@ task_slice_t ksched_scheduler(s_time_t t
    4.13      struct at_dom_info *cur_info;
    4.14      static unsigned long waitq_rrobin = 0;
    4.15      int i;
    4.16 -    task_slice_t ret;
    4.17 +    struct task_slice ret;
    4.18  
    4.19  
    4.20      cur_info = DOM_INFO(cur_sdom);
     5.1 --- a/xen/common/sched_bvt.c	Thu Mar 24 11:04:24 2005 +0000
     5.2 +++ b/xen/common/sched_bvt.c	Thu Mar 24 17:22:38 2005 +0000
     5.3 @@ -363,7 +363,7 @@ static int bvt_adjdom(
     5.4   *   i.e., the domain with lowest EVT.
     5.5   *   The runqueue should be ordered by EVT so that is easy.
     5.6   */
     5.7 -static task_slice_t bvt_do_schedule(s_time_t now)
     5.8 +static struct task_slice bvt_do_schedule(s_time_t now)
     5.9  {
    5.10      struct domain *d;
    5.11      struct exec_domain      *prev = current, *next = NULL, *next_prime, *ed; 
    5.12 @@ -375,7 +375,7 @@ static task_slice_t bvt_do_schedule(s_ti
    5.13      struct bvt_edom_info *p_einf          = NULL;
    5.14      struct bvt_edom_info *next_einf       = NULL;
    5.15      struct bvt_edom_info *next_prime_einf = NULL;
    5.16 -    task_slice_t        ret;
    5.17 +    struct task_slice     ret;
    5.18  
    5.19      ASSERT(prev->ed_sched_priv != NULL);
    5.20      ASSERT(prev_einf != NULL);
     6.1 --- a/xen/common/sched_rrobin.c	Thu Mar 24 11:04:24 2005 +0000
     6.2 +++ b/xen/common/sched_rrobin.c	Thu Mar 24 17:22:38 2005 +0000
     6.3 @@ -99,11 +99,11 @@ static int rr_init_idle_task(struct doma
     6.4  }
     6.5  
     6.6  /* Main scheduling function */
     6.7 -static task_slice_t rr_do_schedule(s_time_t now)
     6.8 +static struct task_slice rr_do_schedule(s_time_t now)
     6.9  {
    6.10      struct domain *prev = current;
    6.11      int cpu = current->processor;
    6.12 -    task_slice_t ret;
    6.13 +    struct task_slice ret;
    6.14      
    6.15      if ( !is_idle_task(prev) )
    6.16      {
     7.1 --- a/xen/common/schedule.c	Thu Mar 24 11:04:24 2005 +0000
     7.2 +++ b/xen/common/schedule.c	Thu Mar 24 17:22:38 2005 +0000
     7.3 @@ -13,6 +13,15 @@
     7.4   *
     7.5   */
     7.6  
     7.7 +/*#define WAKE_HISTO*/
     7.8 +/*#define BLOCKTIME_HISTO*/
     7.9 +
    7.10 +#if defined(WAKE_HISTO)
    7.11 +#define BUCKETS 31
    7.12 +#elif defined(BLOCKTIME_HISTO)
    7.13 +#define BUCKETS 200
    7.14 +#endif
    7.15 +
    7.16  #include <xen/config.h>
    7.17  #include <xen/init.h>
    7.18  #include <xen/lib.h>
    7.19 @@ -31,15 +40,6 @@
    7.20  static char opt_sched[10] = "bvt";
    7.21  string_param("sched", opt_sched);
    7.22  
    7.23 -/*#define WAKE_HISTO*/
    7.24 -/*#define BLOCKTIME_HISTO*/
    7.25 -
    7.26 -#if defined(WAKE_HISTO)
    7.27 -#define BUCKETS 31
    7.28 -#elif defined(BLOCKTIME_HISTO)
    7.29 -#define BUCKETS 200
    7.30 -#endif
    7.31 -
    7.32  #define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
    7.33  
    7.34  /*
    7.35 @@ -66,7 +66,7 @@ static void t_timer_fn(unsigned long unu
    7.36  static void dom_timer_fn(unsigned long data);
    7.37  
    7.38  /* This is global for now so that private implementations can reach it */
    7.39 -schedule_data_t schedule_data[NR_CPUS];
    7.40 +struct schedule_data schedule_data[NR_CPUS];
    7.41  
    7.42  extern struct scheduler sched_bvt_def;
    7.43  // extern struct scheduler sched_rrobin_def;
    7.44 @@ -371,7 +371,7 @@ void __enter_scheduler(void)
    7.45      struct exec_domain *prev = current, *next = NULL;
    7.46      int                 cpu = prev->processor;
    7.47      s_time_t            now;
    7.48 -    task_slice_t        next_slice;
    7.49 +    struct task_slice   next_slice;
    7.50      s32                 r_time;     /* time for new dom to run */
    7.51  
    7.52      perfc_incrc(sched_run);
    7.53 @@ -446,9 +446,15 @@ void __enter_scheduler(void)
    7.54  
    7.55      TRACE_2D(TRC_SCHED_SWITCH, next->domain->id, next);
    7.56  
    7.57 +    prev->sleep_tick = schedule_data[cpu].tick;
    7.58 +
    7.59      /* Ensure that the domain has an up-to-date time base. */
    7.60 -    if ( !is_idle_task(next->domain) && update_dom_time(next) )
    7.61 -        send_guest_virq(next, VIRQ_TIMER);
    7.62 +    if ( !is_idle_task(next->domain) )
    7.63 +    {
    7.64 +        update_dom_time(next);
    7.65 +        if ( next->sleep_tick != schedule_data[cpu].tick )
    7.66 +            send_guest_virq(next, VIRQ_TIMER);
    7.67 +    }
    7.68  
    7.69      context_switch(prev, next);
    7.70  }
    7.71 @@ -468,7 +474,7 @@ int idle_cpu(int cpu)
    7.72   * - dom_timer: per domain timer to specifiy timeout values
    7.73   ****************************************************************************/
    7.74  
    7.75 -/* The scheduler timer: force a run through the scheduler*/
    7.76 +/* The scheduler timer: force a run through the scheduler */
    7.77  static void s_timer_fn(unsigned long unused)
    7.78  {
    7.79      TRACE_0D(TRC_SCHED_S_TIMER_FN);
    7.80 @@ -476,20 +482,26 @@ static void s_timer_fn(unsigned long unu
    7.81      perfc_incrc(sched_irq);
    7.82  }
    7.83  
    7.84 -/* Periodic tick timer: send timer event to current domain*/
    7.85 +/* Periodic tick timer: send timer event to current domain */
    7.86  static void t_timer_fn(unsigned long unused)
    7.87  {
    7.88 -    struct exec_domain *ed = current;
    7.89 +    struct exec_domain *ed  = current;
    7.90 +    unsigned int        cpu = ed->processor;
    7.91  
    7.92      TRACE_0D(TRC_SCHED_T_TIMER_FN);
    7.93  
    7.94 -    if ( !is_idle_task(ed->domain) && update_dom_time(ed) )
    7.95 +    schedule_data[cpu].tick++;
    7.96 +
    7.97 +    if ( !is_idle_task(ed->domain) )
    7.98 +    {
    7.99 +        update_dom_time(ed);
   7.100          send_guest_virq(ed, VIRQ_TIMER);
   7.101 +    }
   7.102  
   7.103      page_scrub_schedule_work();
   7.104  
   7.105 -    t_timer[ed->processor].expires = NOW() + MILLISECS(10);
   7.106 -    add_ac_timer(&t_timer[ed->processor]);
   7.107 +    t_timer[cpu].expires = NOW() + MILLISECS(10);
   7.108 +    add_ac_timer(&t_timer[cpu]);
   7.109  }
   7.110  
   7.111  /* Domain timer function, sends a virtual timer interrupt to domain */
   7.112 @@ -498,7 +510,8 @@ static void dom_timer_fn(unsigned long d
   7.113      struct exec_domain *ed = (struct exec_domain *)data;
   7.114  
   7.115      TRACE_0D(TRC_SCHED_DOM_TIMER_FN);
   7.116 -    (void)update_dom_time(ed);
   7.117 +    
   7.118 +    update_dom_time(ed);
   7.119      send_guest_virq(ed, VIRQ_TIMER);
   7.120  }
   7.121  
     8.1 --- a/xen/include/xen/sched-if.h	Thu Mar 24 11:04:24 2005 +0000
     8.2 +++ b/xen/include/xen/sched-if.h	Thu Mar 24 17:22:38 2005 +0000
     8.3 @@ -1,36 +1,31 @@
     8.4 -#include <asm/types.h>
     8.5 -
     8.6 -/*
     8.7 +/******************************************************************************
     8.8   * Additional declarations for the generic scheduler interface.  This should
     8.9   * only be included by files that implement conforming schedulers.
    8.10   *
    8.11   * Portions by Mark Williamson are (C) 2004 Intel Research Cambridge
    8.12   */
    8.13  
    8.14 -#define BUCKETS 10
    8.15 +#ifndef __XEN_SCHED_IF_H__
    8.16 +#define __XEN_SCHED_IF_H__
    8.17  
    8.18 -typedef struct schedule_data_st
    8.19 -{
    8.20 -    spinlock_t          schedule_lock;  /* spinlock protecting curr pointer
    8.21 -                                            TODO check this */
    8.22 -    struct exec_domain  *curr;          /* current task */
    8.23 -    struct exec_domain  *idle;          /* idle task for this cpu */
    8.24 -    void *              sched_priv;
    8.25 -    struct ac_timer     s_timer;        /* scheduling timer  */
    8.26 +struct schedule_data {
    8.27 +    spinlock_t          schedule_lock;  /* spinlock protecting curr        */
    8.28 +    struct exec_domain *curr;           /* current task                    */
    8.29 +    struct exec_domain *idle;           /* idle task for this cpu          */
    8.30 +    void               *sched_priv;
    8.31 +    struct ac_timer     s_timer;        /* scheduling timer                */
    8.32 +    unsigned long       tick;           /* current periodic 'tick'         */
    8.33  #ifdef BUCKETS
    8.34      u32                 hist[BUCKETS];  /* for scheduler latency histogram */
    8.35  #endif
    8.36 -} __cacheline_aligned schedule_data_t;
    8.37 -
    8.38 +} __cacheline_aligned;
    8.39  
    8.40 -typedef struct task_slice_st
    8.41 -{
    8.42 +struct task_slice {
    8.43      struct exec_domain *task;
    8.44      s_time_t            time;
    8.45 -} task_slice_t;
    8.46 +};
    8.47  
    8.48 -struct scheduler
    8.49 -{
    8.50 +struct scheduler {
    8.51      char *name;             /* full name for this scheduler      */
    8.52      char *opt_name;         /* option name for this scheduler    */
    8.53      unsigned int sched_id;  /* ID for this scheduler             */
    8.54 @@ -44,7 +39,7 @@ struct scheduler
    8.55      void         (*sleep)          (struct exec_domain *);
    8.56      void         (*wake)           (struct exec_domain *);
    8.57      void         (*do_block)       (struct exec_domain *);
    8.58 -    task_slice_t (*do_schedule)    (s_time_t);
    8.59 +    struct task_slice (*do_schedule) (s_time_t);
    8.60      int          (*control)        (struct sched_ctl_cmd *);
    8.61      int          (*adjdom)         (struct domain *,
    8.62                                      struct sched_adjdom_cmd *);
    8.63 @@ -53,7 +48,6 @@ struct scheduler
    8.64      int          (*prn_state)      (int);
    8.65  };
    8.66  
    8.67 -/* per CPU scheduler information */
    8.68 -extern schedule_data_t schedule_data[];
    8.69 +extern struct schedule_data schedule_data[];
    8.70  
    8.71 -
    8.72 +#endif /* __XEN_SCHED_IF_H__ */
     9.1 --- a/xen/include/xen/sched.h	Thu Mar 24 11:04:24 2005 +0000
     9.2 +++ b/xen/include/xen/sched.h	Thu Mar 24 17:22:38 2005 +0000
     9.3 @@ -73,6 +73,7 @@ struct exec_domain
     9.4  #endif
     9.5  
     9.6      struct ac_timer  timer;         /* one-shot timer for timeout values */
     9.7 +    unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
     9.8  
     9.9      s_time_t         lastschd;      /* time this domain was last scheduled */
    9.10      s_time_t         lastdeschd;    /* time this domain was last descheduled */
    10.1 --- a/xen/include/xen/time.h	Thu Mar 24 11:04:24 2005 +0000
    10.2 +++ b/xen/include/xen/time.h	Thu Mar 24 17:22:38 2005 +0000
    10.3 @@ -54,9 +54,9 @@ s_time_t get_s_time(void);
    10.4  #define MILLISECS(_ms)  (((s_time_t)(_ms)) * 1000000ULL )
    10.5  #define MICROSECS(_us)  (((s_time_t)(_us)) * 1000ULL )
    10.6  
    10.7 -extern int update_dom_time(struct exec_domain *ed);
    10.8 -extern void do_settime(unsigned long secs, unsigned long usecs, 
    10.9 -                       u64 system_time_base);
   10.10 +extern void update_dom_time(struct exec_domain *ed);
   10.11 +extern void do_settime(
   10.12 +    unsigned long secs, unsigned long usecs, u64 system_time_base);
   10.13  
   10.14  #endif /* __XEN_TIME_H__ */
   10.15