Merge branch 'core-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6.git] / kernel / timer.c
index ee0a2da..510fe69 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/kernel/timer.c
  *
- *  Kernel internal timers, kernel timekeeping, basic process system calls
+ *  Kernel internal timers, basic process system calls
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/pid_namespace.h>
 #include <linux/notifier.h>
 #include <linux/thread_info.h>
 #include <linux/time.h>
@@ -57,30 +58,59 @@ EXPORT_SYMBOL(jiffies_64);
 #define TVN_MASK (TVN_SIZE - 1)
 #define TVR_MASK (TVR_SIZE - 1)
 
-typedef struct tvec_s {
+struct tvec {
        struct list_head vec[TVN_SIZE];
-} tvec_t;
+};
 
-typedef struct tvec_root_s {
+struct tvec_root {
        struct list_head vec[TVR_SIZE];
-} tvec_root_t;
+};
 
-struct tvec_t_base_s {
+struct tvec_base {
        spinlock_t lock;
        struct timer_list *running_timer;
        unsigned long timer_jiffies;
-       tvec_root_t tv1;
-       tvec_t tv2;
-       tvec_t tv3;
-       tvec_t tv4;
-       tvec_t tv5;
-} ____cacheline_aligned_in_smp;
+       struct tvec_root tv1;
+       struct tvec tv2;
+       struct tvec tv3;
+       struct tvec tv4;
+       struct tvec tv5;
+} ____cacheline_aligned;
+
+struct tvec_base boot_tvec_bases;
+EXPORT_SYMBOL(boot_tvec_bases);
+static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
 
-typedef struct tvec_t_base_s tvec_base_t;
+/*
+ * Note that all tvec_bases are 2 byte aligned and lower bit of
+ * base in timer_list is guaranteed to be zero. Use the LSB for
+ * the new flag to indicate whether the timer is deferrable
+ */
+#define TBASE_DEFERRABLE_FLAG          (0x1)
 
-tvec_base_t boot_tvec_bases;
-EXPORT_SYMBOL(boot_tvec_bases);
-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(struct tvec_base *base)
+{
+       return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
+}
+
+static inline struct tvec_base *tbase_get_base(struct tvec_base *base)
+{
+       return ((struct tvec_base *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG));
+}
+
+static inline void timer_set_deferrable(struct timer_list *timer)
+{
+       timer->base = ((struct tvec_base *)((unsigned long)(timer->base) |
+                                      TBASE_DEFERRABLE_FLAG));
+}
+
+static inline void
+timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
+{
+       timer->base = (struct tvec_base *)((unsigned long)(new_base) |
+                                     tbase_get_deferrable(timer->base));
+}
 
 /**
  * __round_jiffies - function to round jiffies to a full second
@@ -214,7 +244,7 @@ unsigned long round_jiffies_relative(unsigned long j)
 EXPORT_SYMBOL_GPL(round_jiffies_relative);
 
 
-static inline void set_running_timer(tvec_base_t *base,
+static inline void set_running_timer(struct tvec_base *base,
                                        struct timer_list *timer)
 {
 #ifdef CONFIG_SMP
@@ -222,7 +252,7 @@ static inline void set_running_timer(tvec_base_t *base,
 #endif
 }
 
-static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
+static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 {
        unsigned long expires = timer->expires;
        unsigned long idx = expires - base->timer_jiffies;
@@ -274,16 +304,146 @@ 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
 
-/**
- * init_timer - initialize a timer.
- * @timer: the timer to be initialized
- *
- * init_timer() must be done to a timer prior calling *any* of the
- * other timer functions.
+#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
+
+static struct debug_obj_descr timer_debug_descr;
+
+/*
+ * fixup_init is called when:
+ * - an active object is initialized
  */
