lock.h revision 1.12
1/*	$NetBSD: lock.h,v 1.12 2007/02/15 15:27:54 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
49#ifndef _KERNEL
50
51static __inline int
52__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
53{
54	unsigned long t0, v0;
55
56	__asm volatile(
57		"# -- BEGIN __cpu_simple_lock_try\n"
58		"	.set push		\n"
59		"	.set mips2		\n"
60		"1:	ll	%0, %4		\n"
61		"	bnez	%0, 2f		\n"
62		"	nop	       # BDslot	\n"
63		"	li	%0, %3		\n"
64		"	sc	%0, %2		\n"
65		"	beqz	%0, 2f		\n"
66		"	nop	       # BDslot	\n"
67		"	li	%1, 1		\n"
68		"	sync			\n"
69		"	j	3f		\n"
70		"	nop			\n"
71		"	nop			\n"
72		"2:	li	%1, 0		\n"
73		"3:				\n"
74		"	.set pop		\n"
75		"# -- END __cpu_simple_lock_try	\n"
76		: "=r" (t0), "=r" (v0), "+m" (*lp)
77		: "i" (__SIMPLELOCK_LOCKED), "m" (*lp));
78
79	return (v0 != 0);
80}
81
82#ifdef MIPS1
83static __inline void
84mb_read(void)
85{
86	__insn_barrier();
87}
88
89static __inline void
90mb_write(void)
91{
92	__insn_barrier();
93}
94
95static __inline void
96mb_memory(void)
97{
98	__insn_barrier();
99}
100#else	/* MIPS1*/
101static __inline void
102mb_read(void)
103{
104	__asm volatile(
105	    "	.set push\n"
106	    "	.set mips2\n"
107	    "	sync\n"
108	    "	.set pop"
109	    ::: "memory"
110	);
111}
112
113static __inline void
114mb_write(void)
115{
116	mb_read();
117}
118
119static __inline void
120mb_memory(void)
121{
122	mb_read();
123}
124#endif	/* MIPS1 */
125
126#else	/* !_KERNEL */
127
128int	_lock_cas4(volatile uint32_t *, uint32_t, uint32_t);
129void	mb_read(void);
130void	mb_write(void);
131void	mb_memory(void);
132
133static __inline int
134__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
135{
136
137	return _lock_cas4((volatile uint32_t *)lp,
138	    __SIMPLELOCK_UNLOCKED, __SIMPLELOCK_LOCKED);
139}
140
141#endif	/* _KERNEL */
142
143static __inline void
144__cpu_simple_lock_init(__cpu_simple_lock_t *lp)
145{
146
147	*lp = __SIMPLELOCK_UNLOCKED;
148	mb_memory();
149}
150
151static __inline void
152__cpu_simple_lock(__cpu_simple_lock_t *lp)
153{
154
155	while (!__cpu_simple_lock_try(lp))
156		while (*lp == __SIMPLELOCK_LOCKED)
157			/* spin */;
158}
159
160static __inline void
161__cpu_simple_unlock(__cpu_simple_lock_t *lp)
162{
163
164	mb_memory();
165	*lp = __SIMPLELOCK_UNLOCKED;
166}
167
168#endif /* _MIPS_LOCK_H_ */
169