Use __ASSEMBLER__ test macro not ASSEMBLER.
[kopensolaris-gnu/glibc.git] / linuxthreads / sysdeps / i386 / useldt.h
1 /* Special definitions for ix86 machine using segment register based
2    thread descriptor.
3    Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the GNU C Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #ifndef ASSEMBLER
23 #include <stddef.h>     /* For offsetof.  */
24 #include <stdlib.h>     /* For abort().  */
25
26
27 /* We don't want to include the kernel header.  So duplicate the
28    information.  */
29
30 /* Structure passed on `modify_ldt' call.  */
31 struct modify_ldt_ldt_s
32 {
33   unsigned int entry_number;
34   unsigned long int base_addr;
35   unsigned int limit;
36   unsigned int seg_32bit:1;
37   unsigned int contents:2;
38   unsigned int read_exec_only:1;
39   unsigned int limit_in_pages:1;
40   unsigned int seg_not_present:1;
41   unsigned int useable:1;
42   unsigned int empty:25;
43 };
44
45 /* System call to set LDT entry.  */
46 extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
47
48
49 /* Return the thread descriptor for the current thread.
50
51    The contained asm must *not* be marked volatile since otherwise
52    assignments like
53         pthread_descr self = thread_self();
54    do not get optimized away.  */
55 #define THREAD_SELF \
56 ({                                                                            \
57   register pthread_descr __self;                                              \
58   __asm__ ("movl %%gs:%c1,%0" : "=r" (__self)                                 \
59            : "i" (offsetof (struct _pthread_descr_struct,                     \
60                             p_header.data.self)));                            \
61   __self;                                                                     \
62 })
63
64 /* Initialize the thread-unique value.  */
65 #define INIT_THREAD_SELF(descr, nr) \
66 {                                                                             \
67   struct modify_ldt_ldt_s ldt_entry =                                         \
68     { nr, (unsigned long int) descr, sizeof (struct _pthread_descr_struct),   \
69       1, 0, 0, 0, 0, 1, 0 };                                                  \
70   if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)                  \
71     abort ();                                                                 \
72   __asm__ __volatile__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7));               \
73 }
74
75 /* Free resources associated with thread descriptor.  */
76 #define FREE_THREAD(descr, nr) \
77 {                                                                             \
78   struct modify_ldt_ldt_s ldt_entry =                                         \
79     { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };                                        \
80   __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));                           \
81 }
82
83 /* Read member of the thread descriptor directly.  */
84 #define THREAD_GETMEM(descr, member) \
85 ({                                                                            \
86   __typeof__ (descr->member) __value;                                         \
87   if (sizeof (__value) == 1)                                                  \
88     __asm__ __volatile__ ("movb %%gs:%P2,%b0"                                 \
89                           : "=q" (__value)                                    \
90                           : "0" (0),                                          \
91                             "i" (offsetof (struct _pthread_descr_struct,      \
92                                            member)));                         \
93   else if (sizeof (__value) == 4)                                             \
94     __asm__ __volatile__ ("movl %%gs:%P1,%0"                                  \
95                           : "=r" (__value)                                    \
96                           : "i" (offsetof (struct _pthread_descr_struct,      \
97                                            member)));                         \
98   else                                                                        \
99     {                                                                         \
100       if (sizeof (__value) != 8)                                              \
101         /* There should not be any value with a size other than 1, 4 or 8.  */\
102         abort ();                                                             \
103                                                                               \
104       __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t"                         \
105                             "movl %%gs:%P2,%%edx"                             \
106                             : "=A" (__value)                                  \
107                             : "i" (offsetof (struct _pthread_descr_struct,    \
108                                              member)),                        \
109                               "i" (offsetof (struct _pthread_descr_struct,    \
110                                              member) + 4));                   \
111     }                                                                         \
112   __value;                                                                    \
113 })
114
115 /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
116 #define THREAD_GETMEM_NC(descr, member) \
117 ({                                                                            \
118   __typeof__ (descr->member) __value;                                         \
119   if (sizeof (__value) == 1)                                                  \
120     __asm__ __volatile__ ("movb %%gs:(%2),%b0"                                \
121                           : "=q" (__value)                                    \
122                           : "0" (0),                                          \
123                             "r" (offsetof (struct _pthread_descr_struct,      \
124                                            member)));                         \
125   else if (sizeof (__value) == 4)                                             \
126     __asm__ __volatile__ ("movl %%gs:(%1),%0"                                 \
127                           : "=r" (__value)                                    \
128                           : "r" (offsetof (struct _pthread_descr_struct,      \
129                                            member)));                         \
130   else                                                                        \
131     {                                                                         \
132       if (sizeof (__value) != 8)                                              \
133         /* There should not be any value with a size other than 1, 4 or 8.  */\
134         abort ();                                                             \
135                                                                               \
136       __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t"                        \
137                             "movl %%gs:4(%1),%%edx"                           \
138                             : "=&A" (__value)                                 \
139                             : "r" (offsetof (struct _pthread_descr_struct,    \
140                                              member)));                       \
141     }                                                                         \
142   __value;                                                                    \
143 })
144
145 /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
146 #define THREAD_SETMEM(descr, member, value) \
147 ({                                                                            \
148   __typeof__ (descr->member) __value = (value);                               \
149   if (sizeof (__value) == 1)                                                  \
150     __asm__ __volatile__ ("movb %0,%%gs:%P1" :                                \
151                           : "q" (__value),                                    \
152                             "i" (offsetof (struct _pthread_descr_struct,      \
153                                            member)));                         \
154   else if (sizeof (__value) == 4)                                             \
155     __asm__ __volatile__ ("movl %0,%%gs:%P1" :                                \
156                           : "r" (__value),                                    \
157                             "i" (offsetof (struct _pthread_descr_struct,      \
158                                            member)));                         \
159   else                                                                        \
160     {                                                                         \
161       if (sizeof (__value) != 8)                                              \
162         /* There should not be any value with a size other than 1, 4 or 8.  */\
163         abort ();                                                             \
164                                                                               \
165       __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n"                         \
166                             "movl %%edx,%%gs:%P2" :                           \
167                             : "A" (__value),                                  \
168                               "i" (offsetof (struct _pthread_descr_struct,    \
169                                              member)),                        \
170                               "i" (offsetof (struct _pthread_descr_struct,    \
171                                              member) + 4));                   \
172     }                                                                         \
173 })
174
175 /* Set member of the thread descriptor directly.  */
176 #define THREAD_SETMEM_NC(descr, member, value) \
177 ({                                                                            \
178   __typeof__ (descr->member) __value = (value);                               \
179   if (sizeof (__value) == 1)                                                  \
180     __asm__ __volatile__ ("movb %0,%%gs:(%1)" :                               \
181                           : "q" (__value),                                    \
182                             "r" (offsetof (struct _pthread_descr_struct,      \
183                                            member)));                         \
184   else if (sizeof (__value) == 4)                                             \
185     __asm__ __volatile__ ("movl %0,%%gs:(%1)" :                               \
186                           : "r" (__value),                                    \
187                             "r" (offsetof (struct _pthread_descr_struct,      \
188                                            member)));                         \
189   else                                                                        \
190     {                                                                         \
191       if (sizeof (__value) != 8)                                              \
192         /* There should not be any value with a size other than 1, 4 or 8.  */\
193         abort ();                                                             \
194                                                                               \
195       __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t"                        \
196                             "movl %%edx,%%gs:4(%1)" :                         \
197                             : "A" (__value),                                  \
198                               "r" (offsetof (struct _pthread_descr_struct,    \
199                                              member)));                       \
200     }                                                                         \
201 })
202 #endif
203
204 /* We want the OS to assign stack addresses.  */
205 #define FLOATING_STACKS 1
206
207 /* Maximum size of the stack if the rlimit is unlimited.  */
208 #define ARCH_STACK_MAX_SIZE     8*1024*1024