2023-10-08 10:24:48 +08:00

119 lines
3.7 KiB
C++

#pragma once
#if IL2CPP_THREADS_PTHREAD
#include "os/ErrorCodes.h"
#include "utils/NonCopyable.h"
#include <pthread.h>
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