futex: Fix uninterruptible loop due to gate_area
[linux-2.6.git] / kernel / rtmutex-debug.c
index 4aa8a2c..3c7cbc2 100644 (file)
@@ -16,7 +16,6 @@
  *
  * See rt.c in preempt-rt for proper credits and further information
  */
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/plist.h>
 #include <linux/fs.h>
+#include <linux/debug_locks.h>
 
 #include "rtmutex_common.h"
 
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
 # define TRACE_WARN_ON(x)                      WARN_ON(x)
 # define TRACE_BUG_ON(x)                       BUG_ON(x)
 
@@ -43,10 +37,8 @@ do {                                                         \
        if (rt_trace_on) {                                      \
                rt_trace_on = 0;                                \
                console_verbose();                              \
-               if (spin_is_locked(&current->pi_lock))          \
-                       spin_unlock(&current->pi_lock);         \
-               if (spin_is_locked(&current->held_list_lock))   \
-                       spin_unlock(&current->held_list_lock);  \
+               if (raw_spin_is_locked(&current->pi_lock))      \
+                       raw_spin_unlock(&current->pi_lock);     \
        }                                                       \
 } while (0)
 
@@ -90,25 +82,12 @@ do {                                                \
  * into the tracing code when doing error printk or
  * executing a BUG():
  */
-int rt_trace_on = 1;
-
-void deadlock_trace_off(void)
-{
-       rt_trace_on = 0;
-}
-
-static void printk_task(task_t *p)
-{
-       if (p)
-               printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio);
-       else
-               printk("<none>");
-}
+static int rt_trace_on = 1;
 
-static void printk_task_short(task_t *p)
+static void printk_task(struct task_struct *p)
 {
        if (p)
-               printk("%s/%d [%p, %3d]", p->comm, p->pid, p, p->prio);
+               printk("%16s:%5d [%p, %3d]", p->comm, task_pid_nr(p), p, p->prio);
        else
                printk("<none>");
 }
@@ -128,222 +107,6 @@ static void printk_lock(struct rt_mutex *lock, int print_owner)
                printk_task(rt_mutex_owner(lock));
                printk("\n");
        }
