Add TLS (thread local storage) support

This commit is contained in:
fincs 2015-11-25 21:46:54 +01:00
parent 33d05f0fd0
commit 3f9513e62c
6 changed files with 44 additions and 6 deletions

View File

@ -40,11 +40,11 @@ INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
CFLAGS := -g -Wall -Werror -O2 -mword-relocations \
-ffunction-sections -fno-strict-aliasing \
-fomit-frame-pointer -ffast-math \
-fomit-frame-pointer \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS

View File

@ -610,7 +610,6 @@ static void newRow() {
}
consoleClearLine('2');
gfxFlushBuffers();
}
}
//---------------------------------------------------------------------------------

View File

@ -20,6 +20,9 @@ typedef struct
// Pointer to this thread's newlib state
struct _reent* reent;
// Pointer to this thread's thread-local segment
void* tls_tp; // !! Keep offset in sync inside __aeabi_read_tp !!
// FS session override
u32 fs_magic;
Handle fs_session;

View File

@ -0,0 +1,9 @@
.arm
.section .text.__aeabi_read_tp, "ax", %progbits
.global __aeabi_read_tp
.type __aeabi_read_tp, %function
.align 2
__aeabi_read_tp:
mrc p15, 0, r0, c13, c0, 3
ldr r0, [r0, #0xC] @ Read ThreadVars.tls_tp
bx lr

View File

@ -13,6 +13,10 @@
void __ctru_exit(int rc);
int __libctru_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz);
extern const u8 __tdata_lma[];
extern const u8 __tdata_lma_end[];
extern u8 __tls_start[];
static struct _reent* __ctru_get_reent()
{
ThreadVars* tv = getThreadVars();
@ -46,4 +50,9 @@ void __system_initSyscalls(void)
tv->magic = THREADVARS_MAGIC;
tv->reent = _impure_ptr;
tv->thread_ptr = NULL;
tv->tls_tp = __tls_start-8; // ARM ELF TLS ABI mandates an 8-byte header
u32 tls_size = __tdata_lma_end - __tdata_lma;
if (tls_size)
memcpy(__tls_start, __tdata_lma, tls_size);
}

View File

@ -2,6 +2,11 @@
#include <stdlib.h>
#include <string.h>
extern const u8 __tdata_lma[];
extern const u8 __tdata_lma_end[];
extern u8 __tls_start[];
extern u8 __tls_end[];
struct Thread_tag
{
Handle handle;
@ -26,6 +31,7 @@ static void _thread_begin(void* arg)
tv->magic = THREADVARS_MAGIC;
tv->reent = &t->reent;
tv->thread_ptr = t;
tv->tls_tp = (u8*)t->stacktop-8; // ARM ELF TLS ABI mandates an 8-byte header
t->ep(t->arg);
threadExit(0);
}
@ -34,9 +40,16 @@ Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int pri
{
size_t stackoffset = (sizeof(struct Thread_tag)+7)&~7;
size_t allocsize = stackoffset + ((stack_size+7)&~7);
if (allocsize < stackoffset) return NULL; // guard against overflow
if ((allocsize-stackoffset) < stack_size) return NULL; // guard against overflow
Thread t = (Thread)malloc(allocsize);
size_t tlssize = __tls_end-__tls_start;
size_t tlsloadsize = __tdata_lma_end-__tdata_lma;
size_t tbsssize = tlssize-tlsloadsize;
// Guard against overflow
if (allocsize < stackoffset) return NULL;
if ((allocsize-stackoffset) < stack_size) return NULL;
if ((allocsize+tlssize) < allocsize) return NULL;
Thread t = (Thread)malloc(allocsize+tlssize);
if (!t) return NULL;
t->ep = entrypoint;
@ -45,6 +58,11 @@ Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int pri
t->finished = false;
t->stacktop = (u8*)t + allocsize;
if (tlsloadsize)
memcpy(t->stacktop, __tdata_lma, tlsloadsize);
if (tbsssize)
memset((u8*)t->stacktop+tlsloadsize, 0, tbsssize);
// Set up child thread's reent struct, inheriting standard file handles
_REENT_INIT_PTR(&t->reent);
struct _reent* cur = getThreadVars()->reent;