diff options
| author | Ingo Molnar <mingo@elte.hu> | 2006-01-09 18:59:21 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@hera.kernel.org> | 2006-01-09 18:59:21 -0500 |
| commit | de5097c2e73f826302cd8957c225b3725e0c7553 (patch) | |
| tree | 3d56ab6fd891088ac55a9ef529faf4360391a22f | |
| parent | 408894ee4dd4debfdedd472eb4d8414892fc90f6 (diff) | |
[PATCH] mutex subsystem, more debugging code
more mutex debugging: check for held locks during memory freeing,
task exit, enable sysrq printouts, etc.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@infradead.org>
| -rw-r--r-- | arch/i386/mm/pageattr.c | 4 | ||||
| -rw-r--r-- | drivers/char/sysrq.c | 19 | ||||
| -rw-r--r-- | include/linux/mm.h | 4 | ||||
| -rw-r--r-- | kernel/exit.c | 5 | ||||
| -rw-r--r-- | kernel/sched.c | 1 | ||||
| -rw-r--r-- | mm/page_alloc.c | 3 | ||||
| -rw-r--r-- | mm/slab.c | 1 |
7 files changed, 37 insertions, 0 deletions
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index c30a16df6440..e8a53552b13d 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c | |||
| @@ -222,6 +222,10 @@ void kernel_map_pages(struct page *page, int numpages, int enable) | |||
| 222 | { | 222 | { |
| 223 | if (PageHighMem(page)) | 223 | if (PageHighMem(page)) |
| 224 | return; | 224 | return; |
| 225 | if (!enable) | ||
| 226 | mutex_debug_check_no_locks_freed(page_address(page), | ||
| 227 | page_address(page+numpages)); | ||
| 228 | |||
| 225 | /* the return value is ignored - the calls cannot fail, | 229 | /* the return value is ignored - the calls cannot fail, |
| 226 | * large pages are disabled at boot time. | 230 | * large pages are disabled at boot time. |
| 227 | */ | 231 | */ |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 145275ebdd7e..5765f672e853 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
| @@ -153,6 +153,21 @@ static struct sysrq_key_op sysrq_mountro_op = { | |||
| 153 | 153 | ||
| 154 | /* END SYNC SYSRQ HANDLERS BLOCK */ | 154 | /* END SYNC SYSRQ HANDLERS BLOCK */ |
| 155 | 155 | ||
| 156 | #ifdef CONFIG_DEBUG_MUTEXES | ||
| 157 | |||
| 158 | static void | ||
| 159 | sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty) | ||
| 160 | { | ||
| 161 | mutex_debug_show_all_locks(); | ||
| 162 | } | ||
| 163 | |||
| 164 | static struct sysrq_key_op sysrq_showlocks_op = { | ||
| 165 | .handler = sysrq_handle_showlocks, | ||
| 166 | .help_msg = "show-all-locks(D)", | ||
| 167 | .action_msg = "Show Locks Held", | ||
| 168 | }; | ||
| 169 | |||
| 170 | #endif | ||
| 156 | 171 | ||
| 157 | /* SHOW SYSRQ HANDLERS BLOCK */ | 172 | /* SHOW SYSRQ HANDLERS BLOCK */ |
| 158 | 173 | ||
| @@ -294,7 +309,11 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { | |||
| 294 | #else | 309 | #else |
| 295 | /* c */ NULL, | 310 | /* c */ NULL, |
| 296 | #endif | 311 | #endif |
| 312 | #ifdef CONFIG_DEBUG_MUTEXES | ||
| 313 | /* d */ &sysrq_showlocks_op, | ||
| 314 | #else | ||
| 297 | /* d */ NULL, | 315 | /* d */ NULL, |
| 316 | #endif | ||
| 298 | /* e */ &sysrq_term_op, | 317 | /* e */ &sysrq_term_op, |
| 299 | /* f */ &sysrq_moom_op, | 318 | /* f */ &sysrq_moom_op, |
| 300 | /* g */ NULL, | 319 | /* g */ NULL, |
diff --git a/include/linux/mm.h b/include/linux/mm.h index df80e63903b5..3f1fafc0245e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/rbtree.h> | 13 | #include <linux/rbtree.h> |
| 14 | #include <linux/prio_tree.h> | 14 | #include <linux/prio_tree.h> |
| 15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
| 16 | #include <linux/mutex.h> | ||
| 16 | 17 | ||
| 17 | struct mempolicy; | 18 | struct mempolicy; |
| 18 | struct anon_vma; | 19 | struct anon_vma; |
| @@ -1024,6 +1025,9 @@ static inline void vm_stat_account(struct mm_struct *mm, | |||
| 1024 | static inline void | 1025 | static inline void |
| 1025 | kernel_map_pages(struct page *page, int numpages, int enable) | 1026 | kernel_map_pages(struct page *page, int numpages, int enable) |
| 1026 | { | 1027 | { |
| 1028 | if (!PageHighMem(page) && !enable) | ||
| 1029 | mutex_debug_check_no_locks_freed(page_address(page), | ||
| 1030 | page_address(page + numpages)); | ||
| 1027 | } | 1031 | } |
| 1028 | #endif | 1032 | #endif |
| 1029 | 1033 | ||
diff --git a/kernel/exit.c b/kernel/exit.c index caceabf3f230..309a46fa16f8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
| 30 | #include <linux/signal.h> | 30 | #include <linux/signal.h> |
| 31 | #include <linux/cn_proc.h> | 31 | #include <linux/cn_proc.h> |
| 32 | #include <linux/mutex.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| 34 | #include <asm/unistd.h> | 35 | #include <asm/unistd.h> |
| @@ -869,6 +870,10 @@ fastcall NORET_TYPE void do_exit(long code) | |||
| 869 | mpol_free(tsk->mempolicy); | 870 | mpol_free(tsk->mempolicy); |
| 870 | tsk->mempolicy = NULL; | 871 | tsk->mempolicy = NULL; |
| 871 | #endif | 872 | #endif |
| 873 | /* | ||
| 874 | * If DEBUG_MUTEXES is on, make sure we are holding no locks: | ||
| 875 | */ | ||
| 876 | mutex_debug_check_no_locks_held(tsk); | ||
| 872 | 877 | ||
| 873 | /* PF_DEAD causes final put_task_struct after we schedule. */ | 878 | /* PF_DEAD causes final put_task_struct after we schedule. */ |
| 874 | preempt_disable(); | 879 | preempt_disable(); |
diff --git a/kernel/sched.c b/kernel/sched.c index 92733091154c..34a945bcc022 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -4386,6 +4386,7 @@ void show_state(void) | |||
| 4386 | } while_each_thread(g, p); | 4386 | } while_each_thread(g, p); |
| 4387 | 4387 | ||
| 4388 | read_unlock(&tasklist_lock); | 4388 | read_unlock(&tasklist_lock); |
| 4389 | mutex_debug_show_all_locks(); | ||
| 4389 | } | 4390 | } |
| 4390 | 4391 | ||
| 4391 | /** | 4392 | /** |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e0e84924171b..a5e6891f7bb6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -415,6 +415,9 @@ static void __free_pages_ok(struct page *page, unsigned int order) | |||
| 415 | int reserved = 0; | 415 | int reserved = 0; |
| 416 | 416 | ||
| 417 | arch_free_page(page, order); | 417 | arch_free_page(page, order); |
| 418 | if (!PageHighMem(page)) | ||
| 419 | mutex_debug_check_no_locks_freed(page_address(page), | ||
| 420 | page_address(page+(1<<order))); | ||
| 418 | 421 | ||
| 419 | #ifndef CONFIG_MMU | 422 | #ifndef CONFIG_MMU |
| 420 | for (i = 1 ; i < (1 << order) ; ++i) | 423 | for (i = 1 ; i < (1 << order) ; ++i) |
| @@ -3071,6 +3071,7 @@ void kfree(const void *objp) | |||
| 3071 | local_irq_save(flags); | 3071 | local_irq_save(flags); |
| 3072 | kfree_debugcheck(objp); | 3072 | kfree_debugcheck(objp); |
| 3073 | c = page_get_cache(virt_to_page(objp)); | 3073 | c = page_get_cache(virt_to_page(objp)); |
| 3074 | mutex_debug_check_no_locks_freed(objp, objp+obj_reallen(c)); | ||
| 3074 | __cache_free(c, (void *)objp); | 3075 | __cache_free(c, (void *)objp); |
| 3075 | local_irq_restore(flags); | 3076 | local_irq_restore(flags); |
| 3076 | } | 3077 | } |
