Back to index

glibc  2.9
tls.h
Go to the documentation of this file.
00001 /* Definition for thread-local data handling.  linuxthreads/i386 version.
00002    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #ifndef _TLS_H
00021 #define _TLS_H
00022 
00023 # include <dl-sysdep.h>
00024 # include <pt-machine.h>
00025 
00026 #ifndef __ASSEMBLER__
00027 # include <stdbool.h>
00028 # include <stddef.h>
00029 # include <stdint.h>
00030 
00031 /* Type for the dtv.  */
00032 typedef union dtv
00033 {
00034   size_t counter;
00035   struct
00036   {
00037     void *val;
00038     bool is_static;
00039   } pointer;
00040 } dtv_t;
00041 
00042 
00043 typedef struct
00044 {
00045   void *tcb;         /* Pointer to the TCB.  Not necessary the
00046                         thread descriptor used by libpthread.  */
00047   dtv_t *dtv;
00048   void *self;        /* Pointer to the thread descriptor.  */
00049   int multiple_threads;
00050   uintptr_t sysinfo;
00051   uintptr_t stack_guard;
00052   uintptr_t pointer_guard;
00053 } tcbhead_t;
00054 
00055 #else /* __ASSEMBLER__ */
00056 # include <tcb-offsets.h>
00057 #endif
00058 
00059 /* We can support TLS only if the floating-stack support is available.
00060    However, we want to compile in the support and test at runtime whether
00061    the running kernel can support it or not.  To avoid bothering with the
00062    TLS support code at all, use configure --without-tls.
00063 
00064    We need USE_TLS to be consistently defined, for ldsodefs.h conditionals.
00065    But some of the code below can cause problems in building libpthread
00066    (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't).  */
00067 
00068 #if defined HAVE_TLS_SUPPORT \
00069     && (defined FLOATING_STACKS || !defined IS_IN_libpthread)
00070 
00071 /* Signal that TLS support is available.  */
00072 # define USE_TLS     1
00073 
00074 # ifndef __ASSEMBLER__
00075 /* Get system call information.  */
00076 #  include <sysdep.h>
00077 
00078 
00079 /* Get the thread descriptor definition.  */
00080 #  include <linuxthreads/descr.h>
00081 
00082 /* This is the size of the initial TCB.  */
00083 #  define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
00084 
00085 /* Alignment requirements for the initial TCB.  */
00086 #  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
00087 
00088 /* This is the size of the TCB.  */
00089 #  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
00090 
00091 /* Alignment requirements for the TCB.  */
00092 #  define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
00093 
00094 /* The TCB can have any size and the memory following the address the
00095    thread pointer points to is unspecified.  Allocate the TCB there.  */
00096 #  define TLS_TCB_AT_TP     1
00097 
00098 
00099 /* Install the dtv pointer.  The pointer passed is to the element with
00100    index -1 which contain the length.  */
00101 #  define INSTALL_DTV(descr, dtvp) \
00102   ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
00103 
00104 /* Install new dtv for current thread.  */
00105 #  define INSTALL_NEW_DTV(dtv) \
00106   ({ struct _pthread_descr_struct *__descr;                                 \
00107      THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
00108 
00109 /* Return dtv of given thread descriptor.  */
00110 #  define GET_DTV(descr) \
00111   (((tcbhead_t *) (descr))->dtv)
00112 
00113 #  ifdef __PIC__
00114 #   define TLS_EBX_ARG "r"
00115 #   define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
00116 #  else
00117 #   define TLS_EBX_ARG "b"
00118 #   define TLS_LOAD_EBX
00119 #  endif
00120 
00121 #  if !defined IS_IN_linuxthreads && !defined DO_MODIFY_LDT
00122 #   include "useldt.h"             /* For the structure.  */
00123 #  endif
00124 #  if __ASSUME_LDT_WORKS > 0
00125 #   define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) (doit) /* Nothing to check.  */
00126 #  else
00127 #   define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit)                             \
00128   (__builtin_expect (GLRO(dl_osversion) < 131939, 0)                        \
00129    ? "kernel too old for thread-local storage support\n"                           \
00130    : (doit))
00131 #  endif
00132 
00133 #  define TLS_DO_MODIFY_LDT(descr, nr)                                      \
00134 TLS_DO_MODIFY_LDT_KERNEL_CHECK(                                             \
00135 ({                                                                   \
00136   struct modify_ldt_ldt_s ldt_entry =                                       \
00137     { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,          \
00138       1, 0, 0, 1, 0, 1, 0 };                                                \
00139   int result;                                                        \
00140   asm volatile (TLS_LOAD_EBX                                                \
00141               "int $0x80\n\t"                                               \
00142               TLS_LOAD_EBX                                           \
00143               : "=a" (result)                                               \
00144               : "0" (__NR_modify_ldt),                               \
00145               /* The extra argument with the "m" constraint is necessary    \
00146                  to let the compiler know that we are accessing LDT_ENTRY   \
00147                  here.  */                                           \
00148               "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry),           \
00149               "d" (sizeof (ldt_entry)));                             \
00150   __builtin_expect (result, 0) == 0                                         \
00151   ? ({ asm ("movw %w0, %%gs" : : "q" ((nr) * 8 + 7)); NULL; })              \
00152   : "cannot set up LDT for thread-local storage\n";                         \
00153 }))
00154 
00155 #  define TLS_DO_SET_THREAD_AREA(descr, secondcall)                         \
00156 ({                                                                   \
00157   struct modify_ldt_ldt_s ldt_entry =                                       \
00158     { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,          \
00159       1, 0, 0, 1, 0, 1, 0 };                                                \
00160   int result;                                                        \
00161   if (secondcall)                                                    \
00162     ldt_entry.entry_number = ({ int _gs;                             \
00163                             asm ("movw %%gs, %w0" : "=q" (_gs));            \
00164                             (_gs & 0xffff) >> 3; });                 \
00165   asm volatile (TLS_LOAD_EBX                                                \
00166               "int $0x80\n\t"                                               \
00167               TLS_LOAD_EBX                                           \
00168               : "=a" (result), "=m" (ldt_entry.entry_number)                \
00169               : "0" (__NR_set_thread_area),                                 \
00170               /* The extra argument with the "m" constraint is necessary    \
00171                  to let the compiler know that we are accessing LDT_ENTRY   \
00172                  here.  */                                           \
00173               TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry));                   \
00174   if (__builtin_expect (result, 0) == 0)                             \
00175     asm ("movw %w0, %%gs" : : "q" (ldt_entry.entry_number * 8 + 3));        \
00176   result;                                                            \
00177 })
00178 
00179 #  ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
00180 #   define TLS_SETUP_GS_SEGMENT(descr, secondcall)                          \
00181   (TLS_DO_SET_THREAD_AREA (descr, secondcall)                               \
00182    ? "set_thread_area failed when setting up thread-local storage\n" : NULL)
00183 #  elif defined __NR_set_thread_area
00184 #   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
00185   (TLS_DO_SET_THREAD_AREA (descr, secondcall)                               \
00186    ? TLS_DO_MODIFY_LDT (descr, 0) : NULL)
00187 #  else
00188 #   define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
00189   TLS_DO_MODIFY_LDT ((descr), 0)
00190 #  endif
00191 
00192 #if defined NEED_DL_SYSINFO
00193 # define INIT_SYSINFO \
00194   head->sysinfo = GLRO(dl_sysinfo)
00195 #else
00196 # define INIT_SYSINFO
00197 #endif
00198 
00199 /* Code to initially initialize the thread pointer.  This might need
00200    special attention since 'errno' is not yet available and if the
00201    operation can cause a failure 'errno' must not be touched.
00202 
00203    The value of this macro is null if successful, or an error string.  */
00204 #  define TLS_INIT_TP(descr, secondcall)                             \
00205   ({                                                                 \
00206     void *_descr = (descr);                                          \
00207     tcbhead_t *head = _descr;                                               \
00208                                                                      \
00209     head->tcb = _descr;                                                     \
00210     /* For now the thread descriptor is at the same address.  */            \
00211     head->self = _descr;                                             \
00212                                                                      \
00213     INIT_SYSINFO;                                                    \
00214     TLS_SETUP_GS_SEGMENT (_descr, secondcall);                              \
00215   })
00216 
00217 /* Indicate that dynamic linker shouldn't try to initialize TLS even
00218    when no PT_TLS segments are found in the program and libraries
00219    it is linked against.  */
00220 #  define TLS_INIT_TP_EXPENSIVE 1
00221 
00222 /* Return the address of the dtv for the current thread.  */
00223 #  define THREAD_DTV() \
00224   ({ struct _pthread_descr_struct *__descr;                                 \
00225      THREAD_GETMEM (__descr, p_header.data.dtvp); })
00226 
00227 
00228 /* Set the stack guard field in TCB head.  */
00229 #define THREAD_SET_STACK_GUARD(value) \
00230   THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value)
00231 #define THREAD_COPY_STACK_GUARD(descr) \
00232   ((descr)->p_header.data.stack_guard                                \
00233    = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard))
00234 
00235 
00236 /* Set the pointer guard field in the TCB head.  */
00237 #define THREAD_SET_POINTER_GUARD(value) \
00238   THREAD_SETMEM (THREAD_SELF, p_header.data.pointer_guard, value)
00239 #define THREAD_COPY_POINTER_GUARD(descr) \
00240   ((descr)->p_header.data.pointer_guard                              \
00241    = THREAD_GETMEM (THREAD_SELF, p_header.data.pointer_guard))
00242 
00243 
00244 # endif       /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
00245 #endif /* __ASSEMBLER__ */
00246 
00247 #endif /* tls.h */