mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-25 07:19:02 +00:00
Clean up the TLS code
This commit is contained in:
parent
cfcf5918bc
commit
333768440c
8 changed files with 81 additions and 21 deletions
13
ape/ape.lds
13
ape/ape.lds
|
@ -180,6 +180,7 @@
|
||||||
#include "libc/elf/def.h"
|
#include "libc/elf/def.h"
|
||||||
#include "libc/elf/pf2prot.internal.h"
|
#include "libc/elf/pf2prot.internal.h"
|
||||||
#include "libc/nt/pedef.internal.h"
|
#include "libc/nt/pedef.internal.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
#include "libc/zip.h"
|
#include "libc/zip.h"
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
@ -383,17 +384,14 @@ SECTIONS {
|
||||||
HIDDEN(_ezip = .);
|
HIDDEN(_ezip = .);
|
||||||
. = ALIGN(PAGESIZE);
|
. = ALIGN(PAGESIZE);
|
||||||
} :Ram
|
} :Ram
|
||||||
. = ALIGN(PAGESIZE);
|
|
||||||
|
|
||||||
.tdata . : {
|
.tdata . : {
|
||||||
_tdata_start = .;
|
_tdata_start = .;
|
||||||
*(SORT_BY_ALIGNMENT(.tdata))
|
*(SORT_BY_ALIGNMENT(.tdata))
|
||||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||||
. = ALIGN(16);
|
|
||||||
_tdata_end = .;
|
_tdata_end = .;
|
||||||
. = ALIGN(PAGESIZE);
|
. = ALIGN(PAGESIZE);
|
||||||
} :Tls :Ram
|
} :Tls :Ram
|
||||||
. = ALIGN(PAGESIZE);
|
|
||||||
|
|
||||||
/*END: file content that's loaded by o/s */
|
/*END: file content that's loaded by o/s */
|
||||||
/*BEGIN: bss memory void */
|
/*BEGIN: bss memory void */
|
||||||
|
@ -402,7 +400,7 @@ SECTIONS {
|
||||||
_tbss_start = .;
|
_tbss_start = .;
|
||||||
*(SORT_BY_ALIGNMENT(.tbss))
|
*(SORT_BY_ALIGNMENT(.tbss))
|
||||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||||
. = ALIGN(16);
|
. = ALIGN(TLS_ALIGNMENT);
|
||||||
/* the %fs register is based on this location */
|
/* the %fs register is based on this location */
|
||||||
_tbss_end = .;
|
_tbss_end = .;
|
||||||
} :Tls
|
} :Tls
|
||||||
|
@ -488,8 +486,10 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
|
||||||
PFSTUB4(ape_elf_shnum, 0);
|
PFSTUB4(ape_elf_shnum, 0);
|
||||||
PFSTUB4(ape_elf_shstrndx, 0);
|
PFSTUB4(ape_elf_shstrndx, 0);
|
||||||
|
|
||||||
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
|
|
||||||
HIDDEN(_tls_size = _tbss_end - _tdata_start);
|
HIDDEN(_tls_size = _tbss_end - _tdata_start);
|
||||||
|
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
|
||||||
|
HIDDEN(_tbss_size = _tbss_end - _tbss_start);
|
||||||
|
HIDDEN(_tbss_offset = _tbss_start - _tdata_start);
|
||||||
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
|
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
|
||||||
|
|
||||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||||
|
@ -717,6 +717,9 @@ ASSERT(IS2POW(ape_stack_memsz),
|
||||||
ASSERT(!(ape_stack_vaddr & (ape_stack_memsz - 1)),
|
ASSERT(!(ape_stack_vaddr & (ape_stack_memsz - 1)),
|
||||||
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000000000 - ape_stack_memsz);");
|
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000000000 - ape_stack_memsz);");
|
||||||
|
|
||||||
|
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||||
|
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||||
|
|
||||||
/* Let's not be like Knight Capital. */
|
/* Let's not be like Knight Capital. */
|
||||||
/* NOCROSSREFS_TO(.test .text) */
|
/* NOCROSSREFS_TO(.test .text) */
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ o/$(MODE)/ape/ape.lds: \
|
||||||
ape/macros.internal.h \
|
ape/macros.internal.h \
|
||||||
ape/relocations.h \
|
ape/relocations.h \
|
||||||
libc/intrin/bits.h \
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
libc/calls/struct/timespec.h \
|
libc/calls/struct/timespec.h \
|
||||||
libc/dce.h \
|
libc/dce.h \
|
||||||
libc/elf/def.h \
|
libc/elf/def.h \
|
||||||
|
@ -79,6 +80,7 @@ o/$(MODE)/ape/public/ape.lds: \
|
||||||
ape/macros.internal.h \
|
ape/macros.internal.h \
|
||||||
ape/relocations.h \
|
ape/relocations.h \
|
||||||
libc/intrin/bits.h \
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
libc/calls/struct/timespec.h \
|
libc/calls/struct/timespec.h \
|
||||||
libc/dce.h \
|
libc/dce.h \
|
||||||
libc/elf/def.h \
|
libc/elf/def.h \
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/asancodes.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/log/libfatal.internal.h"
|
#include "libc/log/libfatal.internal.h"
|
||||||
|
@ -57,7 +59,7 @@ __msabi extern typeof(TlsAlloc) *const __imp_TlsAlloc;
|
||||||
|
|
||||||
extern unsigned char __tls_mov_nt_rax[];
|
extern unsigned char __tls_mov_nt_rax[];
|
||||||
extern unsigned char __tls_add_nt_rax[];
|
extern unsigned char __tls_add_nt_rax[];
|
||||||
_Alignas(long) static char __static_tls[5008];
|
_Alignas(TLS_ALIGNMENT) static char __static_tls[5008];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables thread local storage for main process.
|
* Enables thread local storage for main process.
|
||||||
|
@ -103,7 +105,6 @@ privileged void __enable_tls(void) {
|
||||||
// if tls requirement is small then use the static tls block
|
// if tls requirement is small then use the static tls block
|
||||||
// which helps avoid a system call for appes with little tls
|
// which helps avoid a system call for appes with little tls
|
||||||
// this is crucial to keeping life.com 16 kilobytes in size!
|
// this is crucial to keeping life.com 16 kilobytes in size!
|
||||||
_Static_assert(alignof(__static_tls) >= alignof(struct CosmoTib));
|
|
||||||
mem = __static_tls;
|
mem = __static_tls;
|
||||||
} else {
|
} else {
|
||||||
// if this binary needs a hefty tls block then we'll bank on
|
// if this binary needs a hefty tls block then we'll bank on
|
||||||
|
@ -115,6 +116,12 @@ privileged void __enable_tls(void) {
|
||||||
mem = weaken(_mapanon)(siz);
|
mem = weaken(_mapanon)(siz);
|
||||||
assert(mem);
|
assert(mem);
|
||||||
}
|
}
|
||||||
|
if (IsAsan()) {
|
||||||
|
// poison the space between .tdata and .tbss
|
||||||
|
__asan_poison(mem + (intptr_t)_tdata_size,
|
||||||
|
(intptr_t)_tbss_offset - (intptr_t)_tdata_size,
|
||||||
|
kAsanProtected);
|
||||||
|
}
|
||||||
tib = (struct CosmoTib *)(mem + siz - _TIBZ);
|
tib = (struct CosmoTib *)(mem + siz - _TIBZ);
|
||||||
tls = mem + siz - _TIBZ - _TLSZ;
|
tls = mem + siz - _TIBZ - _TLSZ;
|
||||||
tib->tib_self = tib;
|
tib->tib_self = tib;
|
||||||
|
|
|
@ -23,6 +23,8 @@ extern unsigned char _tdata_end[];
|
||||||
extern unsigned char _tdata_size[];
|
extern unsigned char _tdata_size[];
|
||||||
extern unsigned char _tbss_start[];
|
extern unsigned char _tbss_start[];
|
||||||
extern unsigned char _tbss_end[];
|
extern unsigned char _tbss_end[];
|
||||||
|
extern unsigned char _tbss_size[];
|
||||||
|
extern unsigned char _tbss_offset[];
|
||||||
extern unsigned char _tls_size[];
|
extern unsigned char _tls_size[];
|
||||||
extern unsigned char _tls_content[];
|
extern unsigned char _tls_content[];
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
_tdata_size = 0
|
_tdata_size = 0
|
||||||
_tbss_start = 0
|
_tbss_start = 0
|
||||||
_tbss_end = 0
|
_tbss_end = 0
|
||||||
|
_tbss_offset = 0
|
||||||
|
_tbss_size = 0
|
||||||
_tls_size = 0
|
_tls_size = 0
|
||||||
_tls_content = 0
|
_tls_content = 0
|
||||||
|
|
||||||
|
@ -73,6 +75,8 @@
|
||||||
.globl _tdata_size
|
.globl _tdata_size
|
||||||
.globl _tbss_start
|
.globl _tbss_start
|
||||||
.globl _tbss_end
|
.globl _tbss_end
|
||||||
|
.globl _tbss_size
|
||||||
|
.globl _tbss_offset
|
||||||
.globl _tls_size
|
.globl _tls_size
|
||||||
.globl _tls_content
|
.globl _tls_content
|
||||||
.globl __data_start
|
.globl __data_start
|
||||||
|
@ -100,8 +104,10 @@
|
||||||
.weak _tdata_size
|
.weak _tdata_size
|
||||||
.weak _tbss_start
|
.weak _tbss_start
|
||||||
.weak _tbss_end
|
.weak _tbss_end
|
||||||
|
.weak _tbss_size
|
||||||
.weak _tls_size
|
.weak _tls_size
|
||||||
.weak _tls_content
|
.weak _tls_content
|
||||||
|
.weak _tbss_offset
|
||||||
.weak __data_start
|
.weak __data_start
|
||||||
.weak __data_end
|
.weak __data_end
|
||||||
.weak __bss_start
|
.weak __bss_start
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/asan.internal.h"
|
||||||
|
#include "libc/intrin/asancodes.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
|
@ -24,10 +27,9 @@
|
||||||
#include "libc/thread/spawn.h"
|
#include "libc/thread/spawn.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
#define _TLSZ ((intptr_t)_tls_size)
|
#define I(x) ((intptr_t)x)
|
||||||
#define _TLDZ ((intptr_t)_tdata_size)
|
|
||||||
#define _TIBZ sizeof(struct CosmoTib)
|
void Bzero(void *, size_t) asm("bzero"); // gcc bug
|
||||||
#define _MEMZ ROUNDUP(_TLSZ + _TIBZ, _Alignof(struct CosmoTib))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates thread-local storage memory for new thread.
|
* Allocates thread-local storage memory for new thread.
|
||||||
|
@ -37,17 +39,25 @@ char *_mktls(char **out_tib) {
|
||||||
char *tls;
|
char *tls;
|
||||||
struct CosmoTib *tib;
|
struct CosmoTib *tib;
|
||||||
|
|
||||||
// Allocate enough TLS memory for all the GNU Linuker (_tls_size)
|
// allocate memory for tdata, tbss, and tib
|
||||||
// organized _Thread_local data, as well as Cosmpolitan Libc (64)
|
tls = memalign(TLS_ALIGNMENT, I(_tls_size) + sizeof(struct CosmoTib));
|
||||||
if (!(tls = calloc(1, _MEMZ))) return 0;
|
if (!tls) return 0;
|
||||||
|
|
||||||
|
// poison memory between tdata and tbss
|
||||||
|
if (IsAsan()) {
|
||||||
|
__asan_poison(tls + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
|
||||||
|
kAsanProtected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize tdata and clear tbss
|
||||||
|
memmove(tls, _tdata_start, I(_tdata_size));
|
||||||
|
Bzero(tls + I(_tbss_offset), I(_tbss_size) + sizeof(struct CosmoTib));
|
||||||
|
|
||||||
// set up thread information block
|
// set up thread information block
|
||||||
tib = (struct CosmoTib *)(tls + _MEMZ - _TIBZ);
|
tib = (struct CosmoTib *)(tls + I(_tls_size));
|
||||||
tib->tib_self = tib;
|
tib->tib_self = tib;
|
||||||
tib->tib_self2 = tib;
|
tib->tib_self2 = tib;
|
||||||
tib->tib_errno = 0;
|
|
||||||
tib->tib_tid = -1;
|
tib->tib_tid = -1;
|
||||||
memmove(tls, _tdata_start, _TLDZ);
|
|
||||||
|
|
||||||
if (out_tib) {
|
if (out_tib) {
|
||||||
*out_tib = (char *)tib;
|
*out_tib = (char *)tib;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_THREAD_TLS_H_
|
#ifndef COSMOPOLITAN_LIBC_THREAD_TLS_H_
|
||||||
#define COSMOPOLITAN_LIBC_THREAD_TLS_H_
|
#define COSMOPOLITAN_LIBC_THREAD_TLS_H_
|
||||||
|
|
||||||
|
#define TLS_ALIGNMENT 64
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,39 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
_Thread_local int x;
|
#define A TLS_ALIGNMENT
|
||||||
_Thread_local int y = 40;
|
|
||||||
int z = 2;
|
long z = 2;
|
||||||
|
pthread_t t;
|
||||||
|
_Thread_local long x;
|
||||||
|
_Thread_local long y[1] = {40};
|
||||||
|
_Alignas(A) _Thread_local long a;
|
||||||
|
|
||||||
|
noubsan void *Worker(void *arg) {
|
||||||
|
ASSERT_EQ(42, x + y[0] + z);
|
||||||
|
ASSERT_EQ(0, (intptr_t)&a & (A - 1));
|
||||||
|
if (IsAsan()) {
|
||||||
|
ASSERT_EQ(kAsanProtected, __asan_check(y + 1, sizeof(long)).kind);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
TEST(tls, test) {
|
TEST(tls, test) {
|
||||||
EXPECT_EQ(42, x + y + z);
|
ASSERT_EQ(A, _Alignof(a));
|
||||||
|
ASSERT_EQ(0, sizeof(struct CosmoTib) % A);
|
||||||
|
ASSERT_EQ(0, (intptr_t)__get_tls() & (A - 1));
|
||||||
|
EXPECT_EQ(42, x + y[0] + z);
|
||||||
|
y[0] = 666;
|
||||||
|
ASSERT_EQ(0, (intptr_t)&a & (A - 1));
|
||||||
|
ASSERT_EQ(0, pthread_create(&t, 0, Worker, 0));
|
||||||
|
ASSERT_EQ(0, pthread_join(t, 0));
|
||||||
|
if (IsAsan()) {
|
||||||
|
ASSERT_EQ(kAsanProtected, __asan_check(y + 1, sizeof(long)).kind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue