1 /* Definition for thread-local data handling. NPTL/NDS32 version. 2 Copyright (C) 2005, 2007 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 22 #ifndef __ASSEMBLER__ 23 # include <stdbool.h> 24 # include <stddef.h> 25 # include <stdint.h> 26 27 /* Type for the dtv. */ 28 typedef union dtv 29 { 30 size_t counter; 31 struct 32 { 33 void *val; 34 bool is_static; 35 } pointer; 36 } dtv_t; 37 38 #else /* __ASSEMBLER__ */ 39 # include <tcb-offsets.h> 40 #endif /* __ASSEMBLER__ */ 41 42 43 /* We require TLS support in the tools. */ 44 #define HAVE_TLS_SUPPORT 1 45 #define HAVE_TLS_MODEL_ATTRIBUTE 1 46 #define HAVE___THREAD 1 47 48 /* Signal that TLS support is available. */ 49 #define USE_TLS 1 50 51 #ifndef __ASSEMBLER__ 52 53 /* Get system call information. */ 54 # include <sysdep.h> 55 56 /* The TP points to the start of the thread blocks. */ 57 # define TLS_DTV_AT_TP 1 58 59 /* We use the multiple_threads field in the pthread struct */ 60 #define TLS_MULTIPLE_THREADS_IN_TCB 1 61 62 /* Get the thread descriptor definition. */ 63 # include <../../descr.h> 64 65 /* The stack_guard is accessed directly by GCC -fstack-protector code, 66 so it is a part of public ABI. The dtv and pointer_guard fields 67 are private. */ 68 typedef struct 69 { 70 dtv_t *dtv; 71 void *private; 72 } tcbhead_t; 73 74 /* This is the size of the initial TCB. */ 75 # define TLS_INIT_TCB_SIZE 0 76 77 /* Alignment requirements for the initial TCB. */ 78 # define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) 79 80 /* This is the size of the TCB. */ 81 # define TLS_TCB_SIZE 0 82 83 /* Alignment requirements for the TCB. */ 84 # define TLS_TCB_ALIGN __alignof__ (struct pthread) 85 86 87 88 /* This is the size we need before TCB - actually, it includes the TCB. */ 89 # define TLS_PRE_TCB_SIZE \ 90 (sizeof (struct pthread) \ 91 + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) 92 93 /* Return the thread descriptor (tp) for the current thread. */ 94 register void *__thread_pointer __asm__ ("$r25"); 95 96 97 /* The thread pointer (in hardware register tp) points to the end of 98 the TCB. The pthread_descr structure is immediately in front of the TCB. */ 99 #ifndef TLS_TCB_OFFSET 100 # define TLS_TCB_OFFSET 0 101 #endif 102 103 /* Install the dtv pointer. The pointer passed is to the element with 104 index -1 which contain the length. */ 105 # define INSTALL_DTV(tcbp, dtvp) \ 106 (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) 107 108 /* Install new dtv for current thread. */ 109 # define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) 110 111 /* Return dtv of given thread descriptor. */ 112 # define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv) 113 114 /* Code to initially initialize the thread pointer (tp). */ 115 # define TLS_INIT_TP(tcbp, secondcall) \ 116 (__thread_pointer = (char *)(tcbp) + TLS_TCB_OFFSET, NULL) 117 118 /* Return the address of the dtv for the current thread. */ 119 # define THREAD_DTV() \ 120 (((tcbhead_t *) (__thread_pointer - TLS_TCB_OFFSET))[-1].dtv) 121 122 /* Return the thread descriptor for the current thread. */ 123 # define THREAD_SELF \ 124 ((struct pthread *) (__thread_pointer \ 125 - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) 126 127 /* Magic for libthread_db to know how to do THREAD_SELF. */ 128 # define DB_THREAD_SELF \ 129 REGISTER (32, 32, 152, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) 130 131 /* Read member of the thread descriptor directly. */ 132 # define THREAD_GETMEM(descr, member) (descr->member) 133 134 /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ 135 # define THREAD_GETMEM_NC(descr, member, idx) \ 136 (descr->member[idx]) 137 138 /* Set member of the thread descriptor directly. */ 139 # define THREAD_SETMEM(descr, member, value) \ 140 (descr->member = (value)) 141 142 /* Same as THREAD_SETMEM, but the member offset can be non-constant. */ 143 # define THREAD_SETMEM_NC(descr, member, idx, value) \ 144 (descr->member[idx] = (value)) 145 146 147 /* l_tls_offset == 0 is perfectly valid on Tile, so we have to use some 148 different value to mean unset l_tls_offset. */ 149 # define NO_TLS_OFFSET -1 150 151 /* Get and set the global scope generation counter in struct pthread. */ 152 #define THREAD_GSCOPE_FLAG_UNUSED 0 153 #define THREAD_GSCOPE_FLAG_USED 1 154 #define THREAD_GSCOPE_FLAG_WAIT 2 155 #define THREAD_GSCOPE_RESET_FLAG() \ 156 do \ 157 { int __res \ 158 = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ 159 THREAD_GSCOPE_FLAG_UNUSED); \ 160 if (__res == THREAD_GSCOPE_FLAG_WAIT) \ 161 lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ 162 } \ 163 while (0) 164 #define THREAD_GSCOPE_SET_FLAG() \ 165 do \ 166 { \ 167 THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ 168 atomic_write_barrier (); \ 169 } \ 170 while (0) 171 #define THREAD_GSCOPE_WAIT() \ 172 GL(dl_wait_lookup_done) () 173 174 #endif /* __ASSEMBLER__ */ 175 176 #endif /* tls.h */ 177 178 179