Back to index

glibc  2.9
tls.h
Go to the documentation of this file.
00001 /* Definition for thread-local data handling.  nptl/IA-64 version.
00002    Copyright (C) 2003, 2004, 2005, 2006, 2007 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       1
00022 
00023 #include <dl-sysdep.h>
00024 #ifndef __ASSEMBLER__
00025 # include <stdbool.h>
00026 # include <stddef.h>
00027 # include <stdint.h>
00028 # include <stdlib.h>
00029 # include <list.h>
00030 
00031 
00032 /* Type for the dtv.  */
00033 typedef union dtv
00034 {
00035   size_t counter;
00036   struct
00037   {
00038     void *val;
00039     bool is_static;
00040   } pointer;
00041 } dtv_t;
00042 
00043 
00044 typedef struct
00045 {
00046   dtv_t *dtv;
00047   void *__private;
00048 } tcbhead_t;
00049 
00050 register struct pthread *__thread_self __asm__("r13");
00051 
00052 # define TLS_MULTIPLE_THREADS_IN_TCB 1
00053 
00054 #else /* __ASSEMBLER__ */
00055 # include <tcb-offsets.h>
00056 #endif
00057 
00058 
00059 /* We require TLS support in the tools.  */
00060 #ifndef HAVE_TLS_SUPPORT
00061 # error "TLS support is required."
00062 #endif
00063 
00064 /* Alignment requirement for the stack.  */
00065 #define STACK_ALIGN  16
00066 
00067 #ifndef __ASSEMBLER__
00068 /* Get system call information.  */
00069 # include <sysdep.h>
00070 
00071 /* This is the size of the initial TCB.  */
00072 # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
00073 
00074 /* Alignment requirements for the initial TCB.  */
00075 # define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
00076 
00077 /* This is the size of the TCB.  */
00078 # define TLS_TCB_SIZE sizeof (tcbhead_t)
00079 
00080 /* This is the size we need before TCB.
00081    If there is not any room for uintptr_t stack_guard and
00082    uintptr_t pointer_guard in struct pthread's final padding,
00083    we need to put struct pthread 16 byte slower.  */
00084 # define TLS_PRE_TCB_SIZE \
00085   (sizeof (struct pthread)                                     \
00086    + (PTHREAD_STRUCT_END_PADDING < 2 * sizeof (uintptr_t)             \
00087       ? ((2 * sizeof (uintptr_t) + __alignof__ (struct pthread) - 1)  \
00088         & ~(__alignof__ (struct pthread) - 1))                        \
00089       : 0))
00090 
00091 /* Alignment requirements for the TCB.  */
00092 # define TLS_TCB_ALIGN __alignof__ (struct pthread)
00093 
00094 /* The DTV is allocated at the TP; the TCB is placed elsewhere.  */
00095 # define TLS_DTV_AT_TP      1
00096 
00097 /* Get the thread descriptor definition.  */
00098 # include <nptl/descr.h>
00099 
00100 /* Install the dtv pointer.  The pointer passed is to the element with
00101    index -1 which contain the length.  */
00102 #  define INSTALL_DTV(descr, dtvp) \
00103   ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
00104 
00105 /* Install new dtv for current thread.  */
00106 #  define INSTALL_NEW_DTV(DTV) \
00107   (((tcbhead_t *)__thread_self)->dtv = (DTV))
00108 
00109 /* Return dtv of given thread descriptor.  */
00110 #  define GET_DTV(descr) \
00111   (((tcbhead_t *) (descr))->dtv)
00112 
00113 #define THREAD_SELF_SYSINFO (((tcbhead_t *) __thread_self)->__private)
00114 #define THREAD_SYSINFO(pd) \
00115   (((tcbhead_t *) ((char *) (pd) + TLS_PRE_TCB_SIZE))->__private)
00116 
00117 #if defined NEED_DL_SYSINFO
00118 # define INIT_SYSINFO   THREAD_SELF_SYSINFO = (void *) GLRO(dl_sysinfo)
00119 #else
00120 # define INIT_SYSINFO   NULL
00121 #endif
00122 
00123 /* Code to initially initialize the thread pointer.  This might need
00124    special attention since 'errno' is not yet available and if the
00125    operation can cause a failure 'errno' must not be touched.  */
00126 # define TLS_INIT_TP(thrdescr, secondcall) \
00127   (__thread_self = (thrdescr), INIT_SYSINFO, NULL)
00128 
00129 /* Return the address of the dtv for the current thread.  */
00130 #  define THREAD_DTV() \
00131   (((tcbhead_t *)__thread_self)->dtv)
00132 
00133 /* Return the thread descriptor for the current thread.  */
00134 # define THREAD_SELF \
00135   ((struct pthread *) ((char *) __thread_self - TLS_PRE_TCB_SIZE))
00136 
00137 /* Magic for libthread_db to know how to do THREAD_SELF.  */
00138 # define DB_THREAD_SELF REGISTER (64, 64, 13 * 8, -TLS_PRE_TCB_SIZE)
00139 
00140 /* Access to data in the thread descriptor is easy.  */
00141 #define THREAD_GETMEM(descr, member) \
00142   descr->member
00143 #define THREAD_GETMEM_NC(descr, member, idx) \
00144   descr->member[idx]
00145 #define THREAD_SETMEM(descr, member, value) \
00146   descr->member = (value)
00147 #define THREAD_SETMEM_NC(descr, member, idx, value) \
00148   descr->member[idx] = (value)
00149 
00150 /* Set the stack guard field in TCB head.  */
00151 #define THREAD_SET_STACK_GUARD(value) \
00152   (((uintptr_t *) __thread_self)[-1] = (value))
00153 #define THREAD_COPY_STACK_GUARD(descr) \
00154   (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-1] \
00155    = ((uintptr_t *) __thread_self)[-1])
00156 
00157 /* Set the pointer guard field in TCB head.  */
00158 #define THREAD_GET_POINTER_GUARD() \
00159   (((uintptr_t *) __thread_self)[-2])
00160 #define THREAD_SET_POINTER_GUARD(value) \
00161   (((uintptr_t *) __thread_self)[-2] = (value))
00162 #define THREAD_COPY_POINTER_GUARD(descr) \
00163   (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-2] \
00164    = THREAD_GET_POINTER_GUARD ())
00165 
00166 /* Get and set the global scope generation counter in struct pthread.  */
00167 #define THREAD_GSCOPE_FLAG_UNUSED 0
00168 #define THREAD_GSCOPE_FLAG_USED   1
00169 #define THREAD_GSCOPE_FLAG_WAIT   2
00170 #define THREAD_GSCOPE_RESET_FLAG() \
00171   do                                                                \
00172     { int __res                                                            \
00173        = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag,            \
00174                             THREAD_GSCOPE_FLAG_UNUSED);             \
00175       if (__res == THREAD_GSCOPE_FLAG_WAIT)                                \
00176        lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);   \
00177     }                                                               \
00178   while (0)
00179 #define THREAD_GSCOPE_SET_FLAG() \
00180   do                                                                \
00181     {                                                               \
00182       THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED;           \
00183       atomic_write_barrier ();                                             \
00184     }                                                               \
00185   while (0)
00186 #define THREAD_GSCOPE_WAIT() \
00187   GL(dl_wait_lookup_done) ()
00188 
00189 #endif /* __ASSEMBLER__ */
00190 
00191 #endif /* tls.h */