xref: /titanic_41/usr/src/lib/libc/inc/thr_inlines.h (revision 6a3e8e8695d5c7d1d18c6800d676990d7f61a2a4)
10ec57554Sraf /*
20ec57554Sraf  * CDDL HEADER START
30ec57554Sraf  *
40ec57554Sraf  * The contents of this file are subject to the terms of the
50ec57554Sraf  * Common Development and Distribution License (the "License").
60ec57554Sraf  * You may not use this file except in compliance with the License.
70ec57554Sraf  *
80ec57554Sraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90ec57554Sraf  * or http://www.opensolaris.org/os/licensing.
100ec57554Sraf  * See the License for the specific language governing permissions
110ec57554Sraf  * and limitations under the License.
120ec57554Sraf  *
130ec57554Sraf  * When distributing Covered Code, include this CDDL HEADER in each
140ec57554Sraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150ec57554Sraf  * If applicable, add the following below this CDDL HEADER, with the
160ec57554Sraf  * fields enclosed by brackets "[]" replaced with your own identifying
170ec57554Sraf  * information: Portions Copyright [yyyy] [name of copyright owner]
180ec57554Sraf  *
190ec57554Sraf  * CDDL HEADER END
200ec57554Sraf  */
210ec57554Sraf 
220ec57554Sraf /*
23ae115bc7Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240ec57554Sraf  * Use is subject to license terms.
250ec57554Sraf  */
260ec57554Sraf 
270ec57554Sraf #ifndef _THR_INLINES_H
280ec57554Sraf #define	_THR_INLINES_H
290ec57554Sraf 
30*6a3e8e86SRichard Lowe #include <sys/ccompile.h>
310ec57554Sraf 
320ec57554Sraf #if !defined(__lint) && defined(__GNUC__)
330ec57554Sraf 
340ec57554Sraf /* inlines for gcc */
350ec57554Sraf 
36*6a3e8e86SRichard Lowe /*
37*6a3e8e86SRichard Lowe  * ON-usable GCC 4.x emits register pseudo-ops declaring %g7 as ignored, rather
38*6a3e8e86SRichard Lowe  * than scratch, GCC 3 does the reverse.  All uses, both ones it generated
39*6a3e8e86SRichard Lowe  * (_curthread) and ones it didn't (__curthread) must agree.
40*6a3e8e86SRichard Lowe  */
41*6a3e8e86SRichard Lowe #if __GNUC__ > 3
42*6a3e8e86SRichard Lowe #define	SPARC_REG_SPEC	"#ignore"
43*6a3e8e86SRichard Lowe #else
44*6a3e8e86SRichard Lowe #define	SPARC_REG_SPEC	"#scratch"
45*6a3e8e86SRichard Lowe #endif
46*6a3e8e86SRichard Lowe 
47*6a3e8e86SRichard Lowe extern __GNU_INLINE ulwp_t *
_curthread(void)480ec57554Sraf _curthread(void)
490ec57554Sraf {
500ec57554Sraf #if defined(__amd64)
510ec57554Sraf 	ulwp_t *__value;
520ec57554Sraf 	__asm__ __volatile__("movq %%fs:0, %0" : "=r" (__value));
530ec57554Sraf #elif defined(__i386)
540ec57554Sraf 	ulwp_t *__value;
550ec57554Sraf 	__asm__ __volatile__("movl %%gs:0, %0" : "=r" (__value));
560ec57554Sraf #elif defined(__sparc)
570ec57554Sraf 	register ulwp_t *__value __asm__("g7");
580ec57554Sraf #else
590ec57554Sraf #error	"port me"
600ec57554Sraf #endif
610ec57554Sraf 	return (__value);
620ec57554Sraf }
630ec57554Sraf 
64*6a3e8e86SRichard Lowe extern __GNU_INLINE ulwp_t *
__curthread(void)650ec57554Sraf __curthread(void)
660ec57554Sraf {
670ec57554Sraf 	ulwp_t *__value;
680ec57554Sraf 	__asm__ __volatile__(
690ec57554Sraf #if defined(__amd64)
700ec57554Sraf 	    "movq %%fs:0, %0\n\t"
710ec57554Sraf #elif defined(__i386)
720ec57554Sraf 	    "movl %%gs:0, %0\n\t"
730ec57554Sraf #elif defined(__sparcv9)
74*6a3e8e86SRichard Lowe 	    ".register %%g7, " SPARC_REG_SPEC "\n\t"
750ec57554Sraf 	    "ldx [%%g7 + 80], %0\n\t"
760ec57554Sraf #elif defined(__sparc)
77*6a3e8e86SRichard Lowe 	    ".register %%g7, " SPARC_REG_SPEC "\n\t"
780ec57554Sraf 	    "ld [%%g7 + 80], %0\n\t"
790ec57554Sraf #else
800ec57554Sraf #error	"port me"
810ec57554Sraf #endif
82*6a3e8e86SRichard Lowe 	    : "=r" (__value));
830ec57554Sraf 	return (__value);
840ec57554Sraf }
850ec57554Sraf 
86*6a3e8e86SRichard Lowe extern __GNU_INLINE greg_t
stkptr(void)870ec57554Sraf stkptr(void)
880ec57554Sraf {
890ec57554Sraf #if defined(__amd64)
900ec57554Sraf 	register greg_t __value __asm__("rsp");
910ec57554Sraf #elif defined(__i386)
920ec57554Sraf 	register greg_t __value __asm__("esp");
930ec57554Sraf #elif defined(__sparc)
940ec57554Sraf 	register greg_t __value __asm__("sp");
950ec57554Sraf #else
960ec57554Sraf #error	"port me"
970ec57554Sraf #endif
980ec57554Sraf 	return (__value);
990ec57554Sraf }
1000ec57554Sraf 
101*6a3e8e86SRichard Lowe extern __GNU_INLINE hrtime_t
gethrtime(void)1020ec57554Sraf gethrtime(void)		/* note: caller-saved registers are trashed */
1030ec57554Sraf {
1040ec57554Sraf #if defined(__amd64)
1050ec57554Sraf 	hrtime_t __value;
1060ec57554Sraf 	__asm__ __volatile__(
1070ec57554Sraf 	    "movl $3, %%eax\n\t"
1080ec57554Sraf 	    "int $0xd2"
1090ec57554Sraf 	    : "=a" (__value)
1100ec57554Sraf 	    : : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "cc");
1110ec57554Sraf #elif defined(__i386)
1120ec57554Sraf 	hrtime_t __value;
1130ec57554Sraf 	__asm__ __volatile__(
1140ec57554Sraf 	    "movl $3, %%eax\n\t"
1150ec57554Sraf 	    "int $0xd2"
1160ec57554Sraf 	    : "=A" (__value)
1170ec57554Sraf 	    : : "ecx", "cc");
1180ec57554Sraf #elif defined(__sparcv9)
1190ec57554Sraf 	register hrtime_t __value __asm__("o0");
1200ec57554Sraf 	__asm__ __volatile__(
1210ec57554Sraf 	    "ta 0x24\n\t"
1220ec57554Sraf 	    "sllx %%o0, 32, %0\n\t"
1230ec57554Sraf 	    "or %%o1, %0, %0"
1240ec57554Sraf 	    : "=r" (__value)
1250ec57554Sraf 	    : : "o1", "o2", "o3", "o4", "o5", "cc");
1260ec57554Sraf #elif defined(__sparc)
1270ec57554Sraf 	register hrtime_t __value __asm__("o0");
1280ec57554Sraf 	__asm__ __volatile__(
1290ec57554Sraf 	    "ta 0x24"
1300ec57554Sraf 	    : "=r" (__value)
1310ec57554Sraf 	    : : "o2", "o3", "o4", "o5", "cc");
1320ec57554Sraf #else
1330ec57554Sraf #error	"port me"
1340ec57554Sraf #endif
1350ec57554Sraf 	return (__value);
1360ec57554Sraf }
1370ec57554Sraf 
138*6a3e8e86SRichard Lowe extern __GNU_INLINE int
set_lock_byte(volatile uint8_t * __lockp)1390ec57554Sraf set_lock_byte(volatile uint8_t *__lockp)
1400ec57554Sraf {
1410ec57554Sraf 	int __value;
1420ec57554Sraf #if defined(__x86)
1430ec57554Sraf 	__asm__ __volatile__(
1440ec57554Sraf 	    "movl $1, %0\n\t"
1450ec57554Sraf 	    "xchgb %%dl, %1"
1460ec57554Sraf 	    : "+d" (__value), "+m" (*__lockp));
1470ec57554Sraf #elif defined(__sparc)
1480ec57554Sraf 	__asm__ __volatile__(
1490ec57554Sraf 	    "ldstub %1, %0\n\t"
1500ec57554Sraf 	    "membar #LoadLoad"
1510ec57554Sraf 	    : "=r" (__value), "+m" (*__lockp));
1520ec57554Sraf #else
1530ec57554Sraf #error	"port me"
1540ec57554Sraf #endif
1550ec57554Sraf 	return (__value);
1560ec57554Sraf }
1570ec57554Sraf 
158*6a3e8e86SRichard Lowe extern __GNU_INLINE uint32_t
atomic_swap_32(volatile uint32_t * __memory,uint32_t __value)15941efec22Sraf atomic_swap_32(volatile uint32_t *__memory, uint32_t __value)
1600ec57554Sraf {
1610ec57554Sraf #if defined(__x86)
1620ec57554Sraf 	__asm__ __volatile__(
1630ec57554Sraf 	    "xchgl %0, %1"
1640ec57554Sraf 	    : "+q" (__value), "+m" (*__memory));
1650ec57554Sraf 	return (__value);
1660ec57554Sraf #elif defined(__sparc)
1670ec57554Sraf 	uint32_t __tmp1, __tmp2;
1680ec57554Sraf 	__asm__ __volatile__(
1690ec57554Sraf 	    "ld [%3], %0\n\t"
1700ec57554Sraf 	    "1:\n\t"
1710ec57554Sraf 	    "mov %4, %1\n\t"
1720ec57554Sraf 	    "cas [%3], %0, %1\n\t"
1730ec57554Sraf 	    "cmp %0, %1\n\t"
1740ec57554Sraf 	    "bne,a,pn %%icc, 1b\n\t"
1750ec57554Sraf 	    "  mov %1, %0"
1760ec57554Sraf 	    : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
1770ec57554Sraf 	    : "r" (__memory), "r" (__value)
1780ec57554Sraf 	    : "cc");
1790ec57554Sraf 	return (__tmp2);
1800ec57554Sraf #else
1810ec57554Sraf #error	"port me"
1820ec57554Sraf #endif
1830ec57554Sraf }
1840ec57554Sraf 
185*6a3e8e86SRichard Lowe extern __GNU_INLINE uint32_t
atomic_cas_32(volatile uint32_t * __memory,uint32_t __cmp,uint32_t __newvalue)18641efec22Sraf atomic_cas_32(volatile uint32_t *__memory, uint32_t __cmp, uint32_t __newvalue)
1870ec57554Sraf {
1880ec57554Sraf 	uint32_t __oldvalue;
1890ec57554Sraf #if defined(__x86)
1900ec57554Sraf 	__asm__ __volatile__(
1910ec57554Sraf 	    "lock; cmpxchgl %3, %0"
1920ec57554Sraf 	    : "=m" (*__memory), "=a" (__oldvalue)
1930ec57554Sraf 	    : "a" (__cmp), "r" (__newvalue));
1940ec57554Sraf #elif defined(__sparc)
1950ec57554Sraf 	__asm__ __volatile__(
1960ec57554Sraf 	    "cas [%2], %3, %1"
19741efec22Sraf 	    : "=m" (*__memory), "=&r" (__oldvalue)
1980ec57554Sraf 	    : "r" (__memory), "r" (__cmp), "1" (__newvalue));
1990ec57554Sraf #else
2000ec57554Sraf #error	"port me"
2010ec57554Sraf #endif
2020ec57554Sraf 	return (__oldvalue);
2030ec57554Sraf }
2040ec57554Sraf 
205*6a3e8e86SRichard Lowe extern __GNU_INLINE void
atomic_inc_32(volatile uint32_t * __memory)20641efec22Sraf atomic_inc_32(volatile uint32_t *__memory)
2070ec57554Sraf {
2080ec57554Sraf #if defined(__x86)
2090ec57554Sraf 	__asm__ __volatile__(
2100ec57554Sraf 	    "lock; incl %0"
2110ec57554Sraf 	    : "+m" (*__memory));
2120ec57554Sraf #elif defined(__sparc)
2130ec57554Sraf 	uint32_t __tmp1, __tmp2;
2140ec57554Sraf 	__asm__ __volatile__(
2150ec57554Sraf 	    "ld [%3], %0\n\t"
2160ec57554Sraf 	    "1:\n\t"
2170ec57554Sraf 	    "add %0, 1, %1\n\t"
2180ec57554Sraf 	    "cas [%3], %0, %1\n\t"
2190ec57554Sraf 	    "cmp %0, %1\n\t"
2200ec57554Sraf 	    "bne,a,pn %%icc, 1b\n\t"
2210ec57554Sraf 	    "  mov %1, %0"
2220ec57554Sraf 	    : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
2230ec57554Sraf 	    : "r" (__memory)
2240ec57554Sraf 	    : "cc");
2250ec57554Sraf #else
2260ec57554Sraf #error	"port me"
2270ec57554Sraf #endif
2280ec57554Sraf }
2290ec57554Sraf 
230*6a3e8e86SRichard Lowe extern __GNU_INLINE void
atomic_dec_32(volatile uint32_t * __memory)23141efec22Sraf atomic_dec_32(volatile uint32_t *__memory)
2320ec57554Sraf {
2330ec57554Sraf #if defined(__x86)
2340ec57554Sraf 	__asm__ __volatile__(
2350ec57554Sraf 	    "lock; decl %0"
2360ec57554Sraf 	    : "+m" (*__memory));
2370ec57554Sraf #elif defined(__sparc)
2380ec57554Sraf 	uint32_t __tmp1, __tmp2;
2390ec57554Sraf 	__asm__ __volatile__(
2400ec57554Sraf 	    "ld [%3], %0\n\t"
2410ec57554Sraf 	    "1:\n\t"
2420ec57554Sraf 	    "sub %0, 1, %1\n\t"
2430ec57554Sraf 	    "cas [%3], %0, %1\n\t"
2440ec57554Sraf 	    "cmp %0, %1\n\t"
2450ec57554Sraf 	    "bne,a,pn %%icc, 1b\n\t"
2460ec57554Sraf 	    "  mov %1, %0"
2470ec57554Sraf 	    : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
2480ec57554Sraf 	    : "r" (__memory)
2490ec57554Sraf 	    : "cc");
2500ec57554Sraf #else
2510ec57554Sraf #error	"port me"
2520ec57554Sraf #endif
2530ec57554Sraf }
2540ec57554Sraf 
255*6a3e8e86SRichard Lowe extern __GNU_INLINE void
atomic_and_32(volatile uint32_t * __memory,uint32_t __bits)25641efec22Sraf atomic_and_32(volatile uint32_t *__memory, uint32_t __bits)
25741efec22Sraf {
25841efec22Sraf #if defined(__x86)
25941efec22Sraf 	__asm__ __volatile__(
26041efec22Sraf 	    "lock; andl %1, %0"
26141efec22Sraf 	    : "+m" (*__memory)
26241efec22Sraf 	    : "r" (__bits));
26341efec22Sraf #elif defined(__sparc)
26441efec22Sraf 	uint32_t __tmp1, __tmp2;
26541efec22Sraf 	__asm__ __volatile__(
26641efec22Sraf 	    "ld [%3], %0\n\t"
26741efec22Sraf 	    "1:\n\t"
26841efec22Sraf 	    "and %0, %4, %1\n\t"
26941efec22Sraf 	    "cas [%3], %0, %1\n\t"
27041efec22Sraf 	    "cmp %0, %1\n\t"
27141efec22Sraf 	    "bne,a,pn %%icc, 1b\n\t"
27241efec22Sraf 	    "  mov %1, %0"
27341efec22Sraf 	    : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
27441efec22Sraf 	    : "r" (__memory), "r" (__bits)
27541efec22Sraf 	    : "cc");
27641efec22Sraf #else
27741efec22Sraf #error	"port me"
27841efec22Sraf #endif
27941efec22Sraf }
28041efec22Sraf 
281*6a3e8e86SRichard Lowe extern __GNU_INLINE void
atomic_or_32(volatile uint32_t * __memory,uint32_t __bits)28241efec22Sraf atomic_or_32(volatile uint32_t *__memory, uint32_t __bits)
28341efec22Sraf {
28441efec22Sraf #if defined(__x86)
28541efec22Sraf 	__asm__ __volatile__(
28641efec22Sraf 	    "lock; orl %1, %0"
28741efec22Sraf 	    : "+m" (*__memory)
28841efec22Sraf 	    : "r" (__bits));
28941efec22Sraf #elif defined(__sparc)
29041efec22Sraf 	uint32_t __tmp1, __tmp2;
29141efec22Sraf 	__asm__ __volatile__(
29241efec22Sraf 	    "ld [%3], %0\n\t"
29341efec22Sraf 	    "1:\n\t"
29441efec22Sraf 	    "or %0, %4, %1\n\t"
29541efec22Sraf 	    "cas [%3], %0, %1\n\t"
29641efec22Sraf 	    "cmp %0, %1\n\t"
29741efec22Sraf 	    "bne,a,pn %%icc, 1b\n\t"
29841efec22Sraf 	    "  mov %1, %0"
29941efec22Sraf 	    : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
30041efec22Sraf 	    : "r" (__memory), "r" (__bits)
30141efec22Sraf 	    : "cc");
30241efec22Sraf #else
30341efec22Sraf #error	"port me"
30441efec22Sraf #endif
30541efec22Sraf }
30641efec22Sraf 
3070ec57554Sraf #if defined(__sparc)	/* only needed on sparc */
3080ec57554Sraf 
309*6a3e8e86SRichard Lowe extern __GNU_INLINE ulong_t
caller(void)3100ec57554Sraf caller(void)
3110ec57554Sraf {
3120ec57554Sraf 	register ulong_t __value __asm__("i7");
3130ec57554Sraf 	return (__value);
3140ec57554Sraf }
3150ec57554Sraf 
316*6a3e8e86SRichard Lowe extern __GNU_INLINE ulong_t
getfp(void)3170ec57554Sraf getfp(void)
3180ec57554Sraf {
3190ec57554Sraf 	register ulong_t __value __asm__("fp");
3200ec57554Sraf 	return (__value);
3210ec57554Sraf }
3220ec57554Sraf 
3230ec57554Sraf #endif	/* __sparc */
3240ec57554Sraf 
3250ec57554Sraf #if defined(__x86)	/* only needed on x86 */
3260ec57554Sraf 
327*6a3e8e86SRichard Lowe extern __GNU_INLINE void
ht_pause(void)3280ec57554Sraf ht_pause(void)
3290ec57554Sraf {
3300ec57554Sraf 	__asm__ __volatile__("rep; nop");
3310ec57554Sraf }
3320ec57554Sraf 
3330ec57554Sraf #endif	/* __x86 */
3340ec57554Sraf 
3350ec57554Sraf #endif	/* !__lint && __GNUC__ */
3360ec57554Sraf 
3370ec57554Sraf #endif	/* _THR_INLINES_H */
338