Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * include/asm-sh/spinlock.h
  3 *
  4 * Copyright (C) 2002, 2003 Paul Mundt
  5 * Copyright (C) 2006, 2007 Akio Idehara
  6 *
  7 * This file is subject to the terms and conditions of the GNU General Public
  8 * License.  See the file "COPYING" in the main directory of this archive
  9 * for more details.
 10 */
 11#ifndef __ASM_SH_SPINLOCK_H
 12#define __ASM_SH_SPINLOCK_H
 13
 14/*
 15 * The only locking implemented here uses SH-4A opcodes. For others,
 16 * split this out as per atomic-*.h.
 17 */
 18#ifndef CONFIG_CPU_SH4A
 19#error "Need movli.l/movco.l for spinlocks"
 20#endif
 21
 22/*
 23 * Your basic SMP spinlocks, allowing only a single CPU anywhere
 24 */
 25
 26#define arch_spin_is_locked(x)		((x)->lock <= 0)
 27#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 28#define arch_spin_unlock_wait(x) \
 29	do { while (arch_spin_is_locked(x)) cpu_relax(); } while (0)
 30
 31/*
 32 * Simple spin lock operations.  There are two variants, one clears IRQ's
 33 * on the local processor, one does not.
 34 *
 35 * We make no fairness assumptions.  They have a cost.
 36 */
 37static inline void arch_spin_lock(arch_spinlock_t *lock)
 38{
 39	unsigned long tmp;
 40	unsigned long oldval;
 41
 42	__asm__ __volatile__ (
 43		"1:						\n\t"
 44		"movli.l	@%2, %0	! arch_spin_lock	\n\t"
 45		"mov		%0, %1				\n\t"
 46		"mov		#0, %0				\n\t"
 47		"movco.l	%0, @%2				\n\t"
 48		"bf		1b				\n\t"
 49		"cmp/pl		%1				\n\t"
 50		"bf		1b				\n\t"
 51		: "=&z" (tmp), "=&r" (oldval)
 52		: "r" (&lock->lock)
 53		: "t", "memory"
 54	);
 55}
 56
 57static inline void arch_spin_unlock(arch_spinlock_t *lock)
 58{
 59	unsigned long tmp;
 60
 61	__asm__ __volatile__ (
 62		"mov		#1, %0 ! arch_spin_unlock	\n\t"
 63		"mov.l		%0, @%1				\n\t"
 64		: "=&z" (tmp)
 65		: "r" (&lock->lock)
 66		: "t", "memory"
 67	);
 68}
 69
 70static inline int arch_spin_trylock(arch_spinlock_t *lock)
 71{
 72	unsigned long tmp, oldval;
 73
 74	__asm__ __volatile__ (
 75		"1:						\n\t"
 76		"movli.l	@%2, %0	! arch_spin_trylock	\n\t"
 77		"mov		%0, %1				\n\t"
 78		"mov		#0, %0				\n\t"
 79		"movco.l	%0, @%2				\n\t"
 80		"bf		1b				\n\t"
 81		"synco						\n\t"
 82		: "=&z" (tmp), "=&r" (oldval)
 83		: "r" (&lock->lock)
 84		: "t", "memory"
 85	);
 86
 87	return oldval;
 88}
 89
 90/*
 91 * Read-write spinlocks, allowing multiple readers but only one writer.
 92 *
 93 * NOTE! it is quite common to have readers in interrupts but no interrupt
 94 * writers. For those circumstances we can "mix" irq-safe locks - any writer
 95 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
 96 * read-locks.
 97 */
 98
 99/**
100 * read_can_lock - would read_trylock() succeed?
101 * @lock: the rwlock in question.
102 */
103#define arch_read_can_lock(x)	((x)->lock > 0)
104
105/**
106 * write_can_lock - would write_trylock() succeed?
107 * @lock: the rwlock in question.
108 */
109#define arch_write_can_lock(x)	((x)->lock == RW_LOCK_BIAS)
110
111static inline void arch_read_lock(arch_rwlock_t *rw)
112{
113	unsigned long tmp;
114
115	__asm__ __volatile__ (
116		"1:						\n\t"
117		"movli.l	@%1, %0	! arch_read_lock	\n\t"
118		"cmp/pl		%0				\n\t"
119		"bf		1b				\n\t"
120		"add		#-1, %0				\n\t"
121		"movco.l	%0, @%1				\n\t"
122		"bf		1b				\n\t"
123		: "=&z" (tmp)
124		: "r" (&rw->lock)
125		: "t", "memory"
126	);
127}
128
129static inline void arch_read_unlock(arch_rwlock_t *rw)
130{
131	unsigned long tmp;
132
133	__asm__ __volatile__ (
134		"1:						\n\t"
135		"movli.l	@%1, %0	! arch_read_unlock	\n\t"
136		"add		#1, %0				\n\t"
137		"movco.l	%0, @%1				\n\t"
138		"bf		1b				\n\t"
139		: "=&z" (tmp)
140		: "r" (&rw->lock)
141		: "t", "memory"
142	);
143}
144
145static inline void arch_write_lock(arch_rwlock_t *rw)
146{
147	unsigned long tmp;
148
149	__asm__ __volatile__ (
150		"1:						\n\t"
151		"movli.l	@%1, %0	! arch_write_lock	\n\t"
152		"cmp/hs		%2, %0				\n\t"
153		"bf		1b				\n\t"
154		"sub		%2, %0				\n\t"
155		"movco.l	%0, @%1				\n\t"
156		"bf		1b				\n\t"
157		: "=&z" (tmp)
158		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
159		: "t", "memory"
160	);
161}
162
163static inline void arch_write_unlock(arch_rwlock_t *rw)
164{
165	__asm__ __volatile__ (
166		"mov.l		%1, @%0 ! arch_write_unlock	\n\t"
167		:
168		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
169		: "t", "memory"
170	);
171}
172
173static inline int arch_read_trylock(arch_rwlock_t *rw)
174{
175	unsigned long tmp, oldval;
176
177	__asm__ __volatile__ (
178		"1:						\n\t"
179		"movli.l	@%2, %0	! arch_read_trylock	\n\t"
180		"mov		%0, %1				\n\t"
181		"cmp/pl		%0				\n\t"
182		"bf		2f				\n\t"
183		"add		#-1, %0				\n\t"
184		"movco.l	%0, @%2				\n\t"
185		"bf		1b				\n\t"
186		"2:						\n\t"
187		"synco						\n\t"
188		: "=&z" (tmp), "=&r" (oldval)
189		: "r" (&rw->lock)
190		: "t", "memory"
191	);
192
193	return (oldval > 0);
194}
195
196static inline int arch_write_trylock(arch_rwlock_t *rw)
197{
198	unsigned long tmp, oldval;
199
200	__asm__ __volatile__ (
201		"1:						\n\t"
202		"movli.l	@%2, %0	! arch_write_trylock	\n\t"
203		"mov		%0, %1				\n\t"
204		"cmp/hs		%3, %0				\n\t"
205		"bf		2f				\n\t"
206		"sub		%3, %0				\n\t"
207		"2:						\n\t"
208		"movco.l	%0, @%2				\n\t"
209		"bf		1b				\n\t"
210		"synco						\n\t"
211		: "=&z" (tmp), "=&r" (oldval)
212		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
213		: "t", "memory"
214	);
215
216	return (oldval > (RW_LOCK_BIAS - 1));
217}
218
219#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
220#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
221
222#define arch_spin_relax(lock)	cpu_relax()
223#define arch_read_relax(lock)	cpu_relax()
224#define arch_write_relax(lock)	cpu_relax()
225
226#endif /* __ASM_SH_SPINLOCK_H */
v3.1
  1/*
  2 * include/asm-sh/spinlock.h
  3 *
  4 * Copyright (C) 2002, 2003 Paul Mundt
  5 * Copyright (C) 2006, 2007 Akio Idehara
  6 *
  7 * This file is subject to the terms and conditions of the GNU General Public
  8 * License.  See the file "COPYING" in the main directory of this archive
  9 * for more details.
 10 */
 11#ifndef __ASM_SH_SPINLOCK_H
 12#define __ASM_SH_SPINLOCK_H
 13
 14/*
 15 * The only locking implemented here uses SH-4A opcodes. For others,
 16 * split this out as per atomic-*.h.
 17 */
 18#ifndef CONFIG_CPU_SH4A
 19#error "Need movli.l/movco.l for spinlocks"
 20#endif
 21
 22/*
 23 * Your basic SMP spinlocks, allowing only a single CPU anywhere
 24 */
 25
 26#define arch_spin_is_locked(x)		((x)->lock <= 0)
 27#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 28#define arch_spin_unlock_wait(x) \
 29	do { while (arch_spin_is_locked(x)) cpu_relax(); } while (0)
 30
 31/*
 32 * Simple spin lock operations.  There are two variants, one clears IRQ's
 33 * on the local processor, one does not.
 34 *
 35 * We make no fairness assumptions.  They have a cost.
 36 */
 37static inline void arch_spin_lock(arch_spinlock_t *lock)
 38{
 39	unsigned long tmp;
 40	unsigned long oldval;
 41
 42	__asm__ __volatile__ (
 43		"1:						\n\t"
 44		"movli.l	@%2, %0	! arch_spin_lock	\n\t"
 45		"mov		%0, %1				\n\t"
 46		"mov		#0, %0				\n\t"
 47		"movco.l	%0, @%2				\n\t"
 48		"bf		1b				\n\t"
 49		"cmp/pl		%1				\n\t"
 50		"bf		1b				\n\t"
 51		: "=&z" (tmp), "=&r" (oldval)
 52		: "r" (&lock->lock)
 53		: "t", "memory"
 54	);
 55}
 56
 57static inline void arch_spin_unlock(arch_spinlock_t *lock)
 58{
 59	unsigned long tmp;
 60
 61	__asm__ __volatile__ (
 62		"mov		#1, %0 ! arch_spin_unlock	\n\t"
 63		"mov.l		%0, @%1				\n\t"
 64		: "=&z" (tmp)
 65		: "r" (&lock->lock)
 66		: "t", "memory"
 67	);
 68}
 69
 70static inline int arch_spin_trylock(arch_spinlock_t *lock)
 71{
 72	unsigned long tmp, oldval;
 73
 74	__asm__ __volatile__ (
 75		"1:						\n\t"
 76		"movli.l	@%2, %0	! arch_spin_trylock	\n\t"
 77		"mov		%0, %1				\n\t"
 78		"mov		#0, %0				\n\t"
 79		"movco.l	%0, @%2				\n\t"
 80		"bf		1b				\n\t"
 81		"synco						\n\t"
 82		: "=&z" (tmp), "=&r" (oldval)
 83		: "r" (&lock->lock)
 84		: "t", "memory"
 85	);
 86
 87	return oldval;
 88}
 89
 90/*
 91 * Read-write spinlocks, allowing multiple readers but only one writer.
 92 *
 93 * NOTE! it is quite common to have readers in interrupts but no interrupt
 94 * writers. For those circumstances we can "mix" irq-safe locks - any writer
 95 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
 96 * read-locks.
 97 */
 98
 99/**
100 * read_can_lock - would read_trylock() succeed?
101 * @lock: the rwlock in question.
102 */
103#define arch_read_can_lock(x)	((x)->lock > 0)
104
105/**
106 * write_can_lock - would write_trylock() succeed?
107 * @lock: the rwlock in question.
108 */
109#define arch_write_can_lock(x)	((x)->lock == RW_LOCK_BIAS)
110
111static inline void arch_read_lock(arch_rwlock_t *rw)
112{
113	unsigned long tmp;
114
115	__asm__ __volatile__ (
116		"1:						\n\t"
117		"movli.l	@%1, %0	! arch_read_lock	\n\t"
118		"cmp/pl		%0				\n\t"
119		"bf		1b				\n\t"
120		"add		#-1, %0				\n\t"
121		"movco.l	%0, @%1				\n\t"
122		"bf		1b				\n\t"
123		: "=&z" (tmp)
124		: "r" (&rw->lock)
125		: "t", "memory"
126	);
127}
128
129static inline void arch_read_unlock(arch_rwlock_t *rw)
130{
131	unsigned long tmp;
132
133	__asm__ __volatile__ (
134		"1:						\n\t"
135		"movli.l	@%1, %0	! arch_read_unlock	\n\t"
136		"add		#1, %0				\n\t"
137		"movco.l	%0, @%1				\n\t"
138		"bf		1b				\n\t"
139		: "=&z" (tmp)
140		: "r" (&rw->lock)
141		: "t", "memory"
142	);
143}
144
145static inline void arch_write_lock(arch_rwlock_t *rw)
146{
147	unsigned long tmp;
148
149	__asm__ __volatile__ (
150		"1:						\n\t"
151		"movli.l	@%1, %0	! arch_write_lock	\n\t"
152		"cmp/hs		%2, %0				\n\t"
153		"bf		1b				\n\t"
154		"sub		%2, %0				\n\t"
155		"movco.l	%0, @%1				\n\t"
156		"bf		1b				\n\t"
157		: "=&z" (tmp)
158		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
159		: "t", "memory"
160	);
161}
162
163static inline void arch_write_unlock(arch_rwlock_t *rw)
164{
165	__asm__ __volatile__ (
166		"mov.l		%1, @%0 ! arch_write_unlock	\n\t"
167		:
168		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
169		: "t", "memory"
170	);
171}
172
173static inline int arch_read_trylock(arch_rwlock_t *rw)
174{
175	unsigned long tmp, oldval;
176
177	__asm__ __volatile__ (
178		"1:						\n\t"
179		"movli.l	@%2, %0	! arch_read_trylock	\n\t"
180		"mov		%0, %1				\n\t"
181		"cmp/pl		%0				\n\t"
182		"bf		2f				\n\t"
183		"add		#-1, %0				\n\t"
184		"movco.l	%0, @%2				\n\t"
185		"bf		1b				\n\t"
186		"2:						\n\t"
187		"synco						\n\t"
188		: "=&z" (tmp), "=&r" (oldval)
189		: "r" (&rw->lock)
190		: "t", "memory"
191	);
192
193	return (oldval > 0);
194}
195
196static inline int arch_write_trylock(arch_rwlock_t *rw)
197{
198	unsigned long tmp, oldval;
199
200	__asm__ __volatile__ (
201		"1:						\n\t"
202		"movli.l	@%2, %0	! arch_write_trylock	\n\t"
203		"mov		%0, %1				\n\t"
204		"cmp/hs		%3, %0				\n\t"
205		"bf		2f				\n\t"
206		"sub		%3, %0				\n\t"
207		"2:						\n\t"
208		"movco.l	%0, @%2				\n\t"
209		"bf		1b				\n\t"
210		"synco						\n\t"
211		: "=&z" (tmp), "=&r" (oldval)
212		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
213		: "t", "memory"
214	);
215
216	return (oldval > (RW_LOCK_BIAS - 1));
217}
218
219#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
220#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
221
222#define arch_spin_relax(lock)	cpu_relax()
223#define arch_read_relax(lock)	cpu_relax()
224#define arch_write_relax(lock)	cpu_relax()
225
226#endif /* __ASM_SH_SPINLOCK_H */