]> git.hungrycats.org Git - linux/commitdiff
[PATCH] increase traffic on linux-kernel
authorAndrew Morton <akpm@digeo.com>
Wed, 25 Sep 2002 14:20:23 +0000 (07:20 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Wed, 25 Sep 2002 14:20:23 +0000 (07:20 -0700)
[This has four scalps already.  Thomas Molina has agreed
 to track things as they are identified ]

Infrastructure to detect sleep-inside-spinlock bugs.  Really only
useful if compiled with CONFIG_PREEMPT=y.  It prints out a whiny
message and a stack backtrace if someone calls a function which might
sleep from within an atomic region.

This patch generates a storm of output at boot, due to
drivers/ide/ide-probe.c:init_irq() calling lots of things which it
shouldn't under ide_lock.

It'll find other bugs too.

include/asm-i386/semaphore.h
include/linux/kernel.h
include/linux/rwsem.h
kernel/ksyms.c
kernel/sched.c
mm/page_alloc.c
mm/slab.c

index a0ce1b8dba69ad9167039901372027c897a228f7..9c456727e8a3ed31a6a68f5ae06d5bb209adc78b 100644 (file)
@@ -116,7 +116,7 @@ static inline void down(struct semaphore * sem)
 #if WAITQUEUE_DEBUG
        CHECK_MAGIC(sem->__magic);
 #endif
-
+       might_sleep();
        __asm__ __volatile__(
                "# atomic down operation\n\t"
                LOCK "decl %0\n\t"     /* --sem->count */
@@ -142,7 +142,7 @@ static inline int down_interruptible(struct semaphore * sem)
 #if WAITQUEUE_DEBUG
        CHECK_MAGIC(sem->__magic);
 #endif
-
+       might_sleep();
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
                LOCK "decl %1\n\t"     /* --sem->count */
index 5efa540d55f87190db9d520b063ab628bbc47140..44c38b134498b59a277fea76d72f210cd1523a12 100644 (file)
 
 struct completion;
 
+#ifdef CONFIG_DEBUG_KERNEL
+void __might_sleep(char *file, int line);
+#define might_sleep() __might_sleep(__FILE__, __LINE__)
+#else
+#define might_sleep() do {} while(0)
+#endif
+
 extern struct notifier_block *panic_notifier_list;
 NORET_TYPE void panic(const char * fmt, ...)
        __attribute__ ((NORET_AND format (printf, 1, 2)));
index 4a7e2bb0d7c4585858ae011be96b18c04c36525d..bfb98888500290d3c945f93e2f544de1384bcacb 100644 (file)
@@ -40,6 +40,7 @@ extern void FASTCALL(rwsemtrace(struct rw_semaphore *sem, const char *str));
  */
 static inline void down_read(struct rw_semaphore *sem)
 {
+       might_sleep();
        rwsemtrace(sem,"Entering down_read");
        __down_read(sem);
        rwsemtrace(sem,"Leaving down_read");
@@ -62,6 +63,7 @@ static inline int down_read_trylock(struct rw_semaphore *sem)
  */
 static inline void down_write(struct rw_semaphore *sem)
 {
+       might_sleep();
        rwsemtrace(sem,"Entering down_write");
        __down_write(sem);
        rwsemtrace(sem,"Leaving down_write");
index cd69b97e8e9d1affc03a16ae53f89ba583465227..0409fc676f291c0dd4009267fd84526e7b43608b 100644 (file)
@@ -497,7 +497,9 @@ EXPORT_SYMBOL(jiffies_64);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(do_settimeofday);
-
+#ifdef CONFIG_DEBUG_KERNEL
+EXPORT_SYMBOL(__might_sleep);
+#endif
 #if !defined(__ia64__)
 EXPORT_SYMBOL(loops_per_jiffy);
 #endif
index 304f90fd4bdf2a18d3318ed58285318d1adca62b..9965e5f7549e766ddac8454794c52d508815900c 100644 (file)
@@ -2150,3 +2150,20 @@ void __init sched_init(void)
        enter_lazy_tlb(&init_mm, current, smp_processor_id());
 }
 
+#ifdef CONFIG_DEBUG_KERNEL
+void __might_sleep(char *file, int line)
+{
+#if defined(in_atomic)
+       static unsigned long prev_jiffy;        /* ratelimiting */
+
+       if (in_atomic()) {
+               if (time_before(jiffies, prev_jiffy + HZ))
+                       return;
+               prev_jiffy = jiffies;
+               printk("Sleeping function called from illegal"
+                               " context at %s:%d\n", file, line);
+               dump_stack();
+       }
+#endif
+}
+#endif
index a1cce719581d70f6a7255f9f8f3f1f65655689c7..ab3284a3b78aab413e6118863e8449c65c90fa71 100644 (file)
@@ -321,6 +321,9 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
        struct page * page;
        int freed, i;
 
+       if (gfp_mask & __GFP_WAIT)
+               might_sleep();
+
        KERNEL_STAT_ADD(pgalloc, 1<<order);
 
        zones = zonelist->zones;  /* the list of zones suitable for gfp_mask */
index 962598c0b1b76d39ecbd5fa8e1fcb25aec6cc224..a6bd0a98734bec7c0fa8b3619a14a7d3e60d74f6 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1370,6 +1370,9 @@ static inline void * __kmem_cache_alloc (kmem_cache_t *cachep, int flags)
        unsigned long save_flags;
        void* objp;
 
+       if (flags & __GFP_WAIT)
+               might_sleep();
+
        kmem_cache_alloc_head(cachep, flags);
 try_again:
        local_irq_save(save_flags);