1 /* Definition for thread-local data handling. linuxthreads/i386 version.
2 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 # include <pt-machine.h>
30 /* Type for the dtv. */
40 void *tcb; /* Pointer to the TCB. Not necessary the
41 thread descriptor used by libpthread. */
43 void *self; /* Pointer to the thread descriptor. */
48 /* We can support TLS only if the floating-stack support is available. */
49 #if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
51 /* Signal that TLS support is available. */
54 # ifndef __ASSEMBLER__
55 /* Get system call information. */
59 /* Get the thread descriptor definition. */
60 # include <linuxthreads/descr.h>
62 /* This is the size of the initial TCB. */
63 # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
65 /* Alignment requirements for the initial TCB. */
66 # define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
68 /* This is the size of the TCB. */
69 # define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
71 /* Alignment requirements for the TCB. */
72 # define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
74 /* The TCB can have any size and the memory following the address the
75 thread pointer points to is unspecified. Allocate the TCB there. */
76 # define TLS_TCB_AT_TP 1
79 /* Install the dtv pointer. The pointer passed is to the element with
80 index -1 which contain the length. */
81 # define INSTALL_DTV(descr, dtvp) \
82 ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
84 /* Install new dtv for current thread. */
85 # define INSTALL_NEW_DTV(dtv) \
86 ({ struct _pthread_descr_struct *__descr; \
87 THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
89 /* Return dtv of given thread descriptor. */
90 # define GET_DTV(descr) \
91 (((tcbhead_t *) (descr))->dtv)
94 # define TLS_EBX_ARG "r"
95 # define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
97 # define TLS_EBX_ARG "b"
101 # define TLS_DO_MODIFY_LDT(descr, nr) \
103 struct modify_ldt_ldt_s ldt_entry = \
104 { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
105 1, 0, 0, 1, 0, 1, 0 }; \
107 __asm__ __volatile__ (TLS_LOAD_EBX \
111 : "0" (__NR_modify_ldt), \
112 /* The extra argument with the "m" constraint is necessary \
113 to let the compiler know that we are accessing LDT_ENTRY \
115 "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \
116 "d" (sizeof (ldt_entry))); \
117 __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \
120 # define TLS_DO_SET_THREAD_AREA(descr, secondcall) \
122 struct modify_ldt_ldt_s ldt_entry = \
123 { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
124 1, 0, 0, 1, 0, 1, 0 }; \
127 ldt_entry.entry_number = ({ int _gs; \
128 __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \
129 (_gs & 0xffff) >> 3; }); \
130 __asm__ __volatile__ (TLS_LOAD_EBX \
133 : "=a" (result), "=m" (ldt_entry.entry_number) \
134 : "0" (__NR_set_thread_area), \
135 /* The extra argument with the "m" constraint is necessary \
136 to let the compiler know that we are accessing LDT_ENTRY \
138 TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \
139 __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \
142 # ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
143 # define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
144 TLS_DO_SET_THREAD_AREA (descr, firstcall)
145 # elif defined __NR_set_thread_area
146 # define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
147 ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \
148 __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; })
150 # define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
151 TLS_DO_MODIFY_LDT ((descr), 0)
154 /* Code to initially initialize the thread pointer. This might need
155 special attention since 'errno' is not yet available and if the
156 operation can cause a failure 'errno' must not be touched. */
157 # define TLS_INIT_TP(descr, secondcall) \
159 void *_descr = (descr); \
160 tcbhead_t *head = _descr; \
163 head->tcb = _descr; \
164 /* For now the thread descriptor is at the same address. */ \
165 head->self = _descr; \
167 __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \
168 if (__builtin_expect (__gs, 7) != -1) \
170 __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \
177 /* Return the address of the dtv for the current thread. */
178 # define THREAD_DTV() \
179 ({ struct _pthread_descr_struct *__descr; \
180 THREAD_GETMEM (__descr, p_header.data.dtvp); })
182 # endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */
183 #endif /* __ASSEMBLER__ */