8 mach/setup-thread.c | 30 +++++++++++++++-
9 ports/sysdeps/mach/alpha/thread_state.h | 1
10 sysdeps/generic/thread_state.h | 1
11 sysdeps/mach/hurd/bits/libc-lock.h | 3 +
12 sysdeps/mach/hurd/bits/libc-tsd.h | 35 ------------------
13 sysdeps/mach/hurd/fork.c | 7 +++
14 sysdeps/mach/hurd/i386/init-first.c | 60 +++++++++++++++++++-------------
15 sysdeps/mach/hurd/i386/tls.h | 55 ++++++++++++++++++++++++-----
16 sysdeps/mach/hurd/i386/tlsdesc.sym | 17 +++++++++
17 sysdeps/mach/hurd/i386/trampoline.c | 2 -
18 sysdeps/mach/hurd/profil.c | 2 +
19 sysdeps/mach/hurd/setitimer.c | 3 +
20 sysdeps/mach/hurd/tls.h | 2 +
21 sysdeps/mach/i386/thread_state.h | 11 +++++
22 sysdeps/mach/powerpc/thread_state.h | 1
23 sysdeps/mach/thread_state.h | 3 +
24 20 files changed, 169 insertions(+), 75 deletions(-)
26 --- a/csu/libc-start.c
27 +++ b/csu/libc-start.c
29 /* Performe IREL{,A} relocations. */
33 /* Initialize the thread library at least a bit since the libgcc
34 functions are using thread functions if these are available and
35 we need to setup errno. */
36 __pthread_initialize_minimal ();
39 /* Set up the stack checker's canary. */
40 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
41 --- a/hurd/hurdfault.c
42 +++ b/hurd/hurdfault.c
44 /* This state will be restored when we fault.
45 It runs the function above. */
46 memset (&state, 0, sizeof state);
48 + MACHINE_THREAD_STATE_FIX_NEW (&state);
49 MACHINE_THREAD_STATE_SET_PC (&state, faulted);
50 MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
55 (vm_address_t *) &__hurd_sigthread_stack_base,
58 + err = __mach_setup_tls (_hurd_msgport_thread);
59 + assert_perror (err);
61 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
62 __hurd_sigthread_variables =
64 __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
65 memset (__hurd_sigthread_variables, 0,
66 __hurd_threadvar_max * sizeof (unsigned long int));
67 - __hurd_sigthread_variables[_HURD_THREADVAR_LOCALE]
68 - = (unsigned long int) &_nl_global_locale;
70 /* Reinitialize the MiG support routines so they will use a per-thread
71 variable for the cached reply port. */
75 vm_address_t *stack_base,
76 vm_size_t *stack_size);
78 +/* Give THREAD a TLS area. */
79 +kern_return_t __mach_setup_tls (thread_t thread);
80 +kern_return_t mach_setup_tls (thread_t thread);
83 --- a/mach/setup-thread.c
84 +++ b/mach/setup-thread.c
86 #include <thread_state.h>
88 #include <mach/machine/vm_param.h>
89 +#include <ldsodefs.h>
90 #include "sysdep.h" /* Defines stack direction. */
92 #define STACK_SIZE (16 * 1024 * 1024) /* 16MB, arbitrary. */
94 if (error = __vm_protect (task, stack, __vm_page_size, 0, VM_PROT_NONE))
97 - return __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
98 + return __thread_set_state (thread, MACHINE_NEW_THREAD_STATE_FLAVOR,
99 (natural_t *) &ts, tssize);
102 weak_alias (__mach_setup_thread, mach_setup_thread)
104 +/* Give THREAD a TLS area. */
106 +__mach_setup_tls (thread_t thread)
108 + kern_return_t error;
109 + struct machine_thread_state ts;
110 + mach_msg_type_number_t tssize = MACHINE_THREAD_STATE_COUNT;
113 + if (error = __thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR,
114 + (natural_t *) &ts, &tssize))
116 + assert (tssize == MACHINE_THREAD_STATE_COUNT);
118 + tcb = _dl_allocate_tls(NULL);
120 + return KERN_RESOURCE_SHORTAGE;
122 + _hurd_tls_new(thread, &ts, tcb);
124 + error = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
125 + (natural_t *) &ts, tssize);
129 +weak_alias (__mach_setup_tls, mach_setup_tls)
130 --- a/sysdeps/generic/thread_state.h
131 +++ b/sysdeps/generic/thread_state.h
134 /* Replace <machine> with "i386" or "mips" or whatever. */
136 +#define MACHINE_NEW_THREAD_STATE_FLAVOR <machine>_NEW_THREAD_STATE
137 #define MACHINE_THREAD_STATE_FLAVOR <machine>_THREAD_STATE
138 #define MACHINE_THREAD_STATE_COUNT <machine>_THREAD_STATE_COUNT
140 --- a/ports/sysdeps/mach/alpha/thread_state.h
141 +++ b/ports/sysdeps/mach/alpha/thread_state.h
144 #include <mach/machine/thread_status.h>
146 +#define MACHINE_NEW_THREAD_STATE_FLAVOR ALPHA_THREAD_STATE
147 #define MACHINE_THREAD_STATE_FLAVOR ALPHA_THREAD_STATE
148 #define MACHINE_THREAD_STATE_COUNT ALPHA_THREAD_STATE_COUNT
150 --- a/sysdeps/mach/hurd/bits/libc-tsd.h
153 -/* libc-internal interface for thread-specific data. Hurd version.
154 - Copyright (C) 1998,2002,2008 Free Software Foundation, Inc.
155 - This file is part of the GNU C Library.
157 - The GNU C Library is free software; you can redistribute it and/or
158 - modify it under the terms of the GNU Lesser General Public
159 - License as published by the Free Software Foundation; either
160 - version 2.1 of the License, or (at your option) any later version.
162 - The GNU C Library is distributed in the hope that it will be useful,
163 - but WITHOUT ANY WARRANTY; without even the implied warranty of
164 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
165 - Lesser General Public License for more details.
167 - You should have received a copy of the GNU Lesser General Public
168 - License along with the GNU C Library; if not, write to the Free
169 - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
172 -#ifndef _BITS_LIBC_TSD_H
173 -#define _BITS_LIBC_TSD_H 1
175 -#include <hurd/threadvar.h>
177 -#define __libc_tsd_define(CLASS, TYPE, KEY) /* nothing, always have threadvars */
179 -#define __libc_tsd_address(TYPE, KEY) \
180 - ((TYPE *) __hurd_threadvar_location (_HURD_THREADVAR_##KEY))
182 -#define __libc_tsd_get(TYPE, KEY) \
183 - (*__libc_tsd_address (TYPE, KEY))
184 -#define __libc_tsd_set(TYPE, KEY, VALUE) \
185 - (*__libc_tsd_address (TYPE, KEY) = (VALUE))
187 -#endif /* bits/libc-tsd.h */
188 --- a/sysdeps/mach/hurd/fork.c
189 +++ b/sysdeps/mach/hurd/fork.c
192 MACHINE_THREAD_STATE_SET_PC (&state,
193 (unsigned long int) _hurd_msgport_receive);
195 + /* Do special thread setup for TLS if needed. */
196 + if (err = _hurd_tls_fork (sigthread, _hurd_msgport_thread, &state))
199 if (err = __thread_set_state (sigthread, MACHINE_THREAD_STATE_FLAVOR,
200 (natural_t *) &state, statecount))
203 _hurd_longjmp_thread_state (&state, env, 1);
205 /* Do special thread setup for TLS if needed. */
206 - if (err = _hurd_tls_fork (thread, &state))
207 + if (err = _hurd_tls_fork (thread, __mach_thread_self (), &state))
210 if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
211 --- a/sysdeps/mach/hurd/i386/init-first.c
212 +++ b/sysdeps/mach/hurd/i386/init-first.c
215 char **envp = &argv[argc + 1];
216 struct hurd_startup_data *d;
218 - extern ElfW(Phdr) *_dl_phdr;
219 - extern size_t _dl_phnum;
225 data block; the argument strings start there. */
226 if ((void *) d == argv[0])
229 - /* We may need to see our own phdrs, e.g. for TLS setup.
230 - Try the usual kludge to find the headers without help from
231 - the exec server. */
232 - extern const void _start;
233 - const ElfW(Ehdr) *const ehdr = &_start;
234 - _dl_phdr = (ElfW(Phdr) *) ((const void *) ehdr + ehdr->e_phoff);
235 - _dl_phnum = ehdr->e_phnum;
236 - assert (ehdr->e_phentsize == sizeof (ElfW(Phdr)));
242 - __libc_enable_secure = d->flags & EXEC_SECURE;
244 - _dl_phdr = (ElfW(Phdr) *) d->phdr;
245 - _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr));
246 - assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
249 _hurd_init_dtable = d->dtable;
250 _hurd_init_dtablesize = d->dtablesize;
252 @@ -172,13 +150,16 @@
253 char **envp = &argv[argc + 1];
254 struct hurd_startup_data *d;
255 unsigned long int threadvars[_HURD_THREADVAR_MAX];
257 + extern ElfW(Phdr) *_dl_phdr;
258 + extern size_t _dl_phnum;
261 /* Provide temporary storage for thread-specific variables on the
262 startup stack so the cthreads initialization code can use them
263 for malloc et al, or so we can use malloc below for the real
265 memset (threadvars, 0, sizeof threadvars);
266 - threadvars[_HURD_THREADVAR_LOCALE] = (unsigned long int) &_nl_global_locale;
267 __hurd_threadvar_stack_offset = (unsigned long int) threadvars;
269 /* Since the cthreads initialization code uses malloc, and the
274 + /* If we are the bootstrap task started by the kernel,
275 + then after the environment pointers there is no Hurd
276 + data block; the argument strings start there. */
277 + if ((void *) d == argv[0])
280 + /* We may need to see our own phdrs, e.g. for TLS setup.
281 + Try the usual kludge to find the headers without help from
282 + the exec server. */
283 + extern const void __executable_start;
284 + const ElfW(Ehdr) *const ehdr = &__executable_start;
285 + _dl_phdr = (ElfW(Phdr) *) ((const void *) ehdr + ehdr->e_phoff);
286 + _dl_phnum = ehdr->e_phnum;
287 + assert (ehdr->e_phentsize == sizeof (ElfW(Phdr)));
293 + __libc_enable_secure = d->flags & EXEC_SECURE;
295 + _dl_phdr = (ElfW(Phdr) *) d->phdr;
296 + _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr));
297 + assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
302 + /* We need to setup TLS before starting sigthread */
303 + extern void __pthread_initialize_minimal(void);
304 + __pthread_initialize_minimal();
307 /* The user might have defined a value for this, to get more variables.
308 Otherwise it will be zero on startup. We must make sure it is set
309 properly before before cthreads initialization, so cthreads can know
310 --- a/sysdeps/mach/hurd/i386/tls.h
311 +++ b/sysdeps/mach/hurd/i386/tls.h
314 # ifndef __ASSEMBLER__
316 +#include <pthread/pthread.h>
318 /* Use i386-specific RPCs to arrange that %gs segment register prefix
319 addresses the TCB in each thread. */
320 # include <mach/i386/mach_i386.h>
323 /* Get the first available selector. */
325 - error_t err = __i386_set_gdt (tcb->self, &sel, desc);
326 + kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc);
327 if (err == MIG_BAD_ID)
329 /* Old kernel, use a per-thread LDT. */
331 /* Fetch the selector set by the first call. */
333 asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0));
334 - if (__builtin_expect (sel, 0x50) & 4) /* LDT selector */
335 + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
337 - error_t err = __i386_set_ldt (tcb->self, sel, &desc, 1);
338 + kern_return_t err = __i386_set_ldt (tcb->self, sel, &desc, 1);
341 return "i386_set_ldt failed";
345 - error_t err = __i386_set_gdt (tcb->self, &sel, desc);
346 + kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc);
349 return "i386_set_gdt failed";
352 #include <mach/machine/thread_status.h>
354 -/* Set up TLS in the new thread of a fork child, copying from our own. */
355 -static inline error_t __attribute__ ((unused))
356 -_hurd_tls_fork (thread_t child, struct i386_thread_state *state)
357 +/* Set up TLS in the new thread of a fork child, copying from the original. */
358 +static inline kern_return_t __attribute__ ((unused))
359 +_hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state)
361 + /* Fetch the selector set by _hurd_tls_init. */
363 + asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0));
364 + if (sel == state->ds) /* _hurd_tls_init was never called. */
367 + struct descriptor desc, *_desc = &desc;
369 + unsigned int count;
371 + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
372 + err = __i386_get_ldt (orig, sel, 1, &_desc, &count);
374 + err = __i386_get_gdt (orig, sel, &desc);
376 + assert_perror (err);
380 + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
381 + err = __i386_set_ldt (child, sel, &desc, 1);
383 + err = __i386_set_gdt (child, &sel, desc);
389 +static inline kern_return_t __attribute__ ((unused))
390 +_hurd_tls_new (thread_t child, struct i386_thread_state *state, tcbhead_t *tcb)
392 /* Fetch the selector set by _hurd_tls_init. */
394 @@ -152,11 +185,13 @@
395 if (sel == state->ds) /* _hurd_tls_init was never called. */
398 - tcbhead_t *const tcb = THREAD_SELF;
399 HURD_TLS_DESC_DECL (desc, tcb);
406 - if (__builtin_expect (sel, 0x50) & 4) /* LDT selector */
407 + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
408 err = __i386_set_ldt (child, sel, &desc, 1);
410 err = __i386_set_gdt (child, &sel, desc);
411 --- a/sysdeps/mach/hurd/i386/trampoline.c
412 +++ b/sysdeps/mach/hurd/i386/trampoline.c
414 sizeof (state->basic));
415 memcpy (&state->fpu, &ss->context->sc_i386_float_state,
416 sizeof (state->fpu));
417 - state->set |= (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE);
418 + state->set |= (1 << i386_REGS_SEGS_STATE) | (1 << i386_FLOAT_STATE);
422 --- a/sysdeps/mach/hurd/profil.c
423 +++ b/sysdeps/mach/hurd/profil.c
426 err = __mach_setup_thread (__mach_task_self (), profile_thread,
427 &profile_waiter, NULL, NULL);
429 + err = __mach_setup_tls(profile_thread);
433 --- a/sysdeps/mach/hurd/setitimer.c
434 +++ b/sysdeps/mach/hurd/setitimer.c
435 @@ -223,11 +223,12 @@
436 return __hurd_fail (err);
437 _hurd_itimer_thread_stack_base = 0; /* Anywhere. */
438 _hurd_itimer_thread_stack_size = __vm_page_size; /* Small stack. */
439 - if (err = __mach_setup_thread (__mach_task_self (),
440 + if ((err = __mach_setup_thread (__mach_task_self (),
443 &_hurd_itimer_thread_stack_base,
444 &_hurd_itimer_thread_stack_size))
445 + || (err = __mach_setup_tls(_hurd_itimer_thread)))
447 __thread_terminate (_hurd_itimer_thread);
448 _hurd_itimer_thread = MACH_PORT_NULL;
449 --- a/sysdeps/mach/i386/thread_state.h
450 +++ b/sysdeps/mach/i386/thread_state.h
453 #include <mach/machine/thread_status.h>
455 -#define MACHINE_THREAD_STATE_FLAVOR i386_THREAD_STATE
456 +#define MACHINE_NEW_THREAD_STATE_FLAVOR i386_THREAD_STATE
457 +#define MACHINE_THREAD_STATE_FLAVOR i386_REGS_SEGS_STATE
458 #define MACHINE_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
460 #define machine_thread_state i386_thread_state
463 #define SYSRETURN eax
465 +#define MACHINE_THREAD_STATE_FIX_NEW(ts) do { \
466 + asm ("mov %%cs, %w0" : "=q" ((ts)->cs)); \
467 + asm ("mov %%ds, %w0" : "=q" ((ts)->ds)); \
468 + asm ("mov %%es, %w0" : "=q" ((ts)->es)); \
469 + asm ("mov %%fs, %w0" : "=q" ((ts)->fs)); \
470 + asm ("mov %%gs, %w0" : "=q" ((ts)->gs)); \
473 struct machine_thread_all_state
475 int set; /* Mask of bits (1 << FLAVOR). */
476 --- a/sysdeps/mach/powerpc/thread_state.h
477 +++ b/sysdeps/mach/powerpc/thread_state.h
480 #include <mach/machine/thread_status.h>
482 +#define MACHINE_NEW_THREAD_STATE_FLAVOR PPC_THREAD_STATE
483 #define MACHINE_THREAD_STATE_FLAVOR PPC_THREAD_STATE
484 #define MACHINE_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
486 --- a/sysdeps/mach/thread_state.h
487 +++ b/sysdeps/mach/thread_state.h
489 ((ts)->SP = (unsigned long int) (stack) + (size))
492 +#ifndef MACHINE_THREAD_STATE_FIX_NEW
493 +#define MACHINE_THREAD_STATE_FIX_NEW(ts)
496 /* These functions are of use in machine-dependent signal trampoline
498 --- a/sysdeps/mach/hurd/bits/libc-lock.h
499 +++ b/sysdeps/mach/hurd/bits/libc-lock.h
501 #define _BITS_LIBC_LOCK_H 1
503 #if (_LIBC - 0) || (_CTHREADS_ - 0)
507 #include <cthreads.h>
508 #include <hurd/threadvar.h>
510 --- a/sysdeps/mach/hurd/tls.h
511 +++ b/sysdeps/mach/hurd/tls.h
513 #if defined HAVE_TLS_SUPPORT && !defined __ASSEMBLER__
516 +# include <stdint.h>
517 # include <stdbool.h>
518 +# include <sysdep.h>
519 # include <mach/mig_errors.h>
523 +++ b/sysdeps/mach/hurd/i386/tlsdesc.sym
529 +#include <dl-tlsdesc.h>
533 +-- Abuse tls.h macros to derive offsets relative to the thread register.
535 +DTV_OFFSET offsetof(tcbhead_t, dtv)
537 +TLSDESC_ARG offsetof(struct tlsdesc, arg)
539 +TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
540 +TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
541 +TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)