1 /* $OpenBSD: atomic.h,v 1.12 2014/03/29 18:09:28 guenther Exp $ */ 2 /* $NetBSD: atomic.h,v 1.7 2001/12/17 23:34:57 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Misc. `atomic' operations. 36 */ 37 38 #ifndef _MACHINE_ATOMIC_H_ 39 #define _MACHINE_ATOMIC_H_ 40 41 #if defined(_KERNEL) 42 43 /* 44 * atomic_setbits_ulong: 45 * 46 * Atomically set bits in a `unsigned long'. 47 */ 48 static __inline void 49 atomic_setbits_ulong(volatile unsigned long *ulp, unsigned long v) 50 { 51 unsigned long t0; 52 53 __asm volatile( 54 "# BEGIN atomic_setbits_ulong\n" 55 "1: ldq_l %0, %1 \n" 56 " or %0, %2, %0 \n" 57 " stq_c %0, %1 \n" 58 " beq %0, 2f \n" 59 " mb \n" 60 " br 3f \n" 61 "2: br 1b \n" 62 "3: \n" 63 " # END atomic_setbits_ulong" 64 : "=&r" (t0), "=m" (*ulp) 65 : "r" (v) 66 : "memory"); 67 } 68 69 /* 70 * atomic_clearbits_ulong: 71 * 72 * Atomically clear bits in a `unsigned long'. 73 */ 74 static __inline void 75 atomic_clearbits_ulong(volatile unsigned long *ulp, unsigned long v) 76 { 77 unsigned long t0; 78 79 __asm volatile( 80 "# BEGIN atomic_clearbits_ulong\n" 81 "1: ldq_l %0, %1 \n" 82 " and %0, %2, %0 \n" 83 " stq_c %0, %1 \n" 84 " beq %0, 2f \n" 85 " mb \n" 86 " br 3f \n" 87 "2: br 1b \n" 88 "3: \n" 89 " # END atomic_clearbits_ulong" 90 : "=&r" (t0), "=m" (*ulp) 91 : "r" (~v) 92 : "memory"); 93 } 94 95 /* 96 * atomic_add_ulong: 97 * 98 * Atomically add a value to a `unsigned long'. 99 */ 100 static __inline void 101 atomic_add_ulong(volatile unsigned long *ulp, unsigned long v) 102 { 103 unsigned long t0; 104 105 __asm volatile( 106 "# BEGIN atomic_add_ulong\n" 107 "1: ldq_l %0, %1 \n" 108 " addq %0, %2, %0 \n" 109 " stq_c %0, %1 \n" 110 " beq %0, 2f \n" 111 " mb \n" 112 " br 3f \n" 113 "2: br 1b \n" 114 "3: \n" 115 " # END atomic_add_ulong" 116 : "=&r" (t0), "=m" (*ulp) 117 : "r" (v) 118 : "memory"); 119 } 120 121 /* 122 * atomic_sub_ulong: 123 * 124 * Atomically subtract a value from a `unsigned long'. 125 */ 126 static __inline void 127 atomic_sub_ulong(volatile unsigned long *ulp, unsigned long v) 128 { 129 unsigned long t0; 130 131 __asm volatile( 132 "# BEGIN atomic_sub_ulong\n" 133 "1: ldq_l %0, %1 \n" 134 " subq %0, %2, %0 \n" 135 " stq_c %0, %1 \n" 136 " beq %0, 2f \n" 137 " mb \n" 138 " br 3f \n" 139 "2: br 1b \n" 140 "3: \n" 141 " # END atomic_sub_ulong" 142 : "=&r" (t0), "=m" (*ulp) 143 : "r" (v) 144 : "memory"); 145 } 146 147 /* 148 * atomic_loadlatch_ulong: 149 * 150 * Atomically load and latch a `unsigned long' value. 151 */ 152 static __inline unsigned long 153 atomic_loadlatch_ulong(volatile unsigned long *ulp, unsigned long v) 154 { 155 unsigned long t0, v0; 156 157 __asm volatile( 158 "# BEGIN atomic_loadlatch_ulong\n" 159 "1: mov %3, %0 \n" 160 " ldq_l %1, %2 \n" 161 " stq_c %0, %2 \n" 162 " beq %0, 2f \n" 163 " mb \n" 164 " br 3f \n" 165 "2: br 1b \n" 166 "3: \n" 167 " # END atomic_loadlatch_ulong" 168 : "=&r" (t0), "=r" (v0), "=m" (*ulp) 169 : "r" (v) 170 : "memory"); 171 172 return (v0); 173 } 174 175 /* 176 * atomic_setbits_int: 177 * 178 * Atomically set bits in a `unsigned int'. 179 */ 180 static __inline void 181 atomic_setbits_int(volatile unsigned int *uip, unsigned int v) 182 { 183 unsigned int t0; 184 185 __asm volatile( 186 "# BEGIN atomic_setbits_ulong\n" 187 "1: ldl_l %0, %1 \n" 188 " or %0, %2, %0 \n" 189 " stl_c %0, %1 \n" 190 " beq %0, 2f \n" 191 " mb \n" 192 " br 3f \n" 193 "2: br 1b \n" 194 "3: \n" 195 " # END atomic_setbits_int" 196 : "=&r" (t0), "=m" (*uip) 197 : "r" (v) 198 : "memory"); 199 } 200 201 /* 202 * atomic_clearbits_int: 203 * 204 * Atomically clear bits in a `unsigned int'. 205 */ 206 static __inline void 207 atomic_clearbits_int(volatile unsigned int *uip, unsigned int v) 208 { 209 unsigned int t0; 210 211 __asm volatile( 212 "# BEGIN atomic_clearbits_int\n" 213 "1: ldl_l %0, %1 \n" 214 " and %0, %2, %0 \n" 215 " stl_c %0, %1 \n" 216 " beq %0, 2f \n" 217 " mb \n" 218 " br 3f \n" 219 "2: br 1b \n" 220 "3: \n" 221 " # END atomic_clearbits_int" 222 : "=&r" (t0), "=m" (*uip) 223 : "r" (~v) 224 : "memory"); 225 } 226 227 /* 228 * atomic_add_int: 229 * 230 * Atomically add a value to an `int'. 231 */ 232 static __inline void 233 atomic_add_int(volatile int *ulp, int v) 234 { 235 unsigned long t0; 236 237 __asm volatile( 238 "# BEGIN atomic_add_int\n" 239 "1: ldl_l %0, %1 \n" 240 " addl %0, %2, %0 \n" 241 " stl_c %0, %1 \n" 242 " beq %0, 2f \n" 243 " mb \n" 244 " br 3f \n" 245 "2: br 1b \n" 246 "3: \n" 247 " # END atomic_add_ulong" 248 : "=&r" (t0), "=m" (*ulp) 249 : "r" (v) 250 : "memory"); 251 } 252 253 #endif /* defined(_KERNEL) */ 254 #endif /* _MACHINE_ATOMIC_H_ */ 255