-       if (rt_mutex_owner(lock)) {
-               printk("... acquired at:               ");
-               print_symbol("%s\n", lock->acquire_ip);
-       }
-}
-
-static void printk_waiter(struct rt_mutex_waiter *w)
-{
-       printk("-------------------------\n");
-       printk("| waiter struct %p:\n", w);
-       printk("| w->list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n",
-              w->list_entry.plist.prio_list.prev, w->list_entry.plist.prio_list.next,
-              w->list_entry.plist.node_list.prev, w->list_entry.plist.node_list.next,
-              w->list_entry.prio);
-       printk("| w->pi_list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n",
-              w->pi_list_entry.plist.prio_list.prev, w->pi_list_entry.plist.prio_list.next,
-              w->pi_list_entry.plist.node_list.prev, w->pi_list_entry.plist.node_list.next,
-              w->pi_list_entry.prio);
-       printk("\n| lock:\n");
-       printk_lock(w->lock, 1);
-       printk("| w->ti->task:\n");
-       printk_task(w->task);
-       printk("| blocked at:  ");
-       print_symbol("%s\n", w->ip);
-       printk("-------------------------\n");
-}
-
-static void show_task_locks(task_t *p)
-{
-       switch (p->state) {
-       case TASK_RUNNING:              printk("R"); break;
-       case TASK_INTERRUPTIBLE:        printk("S"); break;
-       case TASK_UNINTERRUPTIBLE:      printk("D"); break;
-       case TASK_STOPPED:              printk("T"); break;
-       case EXIT_ZOMBIE:               printk("Z"); break;
-       case EXIT_DEAD:                 printk("X"); break;
-       default:                        printk("?"); break;
-       }
-       printk_task(p);
-       if (p->pi_blocked_on) {
-               struct rt_mutex *lock = p->pi_blocked_on->lock;
-
-               printk(" blocked on:");
-               printk_lock(lock, 1);
-       } else
-               printk(" (not blocked)\n");
-}
-
-void rt_mutex_show_held_locks(task_t *task, int verbose)
-{
-       struct list_head *curr, *cursor = NULL;
-       struct rt_mutex *lock;
-       task_t *t;
-       unsigned long flags;
-       int count = 0;
-
-       if (!rt_trace_on)
-               return;
-
-       if (verbose) {
-               printk("------------------------------\n");
-               printk("| showing all locks held by: |  (");
-               printk_task_short(task);
-               printk("):\n");
-               printk("------------------------------\n");
-       }
-
-next:
-       spin_lock_irqsave(&task->held_list_lock, flags);
-       list_for_each(curr, &task->held_list_head) {
-               if (cursor && curr != cursor)
-                       continue;
-               lock = list_entry(curr, struct rt_mutex, held_list_entry);
-               t = rt_mutex_owner(lock);
-               WARN_ON(t != task);
-               count++;
-               cursor = curr->next;
-               spin_unlock_irqrestore(&task->held_list_lock, flags);
-
-               printk("\n#%03d:            ", count);
-               printk_lock(lock, 0);
-               goto next;
-       }
-       spin_unlock_irqrestore(&task->held_list_lock, flags);
-
-       printk("\n");
-}
-
-void rt_mutex_show_all_locks(void)
-{
-       task_t *g, *p;
-       int count = 10;
-       int unlock = 1;
-
-       printk("\n");
-       printk("----------------------\n");
-       printk("| showing all tasks: |\n");
-       printk("----------------------\n");
-
-       /*
-        * Here we try to get the tasklist_lock as hard as possible,
-        * if not successful after 2 seconds we ignore it (but keep
-        * trying). This is to enable a debug printout even if a
-        * tasklist_lock-holding task deadlocks or crashes.
-        */
-retry:
-       if (!read_trylock(&tasklist_lock)) {
-               if (count == 10)
-                       printk("hm, tasklist_lock locked, retrying... ");
-               if (count) {
-                       count--;
-                       printk(" #%d", 10-count);
-                       mdelay(200);
-                       goto retry;
-               }
-               printk(" ignoring it.\n");
-               unlock = 0;
-       }
-       if (count != 10)
-               printk(" locked it.\n");
-
-       do_each_thread(g, p) {
-               show_task_locks(p);
-               if (!unlock)
-                       if (read_trylock(&tasklist_lock))
-                               unlock = 1;
-       } while_each_thread(g, p);
-
-       printk("\n");
-
-       printk("-----------------------------------------\n");
-       printk("| showing all locks held in the system: |\n");
-       printk("-----------------------------------------\n");
-
-       do_each_thread(g, p) {
-               rt_mutex_show_held_locks(p, 0);
-               if (!unlock)
-                       if (read_trylock(&tasklist_lock))
-                               unlock = 1;
-       } while_each_thread(g, p);
-
-
-       printk("=============================================\n\n");
-
-       if (unlock)
-               read_unlock(&tasklist_lock);
-}
-
-void rt_mutex_debug_check_no_locks_held(task_t *task)
-{
-       struct rt_mutex_waiter *w;
-       struct list_head *curr;
-       struct rt_mutex *lock;
-
-       if (!rt_trace_on)
-               return;
-       if (!rt_prio(task->normal_prio) && rt_prio(task->prio)) {
-               printk("BUG: PI priority boost leaked!\n");
-               printk_task(task);
-               printk("\n");
-       }
-       if (list_empty(&task->held_list_head))
-               return;
-
-       spin_lock(&task->pi_lock);
-       plist_for_each_entry(w, &task->pi_waiters, pi_list_entry) {
-               TRACE_OFF();
-
-               printk("hm, PI interest held at exit time? Task:\n");
-               printk_task(task);
-               printk_waiter(w);
-               return;
-       }
-       spin_unlock(&task->pi_lock);
-
-       list_for_each(curr, &task->held_list_head) {
-               lock = list_entry(curr, struct rt_mutex, held_list_entry);
-
-               printk("BUG: %s/%d, lock held at task exit time!\n",
-                      task->comm, task->pid);
-               printk_lock(lock, 1);
-               if (rt_mutex_owner(lock) != task)
-                       printk("exiting task is not even the owner??\n");
-       }
-}
-
-int rt_mutex_debug_check_no_locks_freed(const void *from, unsigned long len)
-{
-       const void *to = from + len;
-       struct list_head *curr;
-       struct rt_mutex *lock;
-       unsigned long flags;
-       void *lock_addr;
-
-       if (!rt_trace_on)
-               return 0;
-
-       spin_lock_irqsave(&current->held_list_lock, flags);
-       list_for_each(curr, &current->held_list_head) {
-               lock = list_entry(curr, struct rt_mutex, held_list_entry);
-               lock_addr = lock;
-               if (lock_addr < from || lock_addr >= to)
-                       continue;
-               TRACE_OFF();
-
-               printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n",
-                       current->comm, current->pid, lock, from, to);
-               dump_stack();
-               printk_lock(lock, 1);
-               if (rt_mutex_owner(lock) != current)
-                       printk("freeing task is not even the owner??\n");
-               return 1;
-       }
-       spin_unlock_irqrestore(&current->held_list_lock, flags);
-
-       return 0;
 }
 
 void rt_mutex_debug_task_free(struct task_struct *task)
@@ -367,7 +130,7 @@ void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *act_waiter,
 
        task = rt_mutex_owner(act_waiter->lock);
        if (task && task != current) {
-               act_waiter->deadlock_task_pid = task->pid;
+               act_waiter->deadlock_task_pid = get_pid(task_pid(task));
                act_waiter->deadlock_lock = lock;
        }
 }
@@ -379,9 +142,12 @@ void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
        if (!waiter->deadlock_lock || !rt_trace_on)
                return;
 
-       task = find_task_by_pid(waiter->deadlock_task_pid);
-       if (!task)
+       rcu_read_lock();
+       task = pid_task(waiter->deadlock_task_pid, PIDTYPE_PID);
+       if (!task) {
+               rcu_read_unlock();
                return;
+       }
 
        TRACE_OFF_NOLOCK();
 
