xref: /openbsd/sys/arch/hppa/hppa/mutex.c (revision 771fbea0)
1 /*	$OpenBSD: mutex.c,v 1.17 2019/04/23 13:35:12 visa 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 #ifdef MULTIPROCESSOR
38 /* Note: lock must be 16-byte aligned. */
39 #define __mtx_lock(mtx) ((int *)(((vaddr_t)mtx->mtx_lock + 0xf) & ~0xf))
40 #endif
41 
42 void
43 __mtx_init(struct mutex *mtx, int wantipl)
44 {
45 #ifdef MULTIPROCESSOR
46 	mtx->mtx_lock[0] = 1;
47 	mtx->mtx_lock[1] = 1;
48 	mtx->mtx_lock[2] = 1;
49 	mtx->mtx_lock[3] = 1;
50 #endif
51 	mtx->mtx_wantipl = wantipl;
52 	mtx->mtx_oldipl = IPL_NONE;
53 	mtx->mtx_owner = NULL;
54 }
55 
56 #ifdef MULTIPROCESSOR
57 void
58 mtx_enter(struct mutex *mtx)
59 {
60 	while (mtx_enter_try(mtx) == 0)
61 		;
62 }
63 
64 int
65 mtx_enter_try(struct mutex *mtx)
66 {
67 	struct cpu_info *ci = curcpu();
68 	volatile int *lock = __mtx_lock(mtx);
69 	int ret;
70 	int s;
71 
72  	if (mtx->mtx_wantipl != IPL_NONE)
73 		s = splraise(mtx->mtx_wantipl);
74 
75 #ifdef DIAGNOSTIC
76 	if (__predict_false(mtx->mtx_owner == ci))
77 		panic("mtx %p: locking against myself", mtx);
78 #endif
79 
80 	asm volatile (
81 		"ldcws      0(%2), %0"
82 		: "=&r" (ret), "+m" (lock)
83 		: "r" (lock)
84 	);
85 
86 	if (ret) {
87 		membar_enter();
88 		mtx->mtx_owner = ci;
89 		if (mtx->mtx_wantipl != IPL_NONE)
90 			mtx->mtx_oldipl = s;
91 #ifdef DIAGNOSTIC
92 		ci->ci_mutex_level++;
93 #endif
94 
95 		return (1);
96 	}
97 
98 	if (mtx->mtx_wantipl != IPL_NONE)
99 		splx(s);
100 
101 	return (0);
102 }
103 #else
104 void
105 mtx_enter(struct mutex *mtx)
106 {
107 	struct cpu_info *ci = curcpu();
108 
109 #ifdef DIAGNOSTIC
110 	if (__predict_false(mtx->mtx_owner == ci))
111 		panic("mtx %p: locking against myself", mtx);
112 #endif
113 
114 	if (mtx->mtx_wantipl != IPL_NONE)
115 		mtx->mtx_oldipl = splraise(mtx->mtx_wantipl);
116 
117 	mtx->mtx_owner = ci;
118 
119 #ifdef DIAGNOSTIC
120 	ci->ci_mutex_level++;
121 #endif
122 }
123 
124 int
125 mtx_enter_try(struct mutex *mtx)
126 {
127 	mtx_enter(mtx);
128 	return (1);
129 }
130 #endif
131 
132 void
133 mtx_leave(struct mutex *mtx)
134 {
135 #ifdef MULTIPROCESSOR
136 	volatile int *lock = __mtx_lock(mtx);
137 #endif
138 	int s;
139 
140 	MUTEX_ASSERT_LOCKED(mtx);
141 
142 #ifdef DIAGNOSTIC
143 	curcpu()->ci_mutex_level--;
144 #endif
145 	s = mtx->mtx_oldipl;
146 	mtx->mtx_owner = NULL;
147 #ifdef MULTIPROCESSOR
148 	membar_exit();
149 	*lock = 1;
150 #endif
151 
152 	if (mtx->mtx_wantipl != IPL_NONE)
153 		splx(s);
154 }
155