xref: /titanic_52/usr/src/lib/libc/inc/thr_inlines.h (revision 67e3a03ed4a2813074d36330f062ed6e593a4937)
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