diff options
author | Jakub Jelinek <jakub@redhat.com> | 2004-11-02 12:26:42 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2004-11-02 12:26:42 +0000 |
commit | 80c96e8e6f452d6d9803f5a2e17030658f30afc4 (patch) | |
tree | ef584f35ed7167c7a680783415a66799c3789233 /sysdeps/mach | |
parent | 0b5cfa4e0b7c9dc2cd81635307613c86c0f5e200 (diff) | |
download | glibc-80c96e8e6f452d6d9803f5a2e17030658f30afc4.tar glibc-80c96e8e6f452d6d9803f5a2e17030658f30afc4.tar.gz glibc-80c96e8e6f452d6d9803f5a2e17030658f30afc4.tar.bz2 glibc-80c96e8e6f452d6d9803f5a2e17030658f30afc4.zip |
Updated to fedora-glibc-20041102T1153
Diffstat (limited to 'sysdeps/mach')
-rw-r--r-- | sysdeps/mach/hurd/fork.c | 10 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/tls.h | 67 |
2 files changed, 60 insertions, 17 deletions
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c index c3f8a1a86b..8728596915 100644 --- a/sysdeps/mach/hurd/fork.c +++ b/sysdeps/mach/hurd/fork.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1994,95,96,97,99,2001,02 Free Software Foundation, Inc. +/* Copyright (C) 1994,95,96,97,99,2001,02, 04 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,6 +26,7 @@ #include "set-hooks.h" #include <assert.h> #include "hurdmalloc.h" /* XXX */ +#include <tls.h> #undef __fork @@ -529,6 +530,13 @@ __fork (void) /* Set the child user thread up to return 1 from the setjmp above. */ _hurd_longjmp_thread_state (&state, env, 1); + +#if USE_TLS + /* Do special thread setup for TLS if needed. */ + if (err = _hurd_tls_fork (thread, &state)) + LOSE; +#endif + if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR, (natural_t *) &state, statecount)) LOSE; diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h index 8adbee98fc..ff849716e0 100644 --- a/sysdeps/mach/hurd/i386/tls.h +++ b/sysdeps/mach/hurd/i386/tls.h @@ -45,24 +45,31 @@ # include <errno.h> # include <assert.h> +#define HURD_TLS_DESC_DECL(desc, tcb) \ + struct descriptor desc = \ + { /* low word: */ \ + 0xffff /* limit 0..15 */ \ + | (((unsigned int) (tcb)) << 16) /* base 0..15 */ \ + , /* high word: */ \ + ((((unsigned int) (tcb)) >> 16) & 0xff) /* base 16..23 */ \ + | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ \ + | (0xf << 16) /* limit 16..19 */ \ + | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ \ + | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ + } + + static inline const char * __attribute__ ((unused)) _hurd_tls_init (tcbhead_t *tcb, int secondcall) { - const unsigned int base = (unsigned int) tcb; - struct descriptor desc = - { /* low word: */ - 0xffff /* limit 0..15 */ - | (base << 16) /* base 0..15 */ - , /* high word: */ - ((base >> 16) & 0xff) /* base 16..23 */ - | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ - | (0xf << 16) /* limit 16..19 */ - | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ - | (base & 0xff000000) /* base 24..31 */ - }; + HURD_TLS_DESC_DECL (desc, tcb); if (!secondcall) { + /* This field is used by TLS accesses to get our "thread pointer" + from the TLS point of view. */ + tcb->tcb = tcb; + /* Cache our thread port. */ tcb->self = __mach_thread_self (); @@ -75,9 +82,10 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall) sel = 0x27; err = __i386_set_ldt (tcb->self, sel, &desc, 1); assert_perror (err); - return "i386_set_ldt failed"; + if (err) + return "i386_set_ldt failed"; } - else + else if (err) { assert_perror (err); /* Separate from above with different line #. */ return "i386_set_gdt failed"; @@ -95,13 +103,15 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall) { error_t err = __i386_set_ldt (tcb->self, sel, &desc, 1); assert_perror (err); - return "i386_set_ldt failed"; + if (err) + return "i386_set_ldt failed"; } else { error_t err = __i386_set_gdt (tcb->self, &sel, desc); assert_perror (err); - return "i386_set_gdt failed"; + if (err) + return "i386_set_gdt failed"; } } @@ -133,6 +143,31 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall) asm ("movl %%gs:%P1,%0" : "=q" (_dtv) : "i" (offsetof (tcbhead_t, dtv)));\ _dtv; }) +#include <mach/machine/thread_status.h> + +/* Set up TLS in the new thread of a fork child, copying from our own. */ +static inline error_t __attribute__ ((unused)) +_hurd_tls_fork (thread_t child, struct i386_thread_state *state) +{ + /* Fetch the selector set by _hurd_tls_init. */ + int sel; + asm ("mov %%gs, %w0" : "=q" (sel)); + if (sel == state->ds) /* _hurd_tls_init was never called. */ + return 0; + + tcbhead_t *const tcb = THREAD_SELF; + HURD_TLS_DESC_DECL (desc, tcb); + error_t err; + + if (__builtin_expect (sel, 0x50) & 4) /* LDT selector */ + err = __i386_set_ldt (child, sel, &desc, 1); + else + err = __i386_set_gdt (child, &sel, desc); + + state->gs = sel; + return err; +} + # endif /* !ASSEMBLER */ #endif /* HAVE_TLS_SUPPORT */ |