1 #define SYSCALL_NO_TLS 1
7 #include "pthread_impl.h"
12 volatile int __thread_list_lock
;
14 int __init_tp(void *p
)
18 int r
= __set_thread_area(TP_ADJ(p
));
20 if (!r
) libc
.can_do_threads
= 1;
21 td
->detach_state
= DT_JOINABLE
;
22 td
->tid
= __syscall(SYS_set_tid_address
, &__thread_list_lock
);
23 td
->locale
= &libc
.global_locale
;
24 td
->robust_list
.head
= &td
->robust_list
.head
;
25 td
->sysinfo
= __sysinfo
;
26 td
->next
= td
->prev
= td
;
30 static struct builtin_tls
{
35 #define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt)
37 static struct tls_module main_tls
;
39 void *__copy_tls(unsigned char *mem
)
47 dtv
= (uintptr_t*)(mem
+ libc
.tls_size
) - (libc
.tls_cnt
+ 1);
49 mem
+= -((uintptr_t)mem
+ sizeof(struct pthread
)) & (libc
.tls_align
-1);
51 mem
+= sizeof(struct pthread
);
53 for (i
=1, p
=libc
.tls_head
; p
; i
++, p
=p
->next
) {
54 dtv
[i
] = (uintptr_t)(mem
+ p
->offset
) + DTP_OFFSET
;
55 memcpy(mem
+ p
->offset
, p
->image
, p
->len
);
58 dtv
= (uintptr_t *)mem
;
60 mem
+= libc
.tls_size
- sizeof(struct pthread
);
61 mem
-= (uintptr_t)mem
& (libc
.tls_align
-1);
64 for (i
=1, p
=libc
.tls_head
; p
; i
++, p
=p
->next
) {
65 dtv
[i
] = (uintptr_t)(mem
- p
->offset
) + DTP_OFFSET
;
66 memcpy(mem
- p
->offset
, p
->image
, p
->len
);
69 dtv
[0] = libc
.tls_cnt
;
70 td
->dtv
= td
->dtv_copy
= dtv
;
74 #if ULONG_MAX == 0xffffffff
75 typedef Elf32_Phdr Phdr
;
77 typedef Elf64_Phdr Phdr
;
80 extern weak hidden
const size_t _DYNAMIC
[];
82 static void static_init_tls(size_t *aux
)
86 Phdr
*phdr
, *tls_phdr
=0;
90 for (p
=(void *)aux
[AT_PHDR
],n
=aux
[AT_PHNUM
]; n
; n
--,p
+=aux
[AT_PHENT
]) {
92 if (phdr
->p_type
== PT_PHDR
)
93 base
= aux
[AT_PHDR
] - phdr
->p_vaddr
;
94 if (phdr
->p_type
== PT_DYNAMIC
&& _DYNAMIC
)
95 base
= (size_t)_DYNAMIC
- phdr
->p_vaddr
;
96 if (phdr
->p_type
== PT_TLS
)
98 if (phdr
->p_type
== PT_GNU_STACK
&&
99 phdr
->p_memsz
> __default_stacksize
)
100 __default_stacksize
=
101 phdr
->p_memsz
< DEFAULT_STACK_MAX
?
102 phdr
->p_memsz
: DEFAULT_STACK_MAX
;
106 main_tls
.image
= (void *)(base
+ tls_phdr
->p_vaddr
);
107 main_tls
.len
= tls_phdr
->p_filesz
;
108 main_tls
.size
= tls_phdr
->p_memsz
;
109 main_tls
.align
= tls_phdr
->p_align
;
111 libc
.tls_head
= &main_tls
;
114 main_tls
.size
+= (-main_tls
.size
- (uintptr_t)main_tls
.image
)
115 & (main_tls
.align
-1);
117 main_tls
.offset
= GAP_ABOVE_TP
;
118 main_tls
.offset
+= (-GAP_ABOVE_TP
+ (uintptr_t)main_tls
.image
)
119 & (main_tls
.align
-1);
121 main_tls
.offset
= main_tls
.size
;
123 if (main_tls
.align
< MIN_TLS_ALIGN
) main_tls
.align
= MIN_TLS_ALIGN
;
125 libc
.tls_align
= main_tls
.align
;
126 libc
.tls_size
= 2*sizeof(void *) + sizeof(struct pthread
)
130 + main_tls
.size
+ main_tls
.align
131 + MIN_TLS_ALIGN
-1 & -MIN_TLS_ALIGN
;
133 if (libc
.tls_size
> sizeof builtin_tls
) {
135 #define SYS_mmap2 SYS_mmap
137 mem
= (void *)__syscall(
139 0, libc
.tls_size
, PROT_READ
|PROT_WRITE
,
140 MAP_ANONYMOUS
|MAP_PRIVATE
, -1, 0);
141 /* -4095...-1 cast to void * will crash on dereference anyway,
142 * so don't bloat the init code checking for error codes and
143 * explicitly calling a_crash(). */
148 /* Failure to initialize thread pointer is always fatal. */
149 if (__init_tp(__copy_tls(mem
)) < 0)
153 weak_alias(static_init_tls
, __init_tls
);