#pragma once #if IL2CPP_THREADS_PTHREAD #include "os/ErrorCodes.h" #include "utils/NonCopyable.h" #include namespace il2cpp { namespace os { class ThreadLocalValueImpl : public il2cpp::utils::NonCopyable { public: inline ThreadLocalValueImpl() { pthread_key_t key; int result = pthread_key_create(&key, NULL); IL2CPP_ASSERT(result == 0); NO_UNUSED_WARNING(result); m_Key = key; } inline ~ThreadLocalValueImpl() { int result = pthread_key_delete(m_Key); IL2CPP_ASSERT(result == 0); NO_UNUSED_WARNING(result); } inline ErrorCode SetValue(void* value) { #if IL2CPP_TARGET_DARWIN apple_pthread_setspecific_direct(m_Key, value); #else if (pthread_setspecific(m_Key, value)) return kErrorCodeGenFailure; #endif return kErrorCodeSuccess; } inline ErrorCode GetValue(void** value) { #if IL2CPP_TARGET_DARWIN *value = apple_pthread_getspecific_direct(m_Key); #else *value = pthread_getspecific(m_Key); #endif return kErrorCodeSuccess; } private: #if IL2CPP_TARGET_DARWIN static inline void * apple_pthread_getspecific_direct(unsigned long slot) { void *ret; #if defined(__i386__) || defined(__x86_64__) __asm__ ("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void**)(slot * sizeof(void *)))); #elif (defined(__arm__) && (defined(_ARM_ARCH_6) || defined(_ARM_ARCH_5))) void **__pthread_tsd; #if defined(__arm__) && defined(_ARM_ARCH_6) uintptr_t __pthread_tpid; __asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r" (__pthread_tpid)); __pthread_tsd = (void**)(__pthread_tpid & ~0x3ul); #elif defined(__arm__) && defined(_ARM_ARCH_5) register uintptr_t __pthread_tpid asm ("r9"); __pthread_tsd = (void**)__pthread_tpid; #endif ret = __pthread_tsd[slot]; #elif defined(__arm64__) ret = pthread_getspecific(slot); #else #error no _pthread_getspecific_direct implementation for this arch #endif return ret; } inline static void apple_pthread_setspecific_direct(unsigned long slot, void * val) { #if defined(__i386__) #if defined(__PIC__) __asm__ ("movl %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "rn" (val)); #else __asm__ ("movl %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "ri" (val)); #endif #elif defined(__x86_64__) /* PIC is free and cannot be disabled, even with: gcc -mdynamic-no-pic ... */ __asm__ ("movq %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "rn" (val)); #elif (defined(__arm__) && (defined(_ARM_ARCH_6) || defined(_ARM_ARCH_5))) void **__pthread_tsd; #if defined(__arm__) && defined(_ARM_ARCH_6) uintptr_t __pthread_tpid; __asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r" (__pthread_tpid)); __pthread_tsd = (void**)(__pthread_tpid & ~0x3ul); #elif defined(__arm__) && defined(_ARM_ARCH_5) register uintptr_t __pthread_tpid asm ("r9"); __pthread_tsd = (void**)__pthread_tpid; #endif __pthread_tsd[slot] = val; #elif defined(__arm64__) pthread_setspecific(slot, val); #else #error no _pthread_setspecific_direct implementation for this arch #endif } #endif pthread_key_t m_Key; }; } } #endif