]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/timer.c
[PATCH] autofs4: autofs4_follow_link false negative fix
[linux-2.6-omap-h63xx.git] / kernel / timer.c
index 396a3c024c2c5ba95a9cb663d009acba16b5df0f..4f55622b0d38462ad59b28322d31ebeee8a0c40c 100644 (file)
@@ -84,7 +84,7 @@ typedef struct tvec_t_base_s tvec_base_t;
 
 tvec_base_t boot_tvec_bases;
 EXPORT_SYMBOL(boot_tvec_bases);
-static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases };
+static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
 
 static inline void set_running_timer(tvec_base_t *base,
                                        struct timer_list *timer)
@@ -136,7 +136,7 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
        list_add_tail(&timer->entry, vec);
 }
 
-/***
+/**
  * init_timer - initialize a timer.
  * @timer: the timer to be initialized
  *
@@ -175,6 +175,7 @@ static inline void detach_timer(struct timer_list *timer,
  */
 static tvec_base_t *lock_timer_base(struct timer_list *timer,
                                        unsigned long *flags)
+       __acquires(timer->base->lock)
 {
        tvec_base_t *base;
 
@@ -235,7 +236,7 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
 
 EXPORT_SYMBOL(__mod_timer);
 
-/***
+/**
  * add_timer_on - start a timer on a particular CPU
  * @timer: the timer to be added
  * @cpu: the CPU to start it on
@@ -255,9 +256,10 @@ void add_timer_on(struct timer_list *timer, int cpu)
 }
 
 
-/***
+/**
  * mod_timer - modify a timer's timeout
  * @timer: the timer to be modified
+ * @expires: new timeout in jiffies
  *
  * mod_timer is a more efficient way to update the expire field of an
  * active timer (if the timer is inactive it will be activated)
@@ -291,7 +293,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
 
 EXPORT_SYMBOL(mod_timer);
 
-/***
+/**
  * del_timer - deactive a timer.
  * @timer: the timer to be deactivated
  *
@@ -323,7 +325,10 @@ int del_timer(struct timer_list *timer)
 EXPORT_SYMBOL(del_timer);
 
 #ifdef CONFIG_SMP
-/*
+/**
+ * try_to_del_timer_sync - Try to deactivate a timer
+ * @timer: timer do del
+ *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
  *
@@ -351,7 +356,7 @@ out:
        return ret;
 }
 
-/***
+/**
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
  *
@@ -374,6 +379,7 @@ int del_timer_sync(struct timer_list *timer)
                int ret = try_to_del_timer_sync(timer);
                if (ret >= 0)
                        return ret;
+               cpu_relax();
        }
 }
 
@@ -400,15 +406,15 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
        return index;
 }
 
-/***
+#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
+
+/**
  * __run_timers - run all expired timers (if any) on this CPU.
  * @base: the timer vector to be processed.
  *
  * This function cascades all vectors and executes all expired timer
  * vectors.
  */
-#define INDEX(N) (base->timer_jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK
-
 static inline void __run_timers(tvec_base_t *base)
 {
        struct timer_list *timer;
@@ -891,6 +897,7 @@ int do_settimeofday(struct timespec *tv)
        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);
@@ -967,7 +974,8 @@ void __init timekeeping_init(void)
 }
 
 
-/*
+static int timekeeping_suspended;
+/**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:       unused
  *
@@ -982,6 +990,18 @@ static int timekeeping_resume(struct sys_device *dev)
        write_seqlock_irqsave(&xtime_lock, flags);
        /* restart the last cycle value */
        clock->cycle_last = clocksource_read(clock);
+       clock->error = 0;
+       timekeeping_suspended = 0;
+       write_sequnlock_irqrestore(&xtime_lock, flags);
+       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;
        write_sequnlock_irqrestore(&xtime_lock, flags);
        return 0;
 }
