]> Chaos Git - corbenik/ctrulib.git/commitdiff
Add TLS (thread local storage) support
authorfincs <fincs.alt1@gmail.com>
Wed, 25 Nov 2015 20:46:54 +0000 (21:46 +0100)
committerfincs <fincs.alt1@gmail.com>
Mon, 7 Dec 2015 10:44:36 +0000 (11:44 +0100)
libctru/Makefile
libctru/source/console.c
libctru/source/internal.h
libctru/source/system/readtp.s [new file with mode: 0644]
libctru/source/system/syscalls.c
libctru/source/thread.c

index 5c72c83b056a87df5874048ac0c66769e3dd8b86..bf53ac7aa2c455836695e0877d8db942337f8120 100644 (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
index e19563808f4f3fa6b447134785253382c1b0c1a3..104475803bc75a4f87db86223602c13551d6eb38 100644 (file)
@@ -610,7 +610,6 @@ static void newRow() {
                }\r
 \r
                consoleClearLine('2');\r
-               gfxFlushBuffers();\r
        }\r
 }\r
 //---------------------------------------------------------------------------------\r
index 269c9c34eb0b71a69481b3b9295a0dbaf489d139..65ba9a6b629dc76e63b16201eaf6ae1b96fec8bd 100644 (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;
diff --git a/libctru/source/system/readtp.s b/libctru/source/system/readtp.s
new file mode 100644 (file)
index 0000000..2b229cc
--- /dev/null
@@ -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
index a27482b69cedeb0aa82d5f14904b9e9a07811f7e..711f79aaec883ca920f7332f61d37f544756923c 100644 (file)
 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);
 }
index 382534c9339849e5df0e7e5ecece93cd988c2e50..1b21c48f9eb427042e861a8a24ea545a238b0a07 100644 (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;