(root)/
glibc-2.38/
sysdeps/
x86_64/
nptl/
tls.h
       1  /* Definition for thread-local data handling.  nptl/x86_64 version.
       2     Copyright (C) 2002-2023 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     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _TLS_H
      20  #define _TLS_H	1
      21  
      22  #ifndef __ASSEMBLER__
      23  # include <asm/prctl.h>	/* For ARCH_SET_FS.  */
      24  # include <stdbool.h>
      25  # include <stddef.h>
      26  # include <stdint.h>
      27  # include <stdlib.h>
      28  # include <sysdep.h>
      29  # include <libc-pointer-arith.h> /* For cast_to_integer.  */
      30  # include <kernel-features.h>
      31  # include <dl-dtv.h>
      32  
      33  /* Replacement type for __m128 since this file is included by ld.so,
      34     which is compiled with -mno-sse.  It must not change the alignment
      35     of rtld_savespace_sse.  */
      36  typedef struct
      37  {
      38    int i[4];
      39  } __128bits;
      40  
      41  
      42  typedef struct
      43  {
      44    void *tcb;		/* Pointer to the TCB.  Not necessarily the
      45  			   thread descriptor used by libpthread.  */
      46    dtv_t *dtv;
      47    void *self;		/* Pointer to the thread descriptor.  */
      48    int multiple_threads;
      49    int gscope_flag;
      50    uintptr_t sysinfo;
      51    uintptr_t stack_guard;
      52    uintptr_t pointer_guard;
      53    unsigned long int unused_vgetcpu_cache[2];
      54    /* Bit 0: X86_FEATURE_1_IBT.
      55       Bit 1: X86_FEATURE_1_SHSTK.
      56     */
      57    unsigned int feature_1;
      58    int __glibc_unused1;
      59    /* Reservation of some values for the TM ABI.  */
      60    void *__private_tm[4];
      61    /* GCC split stack support.  */
      62    void *__private_ss;
      63    /* The lowest address of shadow stack,  */
      64    unsigned long long int ssp_base;
      65    /* Must be kept even if it is no longer used by glibc since programs,
      66       like AddressSanitizer, depend on the size of tcbhead_t.  */
      67    __128bits __glibc_unused2[8][4] __attribute__ ((aligned (32)));
      68  
      69    void *__padding[8];
      70  } tcbhead_t;
      71  
      72  # ifdef __ILP32__
      73  /* morestack.S in libgcc uses offset 0x40 to access __private_ss,   */
      74  _Static_assert (offsetof (tcbhead_t, __private_ss) == 0x40,
      75  		"offset of __private_ss != 0x40");
      76  /* NB: ssp_base used to be "long int __glibc_reserved2", which was
      77     changed from 32 bits to 64 bits.  Make sure that the offset of the
      78     next field, __glibc_unused2, is unchanged.  */
      79  _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x60,
      80  		"offset of __glibc_unused2 != 0x60");
      81  # else
      82  /* morestack.S in libgcc uses offset 0x70 to access __private_ss,   */
      83  _Static_assert (offsetof (tcbhead_t, __private_ss) == 0x70,
      84  		"offset of __private_ss != 0x70");
      85  _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
      86  		"offset of __glibc_unused2 != 0x80");
      87  # endif
      88  
      89  #else /* __ASSEMBLER__ */
      90  # include <tcb-offsets.h>
      91  #endif
      92  
      93  
      94  /* Alignment requirement for the stack.  */
      95  #define STACK_ALIGN	16
      96  
      97  
      98  #ifndef __ASSEMBLER__
      99  /* Get system call information.  */
     100  # include <sysdep.h>
     101  
     102  #define LOCK_PREFIX "lock;"
     103  
     104  /* This is the size of the initial TCB.  Can't be just sizeof (tcbhead_t),
     105     because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole
     106     struct pthread even when not linked with -lpthread.  */
     107  # define TLS_INIT_TCB_SIZE sizeof (struct pthread)
     108  
     109  /* This is the size of the TCB.  */
     110  # define TLS_TCB_SIZE sizeof (struct pthread)
     111  
     112  /* The TCB can have any size and the memory following the address the
     113     thread pointer points to is unspecified.  Allocate the TCB there.  */
     114  # define TLS_TCB_AT_TP	1
     115  # define TLS_DTV_AT_TP	0
     116  
     117  /* Get the thread descriptor definition.  */
     118  # include <nptl/descr.h>
     119  
     120  
     121  /* Install the dtv pointer.  The pointer passed is to the element with
     122     index -1 which contain the length.  */
     123  # define INSTALL_DTV(descr, dtvp) \
     124    ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
     125  
     126  /* Install new dtv for current thread.  */
     127  # define INSTALL_NEW_DTV(dtvp) \
     128    ({ struct pthread *__pd;						      \
     129       THREAD_SETMEM (__pd, header.dtv, (dtvp)); })
     130  
     131  /* Return dtv of given thread descriptor.  */
     132  # define GET_DTV(descr) \
     133    (((tcbhead_t *) (descr))->dtv)
     134  
     135  
     136  /* Code to initially initialize the thread pointer.  This might need
     137     special attention since 'errno' is not yet available and if the
     138     operation can cause a failure 'errno' must not be touched.
     139  
     140     We have to make the syscall for both uses of the macro since the
     141     address might be (and probably is) different.  */
     142  # define TLS_INIT_TP(thrdescr) \
     143    ({ void *_thrdescr = (thrdescr);					      \
     144       tcbhead_t *_head = _thrdescr;					      \
     145       int _result;							      \
     146  									      \
     147       _head->tcb = _thrdescr;						      \
     148       /* For now the thread descriptor is at the same address.  */	      \
     149       _head->self = _thrdescr;						      \
     150  									      \
     151       /* It is a simple syscall to set the %fs value for the thread.  */	      \
     152       asm volatile ("syscall"						      \
     153  		   : "=a" (_result)					      \
     154  		   : "0" ((unsigned long int) __NR_arch_prctl),		      \
     155  		     "D" ((unsigned long int) ARCH_SET_FS),		      \
     156  		     "S" (_thrdescr)					      \
     157  		   : "memory", "cc", "r11", "cx");			      \
     158  									      \
     159      _result == 0;							      \
     160    })
     161  
     162  # define TLS_DEFINE_INIT_TP(tp, pd) void *tp = (pd)
     163  
     164  
     165  /* Return the address of the dtv for the current thread.  */
     166  # define THREAD_DTV() \
     167    ({ struct pthread *__pd;						      \
     168       THREAD_GETMEM (__pd, header.dtv); })
     169  
     170  
     171  /* Return the thread descriptor for the current thread.
     172  
     173     The contained asm must *not* be marked volatile since otherwise
     174     assignments like
     175  	pthread_descr self = thread_self();
     176     do not get optimized away.  */
     177  # if __GNUC_PREREQ (6, 0)
     178  #  define THREAD_SELF \
     179    (*(struct pthread *__seg_fs *) offsetof (struct pthread, header.self))
     180  # else
     181  #  define THREAD_SELF \
     182    ({ struct pthread *__self;						      \
     183       asm ("mov %%fs:%c1,%0" : "=r" (__self)				      \
     184  	  : "i" (offsetof (struct pthread, header.self)));	 	      \
     185       __self;})
     186  # endif
     187  
     188  /* Magic for libthread_db to know how to do THREAD_SELF.  */
     189  # define DB_THREAD_SELF_INCLUDE  <sys/reg.h> /* For the FS constant.  */
     190  # define DB_THREAD_SELF CONST_THREAD_AREA (64, FS)
     191  
     192  # include <tcb-access.h>
     193  
     194  /* Set the stack guard field in TCB head.  */
     195  # define THREAD_SET_STACK_GUARD(value) \
     196      THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)
     197  # define THREAD_COPY_STACK_GUARD(descr) \
     198      ((descr)->header.stack_guard					      \
     199       = THREAD_GETMEM (THREAD_SELF, header.stack_guard))
     200  
     201  
     202  /* Set the pointer guard field in the TCB head.  */
     203  # define THREAD_SET_POINTER_GUARD(value) \
     204    THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value)
     205  # define THREAD_COPY_POINTER_GUARD(descr) \
     206    ((descr)->header.pointer_guard					      \
     207     = THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
     208  
     209  
     210  /* Get and set the global scope generation counter in the TCB head.  */
     211  # define THREAD_GSCOPE_FLAG_UNUSED 0
     212  # define THREAD_GSCOPE_FLAG_USED   1
     213  # define THREAD_GSCOPE_FLAG_WAIT   2
     214  # define THREAD_GSCOPE_RESET_FLAG() \
     215    do									      \
     216      { int __res;							      \
     217        asm volatile ("xchgl %0, %%fs:%P1"				      \
     218  		    : "=r" (__res)					      \
     219  		    : "i" (offsetof (struct pthread, header.gscope_flag)),    \
     220  		      "0" (THREAD_GSCOPE_FLAG_UNUSED));			      \
     221        if (__res == THREAD_GSCOPE_FLAG_WAIT)				      \
     222  	lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);    \
     223      }									      \
     224    while (0)
     225  # define THREAD_GSCOPE_SET_FLAG() \
     226    THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED)
     227  
     228  #endif /* __ASSEMBLER__ */
     229  
     230  #endif	/* tls.h */