Add TLS (thread local storage) support
This commit is contained in:
parent
33d05f0fd0
commit
3f9513e62c
@ -40,11 +40,11 @@ INCLUDES := include
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# 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 \
|
CFLAGS := -g -Wall -Werror -O2 -mword-relocations \
|
||||||
-ffunction-sections -fno-strict-aliasing \
|
-ffunction-sections -fno-strict-aliasing \
|
||||||
-fomit-frame-pointer -ffast-math \
|
-fomit-frame-pointer \
|
||||||
$(ARCH)
|
$(ARCH)
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||||
|
@ -610,7 +610,6 @@ static void newRow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
consoleClearLine('2');
|
consoleClearLine('2');
|
||||||
gfxFlushBuffers();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
@ -20,6 +20,9 @@ typedef struct
|
|||||||
// Pointer to this thread's newlib state
|
// Pointer to this thread's newlib state
|
||||||
struct _reent* reent;
|
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
|
// FS session override
|
||||||
u32 fs_magic;
|
u32 fs_magic;
|
||||||
Handle fs_session;
|
Handle fs_session;
|
||||||
|
9
libctru/source/system/readtp.s
Normal file
9
libctru/source/system/readtp.s
Normal 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
|
@ -13,6 +13,10 @@
|
|||||||
void __ctru_exit(int rc);
|
void __ctru_exit(int rc);
|
||||||
int __libctru_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz);
|
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()
|
static struct _reent* __ctru_get_reent()
|
||||||
{
|
{
|
||||||
ThreadVars* tv = getThreadVars();
|
ThreadVars* tv = getThreadVars();
|
||||||
@ -46,4 +50,9 @@ void __system_initSyscalls(void)
|
|||||||
tv->magic = THREADVARS_MAGIC;
|
tv->magic = THREADVARS_MAGIC;
|
||||||
tv->reent = _impure_ptr;
|
tv->reent = _impure_ptr;
|
||||||
tv->thread_ptr = NULL;
|
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);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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
|
struct Thread_tag
|
||||||
{
|
{
|
||||||
Handle handle;
|
Handle handle;
|
||||||
@ -26,6 +31,7 @@ static void _thread_begin(void* arg)
|
|||||||
tv->magic = THREADVARS_MAGIC;
|
tv->magic = THREADVARS_MAGIC;
|
||||||
tv->reent = &t->reent;
|
tv->reent = &t->reent;
|
||||||
tv->thread_ptr = t;
|
tv->thread_ptr = t;
|
||||||
|
tv->tls_tp = (u8*)t->stacktop-8; // ARM ELF TLS ABI mandates an 8-byte header
|
||||||
t->ep(t->arg);
|
t->ep(t->arg);
|
||||||
threadExit(0);
|
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 stackoffset = (sizeof(struct Thread_tag)+7)&~7;
|
||||||
size_t allocsize = stackoffset + ((stack_size+7)&~7);
|
size_t allocsize = stackoffset + ((stack_size+7)&~7);
|
||||||
if (allocsize < stackoffset) return NULL; // guard against overflow
|
size_t tlssize = __tls_end-__tls_start;
|
||||||
if ((allocsize-stackoffset) < stack_size) return NULL; // guard against overflow
|
size_t tlsloadsize = __tdata_lma_end-__tdata_lma;
|
||||||
Thread t = (Thread)malloc(allocsize);
|
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;
|
if (!t) return NULL;
|
||||||
|
|
||||||
t->ep = entrypoint;
|
t->ep = entrypoint;
|
||||||
@ -45,6 +58,11 @@ Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int pri
|
|||||||
t->finished = false;
|
t->finished = false;
|
||||||
t->stacktop = (u8*)t + allocsize;
|
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
|
// Set up child thread's reent struct, inheriting standard file handles
|
||||||
_REENT_INIT_PTR(&t->reent);
|
_REENT_INIT_PTR(&t->reent);
|
||||||
struct _reent* cur = getThreadVars()->reent;
|
struct _reent* cur = getThreadVars()->reent;
|
||||||
|
Loading…
Reference in New Issue
Block a user