]> err.no Git - linux-2.6/commitdiff
[PATCH] work around ppc64 bootup bug by making mutex-debugging save/restore irqs
authorIngo Molnar <mingo@elte.hu>
Mon, 26 Jun 2006 07:24:31 +0000 (00:24 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 26 Jun 2006 16:58:16 +0000 (09:58 -0700)
It seems ppc64 wants to lock mutexes in early bootup code, with interrupts
disabled, and they expect interrupts to stay disabled, else they crash.

Work around this bug by making mutex debugging variants save/restore irq
flags.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
kernel/mutex-debug.c
kernel/mutex-debug.h
kernel/mutex.c
kernel/mutex.h

index f4913c3769505a10a0bfd169b6e2ad5c0f25f48c..036b6285b15ccb195848a64e03fa741fd20e8d89 100644 (file)
@@ -153,13 +153,13 @@ next:
                        continue;
                count++;
                cursor = curr->next;
-               debug_spin_lock_restore(&debug_mutex_lock, flags);
+               debug_spin_unlock_restore(&debug_mutex_lock, flags);
 
                printk("\n#%03d:            ", count);
                printk_lock(lock, filter ? 0 : 1);
                goto next;
        }
-       debug_spin_lock_restore(&debug_mutex_lock, flags);
+       debug_spin_unlock_restore(&debug_mutex_lock, flags);
        printk("\n");
 }
 
@@ -316,7 +316,7 @@ void mutex_debug_check_no_locks_held(struct task_struct *task)
                        continue;
                list_del_init(curr);
                DEBUG_OFF();
-               debug_spin_lock_restore(&debug_mutex_lock, flags);
+               debug_spin_unlock_restore(&debug_mutex_lock, flags);
 
                printk("BUG: %s/%d, lock held at task exit time!\n",
                        task->comm, task->pid);
@@ -325,7 +325,7 @@ void mutex_debug_check_no_locks_held(struct task_struct *task)
                        printk("exiting task is not even the owner??\n");
                return;
        }
-       debug_spin_lock_restore(&debug_mutex_lock, flags);
+       debug_spin_unlock_restore(&debug_mutex_lock, flags);
 }
 
 /*
@@ -352,7 +352,7 @@ void mutex_debug_check_no_locks_freed(const void *from, unsigned long len)
                        continue;
                list_del_init(curr);
                DEBUG_OFF();
-               debug_spin_lock_restore(&debug_mutex_lock, flags);
+               debug_spin_unlock_restore(&debug_mutex_lock, flags);
 
                printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n",
                        current->comm, current->pid, lock, from, to);
@@ -362,7 +362,7 @@ void mutex_debug_check_no_locks_freed(const void *from, unsigned long len)
                        printk("freeing task is not even the owner??\n");
                return;
        }
-       debug_spin_lock_restore(&debug_mutex_lock, flags);
+       debug_spin_unlock_restore(&debug_mutex_lock, flags);
 }
 
 /*
index fd384050acb1b7933ac414774cdf5aa4ae49fb48..a5196c36a5fdce7f21cfd5e56ea9e84720961261 100644 (file)
@@ -46,21 +46,6 @@ extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
 extern void debug_mutex_unlock(struct mutex *lock);
 extern void debug_mutex_init(struct mutex *lock, const char *name);
 
-#define debug_spin_lock(lock)                          \
-       do {                                            \
-               local_irq_disable();                    \
-               if (debug_mutex_on)                     \
-                       spin_lock(lock);                \
-       } while (0)
-
-#define debug_spin_unlock(lock)                                \
-       do {                                            \
-               if (debug_mutex_on)                     \
-                       spin_unlock(lock);              \
-               local_irq_enable();                     \
-               preempt_check_resched();                \
-       } while (0)
-
 #define debug_spin_lock_save(lock, flags)              \
        do {                                            \
                local_irq_save(flags);                  \
@@ -68,7 +53,7 @@ extern void debug_mutex_init(struct mutex *lock, const char *name);
                        spin_lock(lock);                \
        } while (0)
 
-#define debug_spin_lock_restore(lock, flags)           \
+#define debug_spin_unlock_restore(lock, flags)         \
        do {                                            \
                if (debug_mutex_on)                     \
                        spin_unlock(lock);              \
@@ -76,20 +61,20 @@ extern void debug_mutex_init(struct mutex *lock, const char *name);
                preempt_check_resched();                \
        } while (0)
 
-#define spin_lock_mutex(lock)                          \
+#define spin_lock_mutex(lock, flags)                   \
        do {                                            \
                struct mutex *l = container_of(lock, struct mutex, wait_lock); \
                                                        \
                DEBUG_WARN_ON(in_interrupt());          \
-               debug_spin_lock(&debug_mutex_lock);     \
+               debug_spin_lock_save(&debug_mutex_lock, flags); \
                spin_lock(lock);                        \
                DEBUG_WARN_ON(l->magic != l);           \
        } while (0)
 
-#define spin_unlock_mutex(lock)                                \
+#define spin_unlock_mutex(lock, flags)                 \
        do {                                            \
                spin_unlock(lock);                      \
-               debug_spin_unlock(&debug_mutex_lock);   \
+               debug_spin_unlock_restore(&debug_mutex_lock, flags);    \
        } while (0)
 
 #define DEBUG_OFF()                                    \
index 5449b210d9edb1aaf4be340730a47e07d1756edf..7043db21bbce208b098aa60e100ca2c8e0d86009 100644 (file)
@@ -125,10 +125,11 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__)
        struct task_struct *task = current;
        struct mutex_waiter waiter;
        unsigned int old_val;
+       unsigned long flags;
 
        debug_mutex_init_waiter(&waiter);
 
-       spin_lock_mutex(&lock->wait_lock);
+       spin_lock_mutex(&lock->wait_lock, flags);
 
        debug_mutex_add_waiter(lock, &waiter, task->thread_info, ip);
 
@@ -157,7 +158,7 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__)
                if (unlikely(state == TASK_INTERRUPTIBLE &&
                                                signal_pending(task))) {
                        mutex_remove_waiter(lock, &waiter, task->thread_info);
-                       spin_unlock_mutex(&lock->wait_lock);
+                       spin_unlock_mutex(&lock->wait_lock, flags);
 
                        debug_mutex_free_waiter(&waiter);
                        return -EINTR;
@@ -165,9 +166,9 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__)
                __set_task_state(task, state);
 
                /* didnt get the lock, go to sleep: */
