diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2012-11-10 22:01:21 -0500 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2012-12-19 00:10:22 -0500 |
commit | 71872b5fb2bed294fd5afd900890880e9faa82c1 (patch) | |
tree | 2b5506ffb3f9a31130cbe88df713a5fac4a43fdb /arch/xtensa | |
parent | e5a9f6adba79ce2732330fc6d045e98959af8962 (diff) |
xtensa: add s32c1i-based spinlock implementations
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/include/asm/spinlock.h | 188 |
1 files changed, 187 insertions, 1 deletions
diff --git a/arch/xtensa/include/asm/spinlock.h b/arch/xtensa/include/asm/spinlock.h index 8ff23649581b..03975906b36f 100644 --- a/arch/xtensa/include/asm/spinlock.h +++ b/arch/xtensa/include/asm/spinlock.h | |||
@@ -11,6 +11,192 @@ | |||
11 | #ifndef _XTENSA_SPINLOCK_H | 11 | #ifndef _XTENSA_SPINLOCK_H |
12 | #define _XTENSA_SPINLOCK_H | 12 | #define _XTENSA_SPINLOCK_H |
13 | 13 | ||
14 | #include <linux/spinlock.h> | 14 | /* |
15 | * spinlock | ||
16 | * | ||
17 | * There is at most one owner of a spinlock. There are not different | ||
18 | * types of spinlock owners like there are for rwlocks (see below). | ||
19 | * | ||
20 | * When trying to obtain a spinlock, the function "spins" forever, or busy- | ||
21 | * waits, until the lock is obtained. When spinning, presumably some other | ||
22 | * owner will soon give up the spinlock making it available to others. Use | ||
23 | * the trylock functions to avoid spinning forever. | ||
24 | * | ||
25 | * possible values: | ||
26 | * | ||
27 | * 0 nobody owns the spinlock | ||
28 | * 1 somebody owns the spinlock | ||
29 | */ | ||
30 | |||
31 | #define __raw_spin_is_locked(x) ((x)->slock != 0) | ||
32 | #define __raw_spin_unlock_wait(lock) \ | ||
33 | do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) | ||
34 | |||
35 | #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) | ||
36 | |||
37 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | ||
38 | { | ||
39 | unsigned long tmp; | ||
40 | |||
41 | __asm__ __volatile__( | ||
42 | " movi %0, 0\n" | ||
43 | " wsr %0, scompare1\n" | ||
44 | "1: movi %0, 1\n" | ||
45 | " s32c1i %0, %1, 0\n" | ||
46 | " bnez %0, 1b\n" | ||
47 | : "=&a" (tmp) | ||
48 | : "a" (&lock->slock) | ||
49 | : "memory"); | ||
50 | } | ||
51 | |||
52 | /* Returns 1 if the lock is obtained, 0 otherwise. */ | ||
53 | |||
54 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | ||
55 | { | ||
56 | unsigned long tmp; | ||
57 | |||
58 | __asm__ __volatile__( | ||
59 | " movi %0, 0\n" | ||
60 | " wsr %0, scompare1\n" | ||
61 | " movi %0, 1\n" | ||
62 | " s32c1i %0, %1, 0\n" | ||
63 | : "=&a" (tmp) | ||
64 | : "a" (&lock->slock) | ||
65 | : "memory"); | ||
66 | |||
67 | return tmp == 0 ? 1 : 0; | ||
68 | } | ||
69 | |||
70 | static inline void __raw_spin_unlock(raw_spinlock_t *lock) | ||
71 | { | ||
72 | unsigned long tmp; | ||
73 | |||
74 | __asm__ __volatile__( | ||
75 | " movi %0, 0\n" | ||
76 | " s32ri %0, %1, 0\n" | ||
77 | : "=&a" (tmp) | ||
78 | : "a" (&lock->slock) | ||
79 | : "memory"); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * rwlock | ||
84 | * | ||
85 | * Read-write locks are really a more flexible spinlock. They allow | ||
86 | * multiple readers but only one writer. Write ownership is exclusive | ||
87 | * (i.e., all other readers and writers are blocked from ownership while | ||
88 | * there is a write owner). These rwlocks are unfair to writers. Writers | ||
89 | * can be starved for an indefinite time by readers. | ||
90 | * | ||
91 | * possible values: | ||
92 | * | ||
93 | * 0 nobody owns the rwlock | ||
94 | * >0 one or more readers own the rwlock | ||
95 | * (the positive value is the actual number of readers) | ||
96 | * 0x80000000 one writer owns the rwlock, no other writers, no readers | ||
97 | */ | ||
98 | |||
99 | #define __raw_write_can_lock(x) ((x)->lock == 0) | ||
100 | |||
101 | static inline void __raw_write_lock(raw_rwlock_t *rw) | ||
102 | { | ||
103 | unsigned long tmp; | ||
104 | |||
105 | __asm__ __volatile__( | ||
106 | " movi %0, 0\n" | ||
107 | " wsr %0, scompare1\n" | ||
108 | "1: movi %0, 1\n" | ||
109 | " slli %0, %0, 31\n" | ||
110 | " s32c1i %0, %1, 0\n" | ||
111 | " bnez %0, 1b\n" | ||
112 | : "=&a" (tmp) | ||
113 | : "a" (&rw->lock) | ||
114 | : "memory"); | ||
115 | } | ||
116 | |||
117 | /* Returns 1 if the lock is obtained, 0 otherwise. */ | ||
118 | |||
119 | static inline int __raw_write_trylock(raw_rwlock_t *rw) | ||
120 | { | ||
121 | unsigned long tmp; | ||
122 | |||
123 | __asm__ __volatile__( | ||
124 | " movi %0, 0\n" | ||
125 | " wsr %0, scompare1\n" | ||
126 | " movi %0, 1\n" | ||
127 | " slli %0, %0, 31\n" | ||
128 | " s32c1i %0, %1, 0\n" | ||
129 | : "=&a" (tmp) | ||
130 | : "a" (&rw->lock) | ||
131 | : "memory"); | ||
132 | |||
133 | return tmp == 0 ? 1 : 0; | ||
134 | } | ||
135 | |||
136 | static inline void __raw_write_unlock(raw_rwlock_t *rw) | ||
137 | { | ||
138 | unsigned long tmp; | ||
139 | |||
140 | __asm__ __volatile__( | ||
141 | " movi %0, 0\n" | ||
142 | " s32ri %0, %1, 0\n" | ||
143 | : "=&a" (tmp) | ||
144 | : "a" (&rw->lock) | ||
145 | : "memory"); | ||
146 | } | ||
147 | |||
148 | static inline void __raw_read_lock(raw_rwlock_t *rw) | ||
149 | { | ||
150 | unsigned long tmp; | ||
151 | unsigned long result; | ||
152 | |||
153 | __asm__ __volatile__( | ||
154 | "1: l32i %1, %2, 0\n" | ||
155 | " bltz %1, 1b\n" | ||
156 | " wsr %1, scompare1\n" | ||
157 | " addi %0, %1, 1\n" | ||
158 | " s32c1i %0, %2, 0\n" | ||
159 | " bne %0, %1, 1b\n" | ||
160 | : "=&a" (result), "=&a" (tmp) | ||
161 | : "a" (&rw->lock) | ||
162 | : "memory"); | ||
163 | } | ||
164 | |||
165 | /* Returns 1 if the lock is obtained, 0 otherwise. */ | ||
166 | |||
167 | static inline int __raw_read_trylock(raw_rwlock_t *rw) | ||
168 | { | ||
169 | unsigned long result; | ||
170 | unsigned long tmp; | ||
171 | |||
172 | __asm__ __volatile__( | ||
173 | " l32i %1, %2, 0\n" | ||
174 | " addi %0, %1, 1\n" | ||
175 | " bltz %0, 1f\n" | ||
176 | " wsr %1, scompare1\n" | ||
177 | " s32c1i %0, %2, 0\n" | ||
178 | " sub %0, %0, %1\n" | ||
179 | "1:\n" | ||
180 | : "=&a" (result), "=&a" (tmp) | ||
181 | : "a" (&rw->lock) | ||
182 | : "memory"); | ||
183 | |||
184 | return result == 0; | ||
185 | } | ||
186 | |||
187 | static inline void __raw_read_unlock(raw_rwlock_t *rw) | ||
188 | { | ||
189 | unsigned long tmp1, tmp2; | ||
190 | |||
191 | __asm__ __volatile__( | ||
192 | "1: l32i %1, %2, 0\n" | ||
193 | " addi %0, %1, -1\n" | ||
194 | " wsr %1, scompare1\n" | ||
195 | " s32c1i %0, %2, 0\n" | ||
196 | " bne %0, %1, 1b\n" | ||
197 | : "=&a" (tmp1), "=&a" (tmp2) | ||
198 | : "a" (&rw->lock) | ||
199 | : "memory"); | ||
200 | } | ||
15 | 201 | ||
16 | #endif /* _XTENSA_SPINLOCK_H */ | 202 | #endif /* _XTENSA_SPINLOCK_H */ |