ThreadLocalValueImpl.h
3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#pragma once
#if IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
#include "os/ErrorCodes.h"
#include "utils/NonCopyable.h"
#include <pthread.h>
#define _unused(x) ((void)x)
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);
_unused(result);
m_Key = key;
}
inline ~ThreadLocalValueImpl()
{
IL2CPP_ASSERT(!pthread_key_delete(m_Key));
}
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