1 /* Definition for thread-local data handling. NPTL/RISCV64 version. 2 Copyright (C) 2005, 2007, 2011 Free Software Foundation, Inc. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library. If not, see 16 <http://www.gnu.org/licenses/>. */ 17 18 #ifndef _TLS_H 19 #define _TLS_H 1 20 21 #ifndef __ASSEMBLER__ 22 # include <stdbool.h> 23 # include <stddef.h> 24 # include <stdint.h> 25 26 /* Type for the dtv. */ 27 typedef union dtv 28 { 29 size_t counter; 30 struct 31 { 32 void *val; 33 bool is_static; 34 } pointer; 35 } dtv_t; 36 37 #else /* __ASSEMBLER__ */ 38 # include <tcb-offsets.h> 39 #endif /* __ASSEMBLER__ */ 40 41 /* We require TLS support in the tools. */ 42 #define HAVE_TLS_SUPPORT 1 43 #define HAVE_TLS_MODEL_ATTRIBUTE 1 44 #define HAVE___THREAD 1 45 46 /* Signal that TLS support is available. */ 47 #define USE_TLS 1 48 49 #ifndef __ASSEMBLER__ 50 51 register void *__thread_self __asm__("tp"); 52 # define READ_THREAD_POINTER() ({ __thread_self; }) 53 54 /* Get system call information. */ 55 # include <sysdep.h> 56 57 /* The TP points to the start of the TLS block. */ 58 # define TLS_DTV_AT_TP 1 59 60 /* Get the thread descriptor definition. */ 61 # include <../../descr.h> 62 63 typedef struct 64 { 65 dtv_t *dtv; 66 void *private; 67 } tcbhead_t; 68 69 /* This is the size of the initial TCB. Because our TCB is before the thread 70 pointer, we don't need this. */ 71 # define TLS_INIT_TCB_SIZE 0 72 # define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) 73 74 /* This is the size of the TCB. Because our TCB is before the thread 75 pointer, we don't need this. */ 76 # define TLS_TCB_SIZE 0 77 # define TLS_TCB_ALIGN __alignof__ (struct pthread) 78 79 /* This is the size we need before TCB - actually, it includes the TCB. */ 80 # define TLS_PRE_TCB_SIZE \ 81 (sizeof (struct pthread) \ 82 + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \ 83 & ~(__alignof (struct pthread) - 1))) 84 85 /* The thread pointer tp points to the end of the TCB. 86 The pthread_descr structure is immediately in front of the TCB. */ 87 # define TLS_TCB_OFFSET 0 88 89 /* Install the dtv pointer. The pointer passed is to the element with 90 index -1 which contain the length. */ 91 # define INSTALL_DTV(tcbp, dtvp) \ 92 (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) 93 94 /* Install new dtv for current thread */ 95 # define INSTALL_NEW_DTV(dtv) \ 96 (THREAD_DTV() = (dtv)) 97 98 /* Return dtv of given thread descriptor. */ 99 # define GET_DTV(tcbp) \ 100 (((tcbhead_t *) (tcbp))[-1].dtv) 101 102 /* Code to initially initialize the thread pointer. 103 * 104 * Set TP to the address _after_ tcbhead_t. This will allow us 105 * to change the size of tcbhead_t without having to re-link everything. 106 * 107 * secondcall has something to do with USE__THREAD, 108 * seems to always be 0 so we don't care about it. 109 * 110 * This has to return NULL on success (or a string with the failure text). 111 * It's hard to fail this, so return NULL always. 112 */ 113 # define TLS_INIT_TP(tcbp, secondcall) \ 114 ({ __thread_self = (char*)tcbp + TLS_TCB_OFFSET; NULL; }) 115 116 /* Return the address of the dtv for the current thread. */ 117 # define THREAD_DTV() \ 118 (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) 119 120 /* Return the thread descriptor for the current thread. */ 121 # define THREAD_SELF \ 122 ((struct pthread *) (READ_THREAD_POINTER () \ 123 - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) 124 125 /* Informs libthread_db that the thread pointer is register 4, which is used 126 * to know how to do THREAD_SELF. */ 127 # define DB_THREAD_SELF \ 128 REGISTER (64, 64, 4 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) 129 130 /* Access to data in the thread descriptor is easy. */ 131 #define THREAD_GETMEM(descr, member) \ 132 descr->member 133 #define THREAD_GETMEM_NC(descr, member, idx) \ 134 descr->member[idx] 135 #define THREAD_SETMEM(descr, member, value) \ 136 descr->member = (value) 137 #define THREAD_SETMEM_NC(descr, member, idx, value) \ 138 descr->member[idx] = (value) 139 140 /* l_tls_offset == 0 is perfectly valid, so we have to use some different 141 value to mean unset l_tls_offset. */ 142 # define NO_TLS_OFFSET -1 143 144 /* Get and set the global scope generation counter in struct pthread. */ 145 #define THREAD_GSCOPE_FLAG_UNUSED 0 146 #define THREAD_GSCOPE_FLAG_USED 1 147 #define THREAD_GSCOPE_FLAG_WAIT 2 148 #define THREAD_GSCOPE_RESET_FLAG() \ 149 do \ 150 { int __res \ 151 = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ 152 THREAD_GSCOPE_FLAG_UNUSED); \ 153 if (__res == THREAD_GSCOPE_FLAG_WAIT) \ 154 lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ 155 } \ 156 while (0) 157 #define THREAD_GSCOPE_SET_FLAG() \ 158 do \ 159 { \ 160 THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ 161 atomic_write_barrier (); \ 162 } \ 163 while (0) 164 #define THREAD_GSCOPE_WAIT() \ 165 GL(dl_wait_lookup_done) () 166 167 #endif /* __ASSEMBLER__ */ 168 169 #endif /* tls.h */ 170 171