aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd/i386/tls.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/i386/tls.h')
-rw-r--r--sysdeps/mach/hurd/i386/tls.h50
1 files changed, 38 insertions, 12 deletions
diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
index 9108346..a7c291c 100644
--- a/sysdeps/mach/hurd/i386/tls.h
+++ b/sysdeps/mach/hurd/i386/tls.h
@@ -45,21 +45,24 @@
# 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)
{
@@ -140,6 +143,29 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall)
asm ("movl %%gs:%P1,%0" : "=q" (_dtv) : "i" (offsetof (tcbhead_t, dtv)));\
_dtv; })
+/* 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 machine_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 */