From 7326d46218cae763dbca934276cb036511bedc7f Mon Sep 17 00:00:00 2001 From: Hubert Badocha Date: Fri, 13 Sep 2024 15:46:00 +0200 Subject: [PATCH] !tls: move tls handling to libphoenix JIRA: RTOS-921 --- arch/arm/v7a/Makefile | 2 +- arch/arm/v7a/tls.c | 39 +++++++++++ arch/arm/v7m/tls.c | 22 +++++- arch/arm/v8m/tls.c | 22 +++++- arch/arm/v8r/Makefile | 2 +- arch/arm/v8r/tls.c | 39 +++++++++++ arch/ia32/Makefile | 2 +- arch/ia32/tls.c | 39 +++++++++++ arch/riscv64/Makefile | 2 +- arch/riscv64/tls.c | 43 ++++++++++++ arch/sparcv8leon3/Makefile | 2 +- arch/sparcv8leon3/tls.c | 37 ++++++++++ crt0-common.c | 13 ++++ errno/errno.c | 15 +++-- include/arch/armv7a/arch.h | 3 +- include/arch/armv7m/arch.h | 3 +- include/arch/armv8m/arch.h | 3 +- include/arch/armv8r/arch.h | 3 +- include/arch/ia32/arch.h | 3 +- include/arch/riscv64/arch.h | 3 +- include/arch/sparcv8leon3/arch.h | 3 +- include/elf.h | 49 ++++++++++++++ include/sys/auxv.h | 26 +++++++ include/sys/threads.h | 23 ++++++- include/sys/tls.h | 74 ++++++++++++++++++++ misc/init.c | 6 +- sys/Makefile | 2 +- sys/auxv.c | 31 +++++++++ sys/threads.c | 26 +++++++ sys/tls.c | 112 +++++++++++++++++++++++++++++++ 30 files changed, 623 insertions(+), 26 deletions(-) create mode 100644 arch/arm/v7a/tls.c create mode 100644 arch/arm/v8r/tls.c create mode 100644 arch/ia32/tls.c create mode 100644 arch/riscv64/tls.c create mode 100644 arch/sparcv8leon3/tls.c create mode 100644 include/elf.h create mode 100644 include/sys/auxv.h create mode 100644 include/sys/tls.h create mode 100644 sys/auxv.c create mode 100644 sys/tls.c diff --git a/arch/arm/v7a/Makefile b/arch/arm/v7a/Makefile index ae752782..42ae98f8 100644 --- a/arch/arm/v7a/Makefile +++ b/arch/arm/v7a/Makefile @@ -5,4 +5,4 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)arch/arm/v7a/, syscalls.o reboot.o) +OBJS += $(addprefix $(PREFIX_O)arch/arm/v7a/, syscalls.o reboot.o tls.o) diff --git a/arch/arm/v7a/tls.c b/arch/arm/v7a/tls.c new file mode 100644 index 00000000..9296ba50 --- /dev/null +++ b/arch/arm/v7a/tls.c @@ -0,0 +1,39 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls (armv7a) + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include + + +struct tls_tcb *__tls_getTcb(void) +{ + void *tcb; + /* clang-format off */ + __asm__ volatile("mrc p15, 0, %0, cr13, cr0, 3" : "=r"(tcb)); + /* clang-format on */ + return tcb; +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)tcb; +} + + +void __tls_archInit(void) +{ + /* Nothing to do. */ +} diff --git a/arch/arm/v7m/tls.c b/arch/arm/v7m/tls.c index 11434a2e..6edab6e1 100644 --- a/arch/arm/v7m/tls.c +++ b/arch/arm/v7m/tls.c @@ -13,10 +13,12 @@ * %LICENSE% */ + #include +#include -volatile uintptr_t arm_tls_ptr __attribute__((section("armtls"))) = 0; +volatile uintptr_t arm_tls_ptr = 0; void *read_tls_ptr(void) @@ -32,3 +34,21 @@ void __attribute__((naked)) __aeabi_read_tp(void) "bl read_tls_ptr;" "pop {r1-r4,r12,pc}"); } + + +struct tls_tcb *__tls_getTcb(void) +{ + return (struct tls_tcb *)read_tls_ptr(); +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)tcb; +} + + +void __tls_archInit(void) +{ + tlsSetReg((void *)&arm_tls_ptr); +} diff --git a/arch/arm/v8m/tls.c b/arch/arm/v8m/tls.c index 840b93d9..a456028f 100644 --- a/arch/arm/v8m/tls.c +++ b/arch/arm/v8m/tls.c @@ -13,10 +13,12 @@ * %LICENSE% */ + #include +#include -volatile uintptr_t arm_tls_ptr __attribute__((section("armtls"))) = 0; +volatile uintptr_t arm_tls_ptr = 0; void *read_tls_ptr(void) @@ -32,3 +34,21 @@ void __attribute__((naked)) __aeabi_read_tp(void) "bl read_tls_ptr;" "pop {r1-r4,r12,pc}"); } + + +struct tls_tcb *__tls_getTcb(void) +{ + return (struct tls_tcb *)read_tls_ptr(); +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)tcb; +} + + +void __tls_archInit(void) +{ + tlsSetReg((void *)&arm_tls_ptr); +} diff --git a/arch/arm/v8r/Makefile b/arch/arm/v8r/Makefile index de05bb25..141a12d9 100644 --- a/arch/arm/v8r/Makefile +++ b/arch/arm/v8r/Makefile @@ -6,4 +6,4 @@ # %LICENSE% # -OBJS += $(addprefix $(PREFIX_O)arch/arm/v8r/, syscalls.o reboot.o) +OBJS += $(addprefix $(PREFIX_O)arch/arm/v8r/, syscalls.o reboot.o tls.o) diff --git a/arch/arm/v8r/tls.c b/arch/arm/v8r/tls.c new file mode 100644 index 00000000..7a19842b --- /dev/null +++ b/arch/arm/v8r/tls.c @@ -0,0 +1,39 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls (armv8r) + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include + + +struct tls_tcb *__tls_getTcb(void) +{ + void *tcb; + /* clang-format off */ + __asm__ volatile("mrc p15, 0, %0, cr13, cr0, 3" : "=r"(tcb)); + /* clang-format on */ + return tcb; +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)tcb; +} + + +void __tls_archInit(void) +{ + /* Nothing to do. */ +} diff --git a/arch/ia32/Makefile b/arch/ia32/Makefile index 4df355e4..8d098c32 100644 --- a/arch/ia32/Makefile +++ b/arch/ia32/Makefile @@ -5,5 +5,5 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)arch/ia32/, syscalls.o jmp.o signal.o string.o reboot.o) +OBJS += $(addprefix $(PREFIX_O)arch/ia32/, syscalls.o jmp.o signal.o string.o reboot.o tls.o) CRT0_OBJS += $(addprefix $(PREFIX_O)arch/ia32/, crt0.o) diff --git a/arch/ia32/tls.c b/arch/ia32/tls.c new file mode 100644 index 00000000..7293de6f --- /dev/null +++ b/arch/ia32/tls.c @@ -0,0 +1,39 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls (ia32) + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include + + +struct tls_tcb *__tls_getTcb(void) +{ + struct tls_tcb *tcb; + /* clang-format off */ + __asm__ volatile("movl %%gs:0, %0" : "=r"(tcb)); + /* clang-format on */ + return tcb; +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)tcb; +} + + +void __tls_archInit(void) +{ + /* Nothing to do. */ +} diff --git a/arch/riscv64/Makefile b/arch/riscv64/Makefile index 5674f637..cdd606cc 100644 --- a/arch/riscv64/Makefile +++ b/arch/riscv64/Makefile @@ -5,5 +5,5 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)arch/riscv64/, syscalls.o string.o signal.o reboot.o jmp.o) +OBJS += $(addprefix $(PREFIX_O)arch/riscv64/, syscalls.o string.o signal.o reboot.o jmp.o tls.o) CRT0_OBJS += $(addprefix $(PREFIX_O)arch/riscv64/, crt0.o) diff --git a/arch/riscv64/tls.c b/arch/riscv64/tls.c new file mode 100644 index 00000000..cda5eff4 --- /dev/null +++ b/arch/riscv64/tls.c @@ -0,0 +1,43 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls (riscv64) + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include + + +/* As per RISC-V ABI: + * RISC-V uses Variant I as described by the ELF TLS specification, with tp containing the address one past the end of the TCB */ +struct tls_tcb *__tls_getTcb(void) +{ + void *tcb; + /* clang-format off */ + __asm__ volatile("addi %[tcb], tp, %[offset]" + : [tcb] "=r"(tcb) + : [offset] "n"(-sizeof(struct tls_tcb))); + /* clang-format on */ + return tcb; +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)(tcb + 1); +} + + +void __tls_archInit(void) +{ + /* Nothing to do. */ +} diff --git a/arch/sparcv8leon3/Makefile b/arch/sparcv8leon3/Makefile index 48bb489e..d82cef13 100644 --- a/arch/sparcv8leon3/Makefile +++ b/arch/sparcv8leon3/Makefile @@ -5,5 +5,5 @@ # Author: Lukasz Leczkowski # -OBJS += $(addprefix $(PREFIX_O)arch/sparcv8leon3/, syscalls.o jmp.o signal.o string.o reboot.o) +OBJS += $(addprefix $(PREFIX_O)arch/sparcv8leon3/, syscalls.o jmp.o signal.o string.o reboot.o tls.o) CRT0_OBJS += $(addprefix $(PREFIX_O)arch/sparcv8leon3/, crt0.o) diff --git a/arch/sparcv8leon3/tls.c b/arch/sparcv8leon3/tls.c new file mode 100644 index 00000000..7b89038c --- /dev/null +++ b/arch/sparcv8leon3/tls.c @@ -0,0 +1,37 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * tls (sparc) + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include + + +struct tls_tcb *__tls_getTcb(void) +{ + register struct tls_tcb *tcb asm("g7"); + + return tcb; +} + + +void *__tls_tcbPtrToTlsPtr(struct tls_tcb *tcb) +{ + return (void *)tcb; +} + + +void __tls_archInit(void) +{ + /* Nothing to do. */ +} diff --git a/crt0-common.c b/crt0-common.c index 7842f9e6..3975014e 100644 --- a/crt0-common.c +++ b/crt0-common.c @@ -72,6 +72,7 @@ extern int main(int argc, char **argv); char **environ; const char *argv_progname; +char **auxvStart; /* char** instead of void* to make iteration easier and don't waste any stack space. */ __attribute__((noreturn)) void _startc(void (*cleanup)(void), int argc, char **argv, char **env) @@ -79,6 +80,18 @@ __attribute__((noreturn)) void _startc(void (*cleanup)(void), int argc, char **a environ = env; argv_progname = *argv; + if (env == NULL) { + auxvStart = argv; + } + else { + auxvStart = env; + } + + while ((*auxvStart) != NULL) { + auxvStart++; + } + auxvStart++; + _libc_init(); /* cleanup function is not NULL when the dynamic linker is used */ diff --git a/errno/errno.c b/errno/errno.c index fccd3468..750e7607 100644 --- a/errno/errno.c +++ b/errno/errno.c @@ -15,13 +15,15 @@ #include #include +#include #include #include -#ifdef __LIBPHOENIX_ARCH_TLS_SUPPORTED +#ifdef __LIBPHOENIX_ARCH_USE_TLS static __thread int __errno_tls; +static int __errno_singlethread; #else @@ -45,7 +47,7 @@ static int errno_cmp(rbnode_t *n1, rbnode_t *n2) int *__errno_location(void) { -#ifndef __LIBPHOENIX_ARCH_TLS_SUPPORTED +#ifndef __LIBPHOENIX_ARCH_USE_TLS struct __errno_t *e, r; r.tid = gettid(); @@ -58,14 +60,15 @@ int *__errno_location(void) return &errno_global; #else - return &__errno_tls; + /* Errno maybe called before TLS is initialized(malloc) */ + return (__isthreaded == 0) ? &__errno_singlethread : &__errno_tls; #endif } void _errno_new(struct __errno_t *e) { -#ifndef __LIBPHOENIX_ARCH_TLS_SUPPORTED +#ifndef __LIBPHOENIX_ARCH_USE_TLS e->no = 0; e->tid = gettid(); @@ -78,7 +81,7 @@ void _errno_new(struct __errno_t *e) void _errno_remove(struct __errno_t *e) { -#ifndef __LIBPHOENIX_ARCH_TLS_SUPPORTED +#ifndef __LIBPHOENIX_ARCH_USE_TLS mutexLock(errno_common.lock); lib_rbRemove(&errno_common.tree, &e->linkage); mutexUnlock(errno_common.lock); @@ -88,7 +91,7 @@ void _errno_remove(struct __errno_t *e) void _errno_init(void) { -#ifndef __LIBPHOENIX_ARCH_TLS_SUPPORTED +#ifndef __LIBPHOENIX_ARCH_USE_TLS mutexCreate(&errno_common.lock); lib_rbInit(&errno_common.tree, errno_cmp, NULL); #endif diff --git a/include/arch/armv7a/arch.h b/include/arch/armv7a/arch.h index 8a0f5ba2..4cb6ce42 100644 --- a/include/arch/armv7a/arch.h +++ b/include/arch/armv7a/arch.h @@ -60,6 +60,7 @@ static inline float __ieee754_sqrtf(float x) #define _PAGE_SIZE 0x1000 #define SIZE_PAGE _Pragma("GCC warning \"'SIZE_PAGE' is deprecated. Use _PAGE_SIZE from arch.h or PAGE_SIZE from limits.h (POSIX only)\"") _PAGE_SIZE -#define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_I +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/arch/armv7m/arch.h b/include/arch/armv7m/arch.h index 4c69490f..057decdb 100644 --- a/include/arch/armv7m/arch.h +++ b/include/arch/armv7m/arch.h @@ -64,6 +64,7 @@ static inline float __ieee754_sqrtf(float x) * project basis. * Disabled for now as TLS consumes too much * memory to be advantageous on some targets. */ -// #define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_I +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/arch/armv8m/arch.h b/include/arch/armv8m/arch.h index abf78c6c..19aaad46 100644 --- a/include/arch/armv8m/arch.h +++ b/include/arch/armv8m/arch.h @@ -64,6 +64,7 @@ static inline float __ieee754_sqrtf(float x) * project basis. * Disabled for now as TLS consumes too much * memory to be advantageous on some targets. */ -// #define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_I +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/arch/armv8r/arch.h b/include/arch/armv8r/arch.h index 8e3fc446..60d7b7f5 100644 --- a/include/arch/armv8r/arch.h +++ b/include/arch/armv8r/arch.h @@ -59,6 +59,7 @@ static inline float __ieee754_sqrtf(float x) #define _PAGE_SIZE 0x1000 #define SIZE_PAGE _Pragma("GCC warning \"'SIZE_PAGE' is deprecated. Use _PAGE_SIZE from arch.h or PAGE_SIZE from limits.h (POSIX only)\"") _PAGE_SIZE -#define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_I +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/arch/ia32/arch.h b/include/arch/ia32/arch.h index 16985323..25830104 100644 --- a/include/arch/ia32/arch.h +++ b/include/arch/ia32/arch.h @@ -54,6 +54,7 @@ static inline double __ieee754_sqrt(double x) #define _PAGE_SIZE 0x1000 #define SIZE_PAGE _Pragma("GCC warning \"'SIZE_PAGE' is deprecated. Use _PAGE_SIZE from arch.h or PAGE_SIZE from limits.h (POSIX only)\"") _PAGE_SIZE -#define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_II +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/arch/riscv64/arch.h b/include/arch/riscv64/arch.h index 98e70814..1a797158 100644 --- a/include/arch/riscv64/arch.h +++ b/include/arch/riscv64/arch.h @@ -51,6 +51,7 @@ static inline float __ieee754_sqrtf(float x) #define _PAGE_SIZE 0x1000 #define SIZE_PAGE _Pragma("GCC warning \"'SIZE_PAGE' is deprecated. Use _PAGE_SIZE from arch.h or PAGE_SIZE from limits.h (POSIX only)\"") _PAGE_SIZE -#define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_I +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/arch/sparcv8leon3/arch.h b/include/arch/sparcv8leon3/arch.h index c0992e26..b560f639 100644 --- a/include/arch/sparcv8leon3/arch.h +++ b/include/arch/sparcv8leon3/arch.h @@ -60,6 +60,7 @@ static inline float __ieee754_sqrtf(float x) #endif #define SIZE_PAGE _Pragma("GCC warning \"'SIZE_PAGE' is deprecated. Use _PAGE_SIZE from arch.h or PAGE_SIZE from limits.h (POSIX only)\"") _PAGE_SIZE -#define __LIBPHOENIX_ARCH_TLS_SUPPORTED +#define __LIBPHOENIX_ARCH_TLS_VARIANT_II +#define __LIBPHOENIX_ARCH_USE_TLS #endif diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 00000000..fd114d50 --- /dev/null +++ b/include/elf.h @@ -0,0 +1,49 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * elf.h + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _LIBPHOENIX_ELF_H +#define _LIBPHOENIX_ELF_H + +#include + +/* NOTE: many structs have only definitions in phoenix for one of the sizes, thus common interface is missing */ +#if __SIZEOF_POINTER__ == 4 + +typedef Elf32_Half Elf_Half; +typedef Elf32_Word Elf_Word; +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Off Elf_Off; +typedef Elf32_Sword Elf_Sword; + +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Phdr Elf_Phdr; + +#else + +typedef Elf64_Half Elf_Half; +typedef Elf64_Word Elf_Word; +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Off Elf_Off; +typedef Elf64_Sword Elf_Sword; + +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Phdr Elf_Phdr; + +#endif + + +#endif /* _LIBPHOENIX_ELF_H */ diff --git a/include/sys/auxv.h b/include/sys/auxv.h new file mode 100644 index 00000000..89afd170 --- /dev/null +++ b/include/sys/auxv.h @@ -0,0 +1,26 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * sys/auxv.h + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _LIBPHOENIX_SYS_AUXV_H +#define _LIBPHOENIX_SYS_AUXV_H + +#include +#include + + +uint64_t getauxval(uint32_t type); + + +#endif /* _LIBPHOENIX_SYS_AUXV_H */ diff --git a/include/sys/threads.h b/include/sys/threads.h index 04d47197..8cd36006 100644 --- a/include/sys/threads.h +++ b/include/sys/threads.h @@ -18,17 +18,24 @@ #include #include +#include +#include #include #include #include #include #include +#include + #ifdef __cplusplus extern "C" { #endif +extern int __isthreaded; + + typedef struct { handle_t mutex; handle_t cond; @@ -70,11 +77,21 @@ extern int spawnSyspage(const char *imap, const char *dmap, const char *name, ch extern int threadJoin(int tid, time_t timeout); -extern int beginthreadex(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id); +extern int beginthreadexsvc(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id, void *tcb); + + +__attribute__((noreturn)) extern void endthreadsvc(void); -__attribute__((noreturn)) -extern void endthread(void); +__attribute__((noreturn)) static inline void endthread(void) +{ + __tls_release(); + + endthreadsvc(); +} + + +extern int beginthreadex(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id); static inline int beginthread(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg) diff --git a/include/sys/tls.h b/include/sys/tls.h new file mode 100644 index 00000000..cea11fc5 --- /dev/null +++ b/include/sys/tls.h @@ -0,0 +1,74 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * sys/tls + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _LIBPHOENIX_SYS_TLS_H_ +#define _LIBPHOENIX_SYS_TLS_H_ + +#include +#include + + +#if defined(__LIBPHOENIX_ARCH_TLS_VARIANT_I) && defined(__LIBPHOENIX_ARCH_TLS_VARIANT_II) +#error TLS configuration error +#endif + +struct tls_tcb { +#ifdef __LIBPHOENIX_ARCH_TLS_VARIANT_I + void **tcb_dtv; + void *impldef; /* Implementation defined field. Currently not used in phoenix. */ +#elif defined(__LIBPHOENIX_ARCH_TLS_VARIANT_II) + struct tls_tcb *tcb_self; + void **tcb_dtv; +#else + char undef; /* Prevent empty struct */ +#endif +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void tlsSetPtr(void *tlsPtr); + + +extern void tlsSetReg(void *tlsReg); + + +extern void *__tls_tcbPtrToTlsPtr(struct tls_tcb *); + + +extern void __tls_archInit(void); + + +extern struct tls_tcb *__tls_getTcb(void); + + +extern int __tls_alloc(struct tls_tcb **); + + +extern void __tls_release(void); + + +extern void _tls_init(void); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/misc/init.c b/misc/init.c index eba32b43..ae8603de 100644 --- a/misc/init.c +++ b/misc/init.c @@ -15,7 +15,8 @@ extern void _malloc_init(void); -extern int _env_init(void); +extern void _env_init(void); +extern void _tls_init(void); extern void _signals_init(void); extern void _file_init(void); extern void _errno_init(void); @@ -26,9 +27,10 @@ extern void _pthread_init(void); void _libc_init(void) { - _atexit_init(); _errno_init(); _malloc_init(); + _tls_init(); + _atexit_init(); _env_init(); _signals_init(); _file_init(); diff --git a/sys/Makefile b/sys/Makefile index d970ed58..d227f992 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -5,4 +5,4 @@ # OBJS += $(addprefix $(PREFIX_O)sys/, events.o ioctl.o list.o mount.o rb.o resource.o select.o \ -semaphore.o socket.o stat.o statvfs.o threads.o time.o times.o wait.o uio.o proto.o mman.o) +semaphore.o socket.o stat.o statvfs.o threads.o time.o times.o wait.o uio.o proto.o mman.o auxv.o tls.o) diff --git a/sys/auxv.c b/sys/auxv.c new file mode 100644 index 00000000..7cd74a4b --- /dev/null +++ b/sys/auxv.c @@ -0,0 +1,31 @@ +/* + * Phoenix-RTOS + * + * libphoenix + * + * sys/auxv.h + * + * Copyright 2024 Phoenix Systems + * Author: Hubert Badocha + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include + + +extern char **auxvStart; + + +uint64_t getauxval(uint32_t type) +{ + for (struct auxInfo *ai = (struct auxInfo *)auxvStart; ai->a_type != AT_NULL; ai++) { + if (ai->a_type == type) { + return ai->a_v; + } + } + + return 0; +} diff --git a/sys/threads.c b/sys/threads.c index b3545325..dd74ef86 100644 --- a/sys/threads.c +++ b/sys/threads.c @@ -15,6 +15,10 @@ #include #include +#include + + +int __isthreaded; int mutexCreate(handle_t *h) @@ -79,3 +83,25 @@ int mutexLock2(handle_t m1, handle_t m2) return EOK; } + + +int beginthreadex(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id) +{ + struct tls_tcb *tcb; + int ret; + + ret = __tls_alloc(&tcb); + if (ret != 0) { + return ret; + } + + /* Inform that we are threaded. */ + if (__isthreaded == 0) { + /* Make sure errno in initthread is set correctly. */ + int olderrno = errno; + __isthreaded = 1; + errno = olderrno; + } + + return beginthreadexsvc(start, priority, stack, stacksz, arg, id, __tls_tcbPtrToTlsPtr(tcb)); +} diff --git a/sys/tls.c b/sys/tls.c new file mode 100644 index 00000000..f92f480c --- /dev/null +++ b/sys/tls.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static size_t tlsSize; +static size_t tdataSz; +static size_t tlsAlign; +/* NOTE: Provided by linker. Can't use info from header as data can be detached from code. */ +extern char __tdata_start; + + +int __tls_alloc(struct tls_tcb **tcbp) +{ + *tcbp = NULL; + + if (tlsSize == 0) { + return 0; + } + + void *ptr = calloc(1, sizeof(struct tls_tcb) + tlsSize + tlsAlign); + if (ptr == NULL) { + return -1; + } + + struct tls_tcb *tcb; + +#ifdef __LIBPHOENIX_ARCH_TLS_VARIANT_I + tcb = (struct tls_tcb *)ptr; + ptr += sizeof(struct tls_tcb); +#elif defined(__LIBPHOENIX_ARCH_TLS_VARIANT_II) + tcb = (struct tls_tcb *)(ptr + tlsSize + tlsAlign); + tcb->tcb_self = tcb; + ptr = (uint8_t *)tcb - tlsSize; +#endif + + memcpy(ptr, &__tdata_start, tdataSz); + + *tcbp = tcb; + + return 0; +} + + +void __tls_release(void) +{ + if (tlsSize == 0) { + return; + } + + void *tcb = (void *)__tls_getTcb(); + assert(tcb != NULL); /* If size != 0 tcb cannot be NULL */ + +#ifdef __LIBPHOENIX_ARCH_TLS_VARIANT_I + free(tcb); +#elif defined(__LIBPHOENIX_ARCH_TLS_VARIANT_II) + free(tcb - tlsSize - tlsAlign); +#endif +} + + +void _tls_init(void) +{ + uint64_t phdrV = getauxval(AT_PHDR); + uint64_t phnum = getauxval(AT_PHNUM); + + if ((phdrV == 0) || (phnum == 0)) { + /* Assume no TLS. */ + return; + } + + const Elf_Phdr *phdr = (const Elf_Phdr *)(unsigned long)phdrV; + + for (uint64_t i = 0; i < phnum; i++) { + if (phdr[i].p_type == PT_INTERP) { + /* Dynamic linker takes care of TLS init. */ + return; + } + if (phdr[i].p_type == PT_TLS) { + Elf_Off misalign = phdr[i].p_offset & (phdr[i].p_align - 1); + + tdataSz = phdr[i].p_filesz; + tlsSize = phdr[i].p_memsz + misalign; +#ifdef __LIBPHOENIX_ARCH_TLS_VARIANT_II + /* Members of tls_tcb have to be aligned. */ + tlsAlign = (sizeof(void *) - (tlsSize & (sizeof(void *) - 1))) & (sizeof(void *) - 1); +#endif + break; + } + } + + if (tlsSize == 0) { + return; + } + + __tls_archInit(); + + struct tls_tcb *tcb; + + if (__tls_alloc(&tcb) != 0) { + _exit(126); + } + + tlsSetPtr(__tls_tcbPtrToTlsPtr(tcb)); +}