]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/timer.c
[PATCH] lockdep: print kernel version
[linux-2.6-omap-h63xx.git] / kernel / timer.c
index 2a87430a58d4046d10000fcd6bd4e56308a9a4bc..d644f4e9ca0c97731589b3d6db57a3fb6a1420d7 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;
@@ -968,7 +974,8 @@ void __init timekeeping_init(void)
 }
 
 
-/*
+static int timekeeping_suspended;
+/**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:       unused
  *
@@ -983,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;
 }
@@ -990,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"),
 };
 
@@ -1091,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.
@@ -1100,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.
@@ -1306,46 +1329,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;
 }
 
@@ -1479,8 +1475,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)
 {
@@ -1670,7 +1667,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;
@@ -1690,7 +1687,7 @@ 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,
 };