diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/mutex-debug.c | 6 | ||||
| -rw-r--r-- | kernel/mutex.c | 28 | ||||
| -rw-r--r-- | kernel/mutex.h | 2 |
3 files changed, 28 insertions, 8 deletions
diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c index 5569766a1ea2..e3203c654dda 100644 --- a/kernel/mutex-debug.c +++ b/kernel/mutex-debug.c | |||
| @@ -83,12 +83,16 @@ void debug_mutex_unlock(struct mutex *lock) | |||
| 83 | DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info()); | 83 | DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info()); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | void debug_mutex_init(struct mutex *lock, const char *name) | 86 | void debug_mutex_init(struct mutex *lock, const char *name, |
| 87 | struct lock_class_key *key) | ||
| 87 | { | 88 | { |
| 89 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 88 | /* | 90 | /* |
| 89 | * Make sure we are not reinitializing a held lock: | 91 | * Make sure we are not reinitializing a held lock: |
| 90 | */ | 92 | */ |
| 91 | debug_check_no_locks_freed((void *)lock, sizeof(*lock)); | 93 | debug_check_no_locks_freed((void *)lock, sizeof(*lock)); |
| 94 | lockdep_init_map(&lock->dep_map, name, key); | ||
| 95 | #endif | ||
| 92 | lock->owner = NULL; | 96 | lock->owner = NULL; |
| 93 | lock->magic = lock; | 97 | lock->magic = lock; |
| 94 | } | 98 | } |
diff --git a/kernel/mutex.c b/kernel/mutex.c index 43a50c18701a..8c71cf72a497 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c | |||
| @@ -39,13 +39,14 @@ | |||
| 39 | * | 39 | * |
| 40 | * It is not allowed to initialize an already locked mutex. | 40 | * It is not allowed to initialize an already locked mutex. |
| 41 | */ | 41 | */ |
| 42 | __always_inline void fastcall __mutex_init(struct mutex *lock, const char *name) | 42 | void |
| 43 | __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) | ||
| 43 | { | 44 | { |
| 44 | atomic_set(&lock->count, 1); | 45 | atomic_set(&lock->count, 1); |
| 45 | spin_lock_init(&lock->wait_lock); | 46 | spin_lock_init(&lock->wait_lock); |
| 46 | INIT_LIST_HEAD(&lock->wait_list); | 47 | INIT_LIST_HEAD(&lock->wait_list); |
| 47 | 48 | ||
| 48 | debug_mutex_init(lock, name); | 49 | debug_mutex_init(lock, name, key); |
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | EXPORT_SYMBOL(__mutex_init); | 52 | EXPORT_SYMBOL(__mutex_init); |
| @@ -131,6 +132,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | |||
| 131 | spin_lock_mutex(&lock->wait_lock, flags); | 132 | spin_lock_mutex(&lock->wait_lock, flags); |
| 132 | 133 | ||
| 133 | debug_mutex_lock_common(lock, &waiter); | 134 | debug_mutex_lock_common(lock, &waiter); |
| 135 | mutex_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | ||
| 134 | debug_mutex_add_waiter(lock, &waiter, task->thread_info); | 136 | debug_mutex_add_waiter(lock, &waiter, task->thread_info); |
| 135 | 137 | ||
| 136 | /* add waiting tasks to the end of the waitqueue (FIFO): */ | 138 | /* add waiting tasks to the end of the waitqueue (FIFO): */ |
| @@ -158,6 +160,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | |||
| 158 | if (unlikely(state == TASK_INTERRUPTIBLE && | 160 | if (unlikely(state == TASK_INTERRUPTIBLE && |
| 159 | signal_pending(task))) { | 161 | signal_pending(task))) { |
| 160 | mutex_remove_waiter(lock, &waiter, task->thread_info); | 162 | mutex_remove_waiter(lock, &waiter, task->thread_info); |
| 163 | mutex_release(&lock->dep_map, 1, _RET_IP_); | ||
| 161 | spin_unlock_mutex(&lock->wait_lock, flags); | 164 | spin_unlock_mutex(&lock->wait_lock, flags); |
| 162 | 165 | ||
| 163 | debug_mutex_free_waiter(&waiter); | 166 | debug_mutex_free_waiter(&waiter); |
| @@ -194,16 +197,28 @@ __mutex_lock_slowpath(atomic_t *lock_count) | |||
| 194 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0); | 197 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0); |
| 195 | } | 198 | } |
| 196 | 199 | ||
| 200 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 201 | void __sched | ||
| 202 | mutex_lock_nested(struct mutex *lock, unsigned int subclass) | ||
| 203 | { | ||
| 204 | might_sleep(); | ||
| 205 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass); | ||
| 206 | } | ||
| 207 | |||
| 208 | EXPORT_SYMBOL_GPL(mutex_lock_nested); | ||
| 209 | #endif | ||
| 210 | |||
| 197 | /* | 211 | /* |
| 198 | * Release the lock, slowpath: | 212 | * Release the lock, slowpath: |
| 199 | */ | 213 | */ |
| 200 | static fastcall inline void | 214 | static fastcall inline void |
| 201 | __mutex_unlock_common_slowpath(atomic_t *lock_count) | 215 | __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested) |
| 202 | { | 216 | { |
| 203 | struct mutex *lock = container_of(lock_count, struct mutex, count); | 217 | struct mutex *lock = container_of(lock_count, struct mutex, count); |
| 204 | unsigned long flags; | 218 | unsigned long flags; |
| 205 | 219 | ||
| 206 | spin_lock_mutex(&lock->wait_lock, flags); | 220 | spin_lock_mutex(&lock->wait_lock, flags); |
| 221 | mutex_release(&lock->dep_map, nested, _RET_IP_); | ||
| 207 | debug_mutex_unlock(lock); | 222 | debug_mutex_unlock(lock); |
| 208 | 223 | ||
| 209 | /* | 224 | /* |
| @@ -236,7 +251,7 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count) | |||
| 236 | static fastcall noinline void | 251 | static fastcall noinline void |
| 237 | __mutex_unlock_slowpath(atomic_t *lock_count) | 252 | __mutex_unlock_slowpath(atomic_t *lock_count) |
| 238 | { | 253 | { |
| 239 | __mutex_unlock_common_slowpath(lock_count); | 254 | __mutex_unlock_common_slowpath(lock_count, 1); |
| 240 | } | 255 | } |
| 241 | 256 | ||
| 242 | /* | 257 | /* |
| @@ -287,9 +302,10 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count) | |||
| 287 | spin_lock_mutex(&lock->wait_lock, flags); | 302 | spin_lock_mutex(&lock->wait_lock, flags); |
| 288 | 303 | ||
| 289 | prev = atomic_xchg(&lock->count, -1); | 304 | prev = atomic_xchg(&lock->count, -1); |
| 290 | if (likely(prev == 1)) | 305 | if (likely(prev == 1)) { |
| 291 | debug_mutex_set_owner(lock, current_thread_info()); | 306 | debug_mutex_set_owner(lock, current_thread_info()); |
| 292 | 307 | mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_); | |
| 308 | } | ||
| 293 | /* Set it back to 0 if there are no waiters: */ | 309 | /* Set it back to 0 if there are no waiters: */ |
| 294 | if (likely(list_empty(&lock->wait_list))) | 310 | if (likely(list_empty(&lock->wait_list))) |
| 295 | atomic_set(&lock->count, 0); | 311 | atomic_set(&lock->count, 0); |
diff --git a/kernel/mutex.h b/kernel/mutex.h index aeb2d916aa0e..a075dafbb290 100644 --- a/kernel/mutex.h +++ b/kernel/mutex.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #define debug_mutex_free_waiter(waiter) do { } while (0) | 22 | #define debug_mutex_free_waiter(waiter) do { } while (0) |
| 23 | #define debug_mutex_add_waiter(lock, waiter, ti) do { } while (0) | 23 | #define debug_mutex_add_waiter(lock, waiter, ti) do { } while (0) |
| 24 | #define debug_mutex_unlock(lock) do { } while (0) | 24 | #define debug_mutex_unlock(lock) do { } while (0) |
| 25 | #define debug_mutex_init(lock, name) do { } while (0) | 25 | #define debug_mutex_init(lock, name, key) do { } while (0) |
| 26 | 26 | ||
| 27 | static inline void | 27 | static inline void |
| 28 | debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter) | 28 | debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter) |
