import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / inc / thr_inlines.h
blob6caa2214b8500896959eb231f2d3fb8eb5715562
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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 /* inlines for gcc */
35 * ON-usable GCC 4.x emits register pseudo-ops declaring %g7 as ignored, rather
36 * than scratch, GCC 3 does the reverse. All uses, both ones it generated
37 * (_curthread) and ones it didn't (__curthread) must agree.
39 #if __GNUC__ > 3
40 #define SPARC_REG_SPEC "#ignore"
41 #else
42 #define SPARC_REG_SPEC "#scratch"
43 #endif
45 extern __GNU_INLINE ulwp_t *
46 _curthread(void)
48 #if defined(__amd64)
49 ulwp_t *__value;
50 __asm__ __volatile__("movq %%fs:0, %0" : "=r" (__value));
51 #elif defined(__i386)
52 ulwp_t *__value;
53 __asm__ __volatile__("movl %%gs:0, %0" : "=r" (__value));
54 #elif defined(__sparc)
55 register ulwp_t *__value __asm__("g7");
56 #else
57 #error "port me"
58 #endif
59 return (__value);
62 extern __GNU_INLINE ulwp_t *
63 __curthread(void)
65 ulwp_t *__value;
66 __asm__ __volatile__(
67 #if defined(__amd64)
68 "movq %%fs:0, %0\n\t"
69 #elif defined(__i386)
70 "movl %%gs:0, %0\n\t"
71 #elif defined(__sparcv9)
72 ".register %%g7, " SPARC_REG_SPEC "\n\t"
73 "ldx [%%g7 + 80], %0\n\t"
74 #elif defined(__sparc)
75 ".register %%g7, " SPARC_REG_SPEC "\n\t"
76 "ld [%%g7 + 80], %0\n\t"
77 #else
78 #error "port me"
79 #endif
80 : "=r" (__value));
81 return (__value);
84 extern __GNU_INLINE greg_t
85 stkptr(void)
87 #if defined(__amd64)
88 register greg_t __value __asm__("rsp");
89 #elif defined(__i386)
90 register greg_t __value __asm__("esp");
91 #elif defined(__sparc)
92 register greg_t __value __asm__("sp");
93 #else
94 #error "port me"
95 #endif
96 return (__value);
99 extern __GNU_INLINE hrtime_t
100 gethrtime(void) /* note: caller-saved registers are trashed */
102 #if defined(__amd64)
103 hrtime_t __value;
104 __asm__ __volatile__(
105 "movl $3, %%eax\n\t"
106 "int $0xd2"
107 : "=a" (__value)
108 : : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "cc");
109 #elif defined(__i386)
110 hrtime_t __value;
111 __asm__ __volatile__(
112 "movl $3, %%eax\n\t"
113 "int $0xd2"
114 : "=A" (__value)
115 : : "ecx", "cc");
116 #elif defined(__sparcv9)
117 register hrtime_t __value __asm__("o0");
118 __asm__ __volatile__(
119 "ta 0x24\n\t"
120 "sllx %%o0, 32, %0\n\t"
121 "or %%o1, %0, %0"
122 : "=r" (__value)
123 : : "o1", "o2", "o3", "o4", "o5", "cc");
124 #elif defined(__sparc)
125 register hrtime_t __value __asm__("o0");
126 __asm__ __volatile__(
127 "ta 0x24"
128 : "=r" (__value)
129 : : "o2", "o3", "o4", "o5", "cc");
130 #else
131 #error "port me"
132 #endif
133 return (__value);
136 extern __GNU_INLINE int
137 set_lock_byte(volatile uint8_t *__lockp)
139 int __value;
140 #if defined(__x86)
141 __asm__ __volatile__(
142 "movl $1, %0\n\t"
143 "xchgb %%dl, %1"
144 : "+d" (__value), "+m" (*__lockp));
145 #elif defined(__sparc)
146 __asm__ __volatile__(
147 "ldstub %1, %0\n\t"
148 "membar #LoadLoad"
149 : "=r" (__value), "+m" (*__lockp));
150 #else
151 #error "port me"
152 #endif
153 return (__value);
156 extern __GNU_INLINE uint32_t
157 atomic_swap_32(volatile uint32_t *__memory, uint32_t __value)
159 #if defined(__x86)
160 __asm__ __volatile__(
161 "xchgl %0, %1"
162 : "+q" (__value), "+m" (*__memory));
163 return (__value);
164 #elif defined(__sparc)
165 uint32_t __tmp1, __tmp2;
166 __asm__ __volatile__(
167 "ld [%3], %0\n\t"
168 "1:\n\t"
169 "mov %4, %1\n\t"
170 "cas [%3], %0, %1\n\t"
171 "cmp %0, %1\n\t"
172 "bne,a,pn %%icc, 1b\n\t"
173 " mov %1, %0"
174 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
175 : "r" (__memory), "r" (__value)
176 : "cc");
177 return (__tmp2);
178 #else
179 #error "port me"
180 #endif
183 extern __GNU_INLINE uint32_t
184 atomic_cas_32(volatile uint32_t *__memory, uint32_t __cmp, uint32_t __newvalue)
186 uint32_t __oldvalue;
187 #if defined(__x86)
188 __asm__ __volatile__(
189 "lock; cmpxchgl %3, %0"
190 : "=m" (*__memory), "=a" (__oldvalue)
191 : "a" (__cmp), "r" (__newvalue));
192 #elif defined(__sparc)
193 __asm__ __volatile__(
194 "cas [%2], %3, %1"
195 : "=m" (*__memory), "=&r" (__oldvalue)
196 : "r" (__memory), "r" (__cmp), "1" (__newvalue));
197 #else
198 #error "port me"
199 #endif
200 return (__oldvalue);
203 extern __GNU_INLINE void
204 atomic_inc_32(volatile uint32_t *__memory)
206 #if defined(__x86)
207 __asm__ __volatile__(
208 "lock; incl %0"
209 : "+m" (*__memory));
210 #elif defined(__sparc)
211 uint32_t __tmp1, __tmp2;
212 __asm__ __volatile__(
213 "ld [%3], %0\n\t"
214 "1:\n\t"
215 "add %0, 1, %1\n\t"
216 "cas [%3], %0, %1\n\t"
217 "cmp %0, %1\n\t"
218 "bne,a,pn %%icc, 1b\n\t"
219 " mov %1, %0"
220 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
221 : "r" (__memory)
222 : "cc");
223 #else
224 #error "port me"
225 #endif
228 extern __GNU_INLINE void
229 atomic_dec_32(volatile uint32_t *__memory)
231 #if defined(__x86)
232 __asm__ __volatile__(
233 "lock; decl %0"
234 : "+m" (*__memory));
235 #elif defined(__sparc)
236 uint32_t __tmp1, __tmp2;
237 __asm__ __volatile__(
238 "ld [%3], %0\n\t"
239 "1:\n\t"
240 "sub %0, 1, %1\n\t"
241 "cas [%3], %0, %1\n\t"
242 "cmp %0, %1\n\t"
243 "bne,a,pn %%icc, 1b\n\t"
244 " mov %1, %0"
245 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
246 : "r" (__memory)
247 : "cc");
248 #else
249 #error "port me"
250 #endif
253 extern __GNU_INLINE void
254 atomic_and_32(volatile uint32_t *__memory, uint32_t __bits)
256 #if defined(__x86)
257 __asm__ __volatile__(
258 "lock; andl %1, %0"
259 : "+m" (*__memory)
260 : "r" (__bits));
261 #elif defined(__sparc)
262 uint32_t __tmp1, __tmp2;
263 __asm__ __volatile__(
264 "ld [%3], %0\n\t"
265 "1:\n\t"
266 "and %0, %4, %1\n\t"
267 "cas [%3], %0, %1\n\t"
268 "cmp %0, %1\n\t"
269 "bne,a,pn %%icc, 1b\n\t"
270 " mov %1, %0"
271 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
272 : "r" (__memory), "r" (__bits)
273 : "cc");
274 #else
275 #error "port me"
276 #endif
279 extern __GNU_INLINE void
280 atomic_or_32(volatile uint32_t *__memory, uint32_t __bits)
282 #if defined(__x86)
283 __asm__ __volatile__(
284 "lock; orl %1, %0"
285 : "+m" (*__memory)
286 : "r" (__bits));
287 #elif defined(__sparc)
288 uint32_t __tmp1, __tmp2;
289 __asm__ __volatile__(
290 "ld [%3], %0\n\t"
291 "1:\n\t"
292 "or %0, %4, %1\n\t"
293 "cas [%3], %0, %1\n\t"
294 "cmp %0, %1\n\t"
295 "bne,a,pn %%icc, 1b\n\t"
296 " mov %1, %0"
297 : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__memory)
298 : "r" (__memory), "r" (__bits)
299 : "cc");
300 #else
301 #error "port me"
302 #endif
305 #if defined(__sparc) /* only needed on sparc */
307 extern __GNU_INLINE ulong_t
308 caller(void)
310 register ulong_t __value __asm__("i7");
311 return (__value);
314 extern __GNU_INLINE ulong_t
315 getfp(void)
317 register ulong_t __value __asm__("fp");
318 return (__value);
321 #endif /* __sparc */
323 #if defined(__x86) /* only needed on x86 */
325 extern __GNU_INLINE void
326 ht_pause(void)
328 __asm__ __volatile__("rep; nop");
331 #endif /* __x86 */
333 #endif /* _THR_INLINES_H */