blob: 8534cab8035b2e912bd51b0516e2f5d12362de91 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* Definition for thread-local data handling. linuxthreads/i386 version.
2 Copyright (C) 2002, 2003, 2004, 2005 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#ifndef _TLS_H
21#define _TLS_H
22
23# include <pt-machine.h>
24
25#ifndef __ASSEMBLER__
26# include <stdbool.h>
27# include <stddef.h>
28# include <stdint.h>
29
30/* Type for the dtv. */
31typedef union dtv
32{
33 size_t counter;
34 void *pointer;
35} dtv_t;
36
37
38typedef struct
39{
40 void *tcb; /* Pointer to the TCB. Not necessary the
41 thread descriptor used by libpthread. */
42 dtv_t *dtv;
43 void *self; /* Pointer to the thread descriptor. */
44} tcbhead_t;
45#endif
46
47
48/* We can support TLS only if the floating-stack support is available. */
49#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
50
51/* Signal that TLS support is available. */
52//# define USE_TLS 1
53
54# ifndef __ASSEMBLER__
55/* Get system call information. */
56# include <sysdep.h>
57
58
59/* Get the thread descriptor definition. */
60# include <linuxthreads/descr.h>
61
62/* This is the size of the initial TCB. */
63# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
64
65/* Alignment requirements for the initial TCB. */
66# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
67
68/* This is the size of the TCB. */
69# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
70
71/* Alignment requirements for the TCB. */
72# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
73
74/* The TCB can have any size and the memory following the address the
75 thread pointer points to is unspecified. Allocate the TCB there. */
76# define TLS_TCB_AT_TP 1
77
78
79/* Install the dtv pointer. The pointer passed is to the element with
80 index -1 which contain the length. */
81# define INSTALL_DTV(descr, dtvp) \
82 ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
83
84/* Install new dtv for current thread. */
85# define INSTALL_NEW_DTV(dtv) \
86 ({ struct _pthread_descr_struct *__descr; \
87 THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); })
88
89/* Return dtv of given thread descriptor. */
90# define GET_DTV(descr) \
91 (((tcbhead_t *) (descr))->dtv)
92
93# ifdef __PIC__
94# define TLS_EBX_ARG "r"
95# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"
96# else
97# define TLS_EBX_ARG "b"
98# define TLS_LOAD_EBX
99# endif
100
101# define TLS_DO_MODIFY_LDT(descr, nr) \
102({ \
103 struct modify_ldt_ldt_s ldt_entry = \
104 { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
105 1, 0, 0, 1, 0, 1, 0 }; \
106 int result; \
107 __asm__ __volatile__ (TLS_LOAD_EBX \
108 "int $0x80\n\t" \
109 TLS_LOAD_EBX \
110 : "=a" (result) \
111 : "0" (__NR_modify_ldt), \
112 /* The extra argument with the "m" constraint is necessary \
113 to let the compiler know that we are accessing LDT_ENTRY \
114 here. */ \
115 "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \
116 "d" (sizeof (ldt_entry))); \
117 __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \
118})
119
120# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \
121({ \
122 struct modify_ldt_ldt_s ldt_entry = \
123 { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \
124 1, 0, 0, 1, 0, 1, 0 }; \
125 int result; \
126 if (secondcall) \
127 ldt_entry.entry_number = ({ int _gs; \
128 __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \
129 (_gs & 0xffff) >> 3; }); \
130 __asm__ __volatile__ (TLS_LOAD_EBX \
131 "int $0x80\n\t" \
132 TLS_LOAD_EBX \
133 : "=a" (result), "=m" (ldt_entry.entry_number) \
134 : "0" (__NR_set_thread_area), \
135 /* The extra argument with the "m" constraint is necessary \
136 to let the compiler know that we are accessing LDT_ENTRY \
137 here. */ \
138 TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \
139 __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \
140})
141
142# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL
143# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
144 TLS_DO_SET_THREAD_AREA (descr, firstcall)
145# elif defined __NR_set_thread_area
146# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
147 ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \
148 __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; })
149# else
150# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \
151 TLS_DO_MODIFY_LDT ((descr), 0)
152# endif
153
154/* Code to initially initialize the thread pointer. This might need
155 special attention since 'errno' is not yet available and if the
156 operation can cause a failure 'errno' must not be touched. */
157# define TLS_INIT_TP(descr, secondcall) \
158 ({ \
159 void *_descr = (descr); \
160 tcbhead_t *head = _descr; \
161 int __gs; \
162 \
163 head->tcb = _descr; \
164 /* For now the thread descriptor is at the same address. */ \
165 head->self = _descr; \
166 \
167 __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \
168 if (__builtin_expect (__gs, 7) != -1) \
169 { \
170 __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \
171 __gs = 0; \
172 } \
173 __gs; \
174 })
175
176
177/* Return the address of the dtv for the current thread. */
178# define THREAD_DTV() \
179 ({ struct _pthread_descr_struct *__descr; \
180 THREAD_GETMEM (__descr, p_header.data.dtvp); })
181
182# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */
183#endif /* __ASSEMBLER__ */
184
185#endif /* tls.h */