(root)/
glibc-2.38/
sysdeps/
i386/
nptl/
tcb-access.h
       1  /* THREAD_* accessors.  i386 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 %%gs:%P2,%b0"				      \
      28  		     : "=q" (__value)					      \
      29  		     : "0" (0), "i" (offsetof (struct pthread, member)));     \
      30       else if (sizeof (__value) == 4)					      \
      31         asm volatile ("movl %%gs:%P1,%0"					      \
      32  		     : "=r" (__value)					      \
      33  		     : "i" (offsetof (struct pthread, member)));	      \
      34       else /* 8 */								      \
      35         {								      \
      36  	 asm volatile ("movl %%gs:%P1,%%eax\n\t"			      \
      37  		       "movl %%gs:%P2,%%edx"				      \
      38  		       : "=A" (__value)					      \
      39  		       : "i" (offsetof (struct pthread, member)),	      \
      40  			 "i" (offsetof (struct pthread, member) + 4));	      \
      41         }								      \
      42       __value; })
      43  
      44  /* THREAD_GETMEM already forces a read.  */
      45  #define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member)
      46  
      47  /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
      48  #define THREAD_GETMEM_NC(descr, member, idx) \
      49    ({ __typeof (descr->member[0]) __value;				      \
      50       _Static_assert (sizeof (__value) == 1				      \
      51  		     || sizeof (__value) == 4				      \
      52  		     || sizeof (__value) == 8,				      \
      53  		     "size of per-thread data");			      \
      54       if (sizeof (__value) == 1)						      \
      55         asm volatile ("movb %%gs:%P2(%3),%b0"				      \
      56  		     : "=q" (__value)					      \
      57  		     : "0" (0), "i" (offsetof (struct pthread, member[0])),   \
      58  		     "r" (idx));					      \
      59       else if (sizeof (__value) == 4)					      \
      60         asm volatile ("movl %%gs:%P1(,%2,4),%0"				      \
      61  		     : "=r" (__value)					      \
      62  		     : "i" (offsetof (struct pthread, member[0])),	      \
      63  		       "r" (idx));					      \
      64       else /* 8 */							      \
      65         {								      \
      66  	 asm volatile  ("movl %%gs:%P1(,%2,8),%%eax\n\t"		      \
      67  			"movl %%gs:4+%P1(,%2,8),%%edx"			      \
      68  			: "=&A" (__value)				      \
      69  			: "i" (offsetof (struct pthread, member[0])),	      \
      70  			  "r" (idx));					      \
      71         }								      \
      72       __value; })
      73  
      74  
      75  
      76  /* Set member of the thread descriptor directly.  */
      77  #define THREAD_SETMEM(descr, member, value) \
      78    ({									      \
      79       _Static_assert (sizeof (descr->member) == 1			      \
      80  		     || sizeof (descr->member) == 4			      \
      81  		     || sizeof (descr->member) == 8,			      \
      82  		     "size of per-thread data");			      \
      83       if (sizeof (descr->member) == 1)					      \
      84         asm volatile ("movb %b0,%%gs:%P1" :				      \
      85  		     : "iq" (value),					      \
      86  		       "i" (offsetof (struct pthread, member)));	      \
      87       else if (sizeof (descr->member) == 4)				      \
      88         asm volatile ("movl %0,%%gs:%P1" :				      \
      89  		     : "ir" (value),					      \
      90  		       "i" (offsetof (struct pthread, member)));	      \
      91       else /* 8 */							      \
      92         {								      \
      93  	 asm volatile ("movl %%eax,%%gs:%P1\n\t"			      \
      94  		       "movl %%edx,%%gs:%P2" :				      \
      95  		       : "A" ((uint64_t) cast_to_integer (value)),	      \
      96  			 "i" (offsetof (struct pthread, member)),	      \
      97  			 "i" (offsetof (struct pthread, member) + 4));	      \
      98         }})
      99  
     100  
     101  /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
     102  #define THREAD_SETMEM_NC(descr, member, idx, value) \
     103    ({									      \
     104       _Static_assert (sizeof (descr->member[0]) == 1			      \
     105  		     || sizeof (descr->member[0]) == 4			      \
     106  		     || sizeof (descr->member[0]) == 8,			      \
     107  		     "size of per-thread data");			      \
     108       if (sizeof (descr->member[0]) == 1)				      \
     109         asm volatile ("movb %b0,%%gs:%P1(%2)" :				      \
     110  		     : "iq" (value),					      \
     111  		       "i" (offsetof (struct pthread, member)),		      \
     112  		       "r" (idx));					      \
     113       else if (sizeof (descr->member[0]) == 4)				      \
     114         asm volatile ("movl %0,%%gs:%P1(,%2,4)" :			      \
     115  		     : "ir" (value),					      \
     116  		       "i" (offsetof (struct pthread, member)),		      \
     117  		       "r" (idx));					      \
     118       else /* 8 */							      \
     119         {								      \
     120  	 asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t"			      \
     121  		       "movl %%edx,%%gs:4+%P1(,%2,8)" :			      \
     122  		       : "A" ((uint64_t) cast_to_integer (value)),	      \
     123  			 "i" (offsetof (struct pthread, member)),	      \
     124  			 "r" (idx));					      \
     125         }})