aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-i386/spinlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-i386/spinlock.h')
-rw-r--r--include/asm-i386/spinlock.h134
1 files changed, 70 insertions, 64 deletions
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index d1020363c41a..b0b3043f05e1 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -4,8 +4,12 @@
4#include <asm/atomic.h> 4#include <asm/atomic.h>
5#include <asm/rwlock.h> 5#include <asm/rwlock.h>
6#include <asm/page.h> 6#include <asm/page.h>
7#include <asm/processor.h>
7#include <linux/compiler.h> 8#include <linux/compiler.h>
8 9
10#define CLI_STRING "cli"
11#define STI_STRING "sti"
12
9/* 13/*
10 * Your basic SMP spinlocks, allowing only a single CPU anywhere 14 * Your basic SMP spinlocks, allowing only a single CPU anywhere
11 * 15 *
@@ -17,67 +21,64 @@
17 * (the type definitions are in asm/spinlock_types.h) 21 * (the type definitions are in asm/spinlock_types.h)
18 */ 22 */
19 23
20#define __raw_spin_is_locked(x) \ 24static inline int __raw_spin_is_locked(raw_spinlock_t *x)
21 (*(volatile signed char *)(&(x)->slock) <= 0) 25{
22 26 return *(volatile signed char *)(&(x)->slock) <= 0;
23#define __raw_spin_lock_string \ 27}
24 "\n1:\t" \
25 LOCK_PREFIX " ; decb %0\n\t" \
26 "jns 3f\n" \
27 "2:\t" \
28 "rep;nop\n\t" \
29 "cmpb $0,%0\n\t" \
30 "jle 2b\n\t" \
31 "jmp 1b\n" \
32 "3:\n\t"
33
34/*
35 * NOTE: there's an irqs-on section here, which normally would have to be
36 * irq-traced, but on CONFIG_TRACE_IRQFLAGS we never use
37 * __raw_spin_lock_string_flags().
38 */
39#define __raw_spin_lock_string_flags \
40 "\n1:\t" \
41 LOCK_PREFIX " ; decb %0\n\t" \
42 "jns 5f\n" \
43 "2:\t" \
44 "testl $0x200, %1\n\t" \
45 "jz 4f\n\t" \
46 "sti\n" \
47 "3:\t" \
48 "rep;nop\n\t" \
49 "cmpb $0, %0\n\t" \
50 "jle 3b\n\t" \
51 "cli\n\t" \
52 "jmp 1b\n" \
53 "4:\t" \
54 "rep;nop\n\t" \
55 "cmpb $0, %0\n\t" \
56 "jg 1b\n\t" \
57 "jmp 4b\n" \
58 "5:\n\t"
59 28
60static inline void __raw_spin_lock(raw_spinlock_t *lock) 29static inline void __raw_spin_lock(raw_spinlock_t *lock)
61{ 30{
62 asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory"); 31 asm volatile("\n1:\t"
32 LOCK_PREFIX " ; decb %0\n\t"
33 "jns 3f\n"
34 "2:\t"
35 "rep;nop\n\t"
36 "cmpb $0,%0\n\t"
37 "jle 2b\n\t"
38 "jmp 1b\n"
39 "3:\n\t"
40 : "+m" (lock->slock) : : "memory");
63} 41}
64 42
65/* 43/*
66 * It is easier for the lock validator if interrupts are not re-enabled 44 * It is easier for the lock validator if interrupts are not re-enabled
67 * in the middle of a lock-acquire. This is a performance feature anyway 45 * in the middle of a lock-acquire. This is a performance feature anyway
68 * so we turn it off: 46 * so we turn it off:
47 *
48 * NOTE: there's an irqs-on section here, which normally would have to be
49 * irq-traced, but on CONFIG_TRACE_IRQFLAGS we never use this variant.
69 */ 50 */
70#ifndef CONFIG_PROVE_LOCKING 51#ifndef CONFIG_PROVE_LOCKING
71static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) 52static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
72{ 53{
73 asm(__raw_spin_lock_string_flags : "+m" (lock->slock) : "r" (flags) : "memory"); 54 asm volatile(
55 "\n1:\t"
56 LOCK_PREFIX " ; decb %0\n\t"
57 "jns 5f\n"
58 "2:\t"
59 "testl $0x200, %1\n\t"
60 "jz 4f\n\t"
61 STI_STRING "\n"
62 "3:\t"
63 "rep;nop\n\t"
64 "cmpb $0, %0\n\t"
65 "jle 3b\n\t"
66 CLI_STRING "\n\t"
67 "jmp 1b\n"
68 "4:\t"
69 "rep;nop\n\t"
70 "cmpb $0, %0\n\t"
71 "jg 1b\n\t"
72 "jmp 4b\n"
73 "5:\n\t"
74 : "+m" (lock->slock) : "r" (flags) : "memory");
74} 75}
75#endif 76#endif
76 77
77static inline int __raw_spin_trylock(raw_spinlock_t *lock) 78static inline int __raw_spin_trylock(raw_spinlock_t *lock)
78{ 79{
79 char oldval; 80 char oldval;
80 __asm__ __volatile__( 81 asm volatile(
81 "xchgb %b0,%1" 82 "xchgb %b0,%1"
82 :"=q" (oldval), "+m" (lock->slock) 83 :"=q" (oldval), "+m" (lock->slock)
83 :"0" (0) : "memory"); 84 :"0" (0) : "memory");
@@ -93,38 +94,29 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
93 94
94#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE) 95#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
95 96
96#define __raw_spin_unlock_string \
97 "movb $1,%0" \
98 :"+m" (lock->slock) : : "memory"
99
100
101static inline void __raw_spin_unlock(raw_spinlock_t *lock) 97static inline void __raw_spin_unlock(raw_spinlock_t *lock)
102{ 98{
103 __asm__ __volatile__( 99 asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory");
104 __raw_spin_unlock_string
105 );
106} 100}
107 101
108#else 102#else
109 103
110#define __raw_spin_unlock_string \
111 "xchgb %b0, %1" \
112 :"=q" (oldval), "+m" (lock->slock) \
113 :"0" (oldval) : "memory"
114
115static inline void __raw_spin_unlock(raw_spinlock_t *lock) 104static inline void __raw_spin_unlock(raw_spinlock_t *lock)
116{ 105{
117 char oldval = 1; 106 char oldval = 1;
118 107
119 __asm__ __volatile__( 108 asm volatile("xchgb %b0, %1"
120 __raw_spin_unlock_string 109 : "=q" (oldval), "+m" (lock->slock)
121 ); 110 : "0" (oldval) : "memory");
122} 111}
123 112
124#endif 113#endif
125 114
126#define __raw_spin_unlock_wait(lock) \ 115static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
127 do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) 116{
117 while (__raw_spin_is_locked(lock))
118 cpu_relax();
119}
128 120
129/* 121/*
130 * Read-write spinlocks, allowing multiple readers 122 * Read-write spinlocks, allowing multiple readers
@@ -151,22 +143,36 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
151 * read_can_lock - would read_trylock() succeed? 143 * read_can_lock - would read_trylock() succeed?
152 * @lock: the rwlock in question. 144 * @lock: the rwlock in question.
153 */ 145 */
154#define __raw_read_can_lock(x) ((int)(x)->lock > 0) 146static inline int __raw_read_can_lock(raw_rwlock_t *x)
147{
148 return (int)(x)->lock > 0;
149}
155 150
156/** 151/**
157 * write_can_lock - would write_trylock() succeed? 152 * write_can_lock - would write_trylock() succeed?
158 * @lock: the rwlock in question. 153 * @lock: the rwlock in question.
159 */ 154 */
160#define __raw_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS) 155static inline int __raw_write_can_lock(raw_rwlock_t *x)
156{
157 return (x)->lock == RW_LOCK_BIAS;
158}
161 159
162static inline void __raw_read_lock(raw_rwlock_t *rw) 160static inline void __raw_read_lock(raw_rwlock_t *rw)
163{ 161{
164 __build_read_lock(rw, "__read_lock_failed"); 162 asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
163 "jns 1f\n"
164 "call __read_lock_failed\n\t"
165 "1:\n"
166 ::"a" (rw) : "memory");
165} 167}
166 168
167static inline void __raw_write_lock(raw_rwlock_t *rw) 169static inline void __raw_write_lock(raw_rwlock_t *rw)
168{ 170{
169 __build_write_lock(rw, "__write_lock_failed"); 171 asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t"
172 "jz 1f\n"
173 "call __write_lock_failed\n\t"
174 "1:\n"
175 ::"a" (rw) : "memory");
170} 176}
171 177
172static inline int __raw_read_trylock(raw_rwlock_t *lock) 178static inline int __raw_read_trylock(raw_rwlock_t *lock)