Linux Audio

Check our new training course

Loading...
v5.4
  1/* SPDX-License-Identifier: GPL-2.0
  2 *
  3 * include/asm-sh/spinlock-llsc.h
  4 *
  5 * Copyright (C) 2002, 2003 Paul Mundt
  6 * Copyright (C) 2006, 2007 Akio Idehara
  7 */
  8#ifndef __ASM_SH_SPINLOCK_LLSC_H
  9#define __ASM_SH_SPINLOCK_LLSC_H
 10
 11#include <asm/barrier.h>
 12#include <asm/processor.h>
 13
 14/*
 15 * Your basic SMP spinlocks, allowing only a single CPU anywhere
 16 */
 17
 18#define arch_spin_is_locked(x)		((x)->lock <= 0)
 19
 20/*
 21 * Simple spin lock operations.  There are two variants, one clears IRQ's
 22 * on the local processor, one does not.
 23 *
 24 * We make no fairness assumptions.  They have a cost.
 25 */
 26static inline void arch_spin_lock(arch_spinlock_t *lock)
 27{
 28	unsigned long tmp;
 29	unsigned long oldval;
 30
 31	__asm__ __volatile__ (
 32		"1:						\n\t"
 33		"movli.l	@%2, %0	! arch_spin_lock	\n\t"
 34		"mov		%0, %1				\n\t"
 35		"mov		#0, %0				\n\t"
 36		"movco.l	%0, @%2				\n\t"
 37		"bf		1b				\n\t"
 38		"cmp/pl		%1				\n\t"
 39		"bf		1b				\n\t"
 40		: "=&z" (tmp), "=&r" (oldval)
 41		: "r" (&lock->lock)
 42		: "t", "memory"
 43	);
 44}
 45
 46static inline void arch_spin_unlock(arch_spinlock_t *lock)
 47{
 48	unsigned long tmp;
 49
 50	/* This could be optimised with ARCH_HAS_MMIOWB */
 51	mmiowb();
 52	__asm__ __volatile__ (
 53		"mov		#1, %0 ! arch_spin_unlock	\n\t"
 54		"mov.l		%0, @%1				\n\t"
 55		: "=&z" (tmp)
 56		: "r" (&lock->lock)
 57		: "t", "memory"
 58	);
 59}
 60
 61static inline int arch_spin_trylock(arch_spinlock_t *lock)
 62{
 63	unsigned long tmp, oldval;
 64
 65	__asm__ __volatile__ (
 66		"1:						\n\t"
 67		"movli.l	@%2, %0	! arch_spin_trylock	\n\t"
 68		"mov		%0, %1				\n\t"
 69		"mov		#0, %0				\n\t"
 70		"movco.l	%0, @%2				\n\t"
 71		"bf		1b				\n\t"
 72		"synco						\n\t"
 73		: "=&z" (tmp), "=&r" (oldval)
 74		: "r" (&lock->lock)
 75		: "t", "memory"
 76	);
 77
 78	return oldval;
 79}
 80
 81/*
 82 * Read-write spinlocks, allowing multiple readers but only one writer.
 83 *
 84 * NOTE! it is quite common to have readers in interrupts but no interrupt
 85 * writers. For those circumstances we can "mix" irq-safe locks - any writer
 86 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
 87 * read-locks.
 88 */
 89
 90static inline void arch_read_lock(arch_rwlock_t *rw)
 91{
 92	unsigned long tmp;
 93
 94	__asm__ __volatile__ (
 95		"1:						\n\t"
 96		"movli.l	@%1, %0	! arch_read_lock	\n\t"
 97		"cmp/pl		%0				\n\t"
 98		"bf		1b				\n\t"
 99		"add		#-1, %0				\n\t"
100		"movco.l	%0, @%1				\n\t"
101		"bf		1b				\n\t"
102		: "=&z" (tmp)
103		: "r" (&rw->lock)
104		: "t", "memory"
105	);
106}
107
108static inline void arch_read_unlock(arch_rwlock_t *rw)
109{
110	unsigned long tmp;
111
112	__asm__ __volatile__ (
113		"1:						\n\t"
114		"movli.l	@%1, %0	! arch_read_unlock	\n\t"
115		"add		#1, %0				\n\t"
116		"movco.l	%0, @%1				\n\t"
117		"bf		1b				\n\t"
118		: "=&z" (tmp)
119		: "r" (&rw->lock)
120		: "t", "memory"
121	);
122}
123
124static inline void arch_write_lock(arch_rwlock_t *rw)
125{
126	unsigned long tmp;
127
128	__asm__ __volatile__ (
129		"1:						\n\t"
130		"movli.l	@%1, %0	! arch_write_lock	\n\t"
131		"cmp/hs		%2, %0				\n\t"
132		"bf		1b				\n\t"
133		"sub		%2, %0				\n\t"
134		"movco.l	%0, @%1				\n\t"
135		"bf		1b				\n\t"
136		: "=&z" (tmp)
137		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
138		: "t", "memory"
139	);
140}
141
142static inline void arch_write_unlock(arch_rwlock_t *rw)
143{
144	__asm__ __volatile__ (
145		"mov.l		%1, @%0 ! arch_write_unlock	\n\t"
146		:
147		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
148		: "t", "memory"
149	);
150}
151
152static inline int arch_read_trylock(arch_rwlock_t *rw)
153{
154	unsigned long tmp, oldval;
155
156	__asm__ __volatile__ (
157		"1:						\n\t"
158		"movli.l	@%2, %0	! arch_read_trylock	\n\t"
159		"mov		%0, %1				\n\t"
160		"cmp/pl		%0				\n\t"
161		"bf		2f				\n\t"
162		"add		#-1, %0				\n\t"
163		"movco.l	%0, @%2				\n\t"
164		"bf		1b				\n\t"
165		"2:						\n\t"
166		"synco						\n\t"
167		: "=&z" (tmp), "=&r" (oldval)
168		: "r" (&rw->lock)
169		: "t", "memory"
170	);
171
172	return (oldval > 0);
173}
174
175static inline int arch_write_trylock(arch_rwlock_t *rw)
176{
177	unsigned long tmp, oldval;
178
179	__asm__ __volatile__ (
180		"1:						\n\t"
181		"movli.l	@%2, %0	! arch_write_trylock	\n\t"
182		"mov		%0, %1				\n\t"
183		"cmp/hs		%3, %0				\n\t"
184		"bf		2f				\n\t"
185		"sub		%3, %0				\n\t"
186		"2:						\n\t"
187		"movco.l	%0, @%2				\n\t"
188		"bf		1b				\n\t"
189		"synco						\n\t"
190		: "=&z" (tmp), "=&r" (oldval)
191		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
192		: "t", "memory"
193	);
194
195	return (oldval > (RW_LOCK_BIAS - 1));
196}
197
198#endif /* __ASM_SH_SPINLOCK_LLSC_H */
v6.13.7
  1/* SPDX-License-Identifier: GPL-2.0
  2 *
  3 * include/asm-sh/spinlock-llsc.h
  4 *
  5 * Copyright (C) 2002, 2003 Paul Mundt
  6 * Copyright (C) 2006, 2007 Akio Idehara
  7 */
  8#ifndef __ASM_SH_SPINLOCK_LLSC_H
  9#define __ASM_SH_SPINLOCK_LLSC_H
 10
 11#include <asm/barrier.h>
 12#include <asm/processor.h>
 13
 14/*
 15 * Your basic SMP spinlocks, allowing only a single CPU anywhere
 16 */
 17
 18#define arch_spin_is_locked(x)		((x)->lock <= 0)
 19
 20/*
 21 * Simple spin lock operations.  There are two variants, one clears IRQ's
 22 * on the local processor, one does not.
 23 *
 24 * We make no fairness assumptions.  They have a cost.
 25 */
 26static inline void arch_spin_lock(arch_spinlock_t *lock)
 27{
 28	unsigned long tmp;
 29	unsigned long oldval;
 30
 31	__asm__ __volatile__ (
 32		"1:						\n\t"
 33		"movli.l	@%2, %0	! arch_spin_lock	\n\t"
 34		"mov		%0, %1				\n\t"
 35		"mov		#0, %0				\n\t"
 36		"movco.l	%0, @%2				\n\t"
 37		"bf		1b				\n\t"
 38		"cmp/pl		%1				\n\t"
 39		"bf		1b				\n\t"
 40		: "=&z" (tmp), "=&r" (oldval)
 41		: "r" (&lock->lock)
 42		: "t", "memory"
 43	);
 44}
 45
 46static inline void arch_spin_unlock(arch_spinlock_t *lock)
 47{
 48	unsigned long tmp;
 49
 50	/* This could be optimised with ARCH_HAS_MMIOWB */
 51	mmiowb();
 52	__asm__ __volatile__ (
 53		"mov		#1, %0 ! arch_spin_unlock	\n\t"
 54		"mov.l		%0, @%1				\n\t"
 55		: "=&z" (tmp)
 56		: "r" (&lock->lock)
 57		: "t", "memory"
 58	);
 59}
 60
 61static inline int arch_spin_trylock(arch_spinlock_t *lock)
 62{
 63	unsigned long tmp, oldval;
 64
 65	__asm__ __volatile__ (
 66		"1:						\n\t"
 67		"movli.l	@%2, %0	! arch_spin_trylock	\n\t"
 68		"mov		%0, %1				\n\t"
 69		"mov		#0, %0				\n\t"
 70		"movco.l	%0, @%2				\n\t"
 71		"bf		1b				\n\t"
 72		"synco						\n\t"
 73		: "=&z" (tmp), "=&r" (oldval)
 74		: "r" (&lock->lock)
 75		: "t", "memory"
 76	);
 77
 78	return oldval;
 79}
 80
 81/*
 82 * Read-write spinlocks, allowing multiple readers but only one writer.
 83 *
 84 * NOTE! it is quite common to have readers in interrupts but no interrupt
 85 * writers. For those circumstances we can "mix" irq-safe locks - any writer
 86 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
 87 * read-locks.
 88 */
 89
 90static inline void arch_read_lock(arch_rwlock_t *rw)
 91{
 92	unsigned long tmp;
 93
 94	__asm__ __volatile__ (
 95		"1:						\n\t"
 96		"movli.l	@%1, %0	! arch_read_lock	\n\t"
 97		"cmp/pl		%0				\n\t"
 98		"bf		1b				\n\t"
 99		"add		#-1, %0				\n\t"
100		"movco.l	%0, @%1				\n\t"
101		"bf		1b				\n\t"
102		: "=&z" (tmp)
103		: "r" (&rw->lock)
104		: "t", "memory"
105	);
106}
107
108static inline void arch_read_unlock(arch_rwlock_t *rw)
109{
110	unsigned long tmp;
111
112	__asm__ __volatile__ (
113		"1:						\n\t"
114		"movli.l	@%1, %0	! arch_read_unlock	\n\t"
115		"add		#1, %0				\n\t"
116		"movco.l	%0, @%1				\n\t"
117		"bf		1b				\n\t"
118		: "=&z" (tmp)
119		: "r" (&rw->lock)
120		: "t", "memory"
121	);
122}
123
124static inline void arch_write_lock(arch_rwlock_t *rw)
125{
126	unsigned long tmp;
127
128	__asm__ __volatile__ (
129		"1:						\n\t"
130		"movli.l	@%1, %0	! arch_write_lock	\n\t"
131		"cmp/hs		%2, %0				\n\t"
132		"bf		1b				\n\t"
133		"sub		%2, %0				\n\t"
134		"movco.l	%0, @%1				\n\t"
135		"bf		1b				\n\t"
136		: "=&z" (tmp)
137		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
138		: "t", "memory"
139	);
140}
141
142static inline void arch_write_unlock(arch_rwlock_t *rw)
143{
144	__asm__ __volatile__ (
145		"mov.l		%1, @%0 ! arch_write_unlock	\n\t"
146		:
147		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
148		: "t", "memory"
149	);
150}
151
152static inline int arch_read_trylock(arch_rwlock_t *rw)
153{
154	unsigned long tmp, oldval;
155
156	__asm__ __volatile__ (
157		"1:						\n\t"
158		"movli.l	@%2, %0	! arch_read_trylock	\n\t"
159		"mov		%0, %1				\n\t"
160		"cmp/pl		%0				\n\t"
161		"bf		2f				\n\t"
162		"add		#-1, %0				\n\t"
163		"movco.l	%0, @%2				\n\t"
164		"bf		1b				\n\t"
165		"2:						\n\t"
166		"synco						\n\t"
167		: "=&z" (tmp), "=&r" (oldval)
168		: "r" (&rw->lock)
169		: "t", "memory"
170	);
171
172	return (oldval > 0);
173}
174
175static inline int arch_write_trylock(arch_rwlock_t *rw)
176{
177	unsigned long tmp, oldval;
178
179	__asm__ __volatile__ (
180		"1:						\n\t"
181		"movli.l	@%2, %0	! arch_write_trylock	\n\t"
182		"mov		%0, %1				\n\t"
183		"cmp/hs		%3, %0				\n\t"
184		"bf		2f				\n\t"
185		"sub		%3, %0				\n\t"
186		"2:						\n\t"
187		"movco.l	%0, @%2				\n\t"
188		"bf		1b				\n\t"
189		"synco						\n\t"
190		: "=&z" (tmp), "=&r" (oldval)
191		: "r" (&rw->lock), "r" (RW_LOCK_BIAS)
192		: "t", "memory"
193	);
194
195	return (oldval > (RW_LOCK_BIAS - 1));
196}
197
198#endif /* __ASM_SH_SPINLOCK_LLSC_H */