Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.26-rc1 /kernel/timer.c

Filename:/kernel/timer.c
Lines Added:149
Lines Deleted:20
Also changed in: (Previous) 2.6.25-git20  2.6.25-git19  2.6.25-git18  2.6.25-git17  2.6.25-git16  2.6.25-git15 
(Following) 2.6.26-rc2  2.6.26-rc3  2.6.26-rc4  2.6.26-rc5  2.6.26-rc6  2.6.26-rc7 

Location
[  2.6.26-rc1
  [  kernel
     o  timer.c

Patch

diff --git a/kernel/timer.c b/kernel/timer.c
index b024106..ceacc66 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -320,14 +320,130 @@ static void timer_stats_account_timer(struct timer_list *timer)
 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 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);
@@ -337,6 +453,19 @@ void 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)
@@ -351,6 +480,8 @@ static inline void detach_timer(struct timer_list *timer,
 {
    struct list_head *entry = &timer->entry;
 
+   debug_timer_deactivate(timer);
+
    __list_del(entry->prev, entry->next);
    if (clear_pending)
       entry->next = NULL;
@@ -405,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) {
@@ -450,6 +583,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
    BUG_ON(timer_pending(timer) || !timer->function);
    spin_lock_irqsave(&base->lock, flags);
    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
@@ -1086,11 +1220,14 @@ 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:
@@ -1228,13 +1365,6 @@ 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 __cpuinit init_timers_cpu(int cpu)
 {
    int j;
@@ -1277,7 +1407,6 @@ static int __cpuinit 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);
@@ -1316,8 +1445,8 @@ static void __cpuinit 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);
 
@@ -1330,8 +1459,8 @@ static void __cpuinit 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);
 }


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.