-               spin_unlock_mutex(&lock->wait_lock);
+               spin_unlock_mutex(&lock->wait_lock, flags);
                schedule();
-               spin_lock_mutex(&lock->wait_lock);
+               spin_lock_mutex(&lock->wait_lock, flags);
        }
 
        /* got the lock - rejoice! */
@@ -178,7 +179,7 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__)
        if (likely(list_empty(&lock->wait_list)))
                atomic_set(&lock->count, 0);
 
-       spin_unlock_mutex(&lock->wait_lock);
+       spin_unlock_mutex(&lock->wait_lock, flags);
 
        debug_mutex_free_waiter(&waiter);
 
@@ -203,10 +204,11 @@ static fastcall noinline void
 __mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__)
 {
        struct mutex *lock = container_of(lock_count, struct mutex, count);
+       unsigned long flags;
 
        DEBUG_WARN_ON(lock->owner != current_thread_info());
 
-       spin_lock_mutex(&lock->wait_lock);
+       spin_lock_mutex(&lock->wait_lock, flags);
 
        /*
         * some architectures leave the lock unlocked in the fastpath failure
@@ -231,7 +233,7 @@ __mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__)
 
        debug_mutex_clear_owner(lock);
 
-       spin_unlock_mutex(&lock->wait_lock);
+       spin_unlock_mutex(&lock->wait_lock, flags);
 }
 
 /*
@@ -276,9 +278,10 @@ __mutex_lock_interruptible_slowpath(atomic_t *lock_count __IP_DECL__)
 static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
 {
        struct mutex *lock = container_of(lock_count, struct mutex, count);
+       unsigned long flags;
        int prev;
 
-       spin_lock_mutex(&lock->wait_lock);
+       spin_lock_mutex(&lock->wait_lock, flags);
 
        prev = atomic_xchg(&lock->count, -1);
        if (likely(prev == 1))
@@ -287,7 +290,7 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
        if (likely(list_empty(&lock->wait_list)))
                atomic_set(&lock->count, 0);
 
-       spin_unlock_mutex(&lock->wait_lock);
+       spin_unlock_mutex(&lock->wait_lock, flags);
 
        return prev == 1;
 }
index 00fe84e7b672ba39e1fb86648511aba53c76a514..06918994725726cec4e0f98456d391a821258d49 100644 (file)
@@ -9,8 +9,10 @@
  * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs:
  */
 
-#define spin_lock_mutex(lock)                  spin_lock(lock)
-#define spin_unlock_mutex(lock)                        spin_unlock(lock)
+#define spin_lock_mutex(lock, flags) \
+               do { spin_lock(lock); (void)(flags); } while (0)
+#define spin_unlock_mutex(lock, flags) \
+               do { spin_unlock(lock); (void)(flags); } while (0)
 #define mutex_remove_waiter(lock, waiter, ti) \
                __list_del((waiter)->list.prev, (waiter)->list.next)