-void fastcall init_timer(struct timer_list *timer)
+static int timer_fixup_init(void *addr, enum debug_obj_state state)
+{
+       struct timer_list *timer = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               del_timer_sync(timer);
+               debug_object_init(timer, &timer_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_activate is called when:
+ * - an active object is activated
+ * - an unknown object is activated (might be a statically initialized object)
+ */
+static int timer_fixup_activate(void *addr, enum debug_obj_state state)
+{
+       struct timer_list *timer = addr;
+
+       switch (state) {
+
+       case ODEBUG_STATE_NOTAVAILABLE:
+               /*
+                * This is not really a fixup. The timer was
+                * statically initialized. We just make sure that it
+                * is tracked in the object tracker.
+                */
+               if (timer->entry.next == NULL &&
+                   timer->entry.prev == TIMER_ENTRY_STATIC) {
+                       debug_object_init(timer, &timer_debug_descr);
+                       debug_object_activate(timer, &timer_debug_descr);
+                       return 0;
+               } else {
+                       WARN_ON_ONCE(1);
+               }
+               return 0;
+
+       case ODEBUG_STATE_ACTIVE:
+               WARN_ON(1);
+
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_free is called when:
+ * - an active object is freed
+ */
+static int timer_fixup_free(void *addr, enum debug_obj_state state)
+{
+       struct timer_list *timer = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               del_timer_sync(timer);
+               debug_object_free(timer, &timer_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static struct debug_obj_descr timer_debug_descr = {
+       .name           = "timer_list",
+       .fixup_init     = timer_fixup_init,
+       .fixup_activate = timer_fixup_activate,
+       .fixup_free     = timer_fixup_free,
+};
+
+static inline void debug_timer_init(struct timer_list *timer)
+{
+       debug_object_init(timer, &timer_debug_descr);
+}
+
+static inline void debug_timer_activate(struct timer_list *timer)
+{
+       debug_object_activate(timer, &timer_debug_descr);
+}
+
+static inline void debug_timer_deactivate(struct timer_list *timer)
+{
+       debug_object_deactivate(timer, &timer_debug_descr);
+}
+
+static inline void debug_timer_free(struct timer_list *timer)
+{
+       debug_object_free(timer, &timer_debug_descr);
+}
+
+static void __init_timer(struct timer_list *timer);
+
+void init_timer_on_stack(struct timer_list *timer)
+{
+       debug_object_init_on_stack(timer, &timer_debug_descr);
+       __init_timer(timer);
+}
+EXPORT_SYMBOL_GPL(init_timer_on_stack);
+
+void destroy_timer_on_stack(struct timer_list *timer)
+{
+       debug_object_free(timer, &timer_debug_descr);
+}
+EXPORT_SYMBOL_GPL(destroy_timer_on_stack);
+
+#else
+static inline void debug_timer_init(struct timer_list *timer) { }
+static inline void debug_timer_activate(struct timer_list *timer) { }
+static inline void debug_timer_deactivate(struct timer_list *timer) { }
+#endif
+
+static void __init_timer(struct timer_list *timer)
 {
        timer->entry.next = NULL;
        timer->base = __raw_get_cpu_var(tvec_bases);
@@ -293,13 +453,35 @@ void fastcall init_timer(struct timer_list *timer)
        memset(timer->start_comm, 0, TASK_COMM_LEN);
 #endif
 }
+
+/**
+ * init_timer - initialize a timer.
+ * @timer: the timer to be initialized
+ *
+ * init_timer() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void init_timer(struct timer_list *timer)
+{
+       debug_timer_init(timer);
+       __init_timer(timer);
+}
 EXPORT_SYMBOL(init_timer);
 
+void init_timer_deferrable(struct timer_list *timer)
+{
+       init_timer(timer);
+       timer_set_deferrable(timer);
+}
+EXPORT_SYMBOL(init_timer_deferrable);
+
 static inline void detach_timer(struct timer_list *timer,
                                int clear_pending)
 {
        struct list_head *entry = &timer->entry;
 
+       debug_timer_deactivate(timer);
+
        __list_del(entry->prev, entry->next);
        if (clear_pending)
                entry->next = NULL;
@@ -318,17 +500,18 @@ static inline void detach_timer(struct timer_list *timer,
  * possible to set timer->base = NULL and drop the lock: the timer remains
  * locked.
  */
-static tvec_base_t *lock_timer_base(struct timer_list *timer,
+static struct tvec_base *lock_timer_base(struct timer_list *timer,
                                        unsigned long *flags)
        __acquires(timer->base->lock)
 {
-       tvec_base_t *base;
+       struct tvec_base *base;
 
        for (;;) {
-               base = timer->base;
+               struct tvec_base *prelock_base = timer->base;
+               base = tbase_get_base(prelock_base);
                if (likely(base != NULL)) {
                        spin_lock_irqsave(&base->lock, *flags);
-                       if (likely(base == timer->base))
+                       if (likely(prelock_base == timer->base))
                                return base;
                        /* The timer has migrated to another CPU */
                        spin_unlock_irqrestore(&base->lock, *flags);
@@ -339,7 +522,7 @@ static tvec_base_t *lock_timer_base(struct timer_list *timer,
 
 int __mod_timer(struct timer_list *timer, unsigned long expires)
 {
-       tvec_base_t *base, *new_base;
+       struct tvec_base *base, *new_base;
        unsigned long flags;
        int ret = 0;
 
@@ -353,6 +536,8 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
                ret = 1;
        }
 
+       debug_timer_activate(timer);
+
        new_base = __get_cpu_var(tvec_bases);
 
        if (base != new_base) {
@@ -365,11 +550,11 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
                 */
                if (likely(base->running_timer != timer)) {
                        /* See the comment in lock_timer_base() */
-                       timer->base = NULL;
+                       timer_set_base(timer, NULL);
                        spin_unlock(&base->lock);
                        base = new_base;
                        spin_lock(&base->lock);
-                       timer->base = base;
+                       timer_set_base(timer, base);
                }
        }
 
@@ -391,18 +576,27 @@ 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;
+       struct tvec_base *base = per_cpu(tvec_bases, cpu);
+       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->base = base;
+       timer_set_base(timer, base);
+       debug_timer_activate(timer);
        internal_add_timer(base, timer);
+       /*
+        * Check whether the other CPU is idle and needs to be
+        * triggered to reevaluate the timer wheel when nohz is
+        * active. We are protected against the other CPU fiddling
+        * with the timer by holding the timer base lock. This also
+        * makes sure that a CPU on the way to idle can not evaluate
+        * the timer wheel.
+        */
+       wake_up_idle_cpu(cpu);
        spin_unlock_irqrestore(&base->lock, flags);
 }
 
-
 /**
  * mod_timer - modify a timer's timeout
  * @timer: the timer to be modified
@@ -454,7 +648,7 @@ EXPORT_SYMBOL(mod_timer);
  */
 int del_timer(struct timer_list *timer)
 {
-       tvec_base_t *base;
+       struct tvec_base *base;
        unsigned long flags;
        int ret = 0;
 
@@ -485,7 +679,7 @@ EXPORT_SYMBOL(del_timer);
  */
 int try_to_del_timer_sync(struct timer_list *timer)
 {
-       tvec_base_t *base;
+       struct tvec_base *base;
        unsigned long flags;
        int ret = -1;
 
@@ -505,6 +699,8 @@ out:
        return ret;
 }
 
+EXPORT_SYMBOL(try_to_del_timer_sync);
+
 /**
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
@@ -535,7 +731,7 @@ int del_timer_sync(struct timer_list *timer)
 EXPORT_SYMBOL(del_timer_sync);
 #endif
 
-static int cascade(tvec_base_t *base, tvec_t *tv, int index)
+static int cascade(struct tvec_base *base, struct tvec *tv, int index)
 {
        /* cascade all the timers from tv up one level */
        struct timer_list *timer, *tmp;
@@ -548,7 +744,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
         * don't have to detach them individually.
         */
        list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
-               BUG_ON(timer->base != base);
+               BUG_ON(tbase_get_base(timer->base) != base);
                internal_add_timer(base, timer);
        }
 
@@ -564,7 +760,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
  * This function cascades all vectors and executes all expired timer
  * vectors.
  */
-static inline void __run_timers(tvec_base_t *base)
+static inline void __run_timers(struct tvec_base *base)
 {
        struct timer_list *timer;
 
@@ -572,7 +768,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:
@@ -588,9 +784,9 @@ static inline void __run_timers(tvec_base_t *base)
                        void (*fn)(unsigned long);
                        unsigned long data;
 
-                       timer = list_entry(head->next,struct timer_list,entry);
-                       fn = timer->function;
-                       data = timer->data;
+                       timer = list_first_entry(head, struct timer_list,entry);
+                       fn = timer->function;
+                       data = timer->data;
 
                        timer_stats_account_timer(timer);
 
@@ -601,7 +797,7 @@ static inline void __run_timers(tvec_base_t *base)
                                int preempt_count = preempt_count();
                                fn(data);
                                if (preempt_count != preempt_count()) {
-                                       printk(KERN_WARNING "huh, entered %p "
+                                       printk(KERN_ERR "huh, entered %p "
                                               "with preempt_count %08x, exited"
                                               " with %08x?\n",
                                               fn, preempt_count,
@@ -616,24 +812,27 @@ static inline void __run_timers(tvec_base_t *base)
        spin_unlock_irq(&base->lock);
 }
 
-#if defined(CONFIG_NO_IDLE_HZ) || defined(CONFIG_NO_HZ)
+#ifdef CONFIG_NO_HZ
 /*
  * Find out when the next timer event is due to happen. This
  * is used on S/390 to stop all activity when a cpus is idle.
  * This functions needs to be called disabled.
  */
-static unsigned long __next_timer_interrupt(tvec_base_t *base)
+static unsigned long __next_timer_interrupt(struct tvec_base *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];
+       struct tvec *varray[4];
 
        /* Look for timer events in tv1. */
        index = slot = timer_jiffies & TVR_MASK;
        do {
                list_for_each_entry(nte, base->tv1.vec + slot, entry) {
+                       if (tbase_get_deferrable(nte->base))
+                               continue;
+
                        found = 1;
                        expires = nte->expires;
                        /* Look at the cascade bucket(s)? */
@@ -657,7 +856,7 @@ cascade:
        varray[3] = &base->tv5;
 
        for (array = 0; array < 4; array++) {
-               tvec_t *varp = varray[array];
+               struct tvec *varp = varray[array];
 
                index = slot = timer_jiffies & TVN_MASK;
                do {
@@ -695,27 +894,48 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
 {
        ktime_t hr_delta = hrtimer_get_next_event();
        struct timespec tsdelta;
+       unsigned long delta;
 
        if (hr_delta.tv64 == KTIME_MAX)
                return expires;
 
-       if (hr_delta.tv64 <= TICK_NSEC)
-               return now;
+       /*
+        * Expired timer available, let it expire in the next tick
+        */
+       if (hr_delta.tv64 <= 0)
+               return now + 1;
 
        tsdelta = ktime_to_timespec(hr_delta);
-       now += timespec_to_jiffies(&tsdelta);
+       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
+        * ping pong due to tick_nohz_stop_sched_tick() retriggering
+        * the timer softirq
+        */
+       if (delta < 1)
+               delta = 1;
+       now += delta;
        if (time_before(now, expires))
                return now;
        return expires;
 }
 
 /**
- * next_timer_interrupt - return the jiffy of the next pending timer
+ * get_next_timer_interrupt - return the jiffy of the next pending timer
  * @now: current time (in jiffies)
  */
 unsigned long get_next_timer_interrupt(unsigned long now)
 {
-       tvec_base_t *base = __get_cpu_var(tvec_bases);
+       struct tvec_base *base = __get_cpu_var(tvec_bases);
        unsigned long expires;
 
        spin_lock(&base->lock);
@@ -727,465 +947,25 @@ unsigned long get_next_timer_interrupt(unsigned long now)
 
        return cmp_next_hrtimer_event(now, expires);
 }
-
-#ifdef CONFIG_NO_IDLE_HZ
-unsigned long next_timer_interrupt(void)
-{
-       return get_next_timer_interrupt(jiffies);
-}
-#endif
-
 #endif
 
-/******************************************************************/
-
-/* 
- * The current time 
- * wall_to_monotonic is what we need to add to xtime (or xtime corrected 
- * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
- * at zero at system boot time, so wall_to_monotonic will be negative,
- * however, we will ALWAYS keep the tv_nsec part positive so we can use
- * the usual normalization.
- */
-struct timespec xtime __attribute__ ((aligned (16)));
-struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
-
-EXPORT_SYMBOL(xtime);
-
-
-/* XXX - all of this timekeeping code should be later moved to time.c */
-#include <linux/clocksource.h>
-static struct clocksource *clock; /* pointer to current clocksource */
-
-#ifdef CONFIG_GENERIC_TIME
-/**
- * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
- *
- * private function, must hold xtime_lock lock when being
- * called. Returns the number of nanoseconds since the
- * last call to update_wall_time() (adjusted by NTP scaling)
- */
-static inline s64 __get_nsec_offset(void)
-{
-       cycle_t cycle_now, cycle_delta;
-       s64 ns_offset;
-
-       /* read clocksource: */
-       cycle_now = clocksource_read(clock);
-
-       /* calculate the delta since the last update_wall_time: */
-       cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
-
-       /* convert to nanoseconds: */
-       ns_offset = cyc2ns(clock, cycle_delta);
-
-       return ns_offset;
-}
-
-/**
- * __get_realtime_clock_ts - Returns the time of day in a timespec
- * @ts:                pointer to the timespec to be set
- *
- * Returns the time of day in a timespec. Used by
- * do_gettimeofday() and get_realtime_clock_ts().
- */
-static inline void __get_realtime_clock_ts(struct timespec *ts)
-{
-       unsigned long seq;
-       s64 nsecs;
-
-       do {
-               seq = read_seqbegin(&xtime_lock);
-
-               *ts = xtime;
-               nsecs = __get_nsec_offset();
-
-       } while (read_seqretry(&xtime_lock, seq));
-
-       timespec_add_ns(ts, nsecs);
-}
-
-/**
- * getnstimeofday - Returns the time of day in a timespec
- * @ts:                pointer to the timespec to be set
- *
- * Returns the time of day in a timespec.
- */
-void getnstimeofday(struct timespec *ts)
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+void account_process_tick(struct task_struct *p, int user_tick)
 {
-       __get_realtime_clock_ts(ts);
-}
-
-EXPORT_SYMBOL(getnstimeofday);
-
-/**
- * do_gettimeofday - Returns the time of day in a timeval
- * @tv:                pointer to the timeval to be set
- *
- * NOTE: Users should be converted to using get_realtime_clock_ts()
- */
-void do_gettimeofday(struct timeval *tv)
-{
-       struct timespec now;
-
-       __get_realtime_clock_ts(&now);
-       tv->tv_sec = now.tv_sec;
-       tv->tv_usec = now.tv_nsec/1000;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-/**
- * do_settimeofday - Sets the time of day
- * @tv:                pointer to the timespec variable containing the new time
- *
- * Sets the time of day to the new time and update NTP and notify hrtimers
- */
-int do_settimeofday(struct timespec *tv)
-{
-       unsigned long flags;
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
-
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-
-       nsec -= __get_nsec_offset();
-
-       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-       clock->error = 0;
-       ntp_clear();
-
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       /* signal hrtimers about time change */
-       clock_was_set();
-
-       return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/**
- * change_clocksource - Swaps clocksources if a new one is available
- *
- * Accumulates current time interval and initializes new clocksource
- */
-static void change_clocksource(void)
-{
-       struct clocksource *new;
-       cycle_t now;
-       u64 nsec;
-
-       new = clocksource_get_next();
-
-       if (clock == new)
-               return;
-
-       now = clocksource_read(new);
-       nsec =  __get_nsec_offset();
-       timespec_add_ns(&xtime, nsec);
-
-       clock = new;
-       clock->cycle_last = now;
+       cputime_t one_jiffy = jiffies_to_cputime(1);
 
-       clock->error = 0;
-       clock->xtime_nsec = 0;
-       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-
-       tick_clock_notify();
-
-       printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-              clock->name);
-}
-#else
-static inline void change_clocksource(void) { }
-#endif
-
-/**
- * timekeeping_is_continuous - check to see if timekeeping is free running
- */
-int timekeeping_is_continuous(void)
-{
-       unsigned long seq;
-       int ret;
-
-       do {
-               seq = read_seqbegin(&xtime_lock);
-
-               ret = clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
-
-       } while (read_seqretry(&xtime_lock, seq));
-
-       return ret;
-}
-
-/**
- * read_persistent_clock -  Return time in seconds from the persistent clock.
- *
- * Weak dummy function for arches that do not yet support it.
- * Returns seconds from epoch using the battery backed persistent clock.
- * Returns zero if unsupported.
- *
- *  XXX - Do be sure to remove it once all arches implement it.
- */
-unsigned long __attribute__((weak)) read_persistent_clock(void)
-{
-       return 0;
-}
-
-/*
- * timekeeping_init - Initializes the clocksource and common timekeeping values
- */
-void __init timekeeping_init(void)
-{
-       unsigned long flags;
-       unsigned long sec = read_persistent_clock();
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-
-       ntp_clear();
-
-       clock = clocksource_get_next();
-       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-       clock->cycle_last = clocksource_read(clock);
-
-       xtime.tv_sec = sec;
-       xtime.tv_nsec = 0;
-       set_normalized_timespec(&wall_to_monotonic,
-               -xtime.tv_sec, -xtime.tv_nsec);
-
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-}
-
-/* flag for if timekeeping is suspended */
-static int timekeeping_suspended;
-/* time in seconds when suspend began */
-static unsigned long timekeeping_suspend_time;
-
-/**
- * timekeeping_resume - Resumes the generic timekeeping subsystem.
- * @dev:       unused
- *
- * This is for the generic clocksource timekeeping.
- * xtime/wall_to_monotonic/jiffies/etc are
- * still managed by arch specific suspend/resume code.
- */
-static int timekeeping_resume(struct sys_device *dev)
-{
-       unsigned long flags;
-       unsigned long now = read_persistent_clock();
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-
-       if (now && (now > timekeeping_suspend_time)) {
-               unsigned long sleep_length = now - timekeeping_suspend_time;
-
-               xtime.tv_sec += sleep_length;
-               wall_to_monotonic.tv_sec -= sleep_length;
-       }
-       /* re-base the last cycle value */
-       clock->cycle_last = clocksource_read(clock);
-       clock->error = 0;
-       timekeeping_suspended = 0;
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       touch_softlockup_watchdog();
-
-       clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-
-       /* Resume hrtimers */
-       clock_was_set();
-
-       return 0;
-}
-
-static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
-{
-       unsigned long flags;
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-       timekeeping_suspended = 1;
-       timekeeping_suspend_time = read_persistent_clock();
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
-
-       return 0;
-}
-
-/* sysfs resume/suspend bits for timekeeping */
-static struct sysdev_class timekeeping_sysclass = {
-       .resume         = timekeeping_resume,
-       .suspend        = timekeeping_suspend,
-       set_kset_name("timekeeping"),
-};
-
-static struct sys_device device_timer = {
-       .id             = 0,
-       .cls            = &timekeeping_sysclass,
-};
-
-static int __init timekeeping_init_device(void)
-{
-       int error = sysdev_class_register(&timekeeping_sysclass);
-       if (!error)
-               error = sysdev_register(&device_timer);
-       return error;
-}
-
-device_initcall(timekeeping_init_device);
-
-/*
- * If the error is already larger, we look ahead even further
- * to compensate for late or lost adjustments.
- */
-static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
-                                                s64 *offset)
-{
-       s64 tick_error, i;
-       u32 look_ahead, adj;
-       s32 error2, mult;
-
-       /*
-        * Use the current error value to determine how much to look ahead.
-        * The larger the error the slower we adjust for it to avoid problems
-        * with losing too many ticks, otherwise we would overadjust and
-        * produce an even larger error.  The smaller the adjustment the
-        * faster we try to adjust for it, as lost ticks can do less harm
-        * here.  This is tuned so that an error of about 1 msec is adusted
-        * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
-        */
-       error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
-       error2 = abs(error2);
-       for (look_ahead = 0; error2 > 0; look_ahead++)
-               error2 >>= 2;
-
-       /*
-        * Now calculate the error in (1 << look_ahead) ticks, but first
-        * remove the single look ahead already included in the error.
-        */
-       tick_error = current_tick_length() >>
-               (TICK_LENGTH_SHIFT - clock->shift + 1);
-       tick_error -= clock->xtime_interval >> 1;
-       error = ((error - tick_error) >> look_ahead) + tick_error;
-
-       /* Finally calculate the adjustment shift value.  */
-       i = *interval;
-       mult = 1;
-       if (error < 0) {
-               error = -error;
-               *interval = -*interval;
-               *offset = -*offset;
-               mult = -1;
+       if (user_tick) {
+               account_user_time(p, one_jiffy);
+               account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
+       } else {
+               account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
+               account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
        }
-       for (adj = 0; error > i; adj++)
-               error >>= 1;
-
-       *interval <<= adj;
-       *offset <<= adj;
-       return mult << adj;
-}
-
-/*
- * Adjust the multiplier to reduce the error value,
- * this is optimized for the most common adjustments of -1,0,1,
- * for other values we can do a bit more work.
- */
-static void clocksource_adjust(struct clocksource *clock, s64 offset)
-{
-       s64 error, interval = clock->cycle_interval;
-       int adj;
-
-       error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
-       if (error > interval) {
-               error >>= 2;
-               if (likely(error <= interval))
-                       adj = 1;
-               else
-                       adj = clocksource_bigadjust(error, &interval, &offset);
-       } else if (error < -interval) {
-               error >>= 2;
-               if (likely(error >= -interval)) {
-                       adj = -1;
-                       interval = -interval;
-                       offset = -offset;
-               } else
-                       adj = clocksource_bigadjust(error, &interval, &offset);
-       } else
-               return;
-
-       clock->mult += adj;
-       clock->xtime_interval += interval;
-       clock->xtime_nsec -= offset;
-       clock->error -= (interval - offset) <<
-                       (TICK_LENGTH_SHIFT - clock->shift);
 }
-
-/**
- * update_wall_time - Uses the current clocksource to increment the wall time
- *
- * Called from the timer interrupt, must hold a write on xtime_lock.
- */
-static void update_wall_time(void)
-{
-       cycle_t offset;
-
-       /* Make sure we're fully resumed: */
-       if (unlikely(timekeeping_suspended))
-               return;
-
-#ifdef CONFIG_GENERIC_TIME
-       offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
-#else
-       offset = clock->cycle_interval;
 #endif
-       clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
-
-       /* normally this loop will run just once, however in the
-        * case of lost or late ticks, it will accumulate correctly.
-        */
-       while (offset >= clock->cycle_interval) {
-               /* accumulate one interval */
-               clock->xtime_nsec += clock->xtime_interval;
-               clock->cycle_last += clock->cycle_interval;
-               offset -= clock->cycle_interval;
-
-               if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
-                       clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
-                       xtime.tv_sec++;
-                       second_overflow();
-               }
-
-               /* interpolator bits */
-               time_interpolator_update(clock->xtime_interval
-                                               >> clock->shift);
-
-               /* accumulate error between NTP and clock interval */
-               clock->error += current_tick_length();
-               clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
-       }
-
-       /* correct the clock when NTP error is too big */
-       clocksource_adjust(clock, offset);
-
-       /* store full nanoseconds into xtime */
-       xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
-       clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
-
-       /* check to see if there is a new clocksource to use */
-       change_clocksource();
-       update_vsyscall(&xtime, clock);
-}
 
 /*
- * Called from the timer interrupt handler to charge one tick to the current 
+ * Called from the timer interrupt handler to charge one tick to the current
  * process.  user_tick is 1 if the tick is user time, 0 for system.
  */
 void update_process_times(int user_tick)
@@ -1194,15 +974,13 @@ void update_process_times(int user_tick)
        int cpu = smp_processor_id();
 
        /* Note: this timer irq context must be accounted for as well. */
-       if (user_tick)
-               account_user_time(p, jiffies_to_cputime(1));
-       else
-               account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
+       account_process_tick(p, user_tick);
        run_local_timers();
        if (rcu_pending(cpu))
                rcu_check_callbacks(cpu, user_tick);
+       printk_tick();
        scheduler_tick();
-       run_posix_cpu_timers(p);
+       run_posix_cpu_timers(p);
 }
 
 /*
@@ -1247,21 +1025,13 @@ static inline void calc_load(unsigned long ticks)
 }
 
 /*
- * This read-write spinlock protects us from races in SMP while
- * playing with xtime and avenrun.
- */
-__attribute__((weak)) __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
-
-EXPORT_SYMBOL(xtime_lock);
-
-/*
  * This function runs timers and the timer-tq in bottom half context.
  */
 static void run_timer_softirq(struct softirq_action *h)
 {
-       tvec_base_t *base = __get_cpu_var(tvec_bases);
+       struct tvec_base *base = __get_cpu_var(tvec_bases);
 
-       hrtimer_run_queues();
+       hrtimer_run_pending();
 
        if (time_after_eq(jiffies, base->timer_jiffies))
                __run_timers(base);
@@ -1272,6 +1042,7 @@ static void run_timer_softirq(struct softirq_action *h)
  */
 void run_local_timers(void)
 {
+       hrtimer_run_queues();
        raise_softirq(TIMER_SOFTIRQ);
        softlockup_tick();
 }
@@ -1285,7 +1056,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.
@@ -1329,7 +1100,7 @@ asmlinkage unsigned long sys_alarm(unsigned int seconds)
  */
 asmlinkage long sys_getpid(void)
 {
-       return current->tgid;
+       return task_tgid_vnr(current);
 }
 
 /*
@@ -1343,7 +1114,7 @@ asmlinkage long sys_getppid(void)
        int pid;
 
        rcu_read_lock();
-       pid = rcu_dereference(current->real_parent)->tgid;
+       pid = task_tgid_vnr(current->real_parent);
        rcu_read_unlock();
 
        return pid;
@@ -1406,7 +1177,7 @@ static void process_timeout(unsigned long __data)
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-fastcall signed long __sched schedule_timeout(signed long timeout)
+signed long __sched schedule_timeout(signed long timeout)
 {
        struct timer_list timer;
        unsigned long expire;
@@ -1442,11 +1213,14 @@ fastcall signed long __sched schedule_timeout(signed long timeout)
 
        expire = timeout + jiffies;
 
-       setup_timer(&timer, process_timeout, (unsigned long)current);
+       setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
        __mod_timer(&timer, expire);
        schedule();
        del_singleshot_timer_sync(&timer);
 
+       /* Remove the timer from the object tracker */
+       destroy_timer_on_stack(&timer);
+
        timeout = expire - jiffies;
 
  out:
@@ -1465,6 +1239,13 @@ signed long __sched schedule_timeout_interruptible(signed long timeout)
 }
 EXPORT_SYMBOL(schedule_timeout_interruptible);
 
+signed long __sched schedule_timeout_killable(signed long timeout)
+{
+       __set_current_state(TASK_KILLABLE);
+       return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_killable);
+
 signed long __sched schedule_timeout_uninterruptible(signed long timeout)
 {
        __set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1475,13 +1256,13 @@ EXPORT_SYMBOL(schedule_timeout_uninterruptible);
 /* Thread ID - the internal kernel "pid" */
 asmlinkage long sys_gettid(void)
 {
-       return current->pid;
+       return task_pid_vnr(current);
 }
 
 /**
  * do_sysinfo - fill in sysinfo struct
  * @info: pointer to buffer to fill
- */ 
+ */
 int do_sysinfo(struct sysinfo *info)
 {
        unsigned long mem_total, sav_total;
@@ -1504,6 +1285,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++;
@@ -1576,18 +1358,11 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
        return 0;
 }
 
-/*
- * lockdep: we want to track each per-CPU base as a separate lock-class,
- * but timer-bases are kmalloc()-ed, so we need to attach separate
- * keys to them:
- */
-static struct lock_class_key base_lock_keys[NR_CPUS];
-
-static int __devinit init_timers_cpu(int cpu)
+static int __cpuinit init_timers_cpu(int cpu)
 {
        int j;
-       tvec_base_t *base;
-       static char __devinitdata tvec_base_done[NR_CPUS];
+       struct tvec_base *base;
+       static char __cpuinitdata tvec_base_done[NR_CPUS];
 
        if (!tvec_base_done[cpu]) {
                static char boot_done;
@@ -1596,11 +1371,18 @@ 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;
-                       memset(base, 0, sizeof(*base));
+
+                       /* Make sure that tvec_base is 2 byte aligned */
+                       if (tbase_get_deferrable(base)) {
+                               WARN_ON(1);
+                               kfree(base);
+                               return -ENOMEM;
+                       }
                        per_cpu(tvec_bases, cpu) = base;
                } else {
                        /*
@@ -1618,7 +1400,6 @@ static int __devinit init_timers_cpu(int cpu)
        }
 
        spin_lock_init(&base->lock);
-       lockdep_set_class(&base->lock, base_lock_keys + cpu);
 
        for (j = 0; j < TVN_SIZE; j++) {
                INIT_LIST_HEAD(base->tv5.vec + j);
@@ -1634,22 +1415,22 @@ static int __devinit init_timers_cpu(int cpu)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
+static void migrate_timer_list(struct tvec_base *new_base, struct list_head *head)
 {
        struct timer_list *timer;
 
        while (!list_empty(head)) {
-               timer = list_entry(head->next, struct timer_list, entry);
+               timer = list_first_entry(head, struct timer_list, entry);
                detach_timer(timer, 0);
-               timer->base = new_base;
+               timer_set_base(timer, new_base);
                internal_add_timer(new_base, timer);
        }
 }
 
-static void __devinit migrate_timers(int cpu)
+static void __cpuinit migrate_timers(int cpu)
 {
-       tvec_base_t *old_base;
-       tvec_base_t *new_base;
+       struct tvec_base *old_base;
+       struct tvec_base *new_base;
        int i;
 
        BUG_ON(cpu_online(cpu));
@@ -1657,8 +1438,8 @@ static void __devinit migrate_timers(int cpu)
        new_base = get_cpu_var(tvec_bases);
 
        local_irq_disable();
-       double_spin_lock(&new_base->lock, &old_base->lock,
-                        smp_processor_id() < cpu);
+       spin_lock(&new_base->lock);
+       spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
 
        BUG_ON(old_base->running_timer);
 
@@ -1671,8 +1452,8 @@ static void __devinit migrate_timers(int cpu)
                migrate_timer_list(new_base, old_base->tv5.vec + i);
        }
 
-       double_spin_unlock(&new_base->lock, &old_base->lock,
-                          smp_processor_id() < cpu);
+       spin_unlock(&old_base->lock);
+       spin_unlock(&new_base->lock);
        local_irq_enable();
        put_cpu_var(tvec_bases);
 }
@@ -1684,11 +1465,13 @@ static int __cpuinit timer_cpu_notify(struct notifier_block *self,
        long cpu = (long)hcpu;
        switch(action) {
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                if (init_timers_cpu(cpu) < 0)
                        return NOTIFY_BAD;
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                migrate_timers(cpu);
                break;
 #endif
@@ -1712,196 +1495,8 @@ void __init init_timers(void)
 
        BUG_ON(err == NOTIFY_BAD);
        register_cpu_notifier(&timers_nb);
-       open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
-}
-
-#ifdef CONFIG_TIME_INTERPOLATION
-
-struct time_interpolator *time_interpolator __read_mostly;
-static struct time_interpolator *time_interpolator_list __read_mostly;
-static DEFINE_SPINLOCK(time_interpolator_lock);
-
-static inline cycles_t time_interpolator_get_cycles(unsigned int src)
-{
-       unsigned long (*x)(void);
-
-       switch (src)
-       {
-               case TIME_SOURCE_FUNCTION:
-                       x = time_interpolator->addr;
-                       return x();
-
-               case TIME_SOURCE_MMIO64 :
-                       return readq_relaxed((void __iomem *)time_interpolator->addr);
-
-               case TIME_SOURCE_MMIO32 :
-                       return readl_relaxed((void __iomem *)time_interpolator->addr);
-
-               default: return get_cycles();
-       }
-}
-
-static inline u64 time_interpolator_get_counter(int writelock)
-{
-       unsigned int src = time_interpolator->source;
-
-       if (time_interpolator->jitter)
-       {
-               cycles_t lcycle;
-               cycles_t now;
-
-               do {
-                       lcycle = time_interpolator->last_cycle;
-                       now = time_interpolator_get_cycles(src);
-                       if (lcycle && time_after(lcycle, now))
-                               return lcycle;
-
-                       /* When holding the xtime write lock, there's no need
-                        * to add the overhead of the cmpxchg.  Readers are
-                        * force to retry until the write lock is released.
-                        */
-                       if (writelock) {
-                               time_interpolator->last_cycle = now;
-                               return now;
-                       }
-                       /* Keep track of the last timer value returned. The use of cmpxchg here
-                        * will cause contention in an SMP environment.
-                        */
-               } while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle));
-               return now;
-       }
-       else
-               return time_interpolator_get_cycles(src);
-}
-
-void time_interpolator_reset(void)
-{
-       time_interpolator->offset = 0;
-       time_interpolator->last_counter = time_interpolator_get_counter(1);
-}
-
-#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
-
-unsigned long time_interpolator_get_offset(void)
-{
-       /* If we do not have a time interpolator set up then just return zero */
-       if (!time_interpolator)
-               return 0;
-
-       return time_interpolator->offset +
-               GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
-}
-
-#define INTERPOLATOR_ADJUST 65536
-#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
-
-void time_interpolator_update(long delta_nsec)
-{
-       u64 counter;
-       unsigned long offset;
-
-       /* If there is no time interpolator set up then do nothing */
-       if (!time_interpolator)
-               return;
-
-       /*
-        * The interpolator compensates for late ticks by accumulating the late
-        * time in time_interpolator->offset. A tick earlier than expected will
-        * lead to a reset of the offset and a corresponding jump of the clock
-        * forward. Again this only works if the interpolator clock is running
-        * slightly slower than the regular clock and the tuning logic insures
-        * that.
-        */
-
-       counter = time_interpolator_get_counter(1);
-       offset = time_interpolator->offset +
-                       GET_TI_NSECS(counter, time_interpolator);
-
-       if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-               time_interpolator->offset = offset - delta_nsec;
-       else {
-               time_interpolator->skips++;
-               time_interpolator->ns_skipped += delta_nsec - offset;
-               time_interpolator->offset = 0;
-       }
-       time_interpolator->last_counter = counter;
-
-       /* Tuning logic for time interpolator invoked every minute or so.
-        * Decrease interpolator clock speed if no skips occurred and an offset is carried.
-        * Increase interpolator clock speed if we skip too much time.
-        */
-       if (jiffies % INTERPOLATOR_ADJUST == 0)
-       {
-               if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
-                       time_interpolator->nsec_per_cyc--;
-               if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
-                       time_interpolator->nsec_per_cyc++;
-               time_interpolator->skips = 0;
-               time_interpolator->ns_skipped = 0;
-       }
-}
-
-static inline int
-is_better_time_interpolator(struct time_interpolator *new)
-{
-       if (!time_interpolator)
-               return 1;
-       return new->frequency > 2*time_interpolator->frequency ||
-           (unsigned long)new->drift < (unsigned long)time_interpolator->drift;
-}
-
-void
-register_time_interpolator(struct time_interpolator *ti)
-{
-       unsigned long flags;
-
-       /* Sanity check */
-       BUG_ON(ti->frequency == 0 || ti->mask == 0);
-
-       ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
-       spin_lock(&time_interpolator_lock);
-       write_seqlock_irqsave(&xtime_lock, flags);
-       if (is_better_time_interpolator(ti)) {
-               time_interpolator = ti;
-               time_interpolator_reset();
-       }
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-
-       ti->next = time_interpolator_list;
-       time_interpolator_list = ti;
-       spin_unlock(&time_interpolator_lock);
-}
-
-void
-unregister_time_interpolator(struct time_interpolator *ti)
-{
-       struct time_interpolator *curr, **prev;
-       unsigned long flags;
-
-       spin_lock(&time_interpolator_lock);
-       prev = &time_interpolator_list;
-       for (curr = *prev; curr; curr = curr->next) {
-               if (curr == ti) {
-                       *prev = curr->next;
-                       break;
-               }
-               prev = &curr->next;
-       }
-
-       write_seqlock_irqsave(&xtime_lock, flags);
-       if (ti == time_interpolator) {
-               /* we lost the best time-interpolator: */
-               time_interpolator = NULL;
-               /* find the next-best interpolator */
-               for (curr = time_interpolator_list; curr; curr = curr->next)
-                       if (is_better_time_interpolator(curr))
-                               time_interpolator = curr;
-               time_interpolator_reset();
-       }
-       write_sequnlock_irqrestore(&xtime_lock, flags);
-       spin_unlock(&time_interpolator_lock);
+       open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
 }
-#endif /* CONFIG_TIME_INTERPOLATION */
 
 /**
  * msleep - sleep safely even with waitqueue interruptions