Sat Jan 22 19:10:17 2011 UTC ()
First attempt at MP _lock_cas.


(skrll)
diff -r1.17 -r1.18 src/sys/arch/hppa/hppa/lock_stubs.S

cvs diff -r1.17 -r1.18 src/sys/arch/hppa/hppa/lock_stubs.S (switch to unified diff)

--- src/sys/arch/hppa/hppa/lock_stubs.S 2011/01/20 19:51:54 1.17
+++ src/sys/arch/hppa/hppa/lock_stubs.S 2011/01/22 19:10:16 1.18
@@ -1,198 +1,300 @@ @@ -1,198 +1,300 @@
1/* $NetBSD: lock_stubs.S,v 1.17 2011/01/20 19:51:54 skrll Exp $ */ 1/* $NetBSD: lock_stubs.S,v 1.18 2011/01/22 19:10:16 skrll Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran and Nick Hudson. 8 * by Andrew Doran and Nick Hudson.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include "opt_multiprocessor.h" 32#include "opt_multiprocessor.h"
33#include "opt_lockdebug.h" 33#include "opt_lockdebug.h"
34#include "opt_cputype.h" 34#include "opt_cputype.h"
35#include "opt_ddb.h" 35#include "opt_ddb.h"
36 36
37#define __MUTEX_PRIVATE 37#define __MUTEX_PRIVATE
38 38
39#include <machine/asm.h> 39#include <machine/asm.h>
40#include <machine/mutex.h> 40#include <machine/mutex.h>
41#include <machine/reg.h> 41#include <machine/reg.h>
42 42
43#include "assym.h" 43#include "assym.h"
44 44
45/* 45/*
46 * uintptr_t _lock_cas(volatile uintptr_t *ptr, uintptr_t old, uintptr_t new); 46 * uintptr_t _lock_cas(volatile uintptr_t *ptr, uintptr_t old, uintptr_t new);
47 * 47 *
48 * Perform an atomic compare-and-swap operation. 48 * Perform an atomic compare-and-swap operation.
49 * 49 *
50 * On single CPU systems this can use a restartable sequence as there 50 * On single CPU systems this can use a restartable sequence as there
51 * we don't need the overhead of interlocking. 51 * we don't need the overhead of interlocking.
52 */ 52 */
53 53
54#ifndef MULTIPROCESSOR 54#ifndef MULTIPROCESSOR
55 55
56 .global _lock_cas_ras_start 56 .global _lock_cas_ras_start
57 .global _lock_cas_ras_end 57 .global _lock_cas_ras_end
58 58
59 .global mutex_enter_crit_start 59 .global mutex_enter_crit_start
60 .global mutex_enter_crit_end 60 .global mutex_enter_crit_end
61 61
62 .import mutex_vector_enter, code 62 .import mutex_vector_enter, code
63 .import mutex_vector_exit, code 63 .import mutex_vector_exit, code
64 .import mutex_wakeup, code 64 .import mutex_wakeup, code
65 65
66LEAF_ENTRY(_lock_cas) 66LEAF_ENTRY(_lock_cas)
67_lock_cas_ras_start: 67_lock_cas_ras_start:
68 ldw 0(%arg0),%t1 68 ldw 0(%arg0),%t1
69 comb,<> %arg1, %t1, 1f 69 comb,<> %arg1, %t1, 1f
70 copy %t1,%ret0 70 copy %t1,%ret0
71_lock_cas_ras_end: 71_lock_cas_ras_end:
72 stw %arg2,0(%arg0) 72 stw %arg2,0(%arg0)
73 copy %arg1,%ret0 73 copy %arg1,%ret0
741: 741:
75 bv,n %r0(%rp) 75 bv,n %r0(%rp)
76 76
77EXIT(_lock_cas) 77EXIT(_lock_cas)
78 78
79STRONG_ALIAS(_atomic_cas_ulong,_lock_cas) 79STRONG_ALIAS(_atomic_cas_ulong,_lock_cas)
80STRONG_ALIAS(atomic_cas_ulong,_lock_cas) 80STRONG_ALIAS(atomic_cas_ulong,_lock_cas)
81STRONG_ALIAS(_atomic_cas_32,_lock_cas) 81STRONG_ALIAS(_atomic_cas_32,_lock_cas)
82STRONG_ALIAS(atomic_cas_32,_lock_cas) 82STRONG_ALIAS(atomic_cas_32,_lock_cas)
83STRONG_ALIAS(_atomic_cas_uint,_lock_cas) 83STRONG_ALIAS(_atomic_cas_uint,_lock_cas)
84STRONG_ALIAS(atomic_cas_uint,_lock_cas) 84STRONG_ALIAS(atomic_cas_uint,_lock_cas)
85STRONG_ALIAS(_atomic_cas_ptr,_lock_cas) 85STRONG_ALIAS(_atomic_cas_ptr,_lock_cas)
86STRONG_ALIAS(atomic_cas_ptr,_lock_cas) 86STRONG_ALIAS(atomic_cas_ptr,_lock_cas)
87 87
88STRONG_ALIAS(_atomic_cas_ulong_ni,_lock_cas) 88STRONG_ALIAS(_atomic_cas_ulong_ni,_lock_cas)
89STRONG_ALIAS(atomic_cas_ulong_ni,_lock_cas) 89STRONG_ALIAS(atomic_cas_ulong_ni,_lock_cas)
90STRONG_ALIAS(_atomic_cas_32_ni,_lock_cas) 90STRONG_ALIAS(_atomic_cas_32_ni,_lock_cas)
91STRONG_ALIAS(atomic_cas_32_ni,_lock_cas) 91STRONG_ALIAS(atomic_cas_32_ni,_lock_cas)
92STRONG_ALIAS(_atomic_cas_uint_ni,_lock_cas) 92STRONG_ALIAS(_atomic_cas_uint_ni,_lock_cas)
93STRONG_ALIAS(atomic_cas_uint_ni,_lock_cas) 93STRONG_ALIAS(atomic_cas_uint_ni,_lock_cas)
94STRONG_ALIAS(_atomic_cas_ptr_ni,_lock_cas) 94STRONG_ALIAS(_atomic_cas_ptr_ni,_lock_cas)
95STRONG_ALIAS(atomic_cas_ptr_ni,_lock_cas) 95STRONG_ALIAS(atomic_cas_ptr_ni,_lock_cas)
96 96
97#ifndef LOCKDEBUG 97#ifndef LOCKDEBUG
98/* 98/*
99 * void mutex_exit(kmutex_t *mtx); 99 * void mutex_exit(kmutex_t *mtx);
100 */ 100 */
101 101
102LEAF_ENTRY(mutex_exit) 102LEAF_ENTRY(mutex_exit)
103 /* 103 /*
104 * If its a spin mutex or unowned, we have to take the slow path. 104 * If its a spin mutex or unowned, we have to take the slow path.
105 */ 105 */
106 ldi MUTEX_ADAPTIVE_UNOWNED,%t1 106 ldi MUTEX_ADAPTIVE_UNOWNED,%t1
107 ldw MTX_OWNER(%arg0),%t2 107 ldw MTX_OWNER(%arg0),%t2
108 depi 0,27,1,%t2 /* bit27 = 0 */ 108 depi 0,27,1,%t2 /* bit27 = 0 */
109 comb,= %t1,%t2,.Lexit_slowpath 109 comb,= %t1,%t2,.Lexit_slowpath
110 nop 110 nop
111 111
112 /* 112 /*
113 * We know that it's an adapative mutex. Clear the owners 113 * We know that it's an adapative mutex. Clear the owners
114 * field and release the lock. 114 * field and release the lock.
115 */ 115 */
116 116
117 ldi 1,%t2 /* unlocked = 1 */ 117 ldi 1,%t2 /* unlocked = 1 */
118 ldo (MTX_LOCK + HPPA_LDCW_ALIGN - 1)(%arg0), %t3 118 ldo (MTX_LOCK + HPPA_LDCW_ALIGN - 1)(%arg0), %t3
119 depi 0, 31, 4, %t3 119 depi 0, 31, 4, %t3
120 stw %t1,MTX_OWNER(%arg0) 120 stw %t1,MTX_OWNER(%arg0)
121 stw %t2,0(%t3) /* %t3 is properly aligned */ 121 stw %t2,0(%t3) /* %t3 is properly aligned */
122 sync 122 sync
123 123
124 /* 124 /*
125 * We have posted a read memory barrier so the check of mtx_waiters 125 * We have posted a read memory barrier so the check of mtx_waiters
126 * will happen in sequence. If it's set then trap into mutex_wakeup() 126 * will happen in sequence. If it's set then trap into mutex_wakeup()
127 * to wake up any threads sleeping on the lock. 127 * to wake up any threads sleeping on the lock.
128 */ 128 */
129 ldb MTX_WAITERS(%arg0),%t4 129 ldb MTX_WAITERS(%arg0),%t4
130 comib,= 0,%t4,.Lexit_done 130 comib,= 0,%t4,.Lexit_done
131 nop 131 nop
132 132
133 ldil L%mutex_wakeup, %t1 133 ldil L%mutex_wakeup, %t1
134 ldo R%mutex_wakeup(%t1), %t1 134 ldo R%mutex_wakeup(%t1), %t1
135 .call 135 .call
136 bv,n %r0(%t1) 136 bv,n %r0(%t1)
137 137
138.Lexit_slowpath: 138.Lexit_slowpath:
139 ldil L%mutex_vector_exit, %t1 139 ldil L%mutex_vector_exit, %t1
140 ldo R%mutex_vector_exit(%t1), %t1 140 ldo R%mutex_vector_exit(%t1), %t1
141 .call 141 .call
142 bv,n %r0(%t1) 142 bv,n %r0(%t1)
143.Lexit_done: 143.Lexit_done:
144 bv,n %r0(%rp) 144 bv,n %r0(%rp)
145 145
146EXIT(mutex_exit) 146EXIT(mutex_exit)
147 147
148/* 148/*
149 * void mutex_enter(kmutex_t *mtx) 149 * void mutex_enter(kmutex_t *mtx)
150 */ 150 */
151 151
152LEAF_ENTRY(mutex_enter) 152LEAF_ENTRY(mutex_enter)
153 153
154 /* 154 /*
155 * It might be a spin lock, or might be already owned. 155 * It might be a spin lock, or might be already owned.
156 * We short circut the request and go straight into 156 * We short circut the request and go straight into
157 * mutex_vector_enter() if the owners field is not clear. 157 * mutex_vector_enter() if the owners field is not clear.
158 */ 158 */
159 159
160 ldi MUTEX_ADAPTIVE_UNOWNED,%t1 160 ldi MUTEX_ADAPTIVE_UNOWNED,%t1
161 ldw MTX_OWNER(%arg0),%t2 161 ldw MTX_OWNER(%arg0),%t2
162 comb,=,n %t1,%t2,.Lmutexunowned 162 comb,=,n %t1,%t2,.Lmutexunowned
163.Lenter_slowpath: 163.Lenter_slowpath:
164 164
165 ldil L%mutex_vector_enter, %t1 165 ldil L%mutex_vector_enter, %t1
166 ldo R%mutex_vector_enter(%t1), %t1 166 ldo R%mutex_vector_enter(%t1), %t1
167 .call 167 .call
168 bv,n %r0(%t1) 168 bv,n %r0(%t1)
169 nop 169 nop
170 170
171 /* 171 /*
172 * We now know that it's an adaptive mutex. Grab the spin 172 * We now know that it's an adaptive mutex. Grab the spin
173 * lock, which is an atomic operation. Once we have that, 173 * lock, which is an atomic operation. Once we have that,
174 * we can set the owner field. If we can't get it, we 174 * we can set the owner field. If we can't get it, we
175 * need to go the slow path. 175 * need to go the slow path.
176 * 176 *
177 * Even if we are preempted between acquiring the lock and 177 * Even if we are preempted between acquiring the lock and
178 * setting the owners field, there is no problem - noone 178 * setting the owners field, there is no problem - noone
179 * else can acquire the mutex while the lock is held. 179 * else can acquire the mutex while the lock is held.
180 */ 180 */
181.Lmutexunowned: 181.Lmutexunowned:
182 ldo (MTX_LOCK + HPPA_LDCW_ALIGN - 1)(%arg0), %t1 182 ldo (MTX_LOCK + HPPA_LDCW_ALIGN - 1)(%arg0), %t1
183 depi 0, 31, 4, %t1 183 depi 0, 31, 4, %t1
184 ldcw 0(%t1), %ret0 184 ldcw 0(%t1), %ret0
185 185
186mutex_enter_crit_start: 186mutex_enter_crit_start:
187 comib,= 0,%ret0,.Lenter_slowpath 187 comib,= 0,%ret0,.Lenter_slowpath
188 188
189 mfctl CR_CURLWP, %t2 189 mfctl CR_CURLWP, %t2
190 190
191 bv %r0(%rp) 191 bv %r0(%rp)
192mutex_enter_crit_end: 192mutex_enter_crit_end:
193 stw %t2,MTX_OWNER(%arg0) 193 stw %t2,MTX_OWNER(%arg0)
194EXIT(mutex_enter) 194EXIT(mutex_enter)
195 195
196#endif /* !LOCKDEBUG */ 196#endif /* !LOCKDEBUG */
197 197
198#endif /* !MULTIPROCESSOR */ 198#else /* !MULTIPROCESSOR */
 199
 200/*
 201 * uintptr_t _lock_cas(volatile uintptr_t *ptr, uintptr_t old, uintptr_t new);
 202 *
 203 * Perform an atomic compare-and-swap operation.
 204 *
 205 * On multi-CPU systems, this has to use an interlock and disable interrupts.
 206 * The interlock is to protect against another CPU attempting to perform the
 207 * cas. Disabling interrupts is to prevent deadlocks on the current CPU. That
 208 * is, we don't want an interrupts attempting to perform a cas on the interlock
 209 * at the same time.
 210 *
 211 */
 212
 213#define IL \
 214 .word __SIMPLELOCK_RAW_UNLOCKED ! \
 215 .word __SIMPLELOCK_RAW_UNLOCKED ! \
 216 .word __SIMPLELOCK_RAW_UNLOCKED ! \
 217 .word __SIMPLELOCK_RAW_UNLOCKED ! \
 218
 219#define I8 \
 220 IL IL IL IL IL IL IL IL
 221
 222#define I64 \
 223 I8 I8 I8 I8 I8 I8 I8 I8
 224
 225
 226
 227 .section .data
 228 .align 4096
 229 .export _lock_hash, data
 230_lock_hash:
 231 I64 I64
 232 I64 I64
 233 I64 I64
 234 I64 I64
 235 I64 I64
 236 I64 I64
 237 I64 I64
 238 I64 I64
 239
 240LEAF_ENTRY(_lock_cas)
 241ALTENTRY(_lock_cas_mp)
 242
 243 mfctl %eiem, %t1
 244 mtctl %r0, %eiem /* disable interrupts */
 245
 246 extru %arg0, 21+8-1, 8, %ret0
 247 ldil L%_lock_hash, %r1
 248 zdep %ret0, 27, 28, %ret0
 249 ldo R%_lock_hash(%r1), %r1
 250
 251 addl %ret0, %r1, %ret0
 252 ldo 15(%ret0), %ret0
 253 copy %ret0, %t3
 254 depi 0, 31, 4, %t3
 255
 256 /* %t3 is the interlock address */
 257 ldcw 0(%t3), %ret0
 258 comib,<>,n 0,%ret0, _lock_cas_mp_interlocked
 259_lock_cas_mp_spin:
 260 ldw 0(%t3),%ret0
 261 comib,= 0,%ret0, _lock_cas_mp_spin
 262 nop
 263 ldcw 0(%t3), %ret0
 264 comib,= 0,%ret0, _lock_cas_mp_spin
 265 nop
 266
 267_lock_cas_mp_interlocked:
 268 ldw 0(%arg0),%ret0
 269 comclr,<> %arg1, %ret0, %r0 /* If *ptr != old, then nullify */
 270 stw %arg2, 0(%arg0)
 271
 272 sync
 273
 274 ldi __SIMPLELOCK_RAW_UNLOCKED, %t4
 275 stw %t4, 0(%t3)
 276 bv %r0(%r2)
 277 mtctl %t1, %eiem /* enable interrupts */
 278
 279EXIT(_lock_cas)
 280
 281STRONG_ALIAS(_atomic_cas_ulong,_lock_cas_mp)
 282STRONG_ALIAS(atomic_cas_ulong,_lock_cas_mp)
 283STRONG_ALIAS(_atomic_cas_32,_lock_cas_mp)
 284STRONG_ALIAS(atomic_cas_32,_lock_cas_mp)
 285STRONG_ALIAS(_atomic_cas_uint,_lock_cas_mp)
 286STRONG_ALIAS(atomic_cas_uint,_lock_cas_mp)
 287STRONG_ALIAS(_atomic_cas_ptr,_lock_cas_mp)
 288STRONG_ALIAS(atomic_cas_ptr,_lock_cas_mp)
 289
 290STRONG_ALIAS(_atomic_cas_ulong_ni,_lock_cas_mp)
 291STRONG_ALIAS(atomic_cas_ulong_ni,_lock_cas_mp)
 292STRONG_ALIAS(_atomic_cas_32_ni,_lock_cas_mp)
 293STRONG_ALIAS(atomic_cas_32_ni,_lock_cas_mp)
 294STRONG_ALIAS(_atomic_cas_uint_ni,_lock_cas_mp)
 295STRONG_ALIAS(atomic_cas_uint_ni,_lock_cas_mp)
 296STRONG_ALIAS(_atomic_cas_ptr_ni,_lock_cas_mp)
 297STRONG_ALIAS(atomic_cas_ptr_ni,_lock_cas_mp)
 298
 299
 300#endif /* MULTIPROCESSOR */