Update.
[platform/upstream/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 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 #include <stddef.h>     /* For offsetof.  */
23 #include <stdlib.h>     /* For abort().  */
24
25
26 /* We don't want to include the kernel header.  So duplicate the
27    information.  */
28
29 /* Structure passed on `modify_ldt' call.  */
30 struct modify_ldt_ldt_s
31 {
32   unsigned int entry_number;
33   unsigned long int base_addr;
34   unsigned int limit;
35   unsigned int seg_32bit:1;
36   unsigned int contents:2;
37   unsigned int read_exec_only:1;
38   unsigned int limit_in_pages:1;
39   unsigned int seg_not_present:1;
40   unsigned int useable:1;
41   unsigned int empty:25;
42 };
43
44 /* System call to set LDT entry.  */
45 extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
46
47
48 /* Return the thread descriptor for the current thread.
49
50    The contained asm must *not* be marked volatile since otherwise
51    assignments like
52         pthread_descr self = thread_self();
53    do not get optimized away.  */
54 #define THREAD_SELF \
55 ({                                                                            \
56   register pthread_descr __self;                                              \
57   __asm__ ("movl %%gs:%c1,%0" : "=r" (__self)                                 \
58            : "i" (offsetof (struct _pthread_descr_struct,                     \
59                             p_header.data.self)));                            \
60   __self;                                                                     \
61 })
62
63 /* Initialize the thread-unique value.  */
64 #define INIT_THREAD_SELF(descr, nr) \
65 {                                                                             \
66   struct modify_ldt_ldt_s ldt_entry =                                         \
67     { nr, (unsigned long int) descr, sizeof (struct _pthread_descr_struct),   \
68       1, 0, 0, 0, 0, 1, 0 };                                                  \
69   if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)                  \
70     abort ();                                                                 \
71   __asm__ __volatile__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7));               \
72 }
73
74 /* Free resources associated with thread descriptor.  */
75 #define FREE_THREAD(descr, nr) \
76 {                                                                             \
77   struct modify_ldt_ldt_s ldt_entry =                                         \
78     { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };                                        \
79   __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));                           \
80 }
81
82 /* Read member of the thread descriptor directly.  */
83 #define THREAD_GETMEM(descr, member) \
84 ({                                                                            \
85   __typeof__ (descr->member) __value;                                         \
86   if (sizeof (__value) == 1)                                                  \
87     __asm__ __volatile__ ("movb %%gs:%P2,%b0"                                 \
88                           : "=q" (__value)                                    \
89                           : "0" (0),                                          \
90                             "i" (offsetof (struct _pthread_descr_struct,      \
91                                            member)));                         \
92   else if (sizeof (__value) == 4)                                             \
93     __asm__ __volatile__ ("movl %%gs:%P1,%0"                                  \
94                           : "=r" (__value)                                    \
95                           : "i" (offsetof (struct _pthread_descr_struct,      \
96                                            member)));                         \
97   else                                                                        \
98     {                                                                         \
99       if (sizeof (__value) != 8)                                              \
100         /* There should not be any value with a size other than 1, 4 or 8.  */\
101         abort ();                                                             \
102                                                                               \
103       __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t"                         \
104                             "movl %%gs:%P2,%%edx"                             \
105                             : "=A" (__value)                                  \
106                             : "i" (offsetof (struct _pthread_descr_struct,    \
107                                              member)),                        \
108                               "i" (offsetof (struct _pthread_descr_struct,    \
109                                              member) + 4));                   \
110     }                                                                         \
111   __value;                                                                    \
112 })
113
114 /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
115 #define THREAD_GETMEM_NC(descr, member) \
116 ({                                                                            \
117   __typeof__ (descr->member) __value;                                         \
118   if (sizeof (__value) == 1)                                                  \
119     __asm__ __volatile__ ("movb %%gs:(%2),%b0"                                \
120                           : "=q" (__value)                                    \
121                           : "0" (0),                                          \
122                             "r" (offsetof (struct _pthread_descr_struct,      \
123                                            member)));                         \
124   else if (sizeof (__value) == 4)                                             \
125     __asm__ __volatile__ ("movl %%gs:(%1),%0"                                 \
126                           : "=r" (__value)                                    \
127                           : "r" (offsetof (struct _pthread_descr_struct,      \
128                                            member)));                         \
129   else                                                                        \
130     {                                                                         \
131       if (sizeof (__value) != 8)                                              \
132         /* There should not be any value with a size other than 1, 4 or 8.  */\
133         abort ();                                                             \
134                                                                               \
135       __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t"                        \
136                             "movl %%gs:4(%1),%%edx"                           \
137                             : "=&A" (__value)                                 \
138                             : "r" (offsetof (struct _pthread_descr_struct,    \
139                                              member)));                       \
140     }                                                                         \
141   __value;                                                                    \
142 })
143
144 /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
145 #define THREAD_SETMEM(descr, member, value) \
146 ({                                                                            \
147   __typeof__ (descr->member) __value = (value);                               \
148   if (sizeof (__value) == 1)                                                  \
149     __asm__ __volatile__ ("movb %0,%%gs:%P1" :                                \
150                           : "q" (__value),                                    \
151                             "i" (offsetof (struct _pthread_descr_struct,      \
152                                            member)));                         \
153   else if (sizeof (__value) == 4)                                             \
154     __asm__ __volatile__ ("movl %0,%%gs:%P1" :                                \
155                           : "r" (__value),                                    \
156                             "i" (offsetof (struct _pthread_descr_struct,      \
157                                            member)));                         \
158   else                                                                        \
159     {                                                                         \
160       if (sizeof (__value) != 8)                                              \
161         /* There should not be any value with a size other than 1, 4 or 8.  */\
162         abort ();                                                             \
163                                                                               \
164       __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n"                         \
165                             "movl %%edx,%%gs:%P2" :                           \
166                             : "A" (__value),                                  \
167                               "i" (offsetof (struct _pthread_descr_struct,    \
168                                              member)),                        \
169                               "i" (offsetof (struct _pthread_descr_struct,    \
170                                              member) + 4));                   \
171     }                                                                         \
172 })
173
174 /* Set member of the thread descriptor directly.  */
175 #define THREAD_SETMEM_NC(descr, member, value) \
176 ({                                                                            \
177   __typeof__ (descr->member) __value = (value);                               \
178   if (sizeof (__value) == 1)                                                  \
179     __asm__ __volatile__ ("movb %0,%%gs:(%1)" :                               \
180                           : "q" (__value),                                    \
181                             "r" (offsetof (struct _pthread_descr_struct,      \
182                                            member)));                         \
183   else if (sizeof (__value) == 4)                                             \
184     __asm__ __volatile__ ("movl %0,%%gs:(%1)" :                               \
185                           : "r" (__value),                                    \
186                             "r" (offsetof (struct _pthread_descr_struct,      \
187                                            member)));                         \
188   else                                                                        \
189     {                                                                         \
190       if (sizeof (__value) != 8)                                              \
191         /* There should not be any value with a size other than 1, 4 or 8.  */\
192         abort ();                                                             \
193                                                                               \
194       __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t"                        \
195                             "movl %%edx,%%gs:4(%1)" :                         \
196                             : "A" (__value),                                  \
197                               "r" (offsetof (struct _pthread_descr_struct,    \
198                                              member)));                       \
199     }                                                                         \
200 })
201
202 /* We want the OS to assign stack addresses.  */
203 #define FLOATING_STACKS 1
204
205 /* Maximum size of the stack if the rlimit is unlimited.  */
206 #define ARCH_STACK_MAX_SIZE     8*1024*1024