@@ -389,91 +155,51 @@ void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
        printk(  "[ BUG: circular locking deadlock detected! ]\n");
        printk(  "--------------------------------------------\n");
        printk("%s/%d is deadlocking current task %s/%d\n\n",
-              task->comm, task->pid, current->comm, current->pid);
+              task->comm, task_pid_nr(task),
+              current->comm, task_pid_nr(current));
 
        printk("\n1) %s/%d is trying to acquire this lock:\n",
-              current->comm, current->pid);
+              current->comm, task_pid_nr(current));
        printk_lock(waiter->lock, 1);
 
-       printk("... trying at:                 ");
-       print_symbol("%s\n", waiter->ip);
-
-       printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid);
+       printk("\n2) %s/%d is blocked on this lock:\n",
+               task->comm, task_pid_nr(task));
        printk_lock(waiter->deadlock_lock, 1);
 
-       rt_mutex_show_held_locks(current, 1);
-       rt_mutex_show_held_locks(task, 1);
+       debug_show_held_locks(current);
+       debug_show_held_locks(task);
 
-       printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid);
+       printk("\n%s/%d's [blocked] stackdump:\n\n",
+               task->comm, task_pid_nr(task));
        show_stack(task, NULL);
        printk("\n%s/%d's [current] stackdump:\n\n",
-              current->comm, current->pid);
+               current->comm, task_pid_nr(current));
        dump_stack();
-       rt_mutex_show_all_locks();
+       debug_show_all_locks();
+       rcu_read_unlock();
+
        printk("[ turning off deadlock detection."
               "Please report this trace. ]\n\n");
        local_irq_disable();
 }
 
-void debug_rt_mutex_lock(struct rt_mutex *lock __IP_DECL__)
+void debug_rt_mutex_lock(struct rt_mutex *lock)
 {
-       unsigned long flags;
-
-       if (rt_trace_on) {
-               TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry));
-
-               spin_lock_irqsave(&current->held_list_lock, flags);
-               list_add_tail(&lock->held_list_entry, &current->held_list_head);
-               spin_unlock_irqrestore(&current->held_list_lock, flags);
-
-               lock->acquire_ip = ip;
-       }
 }
 
 void debug_rt_mutex_unlock(struct rt_mutex *lock)
 {
-       unsigned long flags;
-
-       if (rt_trace_on) {
-               TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current);
-               TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry));
-
-               spin_lock_irqsave(&current->held_list_lock, flags);
-               list_del_init(&lock->held_list_entry);
-               spin_unlock_irqrestore(&current->held_list_lock, flags);
-       }
+       TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current);
 }
 
-void debug_rt_mutex_proxy_lock(struct rt_mutex *lock,
-                              struct task_struct *powner __IP_DECL__)
+void
+debug_rt_mutex_proxy_lock(struct rt_mutex *lock, struct task_struct *powner)
 {
-       unsigned long flags;
-
-       if (rt_trace_on) {
-               TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry));
-
-               spin_lock_irqsave(&powner->held_list_lock, flags);
-               list_add_tail(&lock->held_list_entry, &powner->held_list_head);
-               spin_unlock_irqrestore(&powner->held_list_lock, flags);
-
-               lock->acquire_ip = ip;
-       }
 }
 
 void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock)
 {
-       unsigned long flags;
-
-       if (rt_trace_on) {
-               struct task_struct *owner = rt_mutex_owner(lock);
-
-               TRACE_WARN_ON_LOCKED(!owner);
-               TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry));
-
-               spin_lock_irqsave(&owner->held_list_lock, flags);
-               list_del_init(&lock->held_list_entry);
-               spin_unlock_irqrestore(&owner->held_list_lock, flags);
-       }
+       TRACE_WARN_ON_LOCKED(!rt_mutex_owner(lock));
 }
 
 void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
@@ -481,29 +207,28 @@ void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
        memset(waiter, 0x11, sizeof(*waiter));
        plist_node_init(&waiter->list_entry, MAX_PRIO);
        plist_node_init(&waiter->pi_list_entry, MAX_PRIO);
+       waiter->deadlock_task_pid = NULL;
 }
 
 void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
 {
+       put_pid(waiter->deadlock_task_pid);
        TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry));
        TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
-       TRACE_WARN_ON(waiter->task);
        memset(waiter, 0x22, sizeof(*waiter));
 }
 
 void debug_rt_mutex_init(struct rt_mutex *lock, const char *name)
 {
-       void *addr = lock;
-
-       if (rt_trace_on) {
-               rt_mutex_debug_check_no_locks_freed(addr,
-                                                   sizeof(struct rt_mutex));
-               INIT_LIST_HEAD(&lock->held_list_entry);
-               lock->name = name;
-       }
+       /*
+        * Make sure we are not reinitializing a held lock:
+        */
+       debug_check_no_locks_freed((void *)lock, sizeof(*lock));
+       lock->name = name;
 }
 
-void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, task_t *task)
+void
+rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task)
 {
 }