diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-19 12:27:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-19 12:27:55 -0400 |
commit | d057190925d994b808e1d07e6c76b90a32caac77 (patch) | |
tree | 1f2d104f879435881d77f0d8d1e48c3224264d53 | |
parent | d1743b810d7a306d1dd837e086d18124bc38b575 (diff) | |
parent | 9de8033f1bbcce5ed23fe5da9ca1a5060207f7ed (diff) |
Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fixes from Thomas Gleixner:
"The locking department delivers:
- A rather large and intrusive bundle of fixes to address serious
performance regressions introduced by the new rwsem / mcs
technology. Simpler solutions have been discussed, but they would
have been ugly bandaids with more risk than doing the right thing.
- Make the rwsem spin on owner technology opt-in for architectures
and enable it only on the known to work ones.
- A few fixes to the lockdep userspace library"
* 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
locking/rwsem: Add CONFIG_RWSEM_SPIN_ON_OWNER
locking/mutex: Disable optimistic spinning on some architectures
locking/rwsem: Reduce the size of struct rw_semaphore
locking/rwsem: Rename 'activity' to 'count'
locking/spinlocks/mcs: Micro-optimize osq_unlock()
locking/spinlocks/mcs: Introduce and use init macro and function for osq locks
locking/spinlocks/mcs: Convert osq lock to atomic_t to reduce overhead
locking/spinlocks/mcs: Rename optimistic_spin_queue() to optimistic_spin_node()
locking/rwsem: Allow conservative optimistic spinning when readers have lock
tools/liblockdep: Account for bitfield changes in lockdeps lock_acquire
tools/liblockdep: Remove debug print left over from development
tools/liblockdep: Fix comparison of a boolean value with a value of 2
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm64/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
-rw-r--r-- | arch/sparc/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | include/linux/mutex.h | 4 | ||||
-rw-r--r-- | include/linux/osq_lock.h | 27 | ||||
-rw-r--r-- | include/linux/rwsem-spinlock.h | 8 | ||||
-rw-r--r-- | include/linux/rwsem.h | 34 | ||||
-rw-r--r-- | kernel/Kconfig.locks | 9 | ||||
-rw-r--r-- | kernel/locking/mcs_spinlock.c | 64 | ||||
-rw-r--r-- | kernel/locking/mcs_spinlock.h | 9 | ||||
-rw-r--r-- | kernel/locking/mutex.c | 2 | ||||
-rw-r--r-- | kernel/locking/rwsem-spinlock.c | 28 | ||||
-rw-r--r-- | kernel/locking/rwsem-xadd.c | 16 | ||||
-rw-r--r-- | kernel/locking/rwsem.c | 2 | ||||
-rw-r--r-- | tools/lib/lockdep/include/liblockdep/mutex.h | 4 | ||||
-rw-r--r-- | tools/lib/lockdep/include/liblockdep/rwlock.h | 8 | ||||
-rw-r--r-- | tools/lib/lockdep/preload.c | 20 |
19 files changed, 154 insertions, 86 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 245058b3b0ef..88acf8bc1490 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -6,6 +6,7 @@ config ARM | |||
6 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 6 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
7 | select ARCH_HAVE_CUSTOM_GPIO_H | 7 | select ARCH_HAVE_CUSTOM_GPIO_H |
8 | select ARCH_MIGHT_HAVE_PC_PARPORT | 8 | select ARCH_MIGHT_HAVE_PC_PARPORT |
9 | select ARCH_SUPPORTS_ATOMIC_RMW | ||
9 | select ARCH_USE_BUILTIN_BSWAP | 10 | select ARCH_USE_BUILTIN_BSWAP |
10 | select ARCH_USE_CMPXCHG_LOCKREF | 11 | select ARCH_USE_CMPXCHG_LOCKREF |
11 | select ARCH_WANT_IPC_PARSE_VERSION | 12 | select ARCH_WANT_IPC_PARSE_VERSION |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a474de346be6..839f48c26ef0 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -4,6 +4,7 @@ config ARM64 | |||
4 | select ARCH_HAS_OPP | 4 | select ARCH_HAS_OPP |
5 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 5 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
6 | select ARCH_USE_CMPXCHG_LOCKREF | 6 | select ARCH_USE_CMPXCHG_LOCKREF |
7 | select ARCH_SUPPORTS_ATOMIC_RMW | ||
7 | select ARCH_WANT_OPTIONAL_GPIOLIB | 8 | select ARCH_WANT_OPTIONAL_GPIOLIB |
8 | select ARCH_WANT_COMPAT_IPC_PARSE_VERSION | 9 | select ARCH_WANT_COMPAT_IPC_PARSE_VERSION |
9 | select ARCH_WANT_FRAME_POINTERS | 10 | select ARCH_WANT_FRAME_POINTERS |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fefe7c8bf05f..80b94b0add1f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -145,6 +145,7 @@ config PPC | |||
145 | select HAVE_IRQ_EXIT_ON_IRQ_STACK | 145 | select HAVE_IRQ_EXIT_ON_IRQ_STACK |
146 | select ARCH_USE_CMPXCHG_LOCKREF if PPC64 | 146 | select ARCH_USE_CMPXCHG_LOCKREF if PPC64 |
147 | select HAVE_ARCH_AUDITSYSCALL | 147 | select HAVE_ARCH_AUDITSYSCALL |
148 | select ARCH_SUPPORTS_ATOMIC_RMW | ||
148 | 149 | ||
149 | config GENERIC_CSUM | 150 | config GENERIC_CSUM |
150 | def_bool CPU_LITTLE_ENDIAN | 151 | def_bool CPU_LITTLE_ENDIAN |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 29f2e988c56a..407c87d9879a 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -78,6 +78,7 @@ config SPARC64 | |||
78 | select HAVE_C_RECORDMCOUNT | 78 | select HAVE_C_RECORDMCOUNT |
79 | select NO_BOOTMEM | 79 | select NO_BOOTMEM |
80 | select HAVE_ARCH_AUDITSYSCALL | 80 | select HAVE_ARCH_AUDITSYSCALL |
81 | select ARCH_SUPPORTS_ATOMIC_RMW | ||
81 | 82 | ||
82 | config ARCH_DEFCONFIG | 83 | config ARCH_DEFCONFIG |
83 | string | 84 | string |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a8f749ef0fdc..d24887b645dc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -131,6 +131,7 @@ config X86 | |||
131 | select HAVE_CC_STACKPROTECTOR | 131 | select HAVE_CC_STACKPROTECTOR |
132 | select GENERIC_CPU_AUTOPROBE | 132 | select GENERIC_CPU_AUTOPROBE |
133 | select HAVE_ARCH_AUDITSYSCALL | 133 | select HAVE_ARCH_AUDITSYSCALL |
134 | select ARCH_SUPPORTS_ATOMIC_RMW | ||
134 | 135 | ||
135 | config INSTRUCTION_DECODER | 136 | config INSTRUCTION_DECODER |
136 | def_bool y | 137 | def_bool y |
diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 11692dea18aa..42aa9b9ecd5f 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/lockdep.h> | 17 | #include <linux/lockdep.h> |
18 | #include <linux/atomic.h> | 18 | #include <linux/atomic.h> |
19 | #include <asm/processor.h> | 19 | #include <asm/processor.h> |
20 | #include <linux/osq_lock.h> | ||
20 | 21 | ||
21 | /* | 22 | /* |
22 | * Simple, straightforward mutexes with strict semantics: | 23 | * Simple, straightforward mutexes with strict semantics: |
@@ -46,7 +47,6 @@ | |||
46 | * - detects multi-task circular deadlocks and prints out all affected | 47 | * - detects multi-task circular deadlocks and prints out all affected |
47 | * locks and tasks (and only those tasks) | 48 | * locks and tasks (and only those tasks) |
48 | */ | 49 | */ |
49 | struct optimistic_spin_queue; | ||
50 | struct mutex { | 50 | struct mutex { |
51 | /* 1: unlocked, 0: locked, negative: locked, possible waiters */ | 51 | /* 1: unlocked, 0: locked, negative: locked, possible waiters */ |
52 | atomic_t count; | 52 | atomic_t count; |
@@ -56,7 +56,7 @@ struct mutex { | |||
56 | struct task_struct *owner; | 56 | struct task_struct *owner; |
57 | #endif | 57 | #endif |
58 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER | 58 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER |
59 | struct optimistic_spin_queue *osq; /* Spinner MCS lock */ | 59 | struct optimistic_spin_queue osq; /* Spinner MCS lock */ |
60 | #endif | 60 | #endif |
61 | #ifdef CONFIG_DEBUG_MUTEXES | 61 | #ifdef CONFIG_DEBUG_MUTEXES |
62 | const char *name; | 62 | const char *name; |
diff --git a/include/linux/osq_lock.h b/include/linux/osq_lock.h new file mode 100644 index 000000000000..90230d5811c5 --- /dev/null +++ b/include/linux/osq_lock.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __LINUX_OSQ_LOCK_H | ||
2 | #define __LINUX_OSQ_LOCK_H | ||
3 | |||
4 | /* | ||
5 | * An MCS like lock especially tailored for optimistic spinning for sleeping | ||
6 | * lock implementations (mutex, rwsem, etc). | ||
7 | */ | ||
8 | |||
9 | #define OSQ_UNLOCKED_VAL (0) | ||
10 | |||
11 | struct optimistic_spin_queue { | ||
12 | /* | ||
13 | * Stores an encoded value of the CPU # of the tail node in the queue. | ||
14 | * If the queue is empty, then it's set to OSQ_UNLOCKED_VAL. | ||
15 | */ | ||
16 | atomic_t tail; | ||
17 | }; | ||
18 | |||
19 | /* Init macro and function. */ | ||
20 | #define OSQ_LOCK_UNLOCKED { ATOMIC_INIT(OSQ_UNLOCKED_VAL) } | ||
21 | |||
22 | static inline void osq_lock_init(struct optimistic_spin_queue *lock) | ||
23 | { | ||
24 | atomic_set(&lock->tail, OSQ_UNLOCKED_VAL); | ||
25 | } | ||
26 | |||
27 | #endif | ||
diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h index d5b13bc07a0b..561e8615528d 100644 --- a/include/linux/rwsem-spinlock.h +++ b/include/linux/rwsem-spinlock.h | |||
@@ -15,13 +15,13 @@ | |||
15 | #ifdef __KERNEL__ | 15 | #ifdef __KERNEL__ |
16 | /* | 16 | /* |
17 | * the rw-semaphore definition | 17 | * the rw-semaphore definition |
18 | * - if activity is 0 then there are no active readers or writers | 18 | * - if count is 0 then there are no active readers or writers |
19 | * - if activity is +ve then that is the number of active readers | 19 | * - if count is +ve then that is the number of active readers |
20 | * - if activity is -1 then there is one active writer | 20 | * - if count is -1 then there is one active writer |
21 | * - if wait_list is not empty, then there are processes waiting for the semaphore | 21 | * - if wait_list is not empty, then there are processes waiting for the semaphore |
22 | */ | 22 | */ |
23 | struct rw_semaphore { | 23 | struct rw_semaphore { |
24 | __s32 activity; | 24 | __s32 count; |
25 | raw_spinlock_t wait_lock; | 25 | raw_spinlock_t wait_lock; |
26 | struct list_head wait_list; | 26 | struct list_head wait_list; |
27 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 27 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 8d79708146aa..035d3c57fc8a 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h | |||
@@ -13,10 +13,11 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | |||
17 | #include <linux/atomic.h> | 16 | #include <linux/atomic.h> |
17 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER | ||
18 | #include <linux/osq_lock.h> | ||
19 | #endif | ||
18 | 20 | ||
19 | struct optimistic_spin_queue; | ||
20 | struct rw_semaphore; | 21 | struct rw_semaphore; |
21 | 22 | ||
22 | #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK | 23 | #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK |
@@ -25,15 +26,15 @@ struct rw_semaphore; | |||
25 | /* All arch specific implementations share the same struct */ | 26 | /* All arch specific implementations share the same struct */ |
26 | struct rw_semaphore { | 27 | struct rw_semaphore { |
27 | long count; | 28 | long count; |
28 | raw_spinlock_t wait_lock; | ||
29 | struct list_head wait_list; | 29 | struct list_head wait_list; |
30 | #ifdef CONFIG_SMP | 30 | raw_spinlock_t wait_lock; |
31 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER | ||
32 | struct optimistic_spin_queue osq; /* spinner MCS lock */ | ||
31 | /* | 33 | /* |
32 | * Write owner. Used as a speculative check to see | 34 | * Write owner. Used as a speculative check to see |
33 | * if the owner is running on the cpu. | 35 | * if the owner is running on the cpu. |
34 | */ | 36 | */ |
35 | struct task_struct *owner; | 37 | struct task_struct *owner; |
36 | struct optimistic_spin_queue *osq; /* spinner MCS lock */ | ||
37 | #endif | 38 | #endif |
38 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 39 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
39 | struct lockdep_map dep_map; | 40 | struct lockdep_map dep_map; |
@@ -64,22 +65,19 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) | |||
64 | # define __RWSEM_DEP_MAP_INIT(lockname) | 65 | # define __RWSEM_DEP_MAP_INIT(lockname) |
65 | #endif | 66 | #endif |
66 | 67 | ||
67 | #if defined(CONFIG_SMP) && !defined(CONFIG_RWSEM_GENERIC_SPINLOCK) | 68 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
68 | #define __RWSEM_INITIALIZER(name) \ | 69 | #define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED, .owner = NULL |
69 | { RWSEM_UNLOCKED_VALUE, \ | ||
70 | __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), \ | ||
71 | LIST_HEAD_INIT((name).wait_list), \ | ||
72 | NULL, /* owner */ \ | ||
73 | NULL /* mcs lock */ \ | ||
74 | __RWSEM_DEP_MAP_INIT(name) } | ||
75 | #else | 70 | #else |
76 | #define __RWSEM_INITIALIZER(name) \ | 71 | #define __RWSEM_OPT_INIT(lockname) |
77 | { RWSEM_UNLOCKED_VALUE, \ | ||
78 | __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), \ | ||
79 | LIST_HEAD_INIT((name).wait_list) \ | ||
80 | __RWSEM_DEP_MAP_INIT(name) } | ||
81 | #endif | 72 | #endif |
82 | 73 | ||
74 | #define __RWSEM_INITIALIZER(name) \ | ||
75 | { .count = RWSEM_UNLOCKED_VALUE, \ | ||
76 | .wait_list = LIST_HEAD_INIT((name).wait_list), \ | ||
77 | .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \ | ||
78 | __RWSEM_OPT_INIT(name) \ | ||
79 | __RWSEM_DEP_MAP_INIT(name) } | ||
80 | |||
83 | #define DECLARE_RWSEM(name) \ | 81 | #define DECLARE_RWSEM(name) \ |
84 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) | 82 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) |
85 | 83 | ||
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks index 35536d9c0964..76768ee812b2 100644 --- a/kernel/Kconfig.locks +++ b/kernel/Kconfig.locks | |||
@@ -220,9 +220,16 @@ config INLINE_WRITE_UNLOCK_IRQRESTORE | |||
220 | 220 | ||
221 | endif | 221 | endif |
222 | 222 | ||
223 | config ARCH_SUPPORTS_ATOMIC_RMW | ||
224 | bool | ||
225 | |||
223 | config MUTEX_SPIN_ON_OWNER | 226 | config MUTEX_SPIN_ON_OWNER |
224 | def_bool y | 227 | def_bool y |
225 | depends on SMP && !DEBUG_MUTEXES | 228 | depends on SMP && !DEBUG_MUTEXES && ARCH_SUPPORTS_ATOMIC_RMW |
229 | |||
230 | config RWSEM_SPIN_ON_OWNER | ||
231 | def_bool y | ||
232 | depends on SMP && RWSEM_XCHGADD_ALGORITHM && ARCH_SUPPORTS_ATOMIC_RMW | ||
226 | 233 | ||
227 | config ARCH_USE_QUEUE_RWLOCK | 234 | config ARCH_USE_QUEUE_RWLOCK |
228 | bool | 235 | bool |
diff --git a/kernel/locking/mcs_spinlock.c b/kernel/locking/mcs_spinlock.c index 838dc9e00669..be9ee1559fca 100644 --- a/kernel/locking/mcs_spinlock.c +++ b/kernel/locking/mcs_spinlock.c | |||
@@ -14,21 +14,47 @@ | |||
14 | * called from interrupt context and we have preemption disabled while | 14 | * called from interrupt context and we have preemption disabled while |
15 | * spinning. | 15 | * spinning. |
16 | */ | 16 | */ |
17 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct optimistic_spin_queue, osq_node); | 17 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct optimistic_spin_node, osq_node); |
18 | |||
19 | /* | ||
20 | * We use the value 0 to represent "no CPU", thus the encoded value | ||
21 | * will be the CPU number incremented by 1. | ||
22 | */ | ||
23 | static inline int encode_cpu(int cpu_nr) | ||
24 | { | ||
25 | return cpu_nr + 1; | ||
26 | } | ||
27 | |||
28 | static inline struct optimistic_spin_node *decode_cpu(int encoded_cpu_val) | ||
29 | { | ||
30 | int cpu_nr = encoded_cpu_val - 1; | ||
31 | |||
32 | return per_cpu_ptr(&osq_node, cpu_nr); | ||
33 | } | ||
18 | 34 | ||
19 | /* | 35 | /* |
20 | * Get a stable @node->next pointer, either for unlock() or unqueue() purposes. | 36 | * Get a stable @node->next pointer, either for unlock() or unqueue() purposes. |
21 | * Can return NULL in case we were the last queued and we updated @lock instead. | 37 | * Can return NULL in case we were the last queued and we updated @lock instead. |
22 | */ | 38 | */ |
23 | static inline struct optimistic_spin_queue * | 39 | static inline struct optimistic_spin_node * |
24 | osq_wait_next(struct optimistic_spin_queue **lock, | 40 | osq_wait_next(struct optimistic_spin_queue *lock, |
25 | struct optimistic_spin_queue *node, | 41 | struct optimistic_spin_node *node, |
26 | struct optimistic_spin_queue *prev) | 42 | struct optimistic_spin_node *prev) |
27 | { | 43 | { |
28 | struct optimistic_spin_queue *next = NULL; | 44 | struct optimistic_spin_node *next = NULL; |
45 | int curr = encode_cpu(smp_processor_id()); | ||
46 | int old; | ||
47 | |||
48 | /* | ||
49 | * If there is a prev node in queue, then the 'old' value will be | ||
50 | * the prev node's CPU #, else it's set to OSQ_UNLOCKED_VAL since if | ||
51 | * we're currently last in queue, then the queue will then become empty. | ||
52 | */ | ||
53 | old = prev ? prev->cpu : OSQ_UNLOCKED_VAL; | ||
29 | 54 | ||
30 | for (;;) { | 55 | for (;;) { |
31 | if (*lock == node && cmpxchg(lock, node, prev) == node) { | 56 | if (atomic_read(&lock->tail) == curr && |
57 | atomic_cmpxchg(&lock->tail, curr, old) == curr) { | ||
32 | /* | 58 | /* |
33 | * We were the last queued, we moved @lock back. @prev | 59 | * We were the last queued, we moved @lock back. @prev |
34 | * will now observe @lock and will complete its | 60 | * will now observe @lock and will complete its |
@@ -59,18 +85,23 @@ osq_wait_next(struct optimistic_spin_queue **lock, | |||
59 | return next; | 85 | return next; |
60 | } | 86 | } |
61 | 87 | ||
62 | bool osq_lock(struct optimistic_spin_queue **lock) | 88 | bool osq_lock(struct optimistic_spin_queue *lock) |
63 | { | 89 | { |
64 | struct optimistic_spin_queue *node = this_cpu_ptr(&osq_node); | 90 | struct optimistic_spin_node *node = this_cpu_ptr(&osq_node); |
65 | struct optimistic_spin_queue *prev, *next; | 91 | struct optimistic_spin_node *prev, *next; |
92 | int curr = encode_cpu(smp_processor_id()); | ||
93 | int old; | ||
66 | 94 | ||
67 | node->locked = 0; | 95 | node->locked = 0; |
68 | node->next = NULL; | 96 | node->next = NULL; |
97 | node->cpu = curr; | ||
69 | 98 | ||
70 | node->prev = prev = xchg(lock, node); | 99 | old = atomic_xchg(&lock->tail, curr); |
71 | if (likely(prev == NULL)) | 100 | if (old == OSQ_UNLOCKED_VAL) |
72 | return true; | 101 | return true; |
73 | 102 | ||
103 | prev = decode_cpu(old); | ||
104 | node->prev = prev; | ||
74 | ACCESS_ONCE(prev->next) = node; | 105 | ACCESS_ONCE(prev->next) = node; |
75 | 106 | ||
76 | /* | 107 | /* |
@@ -149,20 +180,21 @@ unqueue: | |||
149 | return false; | 180 | return false; |
150 | } | 181 | } |
151 | 182 | ||
152 | void osq_unlock(struct optimistic_spin_queue **lock) | 183 | void osq_unlock(struct optimistic_spin_queue *lock) |
153 | { | 184 | { |
154 | struct optimistic_spin_queue *node = this_cpu_ptr(&osq_node); | 185 | struct optimistic_spin_node *node, *next; |
155 | struct optimistic_spin_queue *next; | 186 | int curr = encode_cpu(smp_processor_id()); |
156 | 187 | ||
157 | /* | 188 | /* |
158 | * Fast path for the uncontended case. | 189 | * Fast path for the uncontended case. |
159 | */ | 190 | */ |
160 | if (likely(cmpxchg(lock, node, NULL) == node)) | 191 | if (likely(atomic_cmpxchg(&lock->tail, curr, OSQ_UNLOCKED_VAL) == curr)) |
161 | return; | 192 | return; |
162 | 193 | ||
163 | /* | 194 | /* |
164 | * Second most likely case. | 195 | * Second most likely case. |
165 | */ | 196 | */ |
197 | node = this_cpu_ptr(&osq_node); | ||
166 | next = xchg(&node->next, NULL); | 198 | next = xchg(&node->next, NULL); |
167 | if (next) { | 199 | if (next) { |
168 | ACCESS_ONCE(next->locked) = 1; | 200 | ACCESS_ONCE(next->locked) = 1; |
diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h index a2dbac4aca6b..74356dc0ce29 100644 --- a/kernel/locking/mcs_spinlock.h +++ b/kernel/locking/mcs_spinlock.h | |||
@@ -118,12 +118,13 @@ void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node) | |||
118 | * mutex_lock()/rwsem_down_{read,write}() etc. | 118 | * mutex_lock()/rwsem_down_{read,write}() etc. |
119 | */ | 119 | */ |
120 | 120 | ||
121 | struct optimistic_spin_queue { | 121 | struct optimistic_spin_node { |
122 | struct optimistic_spin_queue *next, *prev; | 122 | struct optimistic_spin_node *next, *prev; |
123 | int locked; /* 1 if lock acquired */ | 123 | int locked; /* 1 if lock acquired */ |
124 | int cpu; /* encoded CPU # value */ | ||
124 | }; | 125 | }; |
125 | 126 | ||
126 | extern bool osq_lock(struct optimistic_spin_queue **lock); | 127 | extern bool osq_lock(struct optimistic_spin_queue *lock); |
127 | extern void osq_unlock(struct optimistic_spin_queue **lock); | 128 | extern void osq_unlock(struct optimistic_spin_queue *lock); |
128 | 129 | ||
129 | #endif /* __LINUX_MCS_SPINLOCK_H */ | 130 | #endif /* __LINUX_MCS_SPINLOCK_H */ |
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index bc73d33c6760..acca2c1a3c5e 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c | |||
@@ -60,7 +60,7 @@ __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) | |||
60 | INIT_LIST_HEAD(&lock->wait_list); | 60 | INIT_LIST_HEAD(&lock->wait_list); |
61 | mutex_clear_owner(lock); | 61 | mutex_clear_owner(lock); |
62 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER | 62 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER |
63 | lock->osq = NULL; | 63 | osq_lock_init(&lock->osq); |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | debug_mutex_init(lock, name, key); | 66 | debug_mutex_init(lock, name, key); |
diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c index 9be8a9144978..2c93571162cb 100644 --- a/kernel/locking/rwsem-spinlock.c +++ b/kernel/locking/rwsem-spinlock.c | |||
@@ -26,7 +26,7 @@ int rwsem_is_locked(struct rw_semaphore *sem) | |||
26 | unsigned long flags; | 26 | unsigned long flags; |
27 | 27 | ||
28 | if (raw_spin_trylock_irqsave(&sem->wait_lock, flags)) { | 28 | if (raw_spin_trylock_irqsave(&sem->wait_lock, flags)) { |
29 | ret = (sem->activity != 0); | 29 | ret = (sem->count != 0); |
30 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | 30 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); |
31 | } | 31 | } |
32 | return ret; | 32 | return ret; |
@@ -46,7 +46,7 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, | |||
46 | debug_check_no_locks_freed((void *)sem, sizeof(*sem)); | 46 | debug_check_no_locks_freed((void *)sem, sizeof(*sem)); |
47 | lockdep_init_map(&sem->dep_map, name, key, 0); | 47 | lockdep_init_map(&sem->dep_map, name, key, 0); |
48 | #endif | 48 | #endif |
49 | sem->activity = 0; | 49 | sem->count = 0; |
50 | raw_spin_lock_init(&sem->wait_lock); | 50 | raw_spin_lock_init(&sem->wait_lock); |
51 | INIT_LIST_HEAD(&sem->wait_list); | 51 | INIT_LIST_HEAD(&sem->wait_list); |
52 | } | 52 | } |
@@ -95,7 +95,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) | |||
95 | waiter = list_entry(next, struct rwsem_waiter, list); | 95 | waiter = list_entry(next, struct rwsem_waiter, list); |
96 | } while (waiter->type != RWSEM_WAITING_FOR_WRITE); | 96 | } while (waiter->type != RWSEM_WAITING_FOR_WRITE); |
97 | 97 | ||
98 | sem->activity += woken; | 98 | sem->count += woken; |
99 | 99 | ||
100 | out: | 100 | out: |
101 | return sem; | 101 | return sem; |
@@ -126,9 +126,9 @@ void __sched __down_read(struct rw_semaphore *sem) | |||
126 | 126 | ||
127 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 127 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
128 | 128 | ||
129 | if (sem->activity >= 0 && list_empty(&sem->wait_list)) { | 129 | if (sem->count >= 0 && list_empty(&sem->wait_list)) { |
130 | /* granted */ | 130 | /* granted */ |
131 | sem->activity++; | 131 | sem->count++; |
132 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | 132 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); |
133 | goto out; | 133 | goto out; |
134 | } | 134 | } |
@@ -170,9 +170,9 @@ int __down_read_trylock(struct rw_semaphore *sem) | |||
170 | 170 | ||
171 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 171 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
172 | 172 | ||
173 | if (sem->activity >= 0 && list_empty(&sem->wait_list)) { | 173 | if (sem->count >= 0 && list_empty(&sem->wait_list)) { |
174 | /* granted */ | 174 | /* granted */ |
175 | sem->activity++; | 175 | sem->count++; |
176 | ret = 1; | 176 | ret = 1; |
177 | } | 177 | } |
178 | 178 | ||
@@ -206,7 +206,7 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass) | |||
206 | * itself into sleep and waiting for system woke it or someone | 206 | * itself into sleep and waiting for system woke it or someone |
207 | * else in the head of the wait list up. | 207 | * else in the head of the wait list up. |
208 | */ | 208 | */ |
209 | if (sem->activity == 0) | 209 | if (sem->count == 0) |
210 | break; | 210 | break; |
211 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | 211 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); |
212 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | 212 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); |
@@ -214,7 +214,7 @@ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass) | |||
214 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 214 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
215 | } | 215 | } |
216 | /* got the lock */ | 216 | /* got the lock */ |
217 | sem->activity = -1; | 217 | sem->count = -1; |
218 | list_del(&waiter.list); | 218 | list_del(&waiter.list); |
219 | 219 | ||
220 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | 220 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); |
@@ -235,9 +235,9 @@ int __down_write_trylock(struct rw_semaphore *sem) | |||
235 | 235 | ||
236 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 236 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
237 | 237 | ||
238 | if (sem->activity == 0) { | 238 | if (sem->count == 0) { |
239 | /* got the lock */ | 239 | /* got the lock */ |
240 | sem->activity = -1; | 240 | sem->count = -1; |
241 | ret = 1; | 241 | ret = 1; |
242 | } | 242 | } |
243 | 243 | ||
@@ -255,7 +255,7 @@ void __up_read(struct rw_semaphore *sem) | |||
255 | 255 | ||
256 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 256 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
257 | 257 | ||
258 | if (--sem->activity == 0 && !list_empty(&sem->wait_list)) | 258 | if (--sem->count == 0 && !list_empty(&sem->wait_list)) |
259 | sem = __rwsem_wake_one_writer(sem); | 259 | sem = __rwsem_wake_one_writer(sem); |
260 | 260 | ||
261 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | 261 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); |
@@ -270,7 +270,7 @@ void __up_write(struct rw_semaphore *sem) | |||
270 | 270 | ||
271 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 271 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
272 | 272 | ||
273 | sem->activity = 0; | 273 | sem->count = 0; |
274 | if (!list_empty(&sem->wait_list)) | 274 | if (!list_empty(&sem->wait_list)) |
275 | sem = __rwsem_do_wake(sem, 1); | 275 | sem = __rwsem_do_wake(sem, 1); |
276 | 276 | ||
@@ -287,7 +287,7 @@ void __downgrade_write(struct rw_semaphore *sem) | |||
287 | 287 | ||
288 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | 288 | raw_spin_lock_irqsave(&sem->wait_lock, flags); |
289 | 289 | ||
290 | sem->activity = 1; | 290 | sem->count = 1; |
291 | if (!list_empty(&sem->wait_list)) | 291 | if (!list_empty(&sem->wait_list)) |
292 | sem = __rwsem_do_wake(sem, 0); | 292 | sem = __rwsem_do_wake(sem, 0); |
293 | 293 | ||
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index dacc32142fcc..a2391ac135c8 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c | |||
@@ -82,9 +82,9 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, | |||
82 | sem->count = RWSEM_UNLOCKED_VALUE; | 82 | sem->count = RWSEM_UNLOCKED_VALUE; |
83 | raw_spin_lock_init(&sem->wait_lock); | 83 | raw_spin_lock_init(&sem->wait_lock); |
84 | INIT_LIST_HEAD(&sem->wait_list); | 84 | INIT_LIST_HEAD(&sem->wait_list); |
85 | #ifdef CONFIG_SMP | 85 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
86 | sem->owner = NULL; | 86 | sem->owner = NULL; |
87 | sem->osq = NULL; | 87 | osq_lock_init(&sem->osq); |
88 | #endif | 88 | #endif |
89 | } | 89 | } |
90 | 90 | ||
@@ -262,7 +262,7 @@ static inline bool rwsem_try_write_lock(long count, struct rw_semaphore *sem) | |||
262 | return false; | 262 | return false; |
263 | } | 263 | } |
264 | 264 | ||
265 | #ifdef CONFIG_SMP | 265 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
266 | /* | 266 | /* |
267 | * Try to acquire write lock before the writer has been put on wait queue. | 267 | * Try to acquire write lock before the writer has been put on wait queue. |
268 | */ | 268 | */ |
@@ -285,10 +285,10 @@ static inline bool rwsem_try_write_lock_unqueued(struct rw_semaphore *sem) | |||
285 | static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) | 285 | static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) |
286 | { | 286 | { |
287 | struct task_struct *owner; | 287 | struct task_struct *owner; |
288 | bool on_cpu = true; | 288 | bool on_cpu = false; |
289 | 289 | ||
290 | if (need_resched()) | 290 | if (need_resched()) |
291 | return 0; | 291 | return false; |
292 | 292 | ||
293 | rcu_read_lock(); | 293 | rcu_read_lock(); |
294 | owner = ACCESS_ONCE(sem->owner); | 294 | owner = ACCESS_ONCE(sem->owner); |
@@ -297,9 +297,9 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) | |||
297 | rcu_read_unlock(); | 297 | rcu_read_unlock(); |
298 | 298 | ||
299 | /* | 299 | /* |
300 | * If sem->owner is not set, the rwsem owner may have | 300 | * If sem->owner is not set, yet we have just recently entered the |
301 | * just acquired it and not set the owner yet or the rwsem | 301 | * slowpath, then there is a possibility reader(s) may have the lock. |
302 | * has been released. | 302 | * To be safe, avoid spinning in these situations. |
303 | */ | 303 | */ |
304 | return on_cpu; | 304 | return on_cpu; |
305 | } | 305 | } |
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index 42f806de49d4..e2d3bc7f03b4 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/atomic.h> | 13 | #include <linux/atomic.h> |
14 | 14 | ||
15 | #if defined(CONFIG_SMP) && defined(CONFIG_RWSEM_XCHGADD_ALGORITHM) | 15 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
16 | static inline void rwsem_set_owner(struct rw_semaphore *sem) | 16 | static inline void rwsem_set_owner(struct rw_semaphore *sem) |
17 | { | 17 | { |
18 | sem->owner = current; | 18 | sem->owner = current; |
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h index c342f7087147..ee53a42818ca 100644 --- a/tools/lib/lockdep/include/liblockdep/mutex.h +++ b/tools/lib/lockdep/include/liblockdep/mutex.h | |||
@@ -35,7 +35,7 @@ static inline int __mutex_init(liblockdep_pthread_mutex_t *lock, | |||
35 | 35 | ||
36 | static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock) | 36 | static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock) |
37 | { | 37 | { |
38 | lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | 38 | lock_acquire(&lock->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_); |
39 | return pthread_mutex_lock(&lock->mutex); | 39 | return pthread_mutex_lock(&lock->mutex); |
40 | } | 40 | } |
41 | 41 | ||
@@ -47,7 +47,7 @@ static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lo | |||
47 | 47 | ||
48 | static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock) | 48 | static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock) |
49 | { | 49 | { |
50 | lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | 50 | lock_acquire(&lock->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_); |
51 | return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0; | 51 | return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0; |
52 | } | 52 | } |
53 | 53 | ||
diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h index a680ab8c2e36..4ec03f861551 100644 --- a/tools/lib/lockdep/include/liblockdep/rwlock.h +++ b/tools/lib/lockdep/include/liblockdep/rwlock.h | |||
@@ -36,7 +36,7 @@ static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock, | |||
36 | 36 | ||
37 | static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock) | 37 | static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock) |
38 | { | 38 | { |
39 | lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_); | 39 | lock_acquire(&lock->dep_map, 0, 0, 2, 1, NULL, (unsigned long)_RET_IP_); |
40 | return pthread_rwlock_rdlock(&lock->rwlock); | 40 | return pthread_rwlock_rdlock(&lock->rwlock); |
41 | 41 | ||
42 | } | 42 | } |
@@ -49,19 +49,19 @@ static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t * | |||
49 | 49 | ||
50 | static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock) | 50 | static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock) |
51 | { | 51 | { |
52 | lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | 52 | lock_acquire(&lock->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_); |
53 | return pthread_rwlock_wrlock(&lock->rwlock); | 53 | return pthread_rwlock_wrlock(&lock->rwlock); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock) | 56 | static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock) |
57 | { | 57 | { |
58 | lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_); | 58 | lock_acquire(&lock->dep_map, 0, 1, 2, 1, NULL, (unsigned long)_RET_IP_); |
59 | return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0; | 59 | return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0; |
60 | } | 60 | } |
61 | 61 | ||
62 | static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock) | 62 | static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock) |
63 | { | 63 | { |
64 | lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | 64 | lock_acquire(&lock->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_); |
65 | return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0; | 65 | return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0; |
66 | } | 66 | } |
67 | 67 | ||
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c index 23bd69cb5ade..6f803609e498 100644 --- a/tools/lib/lockdep/preload.c +++ b/tools/lib/lockdep/preload.c | |||
@@ -92,7 +92,7 @@ enum { none, prepare, done, } __init_state; | |||
92 | static void init_preload(void); | 92 | static void init_preload(void); |
93 | static void try_init_preload(void) | 93 | static void try_init_preload(void) |
94 | { | 94 | { |
95 | if (!__init_state != done) | 95 | if (__init_state != done) |
96 | init_preload(); | 96 | init_preload(); |
97 | } | 97 | } |
98 | 98 | ||
@@ -252,7 +252,7 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) | |||
252 | 252 | ||
253 | try_init_preload(); | 253 | try_init_preload(); |
254 | 254 | ||
255 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, | 255 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 1, NULL, |
256 | (unsigned long)_RET_IP_); | 256 | (unsigned long)_RET_IP_); |
257 | /* | 257 | /* |
258 | * Here's the thing with pthread mutexes: unlike the kernel variant, | 258 | * Here's the thing with pthread mutexes: unlike the kernel variant, |
@@ -281,7 +281,7 @@ int pthread_mutex_trylock(pthread_mutex_t *mutex) | |||
281 | 281 | ||
282 | try_init_preload(); | 282 | try_init_preload(); |
283 | 283 | ||
284 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | 284 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_); |
285 | r = ll_pthread_mutex_trylock(mutex); | 285 | r = ll_pthread_mutex_trylock(mutex); |
286 | if (r) | 286 | if (r) |
287 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); | 287 | lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_); |
@@ -303,7 +303,7 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) | |||
303 | */ | 303 | */ |
304 | r = ll_pthread_mutex_unlock(mutex); | 304 | r = ll_pthread_mutex_unlock(mutex); |
305 | if (r) | 305 | if (r) |
306 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | 306 | lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_); |
307 | 307 | ||
308 | return r; | 308 | return r; |
309 | } | 309 | } |
@@ -352,7 +352,7 @@ int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) | |||
352 | 352 | ||
353 | init_preload(); | 353 | init_preload(); |
354 | 354 | ||
355 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_); | 355 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 2, 1, NULL, (unsigned long)_RET_IP_); |
356 | r = ll_pthread_rwlock_rdlock(rwlock); | 356 | r = ll_pthread_rwlock_rdlock(rwlock); |
357 | if (r) | 357 | if (r) |
358 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | 358 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); |
@@ -366,7 +366,7 @@ int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) | |||
366 | 366 | ||
367 | init_preload(); | 367 | init_preload(); |
368 | 368 | ||
369 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_); | 369 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 2, 1, NULL, (unsigned long)_RET_IP_); |
370 | r = ll_pthread_rwlock_tryrdlock(rwlock); | 370 | r = ll_pthread_rwlock_tryrdlock(rwlock); |
371 | if (r) | 371 | if (r) |
372 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | 372 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); |
@@ -380,7 +380,7 @@ int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) | |||
380 | 380 | ||
381 | init_preload(); | 381 | init_preload(); |
382 | 382 | ||
383 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_); | 383 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 0, 1, NULL, (unsigned long)_RET_IP_); |
384 | r = ll_pthread_rwlock_trywrlock(rwlock); | 384 | r = ll_pthread_rwlock_trywrlock(rwlock); |
385 | if (r) | 385 | if (r) |
386 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | 386 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); |
@@ -394,7 +394,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) | |||
394 | 394 | ||
395 | init_preload(); | 395 | init_preload(); |
396 | 396 | ||
397 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | 397 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_); |
398 | r = ll_pthread_rwlock_wrlock(rwlock); | 398 | r = ll_pthread_rwlock_wrlock(rwlock); |
399 | if (r) | 399 | if (r) |
400 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | 400 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); |
@@ -411,7 +411,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) | |||
411 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); | 411 | lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_); |
412 | r = ll_pthread_rwlock_unlock(rwlock); | 412 | r = ll_pthread_rwlock_unlock(rwlock); |
413 | if (r) | 413 | if (r) |
414 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_); | 414 | lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 1, NULL, (unsigned long)_RET_IP_); |
415 | 415 | ||
416 | return r; | 416 | return r; |
417 | } | 417 | } |
@@ -439,8 +439,6 @@ __attribute__((constructor)) static void init_preload(void) | |||
439 | ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock"); | 439 | ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock"); |
440 | #endif | 440 | #endif |
441 | 441 | ||
442 | printf("%p\n", ll_pthread_mutex_trylock);fflush(stdout); | ||
443 | |||
444 | lockdep_init(); | 442 | lockdep_init(); |
445 | 443 | ||
446 | __init_state = done; | 444 | __init_state = done; |