#pragma once #include "types.h" #include "arm/tls.h" #include "kernel/thread.h" #define THREADVARS_MAGIC 0x21545624 // !TV$ // This structure is exactly 0x20 bytes typedef struct { // Magic value used to check if the struct is initialized u32 magic; // Thread handle, for mutexes Handle handle; // Pointer to the current thread (if exists) Thread* thread_ptr; // Pointer to this thread's newlib state struct _reent* reent; // Pointer to this thread's thread-local segment void* tls_tp; // !! Offset needs to be TLS+0x1F8 for __aarch64_read_tp !! } ThreadVars; extern const u8 __tdata_lma[]; extern const u8 __tdata_lma_end[]; extern u8 __tls_start[]; extern u8 __tls_end[]; extern size_t __tls_align; static inline ThreadVars* getThreadVars(void) { return (ThreadVars*)((u8*)armGetTls() + 0x200 - sizeof(ThreadVars)); } NX_INLINE size_t getTlsStartOffset(void) { // TLS region begins with the Thread Control Block (TCB), which is intended // to contain two pointers. The actual tdata/tbss segment follows the TCB, // however if it requires special alignment the offset is rounded up. size_t tcb_sz = 2*sizeof(void*); return __tls_align > tcb_sz ? __tls_align : tcb_sz; }