ThreadLocalValueImpl.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #pragma once
  2. #if IL2CPP_THREADS_PTHREAD
  3. #include "os/ErrorCodes.h"
  4. #include "utils/NonCopyable.h"
  5. #include <pthread.h>
  6. namespace il2cpp
  7. {
  8. namespace os
  9. {
  10. class ThreadLocalValueImpl : public il2cpp::utils::NonCopyable
  11. {
  12. public:
  13. inline ThreadLocalValueImpl()
  14. {
  15. pthread_key_t key;
  16. int result = pthread_key_create(&key, NULL);
  17. IL2CPP_ASSERT(result == 0);
  18. NO_UNUSED_WARNING(result);
  19. m_Key = key;
  20. }
  21. inline ~ThreadLocalValueImpl()
  22. {
  23. int result = pthread_key_delete(m_Key);
  24. IL2CPP_ASSERT(result == 0);
  25. NO_UNUSED_WARNING(result);
  26. }
  27. inline ErrorCode SetValue(void* value)
  28. {
  29. #if IL2CPP_TARGET_DARWIN
  30. apple_pthread_setspecific_direct(m_Key, value);
  31. #else
  32. if (pthread_setspecific(m_Key, value))
  33. return kErrorCodeGenFailure;
  34. #endif
  35. return kErrorCodeSuccess;
  36. }
  37. inline ErrorCode GetValue(void** value)
  38. {
  39. #if IL2CPP_TARGET_DARWIN
  40. *value = apple_pthread_getspecific_direct(m_Key);
  41. #else
  42. *value = pthread_getspecific(m_Key);
  43. #endif
  44. return kErrorCodeSuccess;
  45. }
  46. private:
  47. #if IL2CPP_TARGET_DARWIN
  48. static inline void * apple_pthread_getspecific_direct(unsigned long slot)
  49. {
  50. void *ret;
  51. #if defined(__i386__) || defined(__x86_64__)
  52. __asm__ ("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void**)(slot * sizeof(void *))));
  53. #elif (defined(__arm__) && (defined(_ARM_ARCH_6) || defined(_ARM_ARCH_5)))
  54. void **__pthread_tsd;
  55. #if defined(__arm__) && defined(_ARM_ARCH_6)
  56. uintptr_t __pthread_tpid;
  57. __asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r" (__pthread_tpid));
  58. __pthread_tsd = (void**)(__pthread_tpid & ~0x3ul);
  59. #elif defined(__arm__) && defined(_ARM_ARCH_5)
  60. register uintptr_t __pthread_tpid asm ("r9");
  61. __pthread_tsd = (void**)__pthread_tpid;
  62. #endif
  63. ret = __pthread_tsd[slot];
  64. #elif defined(__arm64__)
  65. ret = pthread_getspecific(slot);
  66. #else
  67. #error no _pthread_getspecific_direct implementation for this arch
  68. #endif
  69. return ret;
  70. }
  71. inline static void apple_pthread_setspecific_direct(unsigned long slot, void * val)
  72. {
  73. #if defined(__i386__)
  74. #if defined(__PIC__)
  75. __asm__ ("movl %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "rn" (val));
  76. #else
  77. __asm__ ("movl %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "ri" (val));
  78. #endif
  79. #elif defined(__x86_64__)
  80. /* PIC is free and cannot be disabled, even with: gcc -mdynamic-no-pic ... */
  81. __asm__ ("movq %1,%%gs:%0" : "=m" (*(void**)(slot * sizeof(void *))) : "rn" (val));
  82. #elif (defined(__arm__) && (defined(_ARM_ARCH_6) || defined(_ARM_ARCH_5)))
  83. void **__pthread_tsd;
  84. #if defined(__arm__) && defined(_ARM_ARCH_6)
  85. uintptr_t __pthread_tpid;
  86. __asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r" (__pthread_tpid));
  87. __pthread_tsd = (void**)(__pthread_tpid & ~0x3ul);
  88. #elif defined(__arm__) && defined(_ARM_ARCH_5)
  89. register uintptr_t __pthread_tpid asm ("r9");
  90. __pthread_tsd = (void**)__pthread_tpid;
  91. #endif
  92. __pthread_tsd[slot] = val;
  93. #elif defined(__arm64__)
  94. pthread_setspecific(slot, val);
  95. #else
  96. #error no _pthread_setspecific_direct implementation for this arch
  97. #endif
  98. }
  99. #endif
  100. pthread_key_t m_Key;
  101. };
  102. }
  103. }
  104. #endif