Use __ASSEMBLER__ test macro not ASSEMBLER.
[kopensolaris-gnu/glibc.git] / linuxthreads / sysdeps / x86_64 / pt-machine.h
1 /* Machine-dependent pthreads configuration and inline functions.
2    x86-64 version.
3    Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #ifndef _PT_MACHINE_H
22 #define _PT_MACHINE_H   1
23
24 #include <stddef.h>     /* For offsetof.  */
25 #include <stdlib.h>     /* For abort().  */
26 #include <asm/prctl.h>
27
28
29 #ifndef PT_EI
30 # define PT_EI extern inline
31 #endif
32
33 extern long int testandset (int *spinlock);
34 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
35
36 /* Get some notion of the current stack.  Need not be exactly the top
37    of the stack, just something somewhere in the current frame.  */
38 #define CURRENT_STACK_FRAME  stack_pointer
39 register char * stack_pointer __asm__ ("%rsp");
40
41
42 /* Spinlock implementation; required.  */
43 PT_EI long int
44 testandset (int *spinlock)
45 {
46   long int ret;
47
48   __asm__ __volatile__ (
49         "xchgq %0, %1"
50         : "=r"(ret), "=m"(*spinlock)
51         : "0"(1), "m"(*spinlock)
52         : "memory");
53
54   return ret;
55 }
56
57
58 /* Compare-and-swap for semaphores.  */
59 #define HAS_COMPARE_AND_SWAP
60
61 PT_EI int
62 __compare_and_swap (long int *p, long int oldval, long int newval)
63 {
64   char ret;
65   long int readval;
66
67   __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
68                         : "=q" (ret), "=m" (*p), "=a" (readval)
69                         : "r" (newval), "m" (*p), "a" (oldval)
70                         : "memory");
71   return ret;
72 }
73
74
75 /* Return the thread descriptor for the current thread.
76
77    The contained asm must *not* be marked volatile since otherwise
78    assignments like
79         pthread_descr self = thread_self();
80    do not get optimized away.  */
81 #define THREAD_SELF \
82 ({                                                                            \
83   register pthread_descr __self;                                              \
84   __asm__ ("movq %%gs:%c1,%0" : "=r" (__self)                                 \
85            : "i" (offsetof (struct _pthread_descr_struct,                     \
86                             p_header.data.self)));                            \
87   __self;                                                                     \
88 })
89
90 /* Prototype for the system call.  */
91 extern int __arch_prctl (int __code, unsigned long __addr);
92
93 /* Initialize the thread-unique value.  */
94 #define INIT_THREAD_SELF(descr, nr) \
95 {                                                                             \
96   if (__arch_prctl (ARCH_SET_GS, (unsigned long)descr) != 0)                                  \
97     abort ();                                                                 \
98 }
99
100 /* Read member of the thread descriptor directly.  */
101 #define THREAD_GETMEM(descr, member) \
102 ({                                                                            \
103   __typeof__ (descr->member) __value;                                         \
104   if (sizeof (__value) == 1)                                                  \
105     __asm__ __volatile__ ("movb %%gs:%P2,%b0"                                 \
106                           : "=q" (__value)                                    \
107                           : "0" (0),                                          \
108                             "i" (offsetof (struct _pthread_descr_struct,      \
109                                            member)));                         \
110   else if (sizeof (__value) == 4)                                             \
111     __asm__ __volatile__ ("movl %%gs:%P1,%0"                                  \
112                           : "=r" (__value)                                    \
113                           : "i" (offsetof (struct _pthread_descr_struct,      \
114                                            member)));                         \
115   else                                                                        \
116     {                                                                         \
117       if (sizeof (__value) != 8)                                              \
118         /* There should not be any value with a size other than 1, 4 or 8.  */\
119         abort ();                                                             \
120                                                                               \
121       __asm__ __volatile__ ("movq %%gs:%P1,%0"                                \
122                             : "=r" (__value)                                  \
123                             : "i" (offsetof (struct _pthread_descr_struct,    \
124                                              member)));                       \
125     }                                                                         \
126   __value;                                                                    \
127 })
128
129 /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
130 #define THREAD_GETMEM_NC(descr, member) \
131 ({                                                                            \
132   __typeof__ (descr->member) __value;                                         \
133   if (sizeof (__value) == 1)                                                  \
134     __asm__ __volatile__ ("movb %%gs:(%2),%b0"                                \
135                           : "=q" (__value)                                    \
136                           : "0" (0),                                          \
137                             "r" (offsetof (struct _pthread_descr_struct,      \
138                                            member)));                         \
139   else if (sizeof (__value) == 4)                                             \
140     __asm__ __volatile__ ("movl %%gs:(%1),%0"                                 \
141                           : "=r" (__value)                                    \
142                           : "r" (offsetof (struct _pthread_descr_struct,      \
143                                            member)));                         \
144   else                                                                        \
145     {                                                                         \
146       if (sizeof (__value) != 8)                                              \
147         /* There should not be any value with a size other than 1, 4 or 8.  */\
148         abort ();                                                             \
149                                                                               \
150       __asm__ __volatile__ ("movq %%gs:(%1),%0"                               \
151                             : "=r" (__value)                                  \
152                             : "r" (offsetof (struct _pthread_descr_struct,    \
153                                              member)));                       \
154     }                                                                         \
155   __value;                                                                    \
156 })
157
158 /* Set member of the thread descriptor directly.  */
159 #define THREAD_SETMEM(descr, member, value) \
160 ({                                                                            \
161   __typeof__ (descr->member) __value = (value);                               \
162   if (sizeof (__value) == 1)                                                  \
163     __asm__ __volatile__ ("movb %0,%%gs:%P1" :                                \
164                           : "q" (__value),                                    \
165                             "i" (offsetof (struct _pthread_descr_struct,      \
166                                            member)));                         \
167   else if (sizeof (__value) == 4)                                             \
168     __asm__ __volatile__ ("movl %0,%%gs:%P1" :                                \
169                           : "r" (__value),                                    \
170                             "i" (offsetof (struct _pthread_descr_struct,      \
171                                            member)));                         \
172   else                                                                        \
173     {                                                                         \
174       if (sizeof (__value) != 8)                                              \
175         /* There should not be any value with a size other than 1, 4 or 8.  */\
176         abort ();                                                             \
177                                                                               \
178       __asm__ __volatile__ ("movq %0,%%gs:%P1" :                              \
179                             : "r" (__value),                                  \
180                               "i" (offsetof (struct _pthread_descr_struct,    \
181                                              member)));                       \
182     }                                                                         \
183 })
184
185 /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
186 #define THREAD_SETMEM_NC(descr, member, value) \
187 ({                                                                            \
188   __typeof__ (descr->member) __value = (value);                               \
189   if (sizeof (__value) == 1)                                                  \
190     __asm__ __volatile__ ("movb %0,%%gs:(%1)" :                               \
191                           : "q" (__value),                                    \
192                             "r" (offsetof (struct _pthread_descr_struct,      \
193                                            member)));                         \
194   else if (sizeof (__value) == 4)                                             \
195     __asm__ __volatile__ ("movl %0,%%gs:(%1)" :                               \
196                           : "r" (__value),                                    \
197                             "r" (offsetof (struct _pthread_descr_struct,      \
198                                            member)));                         \
199   else                                                                        \
200     {                                                                         \
201       if (sizeof (__value) != 8)                                              \
202         /* There should not be any value with a size other than 1, 4 or 8.  */\
203         abort ();                                                             \
204                                                                               \
205       __asm__ __volatile__ ("movq %0,%%gs:(%1)" :                             \
206                             : "r" (__value),                                  \
207                               "r" (offsetof (struct _pthread_descr_struct,    \
208                                              member)));                       \
209     }                                                                         \
210 })
211
212 /* We want the OS to assign stack addresses.  */
213 #define FLOATING_STACKS 1
214
215 /* Maximum size of the stack if the rlimit is unlimited.  */
216 #define ARCH_STACK_MAX_SIZE     32*1024*1024
217
218 #endif /* pt-machine.h */