xref: /openbsd/sys/arch/hppa/hppa/mutex.c (revision 264ca280)
1 /*	$OpenBSD: mutex.c,v 1.15 2015/09/20 19:19:03 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/param.h>
29 #include <sys/mutex.h>
30 #include <sys/systm.h>
31 #include <sys/atomic.h>
32 
33 #include <machine/intr.h>
34 
35 #include <ddb/db_output.h>
36 
37 int __mtx_enter_try(struct mutex *);
38 
39 #ifdef MULTIPROCESSOR
40 /* Note: lock must be 16-byte aligned. */
41 #define __mtx_lock(mtx) ((int *)(((vaddr_t)mtx->mtx_lock + 0xf) & ~0xf))
42 #endif
43 
44 void
45 __mtx_init(struct mutex *mtx, int wantipl)
46 {
47 #ifdef MULTIPROCESSOR
48 	mtx->mtx_lock[0] = 1;
49 	mtx->mtx_lock[1] = 1;
50 	mtx->mtx_lock[2] = 1;
51 	mtx->mtx_lock[3] = 1;
52 #endif
53 	mtx->mtx_wantipl = wantipl;
54 	mtx->mtx_oldipl = IPL_NONE;
55 	mtx->mtx_owner = NULL;
56 }
57 
58 #ifdef MULTIPROCESSOR
59 void
60 mtx_enter(struct mutex *mtx)
61 {
62 	while (mtx_enter_try(mtx) == 0)
63 		;
64 }
65 
66 int
67 mtx_enter_try(struct mutex *mtx)
68 {
69 	struct cpu_info *ci = curcpu();
70 	volatile int *lock = __mtx_lock(mtx);
71 	int ret;
72 	int s;
73 
74  	if (mtx->mtx_wantipl != IPL_NONE)
75 		s = splraise(mtx->mtx_wantipl);
76 
77 #ifdef DIAGNOSTIC
78 	if (__predict_false(mtx->mtx_owner == ci))
79 		panic("mtx %p: locking against myself", mtx);
80 #endif
81 
82 	asm volatile (
83 		"ldcws      0(%2), %0"
84 		: "=&r" (ret), "+m" (lock)
85 		: "r" (lock)
86 	);
87 
88 	if (ret) {
89 		membar_enter();
90 		mtx->mtx_owner = ci;
91 		if (mtx->mtx_wantipl != IPL_NONE)
92 			mtx->mtx_oldipl = s;
93 #ifdef DIAGNOSTIC
94 		ci->ci_mutex_level++;
95 #endif
96 
97 		return (1);
98 	}
99 
100 	if (mtx->mtx_wantipl != IPL_NONE)
101 		splx(s);
102 
103 	return (0);
104 }
105 #else
106 void
107 mtx_enter(struct mutex *mtx)
108 {
109 	struct cpu_info *ci = curcpu();
110 
111 #ifdef DIAGNOSTIC
112 	if (__predict_false(mtx->mtx_owner == ci))
113 		panic("mtx %p: locking against myself", mtx);
114 #endif
115 
116 	if (mtx->mtx_wantipl != IPL_NONE)
117 		mtx->mtx_oldipl = splraise(mtx->mtx_wantipl);
118 
119 	mtx->mtx_owner = ci;
120 
121 #ifdef DIAGNOSTIC
122 	ci->ci_mutex_level++;
123 #endif
124 }
125 
126 int
127 mtx_enter_try(struct mutex *mtx)
128 {
129 	mtx_enter(mtx);
130 	return (1);
131 }
132 #endif
133 
134 void
135 mtx_leave(struct mutex *mtx)
136 {
137 #ifdef MULTIPROCESSOR
138 	volatile int *lock = __mtx_lock(mtx);
139 #endif
140 	int s;
141 
142 	MUTEX_ASSERT_LOCKED(mtx);
143 
144 #ifdef DIAGNOSTIC
145 	curcpu()->ci_mutex_level--;
146 #endif
147 	s = mtx->mtx_oldipl;
148 	mtx->mtx_owner = NULL;
149 #ifdef MULTIPROCESSOR
150 	membar_exit();
151 	*lock = 1;
152 #endif
153 
154 	if (mtx->mtx_wantipl != IPL_NONE)
155 		splx(s);
156 }
157