ia64/linux-2.6.18-xen.hg

annotate kernel/rtmutex-debug.c @ 562:66faefe721eb

pvSCSI backend driver

Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
Signed-off-by: Jun Kamada <kama@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jun 02 09:58:27 2008 +0100 (2008-06-02)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 * RT-Mutexes: blocking mutual exclusion locks with PI support
ian@0 3 *
ian@0 4 * started by Ingo Molnar and Thomas Gleixner:
ian@0 5 *
ian@0 6 * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
ian@0 7 * Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
ian@0 8 *
ian@0 9 * This code is based on the rt.c implementation in the preempt-rt tree.
ian@0 10 * Portions of said code are
ian@0 11 *
ian@0 12 * Copyright (C) 2004 LynuxWorks, Inc., Igor Manyilov, Bill Huey
ian@0 13 * Copyright (C) 2006 Esben Nielsen
ian@0 14 * Copyright (C) 2006 Kihon Technologies Inc.,
ian@0 15 * Steven Rostedt <rostedt@goodmis.org>
ian@0 16 *
ian@0 17 * See rt.c in preempt-rt for proper credits and further information
ian@0 18 */
ian@0 19 #include <linux/config.h>
ian@0 20 #include <linux/sched.h>
ian@0 21 #include <linux/delay.h>
ian@0 22 #include <linux/module.h>
ian@0 23 #include <linux/spinlock.h>
ian@0 24 #include <linux/kallsyms.h>
ian@0 25 #include <linux/syscalls.h>
ian@0 26 #include <linux/interrupt.h>
ian@0 27 #include <linux/plist.h>
ian@0 28 #include <linux/fs.h>
ian@0 29 #include <linux/debug_locks.h>
ian@0 30
ian@0 31 #include "rtmutex_common.h"
ian@0 32
ian@0 33 #ifdef CONFIG_DEBUG_RT_MUTEXES
ian@0 34 # include "rtmutex-debug.h"
ian@0 35 #else
ian@0 36 # include "rtmutex.h"
ian@0 37 #endif
ian@0 38
ian@0 39 # define TRACE_WARN_ON(x) WARN_ON(x)
ian@0 40 # define TRACE_BUG_ON(x) BUG_ON(x)
ian@0 41
ian@0 42 # define TRACE_OFF() \
ian@0 43 do { \
ian@0 44 if (rt_trace_on) { \
ian@0 45 rt_trace_on = 0; \
ian@0 46 console_verbose(); \
ian@0 47 if (spin_is_locked(&current->pi_lock)) \
ian@0 48 spin_unlock(&current->pi_lock); \
ian@0 49 } \
ian@0 50 } while (0)
ian@0 51
ian@0 52 # define TRACE_OFF_NOLOCK() \
ian@0 53 do { \
ian@0 54 if (rt_trace_on) { \
ian@0 55 rt_trace_on = 0; \
ian@0 56 console_verbose(); \
ian@0 57 } \
ian@0 58 } while (0)
ian@0 59
ian@0 60 # define TRACE_BUG_LOCKED() \
ian@0 61 do { \
ian@0 62 TRACE_OFF(); \
ian@0 63 BUG(); \
ian@0 64 } while (0)
ian@0 65
ian@0 66 # define TRACE_WARN_ON_LOCKED(c) \
ian@0 67 do { \
ian@0 68 if (unlikely(c)) { \
ian@0 69 TRACE_OFF(); \
ian@0 70 WARN_ON(1); \
ian@0 71 } \
ian@0 72 } while (0)
ian@0 73
ian@0 74 # define TRACE_BUG_ON_LOCKED(c) \
ian@0 75 do { \
ian@0 76 if (unlikely(c)) \
ian@0 77 TRACE_BUG_LOCKED(); \
ian@0 78 } while (0)
ian@0 79
ian@0 80 #ifdef CONFIG_SMP
ian@0 81 # define SMP_TRACE_BUG_ON_LOCKED(c) TRACE_BUG_ON_LOCKED(c)
ian@0 82 #else
ian@0 83 # define SMP_TRACE_BUG_ON_LOCKED(c) do { } while (0)
ian@0 84 #endif
ian@0 85
ian@0 86 /*
ian@0 87 * deadlock detection flag. We turn it off when we detect
ian@0 88 * the first problem because we dont want to recurse back
ian@0 89 * into the tracing code when doing error printk or
ian@0 90 * executing a BUG():
ian@0 91 */
ian@0 92 int rt_trace_on = 1;
ian@0 93
ian@0 94 void deadlock_trace_off(void)
ian@0 95 {
ian@0 96 rt_trace_on = 0;
ian@0 97 }
ian@0 98
ian@0 99 static void printk_task(struct task_struct *p)
ian@0 100 {
ian@0 101 if (p)
ian@0 102 printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio);
ian@0 103 else
ian@0 104 printk("<none>");
ian@0 105 }
ian@0 106
ian@0 107 static void printk_lock(struct rt_mutex *lock, int print_owner)
ian@0 108 {
ian@0 109 if (lock->name)
ian@0 110 printk(" [%p] {%s}\n",
ian@0 111 lock, lock->name);
ian@0 112 else
ian@0 113 printk(" [%p] {%s:%d}\n",
ian@0 114 lock, lock->file, lock->line);
ian@0 115
ian@0 116 if (print_owner && rt_mutex_owner(lock)) {
ian@0 117 printk(".. ->owner: %p\n", lock->owner);
ian@0 118 printk(".. held by: ");
ian@0 119 printk_task(rt_mutex_owner(lock));
ian@0 120 printk("\n");
ian@0 121 }
ian@0 122 }
ian@0 123
ian@0 124 void rt_mutex_debug_task_free(struct task_struct *task)
ian@0 125 {
ian@0 126 WARN_ON(!plist_head_empty(&task->pi_waiters));
ian@0 127 WARN_ON(task->pi_blocked_on);
ian@0 128 }
ian@0 129
ian@0 130 /*
ian@0 131 * We fill out the fields in the waiter to store the information about
ian@0 132 * the deadlock. We print when we return. act_waiter can be NULL in
ian@0 133 * case of a remove waiter operation.
ian@0 134 */
ian@0 135 void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *act_waiter,
ian@0 136 struct rt_mutex *lock)
ian@0 137 {
ian@0 138 struct task_struct *task;
ian@0 139
ian@0 140 if (!rt_trace_on || detect || !act_waiter)
ian@0 141 return;
ian@0 142
ian@0 143 task = rt_mutex_owner(act_waiter->lock);
ian@0 144 if (task && task != current) {
ian@0 145 act_waiter->deadlock_task_pid = task->pid;
ian@0 146 act_waiter->deadlock_lock = lock;
ian@0 147 }
ian@0 148 }
ian@0 149
ian@0 150 void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
ian@0 151 {
ian@0 152 struct task_struct *task;
ian@0 153
ian@0 154 if (!waiter->deadlock_lock || !rt_trace_on)
ian@0 155 return;
ian@0 156
ian@0 157 task = find_task_by_pid(waiter->deadlock_task_pid);
ian@0 158 if (!task)
ian@0 159 return;
ian@0 160
ian@0 161 TRACE_OFF_NOLOCK();
ian@0 162
ian@0 163 printk("\n============================================\n");
ian@0 164 printk( "[ BUG: circular locking deadlock detected! ]\n");
ian@0 165 printk( "--------------------------------------------\n");
ian@0 166 printk("%s/%d is deadlocking current task %s/%d\n\n",
ian@0 167 task->comm, task->pid, current->comm, current->pid);
ian@0 168
ian@0 169 printk("\n1) %s/%d is trying to acquire this lock:\n",
ian@0 170 current->comm, current->pid);
ian@0 171 printk_lock(waiter->lock, 1);
ian@0 172
ian@0 173 printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid);
ian@0 174 printk_lock(waiter->deadlock_lock, 1);
ian@0 175
ian@0 176 debug_show_held_locks(current);
ian@0 177 debug_show_held_locks(task);
ian@0 178
ian@0 179 printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid);
ian@0 180 show_stack(task, NULL);
ian@0 181 printk("\n%s/%d's [current] stackdump:\n\n",
ian@0 182 current->comm, current->pid);
ian@0 183 dump_stack();
ian@0 184 debug_show_all_locks();
ian@0 185
ian@0 186 printk("[ turning off deadlock detection."
ian@0 187 "Please report this trace. ]\n\n");
ian@0 188 local_irq_disable();
ian@0 189 }
ian@0 190
ian@0 191 void debug_rt_mutex_lock(struct rt_mutex *lock)
ian@0 192 {
ian@0 193 }
ian@0 194
ian@0 195 void debug_rt_mutex_unlock(struct rt_mutex *lock)
ian@0 196 {
ian@0 197 TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current);
ian@0 198 }
ian@0 199
ian@0 200 void
ian@0 201 debug_rt_mutex_proxy_lock(struct rt_mutex *lock, struct task_struct *powner)
ian@0 202 {
ian@0 203 }
ian@0 204
ian@0 205 void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock)
ian@0 206 {
ian@0 207 TRACE_WARN_ON_LOCKED(!rt_mutex_owner(lock));
ian@0 208 }
ian@0 209
ian@0 210 void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
ian@0 211 {
ian@0 212 memset(waiter, 0x11, sizeof(*waiter));
ian@0 213 plist_node_init(&waiter->list_entry, MAX_PRIO);
ian@0 214 plist_node_init(&waiter->pi_list_entry, MAX_PRIO);
ian@0 215 }
ian@0 216
ian@0 217 void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
ian@0 218 {
ian@0 219 TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry));
ian@0 220 TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
ian@0 221 TRACE_WARN_ON(waiter->task);
ian@0 222 memset(waiter, 0x22, sizeof(*waiter));
ian@0 223 }
ian@0 224
ian@0 225 void debug_rt_mutex_init(struct rt_mutex *lock, const char *name)
ian@0 226 {
ian@0 227 /*
ian@0 228 * Make sure we are not reinitializing a held lock:
ian@0 229 */
ian@0 230 debug_check_no_locks_freed((void *)lock, sizeof(*lock));
ian@0 231 lock->name = name;
ian@0 232 }
ian@0 233
ian@0 234 void
ian@0 235 rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task)
ian@0 236 {
ian@0 237 }
ian@0 238
ian@0 239 void rt_mutex_deadlock_account_unlock(struct task_struct *task)
ian@0 240 {
ian@0 241 }
ian@0 242