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.
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.
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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #ifndef _THR_INLINES_H
28 #define _THR_INLINES_H
30 #include <sys/ccompile.h>
32 #if !defined(__lint) && defined(__GNUC__)
37 * ON-usable GCC 4.x emits register pseudo-ops declaring %g7 as ignored, rather
38 * than scratch, GCC 3 does the reverse. All uses, both ones it generated
39 * (_curthread) and ones it didn't (__curthread) must agree.
42 #define SPARC_REG_SPEC "#ignore"
44 #define SPARC_REG_SPEC "#scratch"
47 extern __GNU_INLINE ulwp_t
*
52 __asm__
__volatile__("movq %%fs:0, %0" : "=r" (__value
));
55 __asm__
__volatile__("movl %%gs:0, %0" : "=r" (__value
));
56 #elif defined(__sparc)
57 register ulwp_t
*__value
__asm__("g7");
64 extern __GNU_INLINE ulwp_t
*
73 #elif defined(__sparcv9)
74 ".register %%g7, " SPARC_REG_SPEC
"\n\t"
75 "ldx [%%g7 + 80], %0\n\t"
76 #elif defined(__sparc)
77 ".register %%g7, " SPARC_REG_SPEC
"\n\t"
78 "ld [%%g7 + 80], %0\n\t"
86 extern __GNU_INLINE greg_t
90 register greg_t __value
__asm__("rsp");
92 register greg_t __value
__asm__("esp");
93 #elif defined(__sparc)
94 register greg_t __value
__asm__("sp");
101 extern __GNU_INLINE hrtime_t
102 gethrtime(void) /* note: caller-saved registers are trashed */
106 __asm__
__volatile__(
110 : : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "cc");
111 #elif defined(__i386)
113 __asm__
__volatile__(
118 #elif defined(__sparcv9)
119 register hrtime_t __value
__asm__("o0");
120 __asm__
__volatile__(
122 "sllx %%o0, 32, %0\n\t"
125 : : "o1", "o2", "o3", "o4", "o5", "cc");
126 #elif defined(__sparc)
127 register hrtime_t __value
__asm__("o0");
128 __asm__
__volatile__(
131 : : "o2", "o3", "o4", "o5", "cc");
138 extern __GNU_INLINE
int
139 set_lock_byte(volatile uint8_t *__lockp
)
143 __asm__
__volatile__(
146 : "+d" (__value
), "+m" (*__lockp
));
147 #elif defined(__sparc)
148 __asm__
__volatile__(
151 : "=r" (__value
), "+m" (*__lockp
));
158 extern __GNU_INLINE
uint32_t
159 atomic_swap_32(volatile uint32_t *__memory
, uint32_t __value
)
162 __asm__
__volatile__(
164 : "+q" (__value
), "+m" (*__memory
));
166 #elif defined(__sparc)
167 uint32_t __tmp1
, __tmp2
;
168 __asm__
__volatile__(
172 "cas [%3], %0, %1\n\t"
174 "bne,a,pn %%icc, 1b\n\t"
176 : "=&r" (__tmp1
), "=&r" (__tmp2
), "=m" (*__memory
)
177 : "r" (__memory
), "r" (__value
)
185 extern __GNU_INLINE
uint32_t
186 atomic_cas_32(volatile uint32_t *__memory
, uint32_t __cmp
, uint32_t __newvalue
)
190 __asm__
__volatile__(
191 "lock; cmpxchgl %3, %0"
192 : "=m" (*__memory
), "=a" (__oldvalue
)
193 : "a" (__cmp
), "r" (__newvalue
));
194 #elif defined(__sparc)
195 __asm__
__volatile__(
197 : "=m" (*__memory
), "=&r" (__oldvalue
)
198 : "r" (__memory
), "r" (__cmp
), "1" (__newvalue
));
205 extern __GNU_INLINE
void
206 atomic_inc_32(volatile uint32_t *__memory
)
209 __asm__
__volatile__(
212 #elif defined(__sparc)
213 uint32_t __tmp1
, __tmp2
;
214 __asm__
__volatile__(
218 "cas [%3], %0, %1\n\t"
220 "bne,a,pn %%icc, 1b\n\t"
222 : "=&r" (__tmp1
), "=&r" (__tmp2
), "=m" (*__memory
)
230 extern __GNU_INLINE
void
231 atomic_dec_32(volatile uint32_t *__memory
)
234 __asm__
__volatile__(
237 #elif defined(__sparc)
238 uint32_t __tmp1
, __tmp2
;
239 __asm__
__volatile__(
243 "cas [%3], %0, %1\n\t"
245 "bne,a,pn %%icc, 1b\n\t"
247 : "=&r" (__tmp1
), "=&r" (__tmp2
), "=m" (*__memory
)
255 extern __GNU_INLINE
void
256 atomic_and_32(volatile uint32_t *__memory
, uint32_t __bits
)
259 __asm__
__volatile__(
263 #elif defined(__sparc)
264 uint32_t __tmp1
, __tmp2
;
265 __asm__
__volatile__(
269 "cas [%3], %0, %1\n\t"
271 "bne,a,pn %%icc, 1b\n\t"
273 : "=&r" (__tmp1
), "=&r" (__tmp2
), "=m" (*__memory
)
274 : "r" (__memory
), "r" (__bits
)
281 extern __GNU_INLINE
void
282 atomic_or_32(volatile uint32_t *__memory
, uint32_t __bits
)
285 __asm__
__volatile__(
289 #elif defined(__sparc)
290 uint32_t __tmp1
, __tmp2
;
291 __asm__
__volatile__(
295 "cas [%3], %0, %1\n\t"
297 "bne,a,pn %%icc, 1b\n\t"
299 : "=&r" (__tmp1
), "=&r" (__tmp2
), "=m" (*__memory
)
300 : "r" (__memory
), "r" (__bits
)
307 #if defined(__sparc) /* only needed on sparc */
309 extern __GNU_INLINE ulong_t
312 register ulong_t __value
__asm__("i7");
316 extern __GNU_INLINE ulong_t
319 register ulong_t __value
__asm__("fp");
325 #if defined(__x86) /* only needed on x86 */
327 extern __GNU_INLINE
void
330 __asm__
__volatile__("rep; nop");
335 #endif /* !__lint && __GNUC__ */
337 #endif /* _THR_INLINES_H */