@@ -989,6 +1009,7 @@ static int timekeeping_resume(struct sys_device *dev)
 /* sysfs resume/suspend bits for timekeeping */
 static struct sysdev_class timekeeping_sysclass = {
        .resume         = timekeeping_resume,
+       .suspend        = timekeeping_suspend,
        set_kset_name("timekeeping"),
 };
 
@@ -1008,52 +1029,52 @@ static int __init timekeeping_init_device(void)
 device_initcall(timekeeping_init_device);
 
 /*
- * If the error is already larger, we look ahead another tick,
+ * If the error is already larger, we look ahead even further
  * to compensate for late or lost adjustments.
  */
-static __always_inline int clocksource_bigadjust(int sign, s64 error, s64 *interval, s64 *offset)
+static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, s64 *offset)
 {
-       int adj;
+       s64 tick_error, i;
+       u32 look_ahead, adj;
+       s32 error2, mult;
 
        /*
-        * As soon as the machine is synchronized to the external time
-        * source this should be the common case.
+        * 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).
         */
-       error >>= 2;
-       if (likely(sign > 0 ? error <= *interval : error >= *interval))
-               return sign;
+       error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
+       error2 = abs(error2);
+       for (look_ahead = 0; error2 > 0; look_ahead++)
+               error2 >>= 2;
 
        /*
-        * An extra look ahead dampens the effect of the current error,
-        * which can grow quite large with continously late updates, as
-        * it would dominate the adjustment value and can lead to
-        * oscillation.
+        * Now calculate the error in (1 << look_ahead) ticks, but first
+        * remove the single look ahead already included in the error.
         */
-       error += current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1);
-       error -= clock->xtime_interval >> 1;
-
-       adj = 0;
-       while (1) {
-               error >>= 1;
-               if (sign > 0 ? error <= *interval : error >= *interval)
-                       break;
-               adj++;
+       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;
        }
-
-       /*
-        * Add the current adjustments to the error and take the offset
-        * into account, the latter can cause the error to be hardly
-        * reduced at the next tick. Check the error again if there's
-        * room for another adjustment, thus further reducing the error
-        * which otherwise had to be corrected at the next update.
-        */
-       error = (error << 1) - *interval + *offset;
-       if (sign > 0 ? error > *interval : error < *interval)
-               adj++;
+       for (adj = 0; error > i; adj++)
+               error >>= 1;
 
        *interval <<= adj;
        *offset <<= adj;
-       return sign << adj;
+       return mult << adj;
 }
 
 /*
@@ -1068,11 +1089,19 @@ static void clocksource_adjust(struct clocksource *clock, s64 offset)
 
        error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
        if (error > interval) {
-               adj = clocksource_bigadjust(1, error, &interval, &offset);
+               error >>= 2;
+               if (likely(error <= interval))
+                       adj = 1;
+               else
+                       adj = clocksource_bigadjust(error, &interval, &offset);
        } else if (error < -interval) {
-               interval = -interval;
-               offset = -offset;
-               adj = clocksource_bigadjust(-1, error, &interval, &offset);
+               error >>= 2;
+               if (likely(error >= -interval)) {
+                       adj = -1;
+                       interval = -interval;
+                       offset = -offset;
+               } else
+                       adj = clocksource_bigadjust(error, &interval, &offset);
        } else
                return;
 
@@ -1082,7 +1111,7 @@ static void clocksource_adjust(struct clocksource *clock, s64 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.
@@ -1091,13 +1120,16 @@ static void update_wall_time(void)
 {
        cycle_t offset;
 
-       clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
+       /* 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.
@@ -1129,7 +1161,7 @@ static void update_wall_time(void)
        clocksource_adjust(clock, offset);
 
        /* store full nanoseconds into xtime */
-       xtime.tv_nsec = clock->xtime_nsec >> clock->shift;
+       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 */
@@ -1190,10 +1222,8 @@ static inline void calc_load(unsigned long ticks)
        unsigned long active_tasks; /* fixed-point */
        static int count = LOAD_FREQ;
 
