lock.h revision 1.15
1/*	$NetBSD: lock.h,v 1.15 2007/11/29 00:14:27 ad Exp $	*/
2
3/*-
4 * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wayne Knowles and Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the NetBSD
21 *	Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * Machine-dependent spin lock operations for MIPS processors.
41 *
42 * Note: R2000/R3000 doesn't have any atomic update instructions; this
43 * will cause problems for user applications using this header.
44 */
45
46#ifndef _MIPS_LOCK_H_
47#define	_MIPS_LOCK_H_
48
49static __inline int
50__SIMPLELOCK_LOCKED_P(__cpu_simple_lock_t *__ptr)
51{
52	return *__ptr == __SIMPLELOCK_LOCKED;
53}
54
55static __inline int
56__SIMPLELOCK_UNLOCKED_P(__cpu_simple_lock_t *__ptr)
57{
58	return *__ptr == __SIMPLELOCK_UNLOCKED;
59}
60
61static __inline void
62__cpu_simple_lock_clear(__cpu_simple_lock_t *__ptr)
63{
64	*__ptr = __SIMPLELOCK_UNLOCKED;
65}
66
67static __inline void
68__cpu_simple_lock_set(__cpu_simple_lock_t *__ptr)
69{
70	*__ptr = __SIMPLELOCK_LOCKED;
71}
72
73#ifndef _KERNEL
74
75static __inline int
76__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
77{
78	unsigned long t0, v0;
79
80	__asm volatile(
81		"# -- BEGIN __cpu_simple_lock_try\n"
82		"	.set push		\n"
83		"	.set mips2		\n"
84		"1:	ll	%0, %4		\n"
85		"	bnez	%0, 2f		\n"
86		"	nop	       # BDslot	\n"
87		"	li	%0, %3		\n"
88		"	sc	%0, %2		\n"
89		"	beqz	%0, 2f		\n"
90		"	nop	       # BDslot	\n"
91		"	li	%1, 1		\n"
92		"	sync			\n"
93		"	j	3f		\n"
94		"	nop			\n"
95		"	nop			\n"
96		"2:	li	%1, 0		\n"
97		"3:				\n"
98		"	.set pop		\n"
99		"# -- END __cpu_simple_lock_try	\n"
100		: "=r" (t0), "=r" (v0), "+m" (*lp)
101		: "i" (__SIMPLELOCK_LOCKED), "m" (*lp));
102
103	return (v0 != 0);
104}
105
106#ifdef MIPS1
107static __inline void
108mb_read(void)
109{
110	__insn_barrier();
111}
112
113static __inline void
114mb_write(void)
115{
116	__insn_barrier();
117}
118
119static __inline void
120mb_memory(void)
121{
122	__insn_barrier();
123}
124#else	/* MIPS1*/
125static __inline void
126mb_read(void)
127{
128	__asm volatile(
129	    "	.set push\n"
130	    "	.set mips2\n"
131	    "	sync\n"
132	    "	.set pop"
133	    ::: "memory"
134	);
135}
136
137static __inline void
138mb_write(void)
139{
140	mb_read();
141}
142
143static __inline void
144mb_memory(void)
145{
146	mb_read();
147}
148#endif	/* MIPS1 */
149
150#else	/* !_KERNEL */
151
152unsigned _atomic_cas_uint(volatile unsigned *, unsigned, unsigned);
153void	mb_read(void);
154void	mb_write(void);
155void	mb_memory(void);
156
157static __inline int
158__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
159{
160
161	return _atomic_cas_uint((volatile unsigned *)lp,
162	    __SIMPLELOCK_UNLOCKED, __SIMPLELOCK_LOCKED) ==
163	    __SIMPLELOCK_UNLOCKED;
164}
165
166#endif	/* _KERNEL */
167
168static __inline void
169__cpu_simple_lock_init(__cpu_simple_lock_t *lp)
170{
171
172	*lp = __SIMPLELOCK_UNLOCKED;
173	mb_memory();
174}
175
176static __inline void
177__cpu_simple_lock(__cpu_simple_lock_t *lp)
178{
179
180	while (!__cpu_simple_lock_try(lp))
181		while (*lp == __SIMPLELOCK_LOCKED)
182			/* spin */;
183}
184
185static __inline void
186__cpu_simple_unlock(__cpu_simple_lock_t *lp)
187{
188
189	mb_memory();
190	*lp = __SIMPLELOCK_UNLOCKED;
191}
192
193#endif /* _MIPS_LOCK_H_ */
194