[PATCH] sched: implement cpu_clock(cpu) high-speed time source
[powerpc.git] / kernel / timer.c
index de85f84..d1e8b97 100644 (file)
@@ -92,25 +92,25 @@ static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
 /* Functions below help us manage 'deferrable' flag */
 static inline unsigned int tbase_get_deferrable(tvec_base_t *base)
 {
-       return (unsigned int)((unsigned long)base & TBASE_DEFERRABLE_FLAG);
+       return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
 }
 
 static inline tvec_base_t *tbase_get_base(tvec_base_t *base)
 {
-       return (tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG);
+       return ((tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG));
 }
 
 static inline void timer_set_deferrable(struct timer_list *timer)
 {
-       timer->base = (tvec_base_t *)((unsigned long)timer->base |
-                                      TBASE_DEFERRABLE_FLAG);
+       timer->base = ((tvec_base_t *)((unsigned long)(timer->base) |
+                                      TBASE_DEFERRABLE_FLAG));
 }
 
 static inline void
 timer_set_base(struct timer_list *timer, tvec_base_t *new_base)
 {
-       timer->base = (tvec_base_t *)((unsigned long)new_base |
-                                     tbase_get_deferrable(timer->base));
+       timer->base = (tvec_base_t *)((unsigned long)(new_base) |
+                                     tbase_get_deferrable(timer->base));
 }
 
 /**
@@ -305,6 +305,20 @@ void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
        memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
        timer->start_pid = current->pid;
 }
+
+static void timer_stats_account_timer(struct timer_list *timer)
+{
+       unsigned int flag = 0;
+
+       if (unlikely(tbase_get_deferrable(timer->base)))
+               flag |= TIMER_STATS_FLAG_DEFERRABLE;
+
+       timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
+                                timer->function, timer->start_comm, flag);
+}
+
+#else
+static void timer_stats_account_timer(struct timer_list *timer) {}
 #endif
 
 /**
@@ -431,10 +445,10 @@ EXPORT_SYMBOL(__mod_timer);
 void add_timer_on(struct timer_list *timer, int cpu)
 {
        tvec_base_t *base = per_cpu(tvec_bases, cpu);
-       unsigned long flags;
+       unsigned long flags;
 
        timer_stats_timer_set_start_info(timer);
-       BUG_ON(timer_pending(timer) || !timer->function);
+       BUG_ON(timer_pending(timer) || !timer->function);
        spin_lock_irqsave(&base->lock, flags);
        timer_set_base(timer, base);
        internal_add_timer(base, timer);
@@ -613,7 +627,7 @@ static inline void __run_timers(tvec_base_t *base)
        while (time_after_eq(jiffies, base->timer_jiffies)) {
                struct list_head work_list;
                struct list_head *head = &work_list;
-               int index = base->timer_jiffies & TVR_MASK;
+               int index = base->timer_jiffies & TVR_MASK;
 
                /*
                 * Cascade timers:
@@ -630,8 +644,8 @@ static inline void __run_timers(tvec_base_t *base)
                        unsigned long data;
 
                        timer = list_first_entry(head, struct timer_list,entry);
-                       fn = timer->function;
-                       data = timer->data;
+                       fn = timer->function;
+                       data = timer->data;
 
                        timer_stats_account_timer(timer);
 
@@ -666,7 +680,7 @@ static inline void __run_timers(tvec_base_t *base)
 static unsigned long __next_timer_interrupt(tvec_base_t *base)
 {
        unsigned long timer_jiffies = base->timer_jiffies;
-       unsigned long expires = timer_jiffies + (LONG_MAX >> 1);
+       unsigned long expires = timer_jiffies + NEXT_TIMER_MAX_DELTA;
        int index, slot, array, found = 0;
        struct timer_list *nte;
        tvec_t *varray[4];
@@ -675,8 +689,8 @@ static unsigned long __next_timer_interrupt(tvec_base_t *base)
        index = slot = timer_jiffies & TVR_MASK;
        do {
                list_for_each_entry(nte, base->tv1.vec + slot, entry) {
-                       if (tbase_get_deferrable(nte->base))
-                               continue;
+                       if (tbase_get_deferrable(nte->base))
+                               continue;
 
                        found = 1;
                        expires = nte->expires;
@@ -752,6 +766,14 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
 
        tsdelta = ktime_to_timespec(hr_delta);
        delta = timespec_to_jiffies(&tsdelta);
+
+       /*
+        * Limit the delta to the max value, which is checked in
+        * tick_nohz_stop_sched_tick():
+        */
+       if (delta > NEXT_TIMER_MAX_DELTA)
+               delta = NEXT_TIMER_MAX_DELTA;
+
        /*
         * Take rounding errors in to account and make sure, that it
         * expires in the next tick. Otherwise we go into an endless
@@ -812,7 +834,7 @@ void update_process_times(int user_tick)
        if (rcu_pending(cpu))
                rcu_check_callbacks(cpu, user_tick);
        scheduler_tick();
-       run_posix_cpu_timers(p);
+       run_posix_cpu_timers(p);
 }
 
 /*
@@ -887,7 +909,7 @@ static inline void update_times(unsigned long ticks)
        update_wall_time();
        calc_load(ticks);
 }
-  
+
 /*
  * The 64-bit jiffies value is not atomic - you MUST NOT read it
  * without sampling the sequence number in xtime_lock.
@@ -1083,7 +1105,7 @@ asmlinkage long sys_gettid(void)
 /**
  * do_sysinfo - fill in sysinfo struct
  * @info: pointer to buffer to fill
- */ 
+ */
 int do_sysinfo(struct sysinfo *info)
 {
        unsigned long mem_total, sav_total;
@@ -1106,6 +1128,7 @@ int do_sysinfo(struct sysinfo *info)
                getnstimeofday(&tp);
                tp.tv_sec += wall_to_monotonic.tv_sec;
                tp.tv_nsec += wall_to_monotonic.tv_nsec;
+               monotonic_to_bootbased(&tp);
                if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
                        tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
                        tp.tv_sec++;
@@ -1198,7 +1221,8 @@ static int __devinit init_timers_cpu(int cpu)
                        /*
                         * The APs use this path later in boot
                         */
-                       base = kmalloc_node(sizeof(*base), GFP_KERNEL,
+                       base = kmalloc_node(sizeof(*base),
+                                               GFP_KERNEL | __GFP_ZERO,
                                                cpu_to_node(cpu));
                        if (!base)
                                return -ENOMEM;
@@ -1209,7 +1233,6 @@ static int __devinit init_timers_cpu(int cpu)
                                kfree(base);
                                return -ENOMEM;
                        }
-                       memset(base, 0, sizeof(*base));
                        per_cpu(tvec_bases, cpu) = base;
                } else {
                        /*