1 /* Definition for thread-local data handling. nptl/IA-64 version. 2 Copyright (C) 2003-2022 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 #ifndef __ASSEMBLER__ 24 # include <stdbool.h> 25 # include <stddef.h> 26 # include <stdint.h> 27 # include <stdlib.h> 28 # include <list.h> 29 # include <dl-dtv.h> 30 31 typedef struct 32 { 33 dtv_t *dtv; 34 void *__private; 35 } tcbhead_t; 36 37 register struct pthread *__thread_self __asm__("r13"); 38 39 # define TLS_MULTIPLE_THREADS_IN_TCB 1 40 41 #else /* __ASSEMBLER__ */ 42 # include <tcb-offsets.h> 43 #endif 44 45 46 /* Alignment requirement for the stack. */ 47 #define STACK_ALIGN 16 48 49 #ifndef __ASSEMBLER__ 50 /* Get system call information. */ 51 # include <sysdep.h> 52 53 /* This is the size of the initial TCB. */ 54 # define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) 55 56 /* This is the size of the TCB. */ 57 # define TLS_TCB_SIZE sizeof (tcbhead_t) 58 59 /* This is the size we need before TCB. 60 If there is not any room for uintptr_t stack_guard and 61 uintptr_t pointer_guard in struct pthread's final padding, 62 we need to put struct pthread 16 byte slower. */ 63 # define TLS_PRE_TCB_SIZE \ 64 (sizeof (struct pthread) \ 65 + (PTHREAD_STRUCT_END_PADDING < 2 * sizeof (uintptr_t) \ 66 ? ((2 * sizeof (uintptr_t) + __alignof__ (struct pthread) - 1) \ 67 & ~(__alignof__ (struct pthread) - 1)) \ 68 : 0)) 69 70 /* The DTV is allocated at the TP; the TCB is placed elsewhere. */ 71 # define TLS_DTV_AT_TP 1 72 # define TLS_TCB_AT_TP 0 73 74 /* Get the thread descriptor definition. */ 75 # include <nptl/descr.h> 76 77 /* Install the dtv pointer. The pointer passed is to the element with 78 index -1 which contain the length. */ 79 # define INSTALL_DTV(descr, dtvp) \ 80 ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 81 82 /* Install new dtv for current thread. */ 83 # define INSTALL_NEW_DTV(DTV) \ 84 (((tcbhead_t *)__thread_self)->dtv = (DTV)) 85 86 /* Return dtv of given thread descriptor. */ 87 # define GET_DTV(descr) \ 88 (((tcbhead_t *) (descr))->dtv) 89 90 #define THREAD_SELF_SYSINFO (((tcbhead_t *) __thread_self)->__private) 91 #define THREAD_SYSINFO(pd) \ 92 (((tcbhead_t *) ((char *) (pd) + TLS_PRE_TCB_SIZE))->__private) 93 94 #ifdef NEED_DL_SYSINFO 95 # define INIT_SYSINFO THREAD_SELF_SYSINFO = (void *) GLRO(dl_sysinfo) 96 # define SETUP_THREAD_SYSINFO(pd) \ 97 (THREAD_SYSINFO (pd) = THREAD_SELF_SYSINFO) 98 # define CHECK_THREAD_SYSINFO(pd) \ 99 assert (THREAD_SYSINFO (pd) == THREAD_SELF_SYSINFO) 100 #else 101 # define INIT_SYSINFO NULL 102 #endif 103 104 /* Code to initially initialize the thread pointer. This might need 105 special attention since 'errno' is not yet available and if the 106 operation can cause a failure 'errno' must not be touched. */ 107 # define TLS_INIT_TP(thrdescr) \ 108 (__thread_self = (thrdescr), INIT_SYSINFO, NULL) 109 110 /* Value passed to 'clone2' for initialization of the thread register. */ 111 # define TLS_DEFINE_INIT_TP(tp, pd) \ 112 void *tp = (char *) (pd) + TLS_PRE_TCB_SIZE 113 114 /* Return the address of the dtv for the current thread. */ 115 # define THREAD_DTV() \ 116 (((tcbhead_t *)__thread_self)->dtv) 117 118 /* Return the thread descriptor for the current thread. */ 119 # define THREAD_SELF \ 120 ((struct pthread *) ((char *) __thread_self - TLS_PRE_TCB_SIZE)) 121 122 /* Magic for libthread_db to know how to do THREAD_SELF. */ 123 # define DB_THREAD_SELF REGISTER (64, 64, 13 * 8, -TLS_PRE_TCB_SIZE) 124 125 # include <tcb-access.h> 126 127 /* Set the stack guard field in TCB head. */ 128 #define THREAD_SET_STACK_GUARD(value) \ 129 (((uintptr_t *) __thread_self)[-1] = (value)) 130 #define THREAD_COPY_STACK_GUARD(descr) \ 131 (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-1] \ 132 = ((uintptr_t *) __thread_self)[-1]) 133 134 /* Set the pointer guard field in TCB head. */ 135 #define THREAD_GET_POINTER_GUARD() \ 136 (((uintptr_t *) __thread_self)[-2]) 137 #define THREAD_SET_POINTER_GUARD(value) \ 138 (((uintptr_t *) __thread_self)[-2] = (value)) 139 #define THREAD_COPY_POINTER_GUARD(descr) \ 140 (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-2] \ 141 = THREAD_GET_POINTER_GUARD ()) 142 143 /* Get and set the global scope generation counter in struct pthread. */ 144 #define THREAD_GSCOPE_FLAG_UNUSED 0 145 #define THREAD_GSCOPE_FLAG_USED 1 146 #define THREAD_GSCOPE_FLAG_WAIT 2 147 #define THREAD_GSCOPE_RESET_FLAG() \ 148 do \ 149 { int __res \ 150 = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ 151 THREAD_GSCOPE_FLAG_UNUSED); \ 152 if (__res == THREAD_GSCOPE_FLAG_WAIT) \ 153 lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ 154 } \ 155 while (0) 156 #define THREAD_GSCOPE_SET_FLAG() \ 157 do \ 158 { \ 159 THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ 160 atomic_write_barrier (); \ 161 } \ 162 while (0) 163 164 #endif /* __ASSEMBLER__ */ 165 166 #endif /* tls.h */ 167