aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86_64
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-09-26 04:52:28 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:28 -0400
commit9a0b26e6bc4ae1979d9bcc6194e57a71b2b5cac6 (patch)
tree01601a502007b85d4fc88f79de7a93c257ef9d97 /include/asm-x86_64
parentb4062b16094038334d9bbadac0397a3fc9e981b0 (diff)
[PATCH] Clean up read write lock assembly
- Move the slow path fallbacks to their own assembly files This makes them much easier to read and is needed for the next change. - Add CFI annotations for unwinding (XXX need review) - Remove constant case which can never happen with out of line spinlocks - Use patchable LOCK prefixes - Don't use lock sections anymore for inline code because they can't be expressed by the unwinder (this adds one taken jump to the lock fast path) Cc: jbeulich@novell.com Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'include/asm-x86_64')
-rw-r--r--include/asm-x86_64/rwlock.h68
-rw-r--r--include/asm-x86_64/spinlock.h11
2 files changed, 12 insertions, 67 deletions
diff --git a/include/asm-x86_64/rwlock.h b/include/asm-x86_64/rwlock.h
index dea0e9459264..28a080d23119 100644
--- a/include/asm-x86_64/rwlock.h
+++ b/include/asm-x86_64/rwlock.h
@@ -18,69 +18,21 @@
18#ifndef _ASM_X86_64_RWLOCK_H 18#ifndef _ASM_X86_64_RWLOCK_H
19#define _ASM_X86_64_RWLOCK_H 19#define _ASM_X86_64_RWLOCK_H
20 20
21#include <linux/stringify.h>
22
23#define RW_LOCK_BIAS 0x01000000 21#define RW_LOCK_BIAS 0x01000000
24#define RW_LOCK_BIAS_STR "0x01000000" 22#define RW_LOCK_BIAS_STR "0x01000000"
25 23
26#define __build_read_lock_ptr(rw, helper) \ 24#define __build_read_lock(rw) \
27 asm volatile(LOCK_PREFIX "subl $1,(%0)\n\t" \ 25 asm volatile(LOCK_PREFIX "subl $1,(%0)\n\t" \
28 "js 2f\n" \ 26 "jns 1f\n" \
29 "1:\n" \ 27 "call __read_lock_failed\n" \
30 LOCK_SECTION_START("") \
31 "2:\tcall " helper "\n\t" \
32 "jmp 1b\n" \
33 LOCK_SECTION_END \
34 ::"a" (rw) : "memory")
35
36#define __build_read_lock_const(rw, helper) \
37 asm volatile(LOCK_PREFIX "subl $1,%0\n\t" \
38 "js 2f\n" \
39 "1:\n" \ 28 "1:\n" \
40 LOCK_SECTION_START("") \ 29 ::"D" (rw), "i" (RW_LOCK_BIAS) : "memory")
41 "2:\tpushq %%rax\n\t" \
42 "leaq %0,%%rax\n\t" \
43 "call " helper "\n\t" \
44 "popq %%rax\n\t" \
45 "jmp 1b\n" \
46 LOCK_SECTION_END \
47 :"=m" (*((volatile int *)rw))::"memory")
48
49#define __build_read_lock(rw, helper) do { \
50 if (__builtin_constant_p(rw)) \
51 __build_read_lock_const(rw, helper); \
52 else \
53 __build_read_lock_ptr(rw, helper); \
54 } while (0)
55 30
56#define __build_write_lock_ptr(rw, helper) \ 31#define __build_write_lock(rw) \
57 asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ 32 asm volatile(LOCK_PREFIX "subl %1,(%0)\n\t" \
58 "jnz 2f\n" \ 33 "jz 1f\n" \
34 "\tcall __write_lock_failed\n\t" \
59 "1:\n" \ 35 "1:\n" \
60 LOCK_SECTION_START("") \ 36 ::"D" (rw), "i" (RW_LOCK_BIAS) : "memory")
61 "2:\tcall " helper "\n\t" \
62 "jmp 1b\n" \
63 LOCK_SECTION_END \
64 ::"a" (rw) : "memory")
65
66#define __build_write_lock_const(rw, helper) \
67 asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
68 "jnz 2f\n" \
69 "1:\n" \
70 LOCK_SECTION_START("") \
71 "2:\tpushq %%rax\n\t" \
72 "leaq %0,%%rax\n\t" \
73 "call " helper "\n\t" \
74 "popq %%rax\n\t" \
75 "jmp 1b\n" \
76 LOCK_SECTION_END \
77 :"=m" (*((volatile long *)rw))::"memory")
78
79#define __build_write_lock(rw, helper) do { \
80 if (__builtin_constant_p(rw)) \
81 __build_write_lock_const(rw, helper); \
82 else \
83 __build_write_lock_ptr(rw, helper); \
84 } while (0)
85 37
86#endif 38#endif
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index 248a79f0eaff..a8e3d89f591f 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -79,13 +79,6 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
79 * 79 *
80 * On x86, we implement read-write locks as a 32-bit counter 80 * On x86, we implement read-write locks as a 32-bit counter
81 * with the high bit (sign) being the "contended" bit. 81 * with the high bit (sign) being the "contended" bit.
82 *
83 * The inline assembly is non-obvious. Think about it.
84 *
85 * Changed to use the same technique as rw semaphores. See
86 * semaphore.h for details. -ben
87 *
88 * the helpers are in arch/i386/kernel/semaphore.c
89 */ 82 */
90 83
91#define __raw_read_can_lock(x) ((int)(x)->lock > 0) 84#define __raw_read_can_lock(x) ((int)(x)->lock > 0)
@@ -93,12 +86,12 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
93 86
94static inline void __raw_read_lock(raw_rwlock_t *rw) 87static inline void __raw_read_lock(raw_rwlock_t *rw)
95{ 88{
96 __build_read_lock(rw, "__read_lock_failed"); 89 __build_read_lock(rw);
97} 90}
98 91
99static inline void __raw_write_lock(raw_rwlock_t *rw) 92static inline void __raw_write_lock(raw_rwlock_t *rw)
100{ 93{
101 __build_write_lock(rw, "__write_lock_failed"); 94 __build_write_lock(rw);
102} 95}
103 96
104static inline int __raw_read_trylock(raw_rwlock_t *lock) 97static inline int __raw_read_trylock(raw_rwlock_t *lock)