| /* | |
| * Mutexes: blocking mutual exclusion locks | |
| * | |
| * started by Ingo Molnar: | |
| * | |
| * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> | |
| * | |
| * This file contains mutex debugging related internal declarations, | |
| * prototypes and inline functions, for the CONFIG_DEBUG_MUTEXES case. | |
| * More details are in kernel/mutex-debug.c. | |
| */ | |
| extern spinlock_t debug_mutex_lock; | |
| extern struct list_head debug_mutex_held_locks; | |
| extern int debug_mutex_on; | |
| /* | |
| * In the debug case we carry the caller's instruction pointer into | |
| * other functions, but we dont want the function argument overhead | |
| * in the nondebug case - hence these macros: | |
| */ | |
| #define __IP_DECL__ , unsigned long ip | |
| #define __IP__ , ip | |
| #define __RET_IP__ , (unsigned long)__builtin_return_address(0) | |
| /* | |
| * This must be called with lock->wait_lock held. | |
| */ | |
| extern void debug_mutex_set_owner(struct mutex *lock, | |
| struct thread_info *new_owner __IP_DECL__); | |
| static inline void debug_mutex_clear_owner(struct mutex *lock) | |
| { | |
| lock->owner = NULL; | |
| } | |
| extern void debug_mutex_init_waiter(struct mutex_waiter *waiter); | |
| extern void debug_mutex_wake_waiter(struct mutex *lock, | |
| struct mutex_waiter *waiter); | |
| extern void debug_mutex_free_waiter(struct mutex_waiter *waiter); | |
| extern void debug_mutex_add_waiter(struct mutex *lock, | |
| struct mutex_waiter *waiter, | |
| struct thread_info *ti __IP_DECL__); | |
| extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, | |
| struct thread_info *ti); | |
| 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); \ | |
| if (debug_mutex_on) \ | |
| spin_lock(lock); \ | |
| } while (0) | |
| #define debug_spin_lock_restore(lock, flags) \ | |
| do { \ | |
| if (debug_mutex_on) \ | |
| spin_unlock(lock); \ | |
| local_irq_restore(flags); \ | |
| preempt_check_resched(); \ | |
| } while (0) | |
| #define spin_lock_mutex(lock) \ | |
| do { \ | |
| struct mutex *l = container_of(lock, struct mutex, wait_lock); \ | |
| \ | |
| DEBUG_WARN_ON(in_interrupt()); \ | |
| debug_spin_lock(&debug_mutex_lock); \ | |
| spin_lock(lock); \ | |
| DEBUG_WARN_ON(l->magic != l); \ | |
| } while (0) | |
| #define spin_unlock_mutex(lock) \ | |
| do { \ | |
| spin_unlock(lock); \ | |
| debug_spin_unlock(&debug_mutex_lock); \ | |
| } while (0) | |
| #define DEBUG_OFF() \ | |
| do { \ | |
| if (debug_mutex_on) { \ | |
| debug_mutex_on = 0; \ | |
| console_verbose(); \ | |
| if (spin_is_locked(&debug_mutex_lock)) \ | |
| spin_unlock(&debug_mutex_lock); \ | |
| } \ | |
| } while (0) | |
| #define DEBUG_BUG() \ | |
| do { \ | |
| if (debug_mutex_on) { \ | |
| DEBUG_OFF(); \ | |
| BUG(); \ | |
| } \ | |
| } while (0) | |
| #define DEBUG_WARN_ON(c) \ | |
| do { \ | |
| if (unlikely(c && debug_mutex_on)) { \ | |
| DEBUG_OFF(); \ | |
| WARN_ON(1); \ | |
| } \ | |
| } while (0) | |
| # define DEBUG_BUG_ON(c) \ | |
| do { \ | |
| if (unlikely(c)) \ | |
| DEBUG_BUG(); \ | |
| } while (0) | |
| #ifdef CONFIG_SMP | |
| # define SMP_DEBUG_WARN_ON(c) DEBUG_WARN_ON(c) | |
| # define SMP_DEBUG_BUG_ON(c) DEBUG_BUG_ON(c) | |
| #else | |
| # define SMP_DEBUG_WARN_ON(c) do { } while (0) | |
| # define SMP_DEBUG_BUG_ON(c) do { } while (0) | |
| #endif | |