OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libpthread/] [linuxthreads/] [sysdeps/] [i386/] [useldt.h] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* 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 Lesser General Public License as
9
   published by the Free Software Foundation; either version 2.1 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
   Lesser General Public License for more details.
16
 
17
   You should have received a copy of the GNU Lesser 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
 
65
/* Initialize the thread-unique value.  Two possible ways to do it.  */
66
 
67
#define DO_MODIFY_LDT(descr, nr)                                              \
68
({                                                                            \
69
  struct modify_ldt_ldt_s ldt_entry =                                         \
70
    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,            \
71
      1, 0, 0, 1, 0, 1, 0 };                                                      \
72
  if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)                   \
73
    abort ();                                                                 \
74
  asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7));                                \
75
})
76
 
77
#ifdef __PIC__
78
# define USETLS_EBX_ARG "r"
79
# define USETLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
80
#else
81
# define USETLS_EBX_ARG "b"
82
# define USETLS_LOAD_EBX
83
#endif
84
 
85
/* When using the new set_thread_area call, we don't need to change %gs
86
   because we inherited the value set up in the main thread by TLS setup.
87
   We need to extract that value and set up the same segment in this
88
   thread.  */
89
#if USE_TLS
90
# define DO_SET_THREAD_AREA_REUSE(nr)   1
91
#else
92
/* Without TLS, we do the initialization of the main thread, where NR == 0.  */
93
# define DO_SET_THREAD_AREA_REUSE(nr)   (!__builtin_constant_p (nr) || (nr))
94
#endif
95
#define DO_SET_THREAD_AREA(descr, nr) \
96
({                                                                            \
97
  int __gs;                                                                   \
98
  if (DO_SET_THREAD_AREA_REUSE (nr))                                          \
99
    {                                                                         \
100
      asm ("movw %%gs, %w0" : "=q" (__gs));                                   \
101
      struct modify_ldt_ldt_s ldt_entry =                                     \
102
        { (__gs & 0xffff) >> 3,                                               \
103
          (unsigned long int) (descr), 0xfffff /* 4GB in pages */,            \
104
          1, 0, 0, 1, 0, 1, 0 };                                          \
105
                                                                              \
106
      int __result;                                                           \
107
      __asm (USETLS_LOAD_EBX                                                  \
108
             "movl %2, %%eax\n\t"                                             \
109
             "int $0x80\n\t"                                                  \
110
             USETLS_LOAD_EBX                                                  \
111
             : "&a" (__result)                                                \
112
             : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area));      \
113
      if (__result == 0)                                               \
114
        asm ("movw %w0, %%gs" :: "q" (__gs));                                 \
115
      else                                                                    \
116
        __gs = -1;                                                            \
117
    }                                                                         \
118
  else                                                                        \
119
    {                                                                         \
120
      struct modify_ldt_ldt_s ldt_entry =                                     \
121
        { -1,                                                                 \
122
          (unsigned long int) (descr), 0xfffff /* 4GB in pages */,            \
123
          1, 0, 0, 1, 0, 1, 0 };                                          \
124
      int __result;                                                           \
125
      __asm (USETLS_LOAD_EBX                                                  \
126
             "movl %2, %%eax\n\t"                                             \
127
             "int $0x80\n\t"                                                  \
128
             USETLS_LOAD_EBX                                                  \
129
             : "&a" (__result)                                                \
130
             : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area));      \
131
      if (__result == 0)                                               \
132
        {                                                                     \
133
          __gs = (ldt_entry.entry_number << 3) + 3;                           \
134
          asm ("movw %w0, %%gs" : : "q" (__gs));                              \
135
        }                                                                     \
136
      else                                                                    \
137
        __gs = -1;                                                            \
138
    }                                                                         \
139
  __gs;                                                                       \
140
})
141
 
142
#if defined __ASSUME_SET_THREAD_AREA_SYSCALL
143
# define INIT_THREAD_SELF(descr, nr)    DO_SET_THREAD_AREA (descr, nr)
144
#elif defined __NR_set_thread_area
145
# define INIT_THREAD_SELF(descr, nr)                                          \
146
({                                                                            \
147
  if (__builtin_expect (__have_no_set_thread_area, 0)                          \
148
      || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1     \
149
          && (__have_no_set_thread_area = 1)))                                \
150
    DO_MODIFY_LDT (descr, nr);                                                \
151
})
152
/* Defined in pspinlock.c.  */
153
extern int __have_no_set_thread_area;
154
#else
155
# define INIT_THREAD_SELF(descr, nr)    DO_MODIFY_LDT (descr, nr)
156
#endif
157
 
158
/* Free resources associated with thread descriptor.  */
159
#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
160
#define FREE_THREAD(descr, nr) do { } while (0)
161
#elif defined __NR_set_thread_area
162
#define FREE_THREAD(descr, nr) \
163
{                                                                             \
164
  int __gs;                                                                   \
165
  __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs));                      \
166
  if (__builtin_expect (__gs & 4, 0))                                          \
167
    {                                                                         \
168
      struct modify_ldt_ldt_s ldt_entry =                                     \
169
        { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };                                   \
170
      __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));                       \
171
    }                                                                         \
172
}
173
#else
174
#define FREE_THREAD(descr, nr) \
175
{                                                                             \
176
  struct modify_ldt_ldt_s ldt_entry =                                         \
177
    { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 };                                       \
178
  __modify_ldt (1, &ldt_entry, sizeof (ldt_entry));                           \
179
}
180
#endif
181
 
