diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 6ef18a8..3b8a1a5 100644 Index: linux-2.6.10/include/linux/interrupt.h =================================================================== --- linux-2.6.10.orig/include/linux/interrupt.h 2006-03-16 13:55:17.000000000 +0100 +++ linux-2.6.10/include/linux/interrupt.h 2006-03-16 13:55:42.000000000 +0100 @@ -68,11 +68,17 @@ # define save_and_cli(x) local_irq_save(x) #endif +void push_bh_user(void *); +void pop_bh_user(void); +void print_bh_user(void); + /* SoftIRQ primitives. */ #define local_bh_disable() \ - do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0) + do { preempt_count() += SOFTIRQ_OFFSET; barrier(); \ + push_bh_user(current_text_addr()); } while (0) #define __local_bh_enable() \ - do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0) + do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; \ + pop_bh_user(); } while (0) extern void local_bh_enable(void); Index: linux-2.6.10/kernel/sched.c =================================================================== --- linux-2.6.10.orig/kernel/sched.c 2006-03-16 13:55:39.000000000 +0100 +++ linux-2.6.10/kernel/sched.c 2006-03-16 13:55:42.000000000 +0100 @@ -2545,6 +2545,7 @@ printk(KERN_ERR "scheduling while atomic: " "%s/0x%08x/%d\n", current->comm, preempt_count(), current->pid); + print_bh_user(); dump_stack(); } } Index: linux-2.6.10/kernel/softirq.c =================================================================== --- linux-2.6.10.orig/kernel/softirq.c 2006-03-16 13:55:17.000000000 +0100 +++ linux-2.6.10/kernel/softirq.c 2006-03-16 14:21:50.993331232 +0100 @@ -135,6 +135,43 @@ #endif +static void *local_bh_user[NR_CPUS][32]; +static atomic_t bh_user_cnt[NR_CPUS]; + + +void +push_bh_user(void *addr) +{ + int cpu = smp_processor_id(); + + local_bh_user[cpu][atomic_inc_return(&bh_user_cnt[cpu])] = addr; +} + +EXPORT_SYMBOL(push_bh_user); + + +void +pop_bh_user(void) +{ + atomic_dec(&bh_user_cnt[smp_processor_id()]); +} + +EXPORT_SYMBOL(pop_bh_user); + + +void +print_bh_user(void) +{ + int cpu = smp_processor_id(); + int i = atomic_read(&bh_user_cnt[cpu]); + + while (i >= 0) + printk("bh_users: %p\n", local_bh_user[cpu][i--]); +} + +EXPORT_SYMBOL(print_bh_user); + + void local_bh_enable(void) { WARN_ON(irqs_disabled()); @@ -144,6 +181,8 @@ */ preempt_count() -= SOFTIRQ_OFFSET - 1; + pop_bh_user(); + if (unlikely(!in_interrupt() && local_softirq_pending())) do_softirq();