(root)/
glibc-2.38/
sysdeps/
or1k/
nptl/
tls.h
       1  /* Definition for thread-local data handling.  NPTL/OpenRISC version.
       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 _TLS_H
      20  #define _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  typedef struct
      31  {
      32    dtv_t *dtv;
      33    void *__padding[3];
      34  } tcbhead_t;
      35  
      36  register tcbhead_t *__thread_self __asm__("r10");
      37  
      38  # define TLS_MULTIPLE_THREADS_IN_TCB 1
      39  
      40  /* Get system call information.  */
      41  # include <sysdep.h>
      42  
      43  /* The TP points to the start of the TLS block.
      44     As I understand it, this isn't strictly that "TP points to DTV" - it's
      45     more where to place the TCB in the TLS block.  This will place it in
      46     the beginning.
      47  
      48     Layout:
      49      +-----+-----+----------------------+
      50      | PRE | TCB | TLS MEMORY ..        |
      51      +-----+-----+----------------------+
      52  		 ^ r10 / TP
      53  
      54     PRE is the struct pthread described below
      55     TCB is tcbhead_t
      56     TLS memory is where the TLS program sections are loaded
      57  
      58     See _dl_allocate_tls_storage and __libc_setup_tls for more information.  */
      59  
      60  # define TLS_DTV_AT_TP  1
      61  # define TLS_TCB_AT_TP  0
      62  
      63  /* Get the thread descriptor definition.  */
      64  # include <nptl/descr.h>
      65  
      66  /* Requirements for the TCB.  */
      67  # define TLS_INIT_TCB_SIZE    sizeof (tcbhead_t)
      68  # define TLS_INIT_TCB_ALIGN   __alignof__ (struct pthread)
      69  
      70  # define TLS_TCB_SIZE         sizeof (tcbhead_t)
      71  # define TLS_TCB_ALIGN        __alignof__ (struct pthread)
      72  
      73  /* This is the size of the TCB.  */
      74  
      75  /* This is the size we need before TCB.
      76     To support THREAD_GETMEM with friends we want to have a
      77     struct pthread available.
      78     Yank it in infront of everything, I'm sure nobody will mind.
      79  
      80     This memory is really allocated PRE the TLS block, so it's possible
      81     to do ((char*)tlsblock) - TLS_PRE_TCB_SIZE to access it.
      82     This is done for THREAD_SELF.  */
      83  
      84  # define TLS_PRE_TCB_SIZE sizeof (struct pthread)
      85  
      86  /* Install the dtv pointer.
      87     When called, dtvp is a pointer not the DTV per say (which should start
      88     with the generation counter) but to the length of the DTV.
      89     We can always index with -1, so we store dtvp[1].  */
      90  
      91  # define INSTALL_DTV(tcbp, dtvp) \
      92    (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
      93  
      94  /* Install new dtv for current thread
      95     In a logicial world dtv here would also point to the length of the DTV.
      96     However it does not, this time it points to the generation counter,
      97     so just store it.
      98  
      99     Note: -1 is still valid and contains the length.  */
     100  
     101  # define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv))
     102  
     103  /* Return dtv of given thread descriptor.  */
     104  # define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))->dtv)
     105  
     106  /* Code to initially initialize the thread pointer.
     107  
     108     Set TP to the address _after_ tcbhead_t.  This will allow us
     109     to change the size of tcbhead_t without having to re-link everything.
     110  
     111     This has to return NULL on success (or a string with the failure text).
     112     It's hard to fail this, so return NULL always.  */
     113  
     114  # define TLS_INIT_TP(tcbp) \
     115    ({__thread_self = ((tcbhead_t *)tcbp + 1); true;})
     116  
     117  /* Value passed to 'clone' for initialization of the thread register.  */
     118  # define TLS_DEFINE_INIT_TP(tp, pd) \
     119    void *tp = ((char *) pd + TLS_PRE_TCB_SIZE + TLS_INIT_TCB_SIZE)
     120  
     121  /* Return the address of the dtv for the current thread.
     122  
     123     Dereference TP, offset to dtv - really straightforward.
     124     Remember that we made TP point to after tcb, so we need to reverse that.  */
     125  
     126  #  define THREAD_DTV() \
     127    ((((tcbhead_t *)__thread_self)-1)->dtv)
     128  
     129  /* Return the thread descriptor for the current thread.
     130  
     131     Return a pointer to the TLS_PRE area where we allocated space for
     132     a struct pthread.  Again, TP points to after tcbhead_t, compensate with
     133     TLS_INIT_TCB_SIZE.
     134  
     135     I regard this is a separate system from the "normal" TLS.  */
     136  
     137  # define THREAD_SELF \
     138    ((struct pthread *) ((char *) __thread_self - TLS_INIT_TCB_SIZE \
     139      - TLS_PRE_TCB_SIZE))
     140  
     141  /* Magic for libthread_db to know how to do THREAD_SELF.  */
     142  
     143  # define DB_THREAD_SELF \
     144    REGISTER (32, 32, 10 * 4, - TLS_INIT_TCB_SIZE - TLS_PRE_TCB_SIZE)
     145  
     146  # include <tcb-access.h>
     147  
     148  /* Access to data in the thread descriptor is easy.  */
     149  
     150  #define THREAD_GETMEM(descr, member) \
     151    descr->member
     152  #define THREAD_GETMEM_NC(descr, member, idx) \
     153    descr->member[idx]
     154  #define THREAD_SETMEM(descr, member, value) \
     155    descr->member = (value)
     156  #define THREAD_SETMEM_NC(descr, member, idx, value) \
     157    descr->member[idx] = (value)
     158  
     159  /* Get and set the global scope generation counter in struct pthread.  */
     160  
     161  #define THREAD_GSCOPE_FLAG_UNUSED 0
     162  #define THREAD_GSCOPE_FLAG_USED   1
     163  #define THREAD_GSCOPE_FLAG_WAIT   2
     164  #define THREAD_GSCOPE_RESET_FLAG()					\
     165    do									\
     166      {									\
     167        int __res = atomic_exchange_release (&THREAD_SELF->header.gscope_flag,\
     168  				       THREAD_GSCOPE_FLAG_UNUSED);	\
     169        if (__res == THREAD_GSCOPE_FLAG_WAIT)				\
     170  	  lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1,		\
     171  			  LLL_PRIVATE);					\
     172      }									\
     173    while (0)
     174  #define THREAD_GSCOPE_SET_FLAG()					\
     175    do									\
     176      {									\
     177        THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED;	\
     178        atomic_write_barrier ();						\
     179      }									\
     180    while (0)
     181  
     182  #endif /* __ASSEMBLER__ */
     183  
     184  #endif  /* tls.h */