Pull locking updates from Ingo Molnar: - improve rwsem scalability - add uninitialized rwsem debugging check - reduce lockdep's stacktrace memory usage and add diagnostics - misc cleanups, code consolidation and constification * 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: mutex: Fix up mutex_waiter usage locking/mutex: Use mutex flags macro instead of hard code locking/mutex: Make __mutex_owner static to mutex.c locking/qspinlock,x86: Clarify virt_spin_lock_key locking/rwsem: Check for operations on an uninitialized rwsem locking/rwsem: Make handoff writer optimistically spin on owner locking/lockdep: Report more stack trace statistics locking/lockdep: Reduce space occupied by stack traces stacktrace: Constify 'entries' arguments locking/lockdep: Make it clear that what lock_class::key points at is not modified
Showing the changes to include/linux (4 of 11 files). Show all
Unified · Split
| @@ -66,10 +66,7 @@ struct lock_class_key { · 65 unmodified lines | |||
| 66 | 66 | ||
| 67 | extern struct lock_class_key __lockdep_no_validate__; | 67 | extern struct lock_class_key __lockdep_no_validate__; |
| 68 | 68 | ||
| 69 | struct lock_trace { | 69 | struct lock_trace; |
| 70 | unsigned int nr_entries; | ||
| 71 | unsigned int offset; | ||
| 72 | }; | ||
| 73 | 70 | ||
| 74 | #define LOCKSTAT_POINTS 4 | 71 | #define LOCKSTAT_POINTS 4 |
| 75 | 72 | ||
| @@ -97,7 +94,7 @@ struct lock_class { · 21 unmodified lines | |||
| 97 | */ | 94 | */ |
| 98 | struct list_head locks_after, locks_before; | 95 | struct list_head locks_after, locks_before; |
| 99 | 96 | ||
| 100 | struct lockdep_subclass_key *key; | 97 | const struct lockdep_subclass_key *key; |
| 101 | unsigned int subclass; | 98 | unsigned int subclass; |
| 102 | unsigned int dep_gen_id; | 99 | unsigned int dep_gen_id; |
| 103 | 100 | ||
| @@ -105,7 +102,7 @@ struct lock_class { · 1 unmodified line | |||
| 105 | * IRQ/softirq usage tracking bits: | 102 | * IRQ/softirq usage tracking bits: |
| 106 | */ | 103 | */ |
| 107 | unsigned long usage_mask; | 104 | unsigned long usage_mask; |
| 108 | struct lock_trace usage_traces[XXX_LOCK_USAGE_STATES]; | 105 | const struct lock_trace *usage_traces[XXX_LOCK_USAGE_STATES]; |
| 109 | 106 | ||
| 110 | /* | 107 | /* |
| 111 | * Generation counter, when doing certain classes of graph walking, | 108 | * Generation counter, when doing certain classes of graph walking, |
| @@ -193,7 +190,7 @@ struct lock_list { · 81 unmodified lines | |||
| 193 | struct list_head entry; | 190 | struct list_head entry; |
| 194 | struct lock_class *class; | 191 | struct lock_class *class; |
| 195 | struct lock_class *links_to; | 192 | struct lock_class *links_to; |
| 196 | struct lock_trace trace; | 193 | const struct lock_trace *trace; |
| 197 | int distance; | 194 | int distance; |
| 198 | 195 | ||
| 199 | /* | 196 | /* |
| @@ -65,16 +65,6 @@ struct mutex { · 64 unmodified lines | |||
| 65 | #endif | 65 | #endif |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | /* | ||
| 69 | * Internal helper function; C doesn't allow us to hide it :/ | ||
| 70 | * | ||
| 71 | * DO NOT USE (outside of mutex code). | ||
| 72 | */ | ||
| 73 | static inline struct task_struct *__mutex_owner(struct mutex *lock) | ||
| 74 | { | ||
| 75 | return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07); | ||
| 76 | } | ||
| 77 | |||
| 78 | /* | 68 | /* |
| 79 | * This is the control structure for tasks blocked on mutex, | 69 | * This is the control structure for tasks blocked on mutex, |
| 80 | * which resides on the blocked task's kernel stack: | 70 | * which resides on the blocked task's kernel stack: |
| @@ -144,10 +134,7 @@ extern void __mutex_init(struct mutex *lock, const char *name, · 63 unmodified lines | |||
| 144 | * | 134 | * |
| 145 | * Returns true if the mutex is locked, false if unlocked. | 135 | * Returns true if the mutex is locked, false if unlocked. |
| 146 | */ | 136 | */ |
| 147 | static inline bool mutex_is_locked(struct mutex *lock) | 137 | extern bool mutex_is_locked(struct mutex *lock); |
| 148 | { | ||
| 149 | return __mutex_owner(lock) != NULL; | ||
| 150 | } | ||
| 151 | 138 | ||
| 152 | /* | 139 | /* |
| 153 | * See kernel/locking/mutex.c for detailed documentation of these APIs. | 140 | * See kernel/locking/mutex.c for detailed documentation of these APIs. |
| @@ -220,13 +207,7 @@ enum mutex_trylock_recursive_enum { · 66 unmodified lines | |||
| 220 | * - MUTEX_TRYLOCK_SUCCESS - lock acquired, | 207 | * - MUTEX_TRYLOCK_SUCCESS - lock acquired, |
| 221 | * - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock. | 208 | * - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock. |
| 222 | */ | 209 | */ |
| 223 | static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum | 210 | extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum |
| 224 | mutex_trylock_recursive(struct mutex *lock) | 211 | mutex_trylock_recursive(struct mutex *lock); |
| 225 | { | ||
| 226 | if (unlikely(__mutex_owner(lock) == current)) | ||
| 227 | return MUTEX_TRYLOCK_RECURSIVE; | ||
| 228 | |||
| 229 | return mutex_trylock(lock); | ||
| 230 | } | ||
| 231 | 212 | ||
| 232 | #endif /* __LINUX_MUTEX_H */ | 213 | #endif /* __LINUX_MUTEX_H */ |
| @@ -45,6 +45,9 @@ struct rw_semaphore { · 44 unmodified lines | |||
| 45 | #endif | 45 | #endif |
| 46 | raw_spinlock_t wait_lock; | 46 | raw_spinlock_t wait_lock; |
| 47 | struct list_head wait_list; | 47 | struct list_head wait_list; |
| 48 | #ifdef CONFIG_DEBUG_RWSEMS | ||
| 49 | void *magic; | ||
| 50 | #endif | ||
| 48 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 51 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 49 | struct lockdep_map dep_map; | 52 | struct lockdep_map dep_map; |
| 50 | #endif | 53 | #endif |
| @@ -73,6 +76,12 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) · 22 unmodified lines | |||
| 73 | # define __RWSEM_DEP_MAP_INIT(lockname) | 76 | # define __RWSEM_DEP_MAP_INIT(lockname) |
| 74 | #endif | 77 | #endif |
| 75 | 78 | ||
| 79 | #ifdef CONFIG_DEBUG_RWSEMS | ||
| 80 | # define __DEBUG_RWSEM_INITIALIZER(lockname) , .magic = &lockname | ||
| 81 | #else | ||
| 82 | # define __DEBUG_RWSEM_INITIALIZER(lockname) | ||
| 83 | #endif | ||
| 84 | |||
| 76 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER | 85 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
| 77 | #define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED | 86 | #define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED |
| 78 | #else | 87 | #else |
| @@ -85,6 +94,7 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) · 6 unmodified lines | |||
| 85 | .wait_list = LIST_HEAD_INIT((name).wait_list), \ | 94 | .wait_list = LIST_HEAD_INIT((name).wait_list), \ |
| 86 | .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \ | 95 | .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \ |
| 87 | __RWSEM_OPT_INIT(name) \ | 96 | __RWSEM_OPT_INIT(name) \ |
| 97 | __DEBUG_RWSEM_INITIALIZER(name) \ | ||
| 88 | __RWSEM_DEP_MAP_INIT(name) } | 98 | __RWSEM_DEP_MAP_INIT(name) } |
| 89 | 99 | ||
| 90 | #define DECLARE_RWSEM(name) \ | 100 | #define DECLARE_RWSEM(name) \ |
| @@ -9,9 +9,9 @@ struct task_struct; · 8 unmodified lines | |||
| 9 | struct pt_regs; | 9 | struct pt_regs; |
| 10 | 10 | ||
| 11 | #ifdef CONFIG_STACKTRACE | 11 | #ifdef CONFIG_STACKTRACE |
| 12 | void stack_trace_print(unsigned long *trace, unsigned int nr_entries, | 12 | void stack_trace_print(const unsigned long *trace, unsigned int nr_entries, |
| 13 | int spaces); | 13 | int spaces); |
| 14 | int stack_trace_snprint(char *buf, size_t size, unsigned long *entries, | 14 | int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries, |
| 15 | unsigned int nr_entries, int spaces); | 15 | unsigned int nr_entries, int spaces); |
| 16 | unsigned int stack_trace_save(unsigned long *store, unsigned int size, | 16 | unsigned int stack_trace_save(unsigned long *store, unsigned int size, |
| 17 | unsigned int skipnr); | 17 | unsigned int skipnr); |