]>
git.proxmox.com Git - wasi-libc.git/blob - libc-top-half/musl/src/env/__init_tls.c
5e32f5446ec7e53fa70dd12388fd25470a9cac96
1 #ifdef __wasilibc_unmodified_upstream
2 #define SYSCALL_NO_TLS 1
6 #ifdef __wasilibc_unmodified_upstream
11 #include "pthread_impl.h"
16 volatile int __thread_list_lock
;
18 #ifndef __wasilibc_unmodified_upstream
20 /* These symbols are generated by wasm-ld. __stack_high/__stack_low
21 * symbols are only available in LLVM v16 and higher, therefore they're
22 * defined as weak symbols and if not available, __heap_base/__data_end
25 * TODO: remove usage of __heap_base/__data_end for stack size calculation
26 * once we drop support for LLVM v15 and older.
28 extern unsigned char __heap_base
;
29 extern unsigned char __data_end
;
30 extern unsigned char __global_base
;
31 extern weak
unsigned char __stack_high
;
32 extern weak
unsigned char __stack_low
;
34 static inline void setup_default_stack_size()
39 stack_size
= &__stack_high
- &__stack_low
;
43 ".globaltype __stack_pointer, i32\n"
44 "global.get __stack_pointer\n"
47 stack_size
= sp
> &__global_base
? &__heap_base
- &__data_end
: (ptrdiff_t)&__global_base
;
50 if (stack_size
> __default_stacksize
)
52 stack_size
< DEFAULT_STACK_MAX
?
53 stack_size
: DEFAULT_STACK_MAX
;
56 void __wasi_init_tp() {
57 __init_tp((void *)__get_tp());
61 int __init_tp(void *p
)
65 #ifdef __wasilibc_unmodified_upstream
66 int r
= __set_thread_area(TP_ADJ(p
));
68 if (!r
) libc
.can_do_threads
= 1;
69 td
->detach_state
= DT_JOINABLE
;
70 td
->tid
= __syscall(SYS_set_tid_address
, &__thread_list_lock
);
72 setup_default_stack_size();
74 td
->locale
= &libc
.global_locale
;
75 td
->robust_list
.head
= &td
->robust_list
.head
;
76 td
->sysinfo
= __sysinfo
;
77 td
->next
= td
->prev
= td
;
81 #ifdef __wasilibc_unmodified_upstream
83 static struct builtin_tls
{
88 #define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt)
90 static struct tls_module main_tls
;
93 #ifndef __wasilibc_unmodified_upstream
94 extern void __wasm_init_tls(void*);
97 void *__copy_tls(unsigned char *mem
)
99 #ifdef __wasilibc_unmodified_upstream
101 struct tls_module
*p
;
106 dtv
= (uintptr_t*)(mem
+ libc
.tls_size
) - (libc
.tls_cnt
+ 1);
108 mem
+= -((uintptr_t)mem
+ sizeof(struct pthread
)) & (libc
.tls_align
-1);
110 mem
+= sizeof(struct pthread
);
112 for (i
=1, p
=libc
.tls_head
; p
; i
++, p
=p
->next
) {
113 dtv
[i
] = (uintptr_t)(mem
+ p
->offset
) + DTP_OFFSET
;
114 memcpy(mem
+ p
->offset
, p
->image
, p
->len
);
117 dtv
= (uintptr_t *)mem
;
119 mem
+= libc
.tls_size
- sizeof(struct pthread
);
120 mem
-= (uintptr_t)mem
& (libc
.tls_align
-1);
123 for (i
=1, p
=libc
.tls_head
; p
; i
++, p
=p
->next
) {
124 dtv
[i
] = (uintptr_t)(mem
- p
->offset
) + DTP_OFFSET
;
125 memcpy(mem
- p
->offset
, p
->image
, p
->len
);
128 dtv
[0] = libc
.tls_cnt
;
132 size_t tls_align
= __builtin_wasm_tls_align();
133 volatile void* tls_base
= __builtin_wasm_tls_base();
135 mem
-= (uintptr_t)mem
& (tls_align
-1);
136 __wasm_init_tls(mem
);
137 __asm__("local.get %0\n"
138 "global.set __tls_base\n"
144 #ifdef __wasilibc_unmodified_upstream
145 #if ULONG_MAX == 0xffffffff
146 typedef Elf32_Phdr Phdr
;
148 typedef Elf64_Phdr Phdr
;
151 extern weak hidden
const size_t _DYNAMIC
[];
153 static void static_init_tls(size_t *aux
)
157 Phdr
*phdr
, *tls_phdr
=0;
161 for (p
=(void *)aux
[AT_PHDR
],n
=aux
[AT_PHNUM
]; n
; n
--,p
+=aux
[AT_PHENT
]) {
163 if (phdr
->p_type
== PT_PHDR
)
164 base
= aux
[AT_PHDR
] - phdr
->p_vaddr
;
165 if (phdr
->p_type
== PT_DYNAMIC
&& _DYNAMIC
)
166 base
= (size_t)_DYNAMIC
- phdr
->p_vaddr
;
167 if (phdr
->p_type
== PT_TLS
)
169 if (phdr
->p_type
== PT_GNU_STACK
&&
170 phdr
->p_memsz
> __default_stacksize
)
171 __default_stacksize
=
172 phdr
->p_memsz
< DEFAULT_STACK_MAX
?
173 phdr
->p_memsz
: DEFAULT_STACK_MAX
;
177 main_tls
.image
= (void *)(base
+ tls_phdr
->p_vaddr
);
178 main_tls
.len
= tls_phdr
->p_filesz
;
179 main_tls
.size
= tls_phdr
->p_memsz
;
180 main_tls
.align
= tls_phdr
->p_align
;
182 libc
.tls_head
= &main_tls
;
185 main_tls
.size
+= (-main_tls
.size
- (uintptr_t)main_tls
.image
)
186 & (main_tls
.align
-1);
188 main_tls
.offset
= GAP_ABOVE_TP
;
189 main_tls
.offset
+= (-GAP_ABOVE_TP
+ (uintptr_t)main_tls
.image
)
190 & (main_tls
.align
-1);
192 main_tls
.offset
= main_tls
.size
;
194 if (main_tls
.align
< MIN_TLS_ALIGN
) main_tls
.align
= MIN_TLS_ALIGN
;
196 libc
.tls_align
= main_tls
.align
;
197 libc
.tls_size
= 2*sizeof(void *) + sizeof(struct pthread
)
201 + main_tls
.size
+ main_tls
.align
202 + MIN_TLS_ALIGN
-1 & -MIN_TLS_ALIGN
;
204 if (libc
.tls_size
> sizeof builtin_tls
) {
206 #define SYS_mmap2 SYS_mmap
208 mem
= (void *)__syscall(
210 0, libc
.tls_size
, PROT_READ
|PROT_WRITE
,
211 MAP_ANONYMOUS
|MAP_PRIVATE
, -1, 0);
212 /* -4095...-1 cast to void * will crash on dereference anyway,
213 * so don't bloat the init code checking for error codes and
214 * explicitly calling a_crash(). */
219 /* Failure to initialize thread pointer is always fatal. */
220 if (__init_tp(__copy_tls(mem
)) < 0)
224 weak_alias(static_init_tls
, __init_tls
);