lock.h revision 1.10
1/*	$NetBSD: lock.h,v 1.10 2007/02/09 21:55:06 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("sync" ::: "memory");
105}
106
107static __inline void
108mb_write(void)
109{
110	___asm volatile("sync" ::: "memory");
111}
112
113static __inline void
114mb_memory(void)
115{
116	___asm volatile("sync" ::: "memory");
117}
118#endif	/* MIPS1 */
119
120#else	/* !_KERNEL */
121
122int	_lock_cas4(volatile uint32_t *, uint32_t, uint32_t);
123void	mb_read(void);
124void	mb_write(void);
125void	mb_memory(void);
126
127static __inline int
128__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
129{
130
131	return _lock_cas4((volatile uint32_t *)lp,
132	    __SIMPLELOCK_UNLOCKED, __SIMPLELOCK_LOCKED);
133}
134
135#endif	/* _KERNEL */
136
137static __inline void
138__cpu_simple_lock_init(__cpu_simple_lock_t *lp)
139{
140
141	*lp = __SIMPLELOCK_UNLOCKED;
142	mb_memory();
143}
144
145static __inline void
146__cpu_simple_lock(__cpu_simple_lock_t *lp)
147{
148
149	while (!__cpu_simple_lock_try(lp))
150		while (*lp == __SIMPLELOCK_LOCKED)
151			/* spin */;
152}
153
154static __inline void
155__cpu_simple_unlock(__cpu_simple_lock_t *lp)
156{
157
158	mb_memory();
159	*lp = __SIMPLELOCK_UNLOCKED;
160}
161
162#endif /* _MIPS_LOCK_H_ */
163