mutex.h revision 1.2
1/*	$NetBSD: mutex.h,v 1.2 2007/02/09 21:55:12 ad Exp $	*/
2
3/*-
4 * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe 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#ifndef _SH3_MUTEX_H_
40#define	_SH3_MUTEX_H_
41
42/*
43 * The SH3 mutex implementation is troublesome, because SH3 lacks
44 * a pointer sized compare-and-set operation.  SMP for spin mutexes
45 * is easy - we don't need to know who owns the lock.  For adaptive
46 * mutexes, we need an owner field and additional interlock
47 *
48 * See arch/sparc/include/mutex.h for a more detailed description.
49 */
50
51#ifndef __MUTEX_PRIVATE
52
53struct kmutex {
54	uintptr_t	mtx_pad1;
55	uint32_t	mtx_pad2;
56};
57
58#else	/* __MUTEX_PRIVATE */
59
60struct kmutex {
61	union {
62		/* Adaptive mutex */
63		volatile uintptr_t	mtxu_owner;		/* 0-3 */
64		__cpu_simple_lock_t	mtxu_interlock;		/* 0 */
65
66		/* Spin mutex. */
67		struct {
68			uint8_t			mtxs_dummy;	/* 0 */
69			uint8_t			mtxs_unused1;	/* 1 */
70			ipl_cookie_t		mtxs_ipl;	/* 2 */
71			uint8_t			mtxs_unused2;	/* 3 */
72		} s;
73	} u;
74	__cpu_simple_lock_t	mtx_lock;			/* 4 */
75	uint8_t			mtx_idtype[3];			/* 5-7 */
76};
77
78#define	__HAVE_MUTEX_STUBS	1
79
80#define	mtx_owner	u.mtxu_owner
81#define	mtx_interlock	u.mtxu_interlock
82#define	mtx_dummy	u.s.mtxs_dummy
83#define	mtx_ipl		u.s.mtxs_ipl
84
85static inline uintptr_t
86MUTEX_OWNER(uintptr_t owner)
87{
88	return owner << 6;
89}
90
91static inline int
92MUTEX_OWNED(uintptr_t owner)
93{
94	return owner != 0;
95}
96
97static inline int
98MUTEX_SET_WAITERS(kmutex_t *mtx, uintptr_t owner)
99{
100	(void)__cpu_simple_lock_try(&mtx->mtx_lock);
101 	return mtx->mtx_owner != 0;
102}
103
104static inline int
105MUTEX_HAS_WAITERS(volatile kmutex_t *mtx)
106{
107	if (mtx->mtx_owner == 0)
108		return 0;
109	return mtx->mtx_lock == __SIMPLELOCK_LOCKED;
110}
111
112static inline void
113MUTEX_INITIALIZE_SPIN(kmutex_t *mtx, u_int id, int ipl)
114{
115	mtx->mtx_idtype[0] = (uint8_t)id;
116	mtx->mtx_idtype[1] = (uint8_t)(id >> 8);
117	mtx->mtx_idtype[2] = (uint8_t)((id >> 16) | 0x80);
118	mtx->mtx_ipl = makeiplcookie(ipl);
119	mtx->mtx_interlock = __SIMPLELOCK_LOCKED;
120	__cpu_simple_lock_init(&mtx->mtx_lock);
121}
122
123static inline void
124MUTEX_INITIALIZE_ADAPTIVE(kmutex_t *mtx, u_int id)
125{
126	mtx->mtx_idtype[0] = (uint8_t)id;
127	mtx->mtx_idtype[1] = (uint8_t)(id >> 8);
128	mtx->mtx_idtype[2] = (uint8_t)(id >> 16);
129	__cpu_simple_lock_init(&mtx->mtx_lock);
130}
131
132static inline void
133MUTEX_DESTROY(kmutex_t *mtx)
134{
135	mtx->mtx_owner = (uintptr_t)-1L;
136	mtx->mtx_idtype[0] = 0xff;
137	mtx->mtx_idtype[1] = 0xff;
138	mtx->mtx_idtype[2] = 0xff;
139}
140
141static inline u_int
142MUTEX_GETID(kmutex_t *mtx)
143{
144	return (u_int)mtx->mtx_idtype[0] |
145	    ((u_int)mtx->mtx_idtype[1] << 8) |
146	    (((u_int)mtx->mtx_idtype[2] & 0x7f) << 16);
147}
148
149static inline int
150MUTEX_SPIN_P(volatile kmutex_t *mtx)
151{
152	return mtx->mtx_idtype[2] & 0x80;
153}
154
155static inline int
156MUTEX_ADAPTIVE_P(volatile kmutex_t *mtx)
157{
158	return (mtx->mtx_idtype[2] & 0x80) == 0;
159}
160
161static inline int
162MUTEX_ACQUIRE(kmutex_t *mtx, uintptr_t curthread)
163{
164	if (!__cpu_simple_lock_try(&mtx->mtx_interlock))
165		return 0;
166	mtx->mtx_owner = (curthread >> 6) | 0xfa000000;
167	return 1;
168}
169
170static inline void
171MUTEX_RELEASE(kmutex_t *mtx)
172{
173	mtx->mtx_owner = 0;
174	__cpu_simple_unlock(&mtx->mtx_lock);
175}
176
177#endif	/* __MUTEX_PRIVATE */
178
179#endif /* _SH3_MUTEX_H_ */
180