182
/* Read member of the thread descriptor directly.  */
183
#define THREAD_GETMEM(descr, member) \
184
({                                                                            \
185
  __typeof__ (descr->member) __value;                                         \
186
  if (sizeof (__value) == 1)                                                  \
187
    __asm__ __volatile__ ("movb %%gs:%P2,%b0"                                 \
188
                          : "=q" (__value)                                    \
189
                          : "0" (0),                                            \
190
                            "i" (offsetof (struct _pthread_descr_struct,      \
191
                                           member)));                         \
192
  else if (sizeof (__value) == 4)                                             \
193
    __asm__ __volatile__ ("movl %%gs:%P1,%0"                                  \
194
                          : "=r" (__value)                                    \
195
                          : "i" (offsetof (struct _pthread_descr_struct,      \
196
                                           member)));                         \
197
  else                                                                        \
198
    {                                                                         \
199
      if (sizeof (__value) != 8)                                              \
200
        /* There should not be any value with a size other than 1, 4 or 8.  */\
201
        abort ();                                                             \
202
                                                                              \
203
      __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t"                         \
204
                            "movl %%gs:%P2,%%edx"                             \
205
                            : "=A" (__value)                                  \
206
                            : "i" (offsetof (struct _pthread_descr_struct,    \
207
                                             member)),                        \
208
                              "i" (offsetof (struct _pthread_descr_struct,    \
209
                                             member) + 4));                   \
210
    }                                                                         \
211
  __value;                                                                    \
212
})
213
 
214
/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
215
#define THREAD_GETMEM_NC(descr, member) \
216
({                                                                            \
217
  __typeof__ (descr->member) __value;                                         \
218
  if (sizeof (__value) == 1)                                                  \
219
    __asm__ __volatile__ ("movb %%gs:(%2),%b0"                                \
220
                          : "=q" (__value)                                    \
221
                          : "0" (0),                                            \
222
                            "r" (offsetof (struct _pthread_descr_struct,      \
223
                                           member)));                         \
224
  else if (sizeof (__value) == 4)                                             \
225
    __asm__ __volatile__ ("movl %%gs:(%1),%0"                                 \
226
                          : "=r" (__value)                                    \
227
                          : "r" (offsetof (struct _pthread_descr_struct,      \
228
                                           member)));                         \
229
  else                                                                        \
230
    {                                                                         \
231
      if (sizeof (__value) != 8)                                              \
232
        /* There should not be any value with a size other than 1, 4 or 8.  */\
233
        abort ();                                                             \
234
                                                                              \
235
      __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t"                        \
236
                            "movl %%gs:4(%1),%%edx"                           \
237
                            : "=&A" (__value)                                 \
238
                            : "r" (offsetof (struct _pthread_descr_struct,    \
239
                                             member)));                       \
240
    }                                                                         \
241
  __value;                                                                    \
242
})
243
 
244
/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
245
#define THREAD_SETMEM(descr, member, value) \
246
({                                                                            \
247
  __typeof__ (descr->member) __value = (value);                               \
248
  if (sizeof (__value) == 1)                                                  \
249
    __asm__ __volatile__ ("movb %0,%%gs:%P1" :                                \
250
                          : "q" (__value),                                    \
251
                            "i" (offsetof (struct _pthread_descr_struct,      \
252
                                           member)));                         \
253
  else if (sizeof (__value) == 4)                                             \
254
    __asm__ __volatile__ ("movl %0,%%gs:%P1" :                                \
255
                          : "r" (__value),                                    \
256
                            "i" (offsetof (struct _pthread_descr_struct,      \
257
                                           member)));                         \
258
  else                                                                        \
259
    {                                                                         \
260
      if (sizeof (__value) != 8)                                              \
261
        /* There should not be any value with a size other than 1, 4 or 8.  */\
262
        abort ();                                                             \
263
                                                                              \
264
      __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n"                         \
265
                            "movl %%edx,%%gs:%P2" :                           \
266
                            : "A" (__value),                                  \
267
                              "i" (offsetof (struct _pthread_descr_struct,    \
268
                                             member)),                        \
269
                              "i" (offsetof (struct _pthread_descr_struct,    \
270
                                             member) + 4));                   \
271
    }                                                                         \
272
})
273
 
274
/* Set member of the thread descriptor directly.  */
275
#define THREAD_SETMEM_NC(descr, member, value) \
276
({                                                                            \
277
  __typeof__ (descr->member) __value = (value);                               \
278
  if (sizeof (__value) == 1)                                                  \
279
    __asm__ __volatile__ ("movb %0,%%gs:(%1)" :                               \
280
                          : "q" (__value),                                    \
281
                            "r" (offsetof (struct _pthread_descr_struct,      \
282
                                           member)));                         \
283
  else if (sizeof (__value) == 4)                                             \
284
    __asm__ __volatile__ ("movl %0,%%gs:(%1)" :                               \
285
                          : "r" (__value),                                    \
286
                            "r" (offsetof (struct _pthread_descr_struct,      \
287
                                           member)));                         \
288
  else                                                                        \
289
    {                                                                         \
290
      if (sizeof (__value) != 8)                                              \
291
        /* There should not be any value with a size other than 1, 4 or 8.  */\
292
        abort ();                                                             \
293
                                                                              \
294
      __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t"                        \
295
                            "movl %%edx,%%gs:4(%1)" :                         \
296
                            : "A" (__value),                                  \
297
                              "r" (offsetof (struct _pthread_descr_struct,    \
298
                                             member)));                       \
299
    }                                                                         \
300
})
301
#endif
302
 
303
/* We want the OS to assign stack addresses.  */
304
#define FLOATING_STACKS 1
305
 
306
/* Maximum size of the stack if the rlimit is unlimited.  */
307
#define ARCH_STACK_MAX_SIZE     8*1024*1024

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.