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. 4 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. 9 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. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 18 19 #ifndef _TLS_H 20 #define _TLS_H 21 22 # include <pt-machine.h> 23 24 #ifndef __ASSEMBLER__ 25 # include <stdbool.h> 26 # include <stddef.h> 27 # include <stdint.h> 28 29 /* Type for the dtv. */ 30 typedef union dtv 31 { 32 size_t counter; 33 void *pointer; 34 } dtv_t; 35 36 37 typedef struct 38 { 39 void *tcb; /* Pointer to the TCB. Not necessary the 40 thread descriptor used by libpthread. */ 41 dtv_t *dtv; 42 void *self; /* Pointer to the thread descriptor. */ 43 } tcbhead_t; 44 #endif 45 46 47 /* We can support TLS only if the floating-stack support is available. */ 48 #if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT 49 50 /* Signal that TLS support is available. */ 51 //# define USE_TLS 1 52 53 # ifndef __ASSEMBLER__ 54 /* Get system call information. */ 55 # include <sysdep.h> 56 57 58 /* Get the thread descriptor definition. */ 59 # include <linuxthreads/descr.h> 60 61 /* This is the size of the initial TCB. */ 62 # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) 63 64 /* Alignment requirements for the initial TCB. */ 65 # define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) 66 67 /* This is the size of the TCB. */ 68 # define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) 69 70 /* Alignment requirements for the TCB. */ 71 # define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) 72 73 /* The TCB can have any size and the memory following the address the 74 thread pointer points to is unspecified. Allocate the TCB there. */ 75 # define TLS_TCB_AT_TP 1 76 77 78 /* Install the dtv pointer. The pointer passed is to the element with 79 index -1 which contain the length. */ 80 # define INSTALL_DTV(descr, dtvp) \ 81 ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 82 83 /* Install new dtv for current thread. */ 84 # define INSTALL_NEW_DTV(dtv) \ 85 ({ struct _pthread_descr_struct *__descr; \ 86 THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) 87 88 /* Return dtv of given thread descriptor. */ 89 # define GET_DTV(descr) \ 90 (((tcbhead_t *) (descr))->dtv) 91 92 # ifdef __PIC__ 93 # define TLS_EBX_ARG "r" 94 # define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" 95 # else 96 # define TLS_EBX_ARG "b" 97 # define TLS_LOAD_EBX 98 # endif 99 100 # define TLS_DO_MODIFY_LDT(descr, nr) \ 101 ({ \ 102 struct modify_ldt_ldt_s ldt_entry = \ 103 { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ 104 1, 0, 0, 1, 0, 1, 0 }; \ 105 int result; \ 106 __asm__ __volatile__ (TLS_LOAD_EBX \ 107 "int $0x80\n\t" \ 108 TLS_LOAD_EBX \ 109 : "=a" (result) \ 110 : "0" (__NR_modify_ldt), \ 111 /* The extra argument with the "m" constraint is necessary \ 112 to let the compiler know that we are accessing LDT_ENTRY \ 113 here. */ \ 114 "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ 115 "d" (sizeof (ldt_entry))); \ 116 __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \ 117 }) 118 119 # define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ 120 ({ \ 121 struct modify_ldt_ldt_s ldt_entry = \ 122 { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ 123 1, 0, 0, 1, 0, 1, 0 }; \ 124 int result; \ 125 if (secondcall) \ 126 ldt_entry.entry_number = ({ int _gs; \ 127 __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \ 128 (_gs & 0xffff) >> 3; }); \ 129 __asm__ __volatile__ (TLS_LOAD_EBX \ 130 "int $0x80\n\t" \ 131 TLS_LOAD_EBX \ 132 : "=a" (result), "=m" (ldt_entry.entry_number) \ 133 : "0" (__NR_set_thread_area), \ 134 /* The extra argument with the "m" constraint is necessary \ 135 to let the compiler know that we are accessing LDT_ENTRY \ 136 here. */ \ 137 TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ 138 __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \ 139 }) 140 141 # ifdef __ASSUME_SET_THREAD_AREA_SYSCALL 142 # define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ 143 TLS_DO_SET_THREAD_AREA (descr, firstcall) 144 # elif defined __NR_set_thread_area 145 # define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ 146 ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \ 147 __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; }) 148 # else 149 # define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ 150 TLS_DO_MODIFY_LDT ((descr), 0) 151 # endif 152 153 /* Code to initially initialize the thread pointer. This might need 154 special attention since 'errno' is not yet available and if the 155 operation can cause a failure 'errno' must not be touched. */ 156 # define TLS_INIT_TP(descr, secondcall) \ 157 ({ \ 158 void *_descr = (descr); \ 159 tcbhead_t *head = _descr; \ 160 int __gs; \ 161 \ 162 head->tcb = _descr; \ 163 /* For now the thread descriptor is at the same address. */ \ 164 head->self = _descr; \ 165 \ 166 __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ 167 if (__builtin_expect (__gs, 7) != -1) \ 168 { \ 169 __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ 170 __gs = 0; \ 171 } \ 172 __gs; \ 173 }) 174 175 176 /* Return the address of the dtv for the current thread. */ 177 # define THREAD_DTV() \ 178 ({ struct _pthread_descr_struct *__descr; \ 179 THREAD_GETMEM (__descr, p_header.data.dtvp); }) 180 181 # endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ 182 #endif /* __ASSEMBLER__ */ 183 184 #endif /* tls.h */ 185