(root)/
glibc-2.38/
sysdeps/
loongarch/
nptl/
tls.h
       1  /* Definition for thread-local data handling.
       2     Copyright (C) 2022-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 _LOONGARCH_TLS_H
      20  #define _LOONGARCH_TLS_H 1
      21  
      22  #include <dl-sysdep.h>
      23  
      24  #ifndef __ASSEMBLER__
      25  #include <stdbool.h>
      26  #include <stddef.h>
      27  #include <stdint.h>
      28  #include <dl-dtv.h>
      29  
      30  register void *__thread_self asm ("$tp");
      31  #define READ_THREAD_POINTER() ({ __thread_self; })
      32  
      33  /* Get system call information.  */
      34  #include <sysdep.h>
      35  
      36  /* The TP points to the start of the thread blocks.  */
      37  #define TLS_DTV_AT_TP 1
      38  #define TLS_TCB_AT_TP 0
      39  
      40  /* Get the thread descriptor definition.  */
      41  #include <nptl/descr.h>
      42  
      43  typedef struct
      44  {
      45    dtv_t *dtv;
      46    void *private;
      47  } tcbhead_t;
      48  
      49  /* This is the size of the initial TCB.  Because our TCB is before the thread
      50     pointer, we don't need this.  */
      51  #define TLS_INIT_TCB_SIZE 0
      52  
      53  /* Alignment requirements for the initial TCB.  */
      54  #define TLS_INIT_TCB_ALIGN __alignof__(struct pthread)
      55  
      56  /* This is the size of the TCB.  Because our TCB is before the thread
      57     pointer, we don't need this.  */
      58  #define TLS_TCB_SIZE 0
      59  
      60  /* Alignment requirements for the TCB.  */
      61  #define TLS_TCB_ALIGN __alignof__(struct pthread)
      62  
      63  /* This is the size we need before TCB - actually, it includes the TCB.  */
      64  #define TLS_PRE_TCB_SIZE \
      65    (sizeof (struct pthread) \
      66     + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
      67  
      68  /* The thread pointer tp points to the end of the TCB.
      69     The pthread_descr structure is immediately in front of the TCB.  */
      70  #define TLS_TCB_OFFSET 0
      71  
      72  /* Install the dtv pointer.  The pointer passed is to the element with
      73     index -1 which contain the length.  */
      74  #define INSTALL_DTV(tcbp, dtvp) (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1)
      75  
      76  /* Install new dtv for current thread.  */
      77  #define INSTALL_NEW_DTV(dtv) (THREAD_DTV () = (dtv))
      78  
      79  /* Return dtv of given thread descriptor.  */
      80  #define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv)
      81  
      82  /* Code to initially initialize the thread pointer.  */
      83  #define TLS_INIT_TP(tcbp) \
      84    ({ \
      85      __thread_self = (char *) tcbp + TLS_TCB_OFFSET; \
      86      true; \
      87    })
      88  
      89  /* Return the address of the dtv for the current thread.  */
      90  #define THREAD_DTV() \
      91    (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv)
      92  
      93  /* Return the thread descriptor for the current thread.  */
      94  #define THREAD_SELF \
      95    ((struct pthread *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET \
      96  		       - TLS_PRE_TCB_SIZE))
      97  
      98  /* Value passed to 'clone' for initialization of the thread register.  */
      99  #define TLS_DEFINE_INIT_TP(tp, pd) \
     100    void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE
     101  
     102  /* Informs libthread_db that the thread pointer is register 2, which is used
     103   * to know how to do THREAD_SELF.  */
     104  #define DB_THREAD_SELF \
     105    REGISTER (64, 64, 2 * 8, -TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
     106  
     107  /* Access to data in the thread descriptor is easy.  */
     108  # include <tcb-access.h>
     109  
     110  /* l_tls_offset == 0 is perfectly valid, so we have to use some different
     111     value to mean unset l_tls_offset.  */
     112  #define NO_TLS_OFFSET -1
     113  
     114  /* Get and set the global scope generation counter in struct pthread.  */
     115  #define THREAD_GSCOPE_IN_TCB 1
     116  #define THREAD_GSCOPE_FLAG_UNUSED 0
     117  #define THREAD_GSCOPE_FLAG_USED 1
     118  #define THREAD_GSCOPE_FLAG_WAIT 2
     119  #define THREAD_GSCOPE_RESET_FLAG() \
     120    do \
     121      { \
     122        int __res = atomic_exchange_release (&THREAD_SELF->header.gscope_flag, \
     123  					   THREAD_GSCOPE_FLAG_UNUSED); \
     124        if (__res == THREAD_GSCOPE_FLAG_WAIT) \
     125  	lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
     126      } \
     127    while (0)
     128  #define THREAD_GSCOPE_SET_FLAG() \
     129    do \
     130      { \
     131        THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
     132        atomic_write_barrier (); \
     133      } \
     134    while (0)
     135  
     136  #endif /* __ASSEMBLER__ */
     137  
     138  #endif /* tls.h */