1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _THR_INLINES_H 28 #define _THR_INLINES_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #if !defined(__lint) && defined(__GNUC__) 33 34 /* inlines for gcc */ 35 36 extern __inline__ ulwp_t * 37 _curthread(void) 38 { 39 #if defined(__amd64) 40 ulwp_t *__value; 41 __asm__ __volatile__("movq %%fs:0, %0" : "=r" (__value)); 42 #elif defined(__i386) 43 ulwp_t *__value; 44 __asm__ __volatile__("movl %%gs:0, %0" : "=r" (__value)); 45 #elif defined(__sparc) 46 register ulwp_t *__value __asm__("g7"); 47 #else 48 #error "port me" 49 #endif 50 return (__value); 51 } 52 53 extern __inline__ ulwp_t * 54 __curthread(void) 55 { 56 ulwp_t *__value; 57 __asm__ __volatile__( 58 #if defined(__amd64) 59 "movq %%fs:0, %0\n\t" 60 #elif defined(__i386) 61 "movl %%gs:0, %0\n\t" 62 #elif defined(__sparcv9) 63 ".register %%g7, #scratch\n\t" 64 "ldx [%%g7 + 80], %0\n\t" 65 #elif defined(__sparc) 66 ".register %%g7, #scratch\n\t" 67 "ld [%%g7 + 80], %0\n\t" 68 #else 69 #error "port me" 70 #endif 71 "1:" 72 : "=r" (__value) 73 : : "cc"); 74 return (__value); 75 } 76 77 extern __inline__ greg_t 78 stkptr(void) 79 { 80 #if defined(__amd64) 81 register greg_t __value __asm__("rsp"); 82 #elif defined(__i386) 83 register greg_t __value __asm__("esp"); 84 #elif defined(__sparc) 85 register greg_t __value __asm__("sp"); 86 #else 87 #error "port me" 88 #endif 89 return (__value); 90 } 91 92 extern __inline__ hrtime_t 93 gethrtime(void) /* note: caller-saved registers are trashed */ 94 { 95 #if defined(__amd64) 96 hrtime_t __value; 97 __asm__ __volatile__( 98 "movl $3, %%eax\n\t" 99 "int $0xd2" 100 : "=a" (__value) 101 : : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "cc"); 102 #elif defined(__i386) 103 hrtime_t __value; 104 __asm__ __volatile__( 105 "movl $3, %%eax\n\t" 106 "int $0xd2" 107 : "=A" (__value) 108 : : "ecx", "cc"); 109 #elif defined(__sparcv9) 110 register hrtime_t __value __asm__("o0"); 111 __asm__ __volatile__( 112 "ta 0x24\n\t" 113 "sllx %%o0, 32, %0\n\t" 114 "or %%o1, %0, %0" 115 : "=r" (__value) 116 : : "o1", "o2", "o3", "o4", "o5", "cc"); 117 #elif defined(__sparc) 118 register hrtime_t __value __asm__("o0"); 119 __asm__ __volatile__( 120 "ta 0x24" 121 : "=r" (__value) 122 : : "o2", "o3", "o4", "o5", "cc"); 123 #else 124 #error "port me" 125 #endif 126 return (__value); 127 } 128 129 extern __inline__ int 130 set_lock_byte(volatile uint8_t *__lockp) 131 { 132 int __value; 133 #if defined(__x86) 134 __asm__ __volatile__( 135 "movl $1, %0\n\t" 136 "xchgb %%dl, %1" 137 : "+d" (__value), "+m" (*__lockp)); 138 #elif defined(__sparc) 139 __asm__ __volatile__( 140 "ldstub %1, %0\n\t" 141 "membar #LoadLoad" 142 : "=r" (__value), "+m" (*__lockp)); 143 #else 144 #error "port me" 145 #endif 146 return (__value); 147 } 148 149 extern __inline__ uint32_t 150 atomic_swap_32(volatile uint32_t *__memory, uint32_t __value) 151 { 152 #if defined(__x86) 153 __asm__ __volatile__( 154 "xchgl %0, %1" 155 : "+q" (__value), "+m" (*__memory)); 156 return (__value); 157 #elif defined(__sparc) 158 uint32_t __tmp1, __tmp2; 159 __asm__ __volatile__( 160 "ld [%3], %0\n\t" 161 "1:\n\t" 162 "mov %4, %1\n\t" 163 "cas [%3], %0, %1\n\t" 164 "cmp %0, %1\n\t" 165 "bne,a,pn %%icc, 1b\n\t" 166 " mov %1, %0" 167 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 168 : "r" (__memory), "r" (__value) 169 : "cc"); 170 return (__tmp2); 171 #else 172 #error "port me" 173 #endif 174 } 175 176 extern __inline__ uint32_t 177 atomic_cas_32(volatile uint32_t *__memory, uint32_t __cmp, uint32_t __newvalue) 178 { 179 uint32_t __oldvalue; 180 #if defined(__x86) 181 __asm__ __volatile__( 182 "lock; cmpxchgl %3, %0" 183 : "=m" (*__memory), "=a" (__oldvalue) 184 : "a" (__cmp), "r" (__newvalue)); 185 #elif defined(__sparc) 186 __asm__ __volatile__( 187 "cas [%2], %3, %1" 188 : "=m" (*__memory), "=&r" (__oldvalue) 189 : "r" (__memory), "r" (__cmp), "1" (__newvalue)); 190 #else 191 #error "port me" 192 #endif 193 return (__oldvalue); 194 } 195 196 extern __inline__ void 197 atomic_inc_32(volatile uint32_t *__memory) 198 { 199 #if defined(__x86) 200 __asm__ __volatile__( 201 "lock; incl %0" 202 : "+m" (*__memory)); 203 #elif defined(__sparc) 204 uint32_t __tmp1, __tmp2; 205 __asm__ __volatile__( 206 "ld [%3], %0\n\t" 207 "1:\n\t" 208 "add %0, 1, %1\n\t" 209 "cas [%3], %0, %1\n\t" 210 "cmp %0, %1\n\t" 211 "bne,a,pn %%icc, 1b\n\t" 212 " mov %1, %0" 213 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 214 : "r" (__memory) 215 : "cc"); 216 #else 217 #error "port me" 218 #endif 219 } 220 221 extern __inline__ void 222 atomic_dec_32(volatile uint32_t *__memory) 223 { 224 #if defined(__x86) 225 __asm__ __volatile__( 226 "lock; decl %0" 227 : "+m" (*__memory)); 228 #elif defined(__sparc) 229 uint32_t __tmp1, __tmp2; 230 __asm__ __volatile__( 231 "ld [%3], %0\n\t" 232 "1:\n\t" 233 "sub %0, 1, %1\n\t" 234 "cas [%3], %0, %1\n\t" 235 "cmp %0, %1\n\t" 236 "bne,a,pn %%icc, 1b\n\t" 237 " mov %1, %0" 238 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 239 : "r" (__memory) 240 : "cc"); 241 #else 242 #error "port me" 243 #endif 244 } 245 246 extern __inline__ void 247 atomic_and_32(volatile uint32_t *__memory, uint32_t __bits) 248 { 249 #if defined(__x86) 250 __asm__ __volatile__( 251 "lock; andl %1, %0" 252 : "+m" (*__memory) 253 : "r" (__bits)); 254 #elif defined(__sparc) 255 uint32_t __tmp1, __tmp2; 256 __asm__ __volatile__( 257 "ld [%3], %0\n\t" 258 "1:\n\t" 259 "and %0, %4, %1\n\t" 260 "cas [%3], %0, %1\n\t" 261 "cmp %0, %1\n\t" 262 "bne,a,pn %%icc, 1b\n\t" 263 " mov %1, %0" 264 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 265 : "r" (__memory), "r" (__bits) 266 : "cc"); 267 #else 268 #error "port me" 269 #endif 270 } 271 272 extern __inline__ void 273 atomic_or_32(volatile uint32_t *__memory, uint32_t __bits) 274 { 275 #if defined(__x86) 276 __asm__ __volatile__( 277 "lock; orl %1, %0" 278 : "+m" (*__memory) 279 : "r" (__bits)); 280 #elif defined(__sparc) 281 uint32_t __tmp1, __tmp2; 282 __asm__ __volatile__( 283 "ld [%3], %0\n\t" 284 "1:\n\t" 285 "or %0, %4, %1\n\t" 286 "cas [%3], %0, %1\n\t" 287 "cmp %0, %1\n\t" 288 "bne,a,pn %%icc, 1b\n\t" 289 " mov %1, %0" 290 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory) 291 : "r" (__memory), "r" (__bits) 292 : "cc"); 293 #else 294 #error "port me" 295 #endif 296 } 297 298 #if defined(__sparc) /* only needed on sparc */ 299 300 extern __inline__ ulong_t 301 caller(void) 302 { 303 register ulong_t __value __asm__("i7"); 304 return (__value); 305 } 306 307 extern __inline__ ulong_t 308 getfp(void) 309 { 310 register ulong_t __value __asm__("fp"); 311 return (__value); 312 } 313 314 #endif /* __sparc */ 315 316 #if defined(__x86) /* only needed on x86 */ 317 318 extern __inline__ void 319 ht_pause(void) 320 { 321 __asm__ __volatile__("rep; nop"); 322 } 323 324 #endif /* __x86 */ 325 326 #endif /* !__lint && __GNUC__ */ 327 328 #endif /* _THR_INLINES_H */ 329