#include "ThreadLocal.h"
#include "Common/Runtime.h"
#include "schedule.h"
#include "Base/Globals.h"
namespace MapleRuntime {
RwLock ThreadLocal::tlEnableLock;
MRT_EXPORT thread_local uint64_t threadLocalData[sizeof(ThreadLocalData) / sizeof(uint64_t)];
thread_local CleanThreadLocalData cleaner;
ThreadLocalData* ThreadLocal::GetThreadLocalData()
{
return reinterpret_cast<ThreadLocalData*>(threadLocalData);
}
void ThreadLocal::InitializeCleaner()
{
(void)cleaner;
}
CleanThreadLocalData::CleanThreadLocalData()
{
std::atomic_thread_fence(std::memory_order_seq_cst);
static volatile bool isInit = false;
if (!isInit) {
isInit = true;
}
}
CleanThreadLocalData::~CleanThreadLocalData()
{
if (!ThreadLocal::TryGetRdLock()) {
return;
}
ThreadLocalData* local = ThreadLocal::GetThreadLocalData();
if (Runtime::CurrentRef() == nullptr ||
local->isCJProcessor || local->foreignCJThread == nullptr) {
ThreadLocal::UnlockRdLock();
return;
}
CJForeignThreadExit(reinterpret_cast<CJThreadHandle>(local->foreignCJThread));
ThreadLocal::UnlockRdLock();
}
extern "C" void MCC_CheckThreadLocalDataOffset()
{
static_assert(offsetof(ThreadLocalData, buffer) == 0,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, mutator) == sizeof(void*),
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, cjthread) == sizeof(void*) * 2,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, schedule) == sizeof(void*) * 3,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, preemptFlag) == sizeof(void*) * 4,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, protectAddr) == sizeof(void*) * 5,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, safepointState) == sizeof(void*) * 6,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
#if defined(__arm__)
static_assert(offsetof(ThreadLocalData, tid) == sizeof(void*) * 6 + sizeof(uint64_t),
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, foreignCJThread) == sizeof(void*) * 6 + sizeof(uint64_t) * 2,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(sizeof(ThreadLocalData) == sizeof(void*) * 10 + sizeof(uint64_t) * 2,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
#else
static_assert(offsetof(ThreadLocalData, tid) == sizeof(void*) * 7,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(offsetof(ThreadLocalData, foreignCJThread) == sizeof(void*) * 8,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
static_assert(sizeof(ThreadLocalData) == sizeof(void*) * 11,
"need to modify the offset of this value in llvm-project and cjthread at the same time");
#endif
}
#ifdef __APPLE__
extern "C" MRT_EXPORT void MRT_CheckThreadLocalDataOffset();
__asm__(
".global _MRT_CheckThreadLocalDataOffset\n\t.set _MRT_CheckThreadLocalDataOffset, _MCC_CheckThreadLocalDataOffset");
extern "C" MRT_EXPORT void CJ_MCC_CheckThreadLocalDataOffset();
__asm__(
".global _CJ_MCC_CheckThreadLocalDataOffset\n\t.set _CJ_MCC_CheckThreadLocalDataOffset, "
"_MCC_CheckThreadLocalDataOffset");
#else
extern "C" MRT_EXPORT void MRT_CheckThreadLocalDataOffset() __attribute__((alias("MCC_CheckThreadLocalDataOffset")));
extern "C" MRT_EXPORT void CJ_MCC_CheckThreadLocalDataOffset() __attribute__((alias("MCC_CheckThreadLocalDataOffset")));
#endif
}