-       count -= ticks;
-       if (count < 0) {
-               count += LOAD_FREQ;
-               active_tasks = count_active_tasks();
+       active_tasks = count_active_tasks();
+       for (count -= ticks; count < 0; count += LOAD_FREQ) {
                CALC_LOAD(avenrun[0], EXP_1, active_tasks);
                CALC_LOAD(avenrun[1], EXP_5, active_tasks);
                CALC_LOAD(avenrun[2], EXP_15, active_tasks);
@@ -1238,11 +1268,8 @@ void run_local_timers(void)
  * Called by the timer interrupt. xtime_lock must already be taken
  * by the timer IRQ!
  */
-static inline void update_times(void)
+static inline void update_times(unsigned long ticks)
 {
-       unsigned long ticks;
-
-       ticks = jiffies - wall_jiffies;
        wall_jiffies += ticks;
        update_wall_time();
        calc_load(ticks);
@@ -1254,12 +1281,10 @@ static inline void update_times(void)
  * jiffies is defined in the linker script...
  */
 
-void do_timer(struct pt_regs *regs)
+void do_timer(unsigned long ticks)
 {
-       jiffies_64++;
-       /* prevent loading jiffies before storing new jiffies_64 value. */
-       barrier();
-       update_times();
+       jiffies_64 += ticks;
+       update_times(ticks);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
@@ -1297,46 +1322,19 @@ asmlinkage long sys_getpid(void)
 }
 
 /*
- * Accessing ->group_leader->real_parent is not SMP-safe, it could
- * change from under us. However, rather than getting any lock
- * we can use an optimistic algorithm: get the parent
- * pid, and go back and check that the parent is still
- * the same. If it has changed (which is extremely unlikely
- * indeed), we just try again..
- *
- * NOTE! This depends on the fact that even if we _do_
- * get an old value of "parent", we can happily dereference
- * the pointer (it was and remains a dereferencable kernel pointer
- * no matter what): we just can't necessarily trust the result
- * until we know that the parent pointer is valid.
- *
- * NOTE2: ->group_leader never changes from under us.
+ * Accessing ->real_parent is not SMP-safe, it could
+ * change from under us. However, we can use a stale
+ * value of ->real_parent under rcu_read_lock(), see
+ * release_task()->call_rcu(delayed_put_task_struct).
  */
 asmlinkage long sys_getppid(void)
 {
        int pid;
-       struct task_struct *me = current;
-       struct task_struct *parent;
 
-       parent = me->group_leader->real_parent;
-       for (;;) {
-               pid = parent->tgid;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-{
-               struct task_struct *old = parent;
+       rcu_read_lock();
+       pid = rcu_dereference(current->real_parent)->tgid;
+       rcu_read_unlock();
 
-               /*
-                * Make sure we read the pid before re-reading the
-                * parent pointer:
-                */
-               smp_rmb();
-               parent = me->group_leader->real_parent;
-               if (old != parent)
-                       continue;
-}
-#endif
-               break;
-       }
        return pid;
 }
 
@@ -1470,8 +1468,9 @@ asmlinkage long sys_gettid(void)
        return current->pid;
 }
 
-/*
+/**
  * sys_sysinfo - fill in sysinfo struct
+ * @info: pointer to buffer to fill
  */ 
 asmlinkage long sys_sysinfo(struct sysinfo __user *info)
 {
@@ -1661,7 +1660,7 @@ static void __devinit migrate_timers(int cpu)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit timer_cpu_notify(struct notifier_block *self,
+static int __cpuinit timer_cpu_notify(struct notifier_block *self,
                                unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
@@ -1681,15 +1680,17 @@ static int __devinit timer_cpu_notify(struct notifier_block *self,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata timers_nb = {
+static struct notifier_block __cpuinitdata timers_nb = {
        .notifier_call  = timer_cpu_notify,
 };
 
 
 void __init init_timers(void)
 {
-       timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
+       int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
                                (void *)(long)smp_processor_id());
+
+       BUG_ON(err == NOTIFY_BAD);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
 }