(root)/
glibc-2.38/
sysdeps/
x86_64/
nptl/
tcb-access.h
       1  /* THREAD_* accessors.  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  /* Read member of the thread descriptor directly.  */
      20  # define THREAD_GETMEM(descr, member) \
      21    ({ __typeof (descr->member) __value;					      \
      22       _Static_assert (sizeof (__value) == 1				      \
      23  		     || sizeof (__value) == 4				      \
      24  		     || sizeof (__value) == 8,				      \
      25  		     "size of per-thread data");			      \
      26       if (sizeof (__value) == 1)						      \
      27         asm volatile ("movb %%fs:%P2,%b0"				      \
      28  		     : "=q" (__value)					      \
      29  		     : "0" (0), "i" (offsetof (struct pthread, member)));     \
      30       else if (sizeof (__value) == 4)					      \
      31         asm volatile ("movl %%fs:%P1,%0"					      \
      32  		     : "=r" (__value)					      \
      33  		     : "i" (offsetof (struct pthread, member)));	      \
      34       else /* 8 */								      \
      35         {								      \
      36  	 asm volatile ("movq %%fs:%P1,%q0"				      \
      37  		       : "=r" (__value)					      \
      38  		       : "i" (offsetof (struct pthread, member)));	      \
      39         }								      \
      40       __value; })
      41  
      42  /* THREAD_GETMEM already forces a read.  */
      43  #define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member)
      44  
      45  /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
      46  # define THREAD_GETMEM_NC(descr, member, idx) \
      47    ({ __typeof (descr->member[0]) __value;				      \
      48       _Static_assert (sizeof (__value) == 1				      \
      49  		     || sizeof (__value) == 4				      \
      50  		     || sizeof (__value) == 8,				      \
      51  		     "size of per-thread data");			      \
      52       if (sizeof (__value) == 1)						      \
      53         asm volatile ("movb %%fs:%P2(%q3),%b0"				      \
      54  		     : "=q" (__value)					      \
      55  		     : "0" (0), "i" (offsetof (struct pthread, member[0])),   \
      56  		       "r" (idx));					      \
      57       else if (sizeof (__value) == 4)					      \
      58         asm volatile ("movl %%fs:%P1(,%q2,4),%0"				      \
      59  		     : "=r" (__value)					      \
      60  		     : "i" (offsetof (struct pthread, member[0])), "r" (idx));\
      61       else /* 8 */							      \
      62         {								      \
      63  	 asm volatile ("movq %%fs:%P1(,%q2,8),%q0"			      \
      64  		       : "=r" (__value)					      \
      65  		       : "i" (offsetof (struct pthread, member[0])),	      \
      66  			 "r" (idx));					      \
      67         }								      \
      68       __value; })
      69  
      70  
      71  /* Loading addresses of objects on x86-64 needs to be treated special
      72     when generating PIC code.  */
      73  #ifdef __pic__
      74  # define IMM_MODE "nr"
      75  #else
      76  # define IMM_MODE "ir"
      77  #endif
      78  
      79  
      80  /* Set member of the thread descriptor directly.  */
      81  # define THREAD_SETMEM(descr, member, value) \
      82    ({									      \
      83       _Static_assert (sizeof (descr->member) == 1			      \
      84  		     || sizeof (descr->member) == 4			      \
      85  		     || sizeof (descr->member) == 8,			      \
      86  		     "size of per-thread data");			      \
      87       if (sizeof (descr->member) == 1)					      \
      88         asm volatile ("movb %b0,%%fs:%P1" :				      \
      89  		     : "iq" (value),					      \
      90  		       "i" (offsetof (struct pthread, member)));	      \
      91       else if (sizeof (descr->member) == 4)				      \
      92         asm volatile ("movl %0,%%fs:%P1" :				      \
      93  		     : IMM_MODE (value),				      \
      94  		       "i" (offsetof (struct pthread, member)));	      \
      95       else /* 8 */							      \
      96         {								      \
      97  	 /* Since movq takes a signed 32-bit immediate or a register source   \
      98  	    operand, use "er" constraint for 32-bit signed integer constant   \
      99  	    or register.  */						      \
     100  	 asm volatile ("movq %q0,%%fs:%P1" :				      \
     101  		       : "er" ((uint64_t) cast_to_integer (value)),	      \
     102  			 "i" (offsetof (struct pthread, member)));	      \
     103         }})
     104  
     105  
     106  /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
     107  # define THREAD_SETMEM_NC(descr, member, idx, value) \
     108    ({									      \
     109       _Static_assert (sizeof (descr->member[0]) == 1			      \
     110  		     || sizeof (descr->member[0]) == 4			      \
     111  		     || sizeof (descr->member[0]) == 8,			      \
     112  		     "size of per-thread data");			      \
     113       if (sizeof (descr->member[0]) == 1)				      \
     114         asm volatile ("movb %b0,%%fs:%P1(%q2)" :				      \
     115  		     : "iq" (value),					      \
     116  		       "i" (offsetof (struct pthread, member[0])),	      \
     117  		       "r" (idx));					      \
     118       else if (sizeof (descr->member[0]) == 4)				      \
     119         asm volatile ("movl %0,%%fs:%P1(,%q2,4)" :			      \
     120  		     : IMM_MODE (value),				      \
     121  		       "i" (offsetof (struct pthread, member[0])),	      \
     122  		       "r" (idx));					      \
     123       else /* 8 */							      \
     124         {								      \
     125  	 /* Since movq takes a signed 32-bit immediate or a register source   \
     126  	    operand, use "er" constraint for 32-bit signed integer constant   \
     127  	    or register.  */						      \
     128  	 asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" :			      \
     129  		       : "er" ((uint64_t) cast_to_integer (value)),	      \
     130  			 "i" (offsetof (struct pthread, member[0])),	      \
     131  			 "r" (idx));					      \
     132         }})