diff options
-rw-r--r-- | .topmsg | 16 | ||||
-rw-r--r-- | include/errno.h | 13 | ||||
-rw-r--r-- | mach/setup-thread.c | 10 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/init-first.c | 11 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/tls.h | 21 | ||||
-rw-r--r-- | sysdeps/mach/hurd/profil.c | 2 | ||||
-rw-r--r-- | sysdeps/mach/hurd/setitimer.c | 2 | ||||
-rw-r--r-- | sysdeps/mach/thread_state.h | 2 |
8 files changed, 47 insertions, 30 deletions
@@ -1,10 +1,14 @@ -From: Thomas Schwinge <thomas@schwinge.name> -Subject: [PATCH] tls +COMMITED -TLS support. +From: Samuel Thibault <samuel.thibault@gnu.org> +Subject: [PATCH] hurd: add TLS support 2009-07-30 Samuel Thibault <samuel.thibault@gnu.org> + Add TLS support: __mach_setup_tls allocates and sets + architecture state for the TLS area. i386 fork needs to + propagate the segment kernel definitions. + * sysdeps/mach/hurd/bits/libc-lock.h [_LIBC - 0]: Include <tls.h> * sysdeps/mach/hurd/tls.h: Include <stdint.h> and <sysdep.h> * include/errno.h (__GNU__): Do not define TLS errno for now. @@ -21,8 +25,10 @@ TLS support. * sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler): Use i386_REGS_SEGS_STATE instead of i386_THREAD_STATE. - * sysdeps/mach/hurd/i386/tls.h (_hurd_tls_init): Use kern_return_t - error type. Use first GDT slot, 0x48. + * sysdeps/mach/hurd/i386/tls.h (__i386_selector_is_ldt): New + macro. + (_hurd_tls_init): Use kern_return_t error type. Use + __i386_selector_is_ldt to test for LDT segment type. (_hurd_tls_fork): Use kern_return_t error type. Duplicate existing LDT descriptor instead of creating a new one. (_hurd_tls_new): New function, creates a new descriptor and updates tcb. diff --git a/include/errno.h b/include/errno.h index 669e4789f3..4f983889ae 100644 --- a/include/errno.h +++ b/include/errno.h @@ -26,12 +26,13 @@ extern int rtld_errno attribute_hidden; # include <tls.h> -# undef errno -# if IS_IN (libc) -# define errno __libc_errno -# else -# define errno errno /* For #ifndef errno tests. */ -# endif +# if !defined __GNU__ +# undef errno +# if IS_IN (libc) +# define errno __libc_errno +# else +# define errno errno /* For #ifndef errno tests. */ +# endif extern __thread int errno attribute_tls_model_ie; # endif diff --git a/mach/setup-thread.c b/mach/setup-thread.c index 1505027feb..c1de3a1fb6 100644 --- a/mach/setup-thread.c +++ b/mach/setup-thread.c @@ -88,16 +88,16 @@ __mach_setup_tls (thread_t thread) mach_msg_type_number_t tssize = MACHINE_THREAD_STATE_COUNT; tcbhead_t *tcb; + tcb = _dl_allocate_tls (NULL); + if (tcb == NULL) + return KERN_RESOURCE_SHORTAGE; + if (error = __thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR, (natural_t *) &ts, &tssize)) return error; assert (tssize == MACHINE_THREAD_STATE_COUNT); - tcb = _dl_allocate_tls(NULL); - if (!tcb) - return KERN_RESOURCE_SHORTAGE; - - _hurd_tls_new(thread, &ts, tcb); + _hurd_tls_new (thread, &ts, tcb); error = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR, (natural_t *) &ts, tssize); diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c index 643d7dbdae..7895206417 100644 --- a/sysdeps/mach/hurd/i386/init-first.c +++ b/sysdeps/mach/hurd/i386/init-first.c @@ -117,9 +117,7 @@ init1 (int argc, char *arg0, ...) then after the environment pointers there is no Hurd data block; the argument strings start there. */ if ((void *) d == argv[0]) - { - return; - } + return; #ifndef SHARED __libc_enable_secure = d->flags & EXEC_SECURE; @@ -206,9 +204,10 @@ init (int *data) assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0); } - /* We need to setup TLS before starting sigthread */ - extern void __pthread_initialize_minimal(void); - __pthread_initialize_minimal(); + /* We need to setup TLS before starting the signal thread. */ + extern void __pthread_initialize_minimal (void); + if (__pthread_initialize_minimal != NULL) + __pthread_initialize_minimal (); #endif /* The user might have defined a value for this, to get more variables. diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h index e94db7a925..fe0622868b 100644 --- a/sysdeps/mach/hurd/i386/tls.h +++ b/sysdeps/mach/hurd/i386/tls.h @@ -62,6 +62,15 @@ typedef struct #define TLS_TCB_AT_TP 1 #define TLS_DTV_AT_TP 0 +/* Alignment requirement for TCB. + + Some processors such as Intel Atom pay a big penalty on every + access using a segment override if that segment's base is not + aligned to the size of a cache line. (See Intel 64 and IA-32 + Architectures Optimization Reference Manual, section 13.3.3.3, + "Segment Base".) On such machines, a cache line is 64 bytes. */ +#define TCB_ALIGNMENT 64 + #ifndef __ASSEMBLER__ /* Use i386-specific RPCs to arrange that %gs segment register prefix @@ -72,6 +81,8 @@ typedef struct # define __i386_set_gdt(thr, sel, desc) ((void) (thr), (void) (sel), (void) (desc), MIG_BAD_ID) # endif +#define __i386_selector_is_ldt(sel) (!!((sel) & 4)) + # include <errno.h> # include <assert.h> @@ -162,10 +173,10 @@ _hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state) return 0; struct descriptor desc, *_desc = &desc; - kern_return_t err; + error_t err; unsigned int count = 1; - if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ + if (__glibc_unlikely (__i386_selector_is_ldt(sel))) err = __i386_get_ldt (orig, sel, 1, &_desc, &count); else err = __i386_get_gdt (orig, sel, &desc); @@ -174,7 +185,7 @@ _hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state) if (err) return err; - if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ + if (__glibc_unlikely (__i386_selector_is_ldt(sel))) err = __i386_set_ldt (child, sel, &desc, 1); else err = __i386_set_gdt (child, &sel, desc); @@ -193,12 +204,12 @@ _hurd_tls_new (thread_t child, struct i386_thread_state *state, tcbhead_t *tcb) return 0; HURD_TLS_DESC_DECL (desc, tcb); - kern_return_t err; + error_t err; tcb->tcb = tcb; tcb->self = child; - if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ + if (__glibc_unlikely (__i386_selector_is_ldt(sel))) err = __i386_set_ldt (child, sel, &desc, 1); else err = __i386_set_gdt (child, &sel, desc); diff --git a/sysdeps/mach/hurd/profil.c b/sysdeps/mach/hurd/profil.c index 27145ea32a..17028522a7 100644 --- a/sysdeps/mach/hurd/profil.c +++ b/sysdeps/mach/hurd/profil.c @@ -69,7 +69,7 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale) err = __mach_setup_thread (__mach_task_self (), profile_thread, &profile_waiter, NULL, NULL); if (! err) - err = __mach_setup_tls(profile_thread); + err = __mach_setup_tls (profile_thread); } else err = 0; diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c index b3341b8d4e..48346e2eab 100644 --- a/sysdeps/mach/hurd/setitimer.c +++ b/sysdeps/mach/hurd/setitimer.c @@ -226,7 +226,7 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old, &timer_thread, &_hurd_itimer_thread_stack_base, &_hurd_itimer_thread_stack_size)) - || (err = __mach_setup_tls(_hurd_itimer_thread))) + || (err = __mach_setup_tls (_hurd_itimer_thread))) { __thread_terminate (_hurd_itimer_thread); _hurd_itimer_thread = MACH_PORT_NULL; diff --git a/sysdeps/mach/thread_state.h b/sysdeps/mach/thread_state.h index 0914b84244..c382eb995a 100644 --- a/sysdeps/mach/thread_state.h +++ b/sysdeps/mach/thread_state.h @@ -38,7 +38,7 @@ #endif #endif #ifndef MACHINE_THREAD_STATE_FIX_NEW -#define MACHINE_THREAD_STATE_FIX_NEW(ts) +# define MACHINE_THREAD_STATE_FIX_NEW(ts) #endif /* These functions are of use in machine-dependent signal trampoline |