xref: /illumos-gate/usr/src/lib/libc/inc/thr_inlines.h (revision 65a89a64c60f3061bbe2381edaacc81660af9a95)
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 2005 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 		"xorq %0, %0\n\t"
60 		"mov %%fs, %0\n\t"
61 		"andq %0, %0\n\t"
62 		"je 1f\n\t"
63 		"movq %%fs:0, %0\n\t"
64 #elif defined(__i386)
65 		"xorl %0, %0\n\t"
66 		"mov %%gs, %0\n\t"
67 		"andl %0, %0\n\t"
68 		"je 1f\n\t"
69 		"movl %%gs:0, %0\n\t"
70 #elif defined(__sparcv9)
71 		".register %%g7, #scratch\n\t"
72 		"tst %%g7\n\t"
73 		"be,a,pn %%xcc, 1f\n\t"
74 		"  mov %%g0, %0\n\t"
75 		"ldx [%%g7 + 80], %0\n\t"
76 #elif defined(__sparc)
77 		".register %%g7, #scratch\n\t"
78 		"tst %%g7\n\t"
79 		"be,a 1f\n\t"
80 		"  mov %%g0, %0\n\t"
81 		"ld [%%g7 + 80], %0\n\t"
82 #else
83 #error	"port me"
84 #endif
85 		"1:"
86 		: "=r" (__value)
87 		: : "cc");
88 	return (__value);
89 }
90 
91 extern __inline__ greg_t
92 stkptr(void)
93 {
94 #if defined(__amd64)
95 	register greg_t __value __asm__("rsp");
96 #elif defined(__i386)
97 	register greg_t __value __asm__("esp");
98 #elif defined(__sparc)
99 	register greg_t __value __asm__("sp");
100 #else
101 #error	"port me"
102 #endif
103 	return (__value);
104 }
105 
106 extern __inline__ hrtime_t
107 gethrtime(void)		/* note: caller-saved registers are trashed */
108 {
109 #if defined(__amd64)
110 	hrtime_t __value;
111 	__asm__ __volatile__(
112 		"movl $3, %%eax\n\t"
113 		"int $0xd2"
114 		: "=a" (__value)
115 		: : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "cc");
116 #elif defined(__i386)
117 	hrtime_t __value;
118 	__asm__ __volatile__(
119 		"movl $3, %%eax\n\t"
120 		"int $0xd2"
121 		: "=A" (__value)
122 		: : "ecx", "cc");
123 #elif defined(__sparcv9)
124 	register hrtime_t __value __asm__("o0");
125 	__asm__ __volatile__(
126 		"ta 0x24\n\t"
127 		"sllx %%o0, 32, %0\n\t"
128 		"or %%o1, %0, %0"
129 		: "=r" (__value)
130 		: : "o1", "o2", "o3", "o4", "o5", "cc");
131 #elif defined(__sparc)
132 	register hrtime_t __value __asm__("o0");
133 	__asm__ __volatile__(
134 		"ta 0x24"
135 		: "=r" (__value)
136 		: : "o2", "o3", "o4", "o5", "cc");
137 #else
138 #error	"port me"
139 #endif
140 	return (__value);
141 }
142 
143 extern __inline__ int
144 set_lock_byte(volatile uint8_t *__lockp)
145 {
146 	int __value;
147 #if defined(__x86)
148 	__asm__ __volatile__(
149 		"movl $1, %0\n\t"
150 		"xchgb %%dl, %1"
151 		: "+d" (__value), "+m" (*__lockp));
152 #elif defined(__sparc)
153 	__asm__ __volatile__(
154 		"ldstub %1, %0\n\t"
155 		"membar #LoadLoad"
156 		: "=r" (__value), "+m" (*__lockp));
157 #else
158 #error	"port me"
159 #endif
160 	return (__value);
161 }
162 
163 extern __inline__ uint32_t
164 swap32(volatile uint32_t *__memory, uint32_t __value)
165 {
166 #if defined(__x86)
167 	__asm__ __volatile__(
168 		"xchgl %0, %1"
169 		: "+q" (__value), "+m" (*__memory));
170 	return (__value);
171 #elif defined(__sparc)
172 	uint32_t __tmp1, __tmp2;
173 	__asm__ __volatile__(
174 		"ld [%3], %0\n\t"
175 		"1:\n\t"
176 		"mov %4, %1\n\t"
177 		"cas [%3], %0, %1\n\t"
178 		"cmp %0, %1\n\t"
179 		"bne,a,pn %%icc, 1b\n\t"
180 		"  mov %1, %0"
181 		: "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
182 		: "r" (__memory), "r" (__value)
183 		: "cc");
184 	return (__tmp2);
185 #else
186 #error	"port me"
187 #endif
188 }
189 
190 extern __inline__ uint32_t
191 cas32(volatile uint32_t *__memory, uint32_t __cmp, uint32_t __newvalue)
192 {
193 	uint32_t __oldvalue;
194 #if defined(__x86)
195 	__asm__ __volatile__(
196 		"lock; cmpxchgl %3, %0"
197 		: "=m" (*__memory), "=a" (__oldvalue)
198 		: "a" (__cmp), "r" (__newvalue));
199 #elif defined(__sparc)
200 	__asm__ __volatile__(
201 		"cas [%2], %3, %1"
202 		: "=m" (*__memory),  "+r" (__oldvalue)
203 		: "r" (__memory), "r" (__cmp), "1" (__newvalue));
204 #else
205 #error	"port me"
206 #endif
207 	return (__oldvalue);
208 }
209 
210 extern __inline__ void
211 incr32(volatile uint32_t *__memory)
212 {
213 #if defined(__x86)
214 	__asm__ __volatile__(
215 		"lock; incl %0"
216 		: "+m" (*__memory));
217 #elif defined(__sparc)
218 	uint32_t __tmp1, __tmp2;
219 	__asm__ __volatile__(
220 		"ld [%3], %0\n\t"
221 		"1:\n\t"
222 		"add %0, 1, %1\n\t"
223 		"cas [%3], %0, %1\n\t"
224 		"cmp %0, %1\n\t"
225 		"bne,a,pn %%icc, 1b\n\t"
226 		"  mov %1, %0"
227 		: "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
228 		: "r" (__memory)
229 		: "cc");
230 #else
231 #error	"port me"
232 #endif
233 }
234 
235 extern __inline__ void
236 decr32(volatile uint32_t *__memory)
237 {
238 #if defined(__x86)
239 	__asm__ __volatile__(
240 		"lock; decl %0"
241 		: "+m" (*__memory));
242 #elif defined(__sparc)
243 	uint32_t __tmp1, __tmp2;
244 	__asm__ __volatile__(
245 		"ld [%3], %0\n\t"
246 		"1:\n\t"
247 		"sub %0, 1, %1\n\t"
248 		"cas [%3], %0, %1\n\t"
249 		"cmp %0, %1\n\t"
250 		"bne,a,pn %%icc, 1b\n\t"
251 		"  mov %1, %0"
252 		: "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
253 		: "r" (__memory)
254 		: "cc");
255 #else
256 #error	"port me"
257 #endif
258 }
259 
260 #if defined(__sparc)	/* only needed on sparc */
261 
262 extern __inline__ ulong_t
263 caller(void)
264 {
265 	register ulong_t __value __asm__("i7");
266 	return (__value);
267 }
268 
269 extern __inline__ ulong_t
270 getfp(void)
271 {
272 	register ulong_t __value __asm__("fp");
273 	return (__value);
274 }
275 
276 #endif	/* __sparc */
277 
278 #if defined(__x86)	/* only needed on x86 */
279 
280 extern __inline__ void
281 ht_pause(void)
282 {
283 	__asm__ __volatile__("rep; nop");
284 }
285 
286 #endif	/* __x86 */
287 
288 #endif	/* !__lint && __GNUC__ */
289 
290 #endif	/* _THR_INLINES_H */
291