diff -ur linux-2.5.24-clean/arch/i386/Config.help linux/arch/i386/Config.help --- linux-2.5.24-clean/arch/i386/Config.help Thu Jun 20 15:53:44 2002 +++ linux/arch/i386/Config.help Fri Jun 28 21:15:35 2002 @@ -932,6 +932,15 @@ best used in conjunction with the NMI watchdog so that spinlock deadlocks are also debuggable. +CONFIG_DEBUG_BKL + Say Y here to get interesting information about the Big Kernel + Lock's use in dmesg. + Shows information on the following: + - nested holds of BKL + - releases in schedule (not yet implemented) + - use in interrupts (not yet implemented) + Send any interesting output to Dave Hansen + CONFIG_DEBUG_BUGVERBOSE Say Y here to make BUG() panics output the file name and line number of the BUG call as well as the EIP and oops trace. This aids diff -ur linux-2.5.24-clean/arch/i386/config.in linux/arch/i386/config.in --- linux-2.5.24-clean/arch/i386/config.in Thu Jun 20 15:53:49 2002 +++ linux/arch/i386/config.in Fri Jun 28 10:57:50 2002 @@ -416,6 +416,7 @@ bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' Big kernel lock (BKL,kernel_flag) debugging' CONFIG_DEBUG_BKL if [ "$CONFIG_HIGHMEM" = "y" ]; then bool ' Highmem debugging' CONFIG_DEBUG_HIGHMEM fi diff -ur linux-2.5.24-clean/include/asm-alpha/smplock.h linux/include/asm-alpha/smplock.h --- linux-2.5.24-clean/include/asm-alpha/smplock.h Thu Jun 20 15:53:49 2002 +++ linux/include/asm-alpha/smplock.h Fri Jun 28 08:50:16 2002 @@ -39,13 +39,13 @@ * so we only need to worry about other * CPU's. */ -static __inline__ void lock_kernel(void) +static __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -static __inline__ void unlock_kernel(void) +static __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-arm/smplock.h linux/include/asm-arm/smplock.h --- linux-2.5.24-clean/include/asm-arm/smplock.h Thu Jun 20 15:53:43 2002 +++ linux/include/asm-arm/smplock.h Fri Jun 28 09:01:59 2002 @@ -41,7 +41,7 @@ * so we only need to worry about other * CPU's. */ -static inline void lock_kernel(void) +static inline void __lock_kernel(void) { #ifdef CONFIG_PREEMPT if (current->lock_depth == -1) @@ -53,7 +53,7 @@ #endif } -static inline void unlock_kernel(void) +static inline void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-cris/smp_lock.h linux/include/asm-cris/smp_lock.h --- linux-2.5.24-clean/include/asm-cris/smp_lock.h Thu Jun 20 15:53:44 2002 +++ linux/include/asm-cris/smp_lock.h Fri Jun 28 09:01:59 2002 @@ -11,7 +11,7 @@ * Locking the kernel */ -extern __inline void lock_kernel(void) +extern __inline void __lock_kernel(void) { unsigned long flags; int proc = smp_processor_id(); @@ -49,7 +49,7 @@ restore_flags(flags); } -extern __inline void unlock_kernel(void) +extern __inline void __unlock_kernel(void) { unsigned long flags; save_flags(flags); diff -ur linux-2.5.24-clean/include/asm-cris/smplock.h linux/include/asm-cris/smplock.h --- linux-2.5.24-clean/include/asm-cris/smplock.h Thu Jun 20 15:53:52 2002 +++ linux/include/asm-cris/smplock.h Fri Jun 28 08:50:41 2002 @@ -11,8 +11,8 @@ #ifndef CONFIG_SMP -#define lock_kernel() do { } while(0) -#define unlock_kernel() do { } while(0) +#define __lock_kernel() do { } while(0) +#define __unlock_kernel() do { } while(0) #define release_kernel_lock(task, cpu, depth) ((depth) = 1) #define reacquire_kernel_lock(task, cpu, depth) do { } while(0) diff -ur linux-2.5.24-clean/include/asm-generic/smplock.h linux/include/asm-generic/smplock.h --- linux-2.5.24-clean/include/asm-generic/smplock.h Thu Jun 20 15:53:43 2002 +++ linux/include/asm-generic/smplock.h Fri Jun 28 09:01:59 2002 @@ -38,13 +38,13 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-i386/smplock.h linux/include/asm-i386/smplock.h --- linux-2.5.24-clean/include/asm-i386/smplock.h Thu Jun 20 15:53:49 2002 +++ linux/include/asm-i386/smplock.h Fri Jun 28 11:05:52 2002 @@ -54,7 +54,7 @@ * so we only need to worry about other * CPU's. */ -static __inline__ void lock_kernel(void) +static __inline__ void __lock_kernel(void) { #ifdef CONFIG_PREEMPT if (current->lock_depth == -1) @@ -76,7 +76,7 @@ #endif } -static __inline__ void unlock_kernel(void) +static __inline__ void __unlock_kernel(void) { if (current->lock_depth < 0) BUG(); diff -ur linux-2.5.24-clean/include/asm-ia64/smplock.h linux/include/asm-ia64/smplock.h --- linux-2.5.24-clean/include/asm-ia64/smplock.h Thu Jun 20 15:53:54 2002 +++ linux/include/asm-ia64/smplock.h Fri Jun 28 08:51:16 2002 @@ -51,14 +51,14 @@ * CPU's. */ static __inline__ void -lock_kernel(void) +__lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } static __inline__ void -unlock_kernel(void) +__unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-m68k/smplock.h linux/include/asm-m68k/smplock.h --- linux-2.5.24-clean/include/asm-m68k/smplock.h Thu Jun 20 15:53:48 2002 +++ linux/include/asm-m68k/smplock.h Fri Jun 28 09:01:59 2002 @@ -38,13 +38,13 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-mips/smplock.h linux/include/asm-mips/smplock.h --- linux-2.5.24-clean/include/asm-mips/smplock.h Thu Jun 20 15:53:49 2002 +++ linux/include/asm-mips/smplock.h Fri Jun 28 09:01:59 2002 @@ -41,13 +41,13 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-mips64/smplock.h linux/include/asm-mips64/smplock.h --- linux-2.5.24-clean/include/asm-mips64/smplock.h Thu Jun 20 15:53:49 2002 +++ linux/include/asm-mips64/smplock.h Fri Jun 28 09:01:59 2002 @@ -41,13 +41,13 @@ * so we only need to worry about other * CPU's. */ -static __inline__ void lock_kernel(void) +static __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -static __inline__ void unlock_kernel(void) +static __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-parisc/smplock.h linux/include/asm-parisc/smplock.h --- linux-2.5.24-clean/include/asm-parisc/smplock.h Thu Jun 20 15:53:43 2002 +++ linux/include/asm-parisc/smplock.h Fri Jun 28 09:01:59 2002 @@ -36,13 +36,13 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-ppc/smplock.h linux/include/asm-ppc/smplock.h --- linux-2.5.24-clean/include/asm-ppc/smplock.h Thu Jun 20 15:53:48 2002 +++ linux/include/asm-ppc/smplock.h Fri Jun 28 09:01:59 2002 @@ -47,7 +47,7 @@ * so we only need to worry about other * CPU's. */ -static __inline__ void lock_kernel(void) +static __inline__ void __lock_kernel(void) { #ifdef CONFIG_PREEMPT if (current->lock_depth == -1) @@ -59,7 +59,7 @@ #endif /* CONFIG_PREEMPT */ } -static __inline__ void unlock_kernel(void) +static __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-ppc64/smplock.h linux/include/asm-ppc64/smplock.h --- linux-2.5.24-clean/include/asm-ppc64/smplock.h Thu Jun 20 15:53:47 2002 +++ linux/include/asm-ppc64/smplock.h Fri Jun 28 09:01:59 2002 @@ -43,13 +43,13 @@ * so we only need to worry about other * CPU's. */ -static __inline__ void lock_kernel(void) +static __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -static __inline__ void unlock_kernel(void) +static __inline__ void __unlock_kernel(void) { if (current->lock_depth < 0) BUG(); diff -ur linux-2.5.24-clean/include/asm-s390/smplock.h linux/include/asm-s390/smplock.h --- linux-2.5.24-clean/include/asm-s390/smplock.h Thu Jun 20 15:53:55 2002 +++ linux/include/asm-s390/smplock.h Fri Jun 28 09:01:59 2002 @@ -48,13 +48,13 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-s390x/smplock.h linux/include/asm-s390x/smplock.h --- linux-2.5.24-clean/include/asm-s390x/smplock.h Thu Jun 20 15:53:49 2002 +++ linux/include/asm-s390x/smplock.h Fri Jun 28 09:01:59 2002 @@ -48,13 +48,13 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { if (!++current->lock_depth) spin_lock(&kernel_flag); } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (--current->lock_depth < 0) spin_unlock(&kernel_flag); diff -ur linux-2.5.24-clean/include/asm-sh/smplock.h linux/include/asm-sh/smplock.h --- linux-2.5.24-clean/include/asm-sh/smplock.h Thu Jun 20 15:53:46 2002 +++ linux/include/asm-sh/smplock.h Fri Jun 28 08:52:21 2002 @@ -11,8 +11,8 @@ #ifndef CONFIG_SMP -#define lock_kernel() do { } while(0) -#define unlock_kernel() do { } while(0) +#define __lock_kernel() do { } while(0) +#define __unlock_kernel() do { } while(0) #define release_kernel_lock(task, cpu, depth) ((depth) = 1) #define reacquire_kernel_lock(task, cpu, depth) do { } while(0) diff -ur linux-2.5.24-clean/include/asm-sparc/smplock.h linux/include/asm-sparc/smplock.h --- linux-2.5.24-clean/include/asm-sparc/smplock.h Thu Jun 20 15:53:53 2002 +++ linux/include/asm-sparc/smplock.h Fri Jun 28 08:52:37 2002 @@ -42,13 +42,13 @@ * so we only need to worry about other * CPU's. */ -#define lock_kernel() \ +#define __lock_kernel() \ do { \ if (!++current->lock_depth) \ spin_lock(&kernel_flag); \ } while(0) -#define unlock_kernel() \ +#define __unlock_kernel() \ do { \ if (--current->lock_depth < 0) \ spin_unlock(&kernel_flag); \ diff -ur linux-2.5.24-clean/include/asm-sparc64/smplock.h linux/include/asm-sparc64/smplock.h --- linux-2.5.24-clean/include/asm-sparc64/smplock.h Thu Jun 20 15:53:56 2002 +++ linux/include/asm-sparc64/smplock.h Fri Jun 28 08:52:53 2002 @@ -50,13 +50,13 @@ * so we only need to worry about other * CPU's. */ -#define lock_kernel() \ +#define __lock_kernel() \ do { \ if (!++current->lock_depth) \ spin_lock(&kernel_flag); \ } while(0) -#define unlock_kernel() \ +#define __unlock_kernel() \ do { \ if (--current->lock_depth < 0) \ spin_unlock(&kernel_flag); \ diff -ur linux-2.5.24-clean/include/asm-x86_64/smplock.h linux/include/asm-x86_64/smplock.h --- linux-2.5.24-clean/include/asm-x86_64/smplock.h Thu Jun 20 15:53:51 2002 +++ linux/include/asm-x86_64/smplock.h Fri Jun 28 09:01:59 2002 @@ -54,7 +54,7 @@ * so we only need to worry about other * CPU's. */ -extern __inline__ void lock_kernel(void) +extern __inline__ void __lock_kernel(void) { #ifdef CONFIG_PREEMPT if (current->lock_depth == -1) @@ -76,7 +76,7 @@ #endif } -extern __inline__ void unlock_kernel(void) +extern __inline__ void __unlock_kernel(void) { if (current->lock_depth < 0) BUG(); diff -ur linux-2.5.24-clean/include/linux/sched.h linux/include/linux/sched.h --- linux-2.5.24-clean/include/linux/sched.h Thu Jun 20 15:53:44 2002 +++ linux/include/linux/sched.h Fri Jun 28 11:03:17 2002 @@ -28,6 +28,7 @@ #include #include #include +#include struct exec_domain; @@ -255,6 +256,8 @@ unsigned long ptrace; int lock_depth; /* Lock depth */ + struct lock_trace lt[MAX_LOCK_TRACE_DEPTH]; + int lt_dirty; /* don't print redundant stuff */ int prio, static_prio; list_t run_list; diff -ur linux-2.5.24-clean/include/linux/smp_lock.h linux/include/linux/smp_lock.h --- linux-2.5.24-clean/include/linux/smp_lock.h Thu Jun 20 15:53:48 2002 +++ linux/include/linux/smp_lock.h Fri Jun 28 08:53:15 2002 @@ -5,8 +5,8 @@ #if !defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT) -#define lock_kernel() do { } while(0) -#define unlock_kernel() do { } while(0) +#define __lock_kernel() do { } while(0) +#define __unlock_kernel() do { } while(0) #define release_kernel_lock(task, cpu) do { } while(0) #define reacquire_kernel_lock(task) do { } while(0) #define kernel_locked() 1 diff -ur linux-2.5.24-clean/include/linux/spinlock.h linux/include/linux/spinlock.h --- linux-2.5.24-clean/include/linux/spinlock.h Thu Jun 20 15:53:52 2002 +++ linux/include/linux/spinlock.h Fri Jun 28 21:40:44 2002 @@ -197,6 +197,91 @@ #define write_trylock(lock) _raw_write_trylock(lock) #endif +#ifdef CONFIG_DEBUG_BKL +/* + * This will increase size of task_struct by + * MAX_LOCK_RECURSION*sizeof(lock_trace) + * + * the longest filename that I can find is 28 + * KBUILD_BASENAME is 2 shorter than that + * find -name '*.[ch]' | awk -F/ '{print length($(NF)), $NF}' | sort -n + */ +#define MAX_LOCK_TRACE_DEPTH 16 +struct lock_trace { + char func_name[32]; + unsigned int line; +}; + +#define LT_ENTRY(i) (current->lt[(i)]) +#define CURR_LT_ENTRY (LT_ENTRY(current->lock_depth)) +#define LT_LABEL (__stringify(KBUILD_BASENAME)) +#define lock_kernel() \ +do { \ + __lock_kernel(); \ + strncpy(CURR_LT_ENTRY.func_name,LT_LABEL,32); \ + CURR_LT_ENTRY.func_name[31] = '\0'; \ + CURR_LT_ENTRY.line = __LINE__; \ + current->lt_dirty = 1; \ + \ +} while (0) +/* + * er == expect recursive hold, print if that isn't found + */ +#define er_lock_kernel() er_lock_kernel_c(1) +#define er_lock_kernel_c(PRINT_COUNT) \ +do { \ + static int prints_allowed = PRINT_COUNT; \ + if( current->lock_depth == -1 && (prints_allowed-->0)) {\ + printk( "BKL not held, %s:%s:%d\n", \ + (__stringify(KBUILD_BASENAME)), \ + __FUNCTION__, \ + __LINE__ ); \ + } \ + lock_kernel(); \ +} while (0) + +/* + * default number of times to print, and allow overriding it + */ +#define unlock_kernel() unlock_kernel_c(1) + +#define unlock_kernel_c(PRINT_COUNT) \ +do { \ + static int prints_allowed = PRINT_COUNT; \ + int i; \ + if( current->lt_dirty && current->lock_depth > 0 && \ + (prints_allowed-->0) ) { \ + printk( "release of recursive BKL hold, depth: %d\n", \ + current->lock_depth ); \ + for( i=0; \ + current->lt_dirty && i<=current->lock_depth; \ + i++ ) { \ \ + printk( "[%2d]%s:%d\n", i, \ + LT_ENTRY(i).func_name, \ + LT_ENTRY(i).line ); \ + } \ + } \ + current->lt_dirty = 0; \ + __unlock_kernel(); \ +} while (0) +#define unlock_kernel_quiet() \ +do { \ + current->lt_dirty = 0; \ + __unlock_kernel(); \ +} while(0) + +#else +#define MAX_LOCK_TRACE_DEPTH 1 +struct lock_trace {}; +#define lock_kernel() __lock_kernel() +#define lock_kernel_c(x) __lock_kernel() +#define er_lock_kernel_c(x) __lock_kernel() +#define er_lock_kernel() __lock_kernel() +#define unlock_kernel() __unlock_kernel() +#define unlock_kernel_c(x) __unlock_kernel() +#define unlock_kernel_quiet() __unlock_kernel() +#endif + /* "lock on reference count zero" */ #ifndef ATOMIC_DEC_AND_LOCK #include