2
0
Эх сурвалжийг харах

[MERGE #1916 @obastemur] Implement ThreadContextTLSEntry Win+Xplat separately

Merge pull request #1916 from obastemur:fix_break_full

ChakraDiag depends on the private TLS member of ThreadContextTLSEntry.
Previous implementation was fast for Win32 but affecting XPLAT.

This PR implements ThreadLocal for XPLAT only.
Oguz Bastemur 9 жил өмнө
parent
commit
855e3e26c8

+ 7 - 0
bin/ChakraCore/ChakraCoreDllFunc.cpp

@@ -39,6 +39,11 @@ static ATOM  lockedDll = 0;
 
 static BOOL AttachProcess(HANDLE hmod)
 {
+    if (!ThreadContextTLSEntry::InitializeProcess())
+    {
+         return FALSE;
+    }
+
     g_hInstance = hmod;
     AutoSystemInfo::SaveModuleFileName(hmod);
 
@@ -109,6 +114,7 @@ static void DetachProcess()
     // thread-bound entrypoint should be able to get cleanup correctly, however tlsentry
     // for current thread might be left behind if this thread was initialized.
     ThreadContextTLSEntry::CleanupThread();
+    ThreadContextTLSEntry::CleanupProcess();
 
 #if PROFILE_DICTIONARY
     DictionaryStats::OutputStats();
@@ -132,6 +138,7 @@ EXTERN_C BOOL WINAPI DllMain(HINSTANCE hmod, DWORD dwReason, PVOID pvReserved)
 // for non-Windows, we handle this part using the tooling from CHAKRA_STATIC_LIBRARY
 #ifdef _WIN32
     case DLL_THREAD_ATTACH:
+        ThreadContextTLSEntry::InitializeThread();
 #ifdef HEAP_TRACK_ALLOC
         HeapAllocator::InitializeThread();
 #endif

+ 78 - 14
lib/Runtime/Base/ThreadContextTlsEntry.cpp

@@ -5,22 +5,72 @@
 #include "RuntimeBasePch.h"
 #include "Base/ThreadContextTlsEntry.h"
 
-static THREAD_LOCAL ThreadContextTLSEntry* s_tlvSlot = nullptr;
+#ifdef _WIN32
+uint32 ThreadContextTLSEntry::s_tlsSlot = TLS_OUT_OF_INDEXES;
+#define ENTRY_FOR_CURRENT_THREAD() GetEntryForCurrentThread()
+#define ASSERT_ENTRY_INITIALIZED() Assert(s_tlsSlot != TLS_OUT_OF_INDEXES)
+#else // !_WIN32
+// entry doesn't need a special initialization
+#define ASSERT_ENTRY_INITIALIZED() Assert(true)
+static THREAD_LOCAL ThreadContextTLSEntry* s_tlsSlot = nullptr;
+#define TlsSetValue(a,b) a = b
+// clang may not optimize the access to THREAD_LOCAL from a sub function
+#define ENTRY_FOR_CURRENT_THREAD() s_tlsSlot
+#endif
+
+bool ThreadContextTLSEntry::InitializeProcess()
+{
+#ifdef _WIN32
+    Assert(s_tlsSlot == TLS_OUT_OF_INDEXES);
+    s_tlsSlot = TlsAlloc();
+    return (s_tlsSlot != TLS_OUT_OF_INDEXES);
+#else
+    return true;
+#endif
+}
 
-void ThreadContextTLSEntry::CleanupThread()
+void ThreadContextTLSEntry::CleanupProcess()
+{
+#ifdef _WIN32
+    Assert(s_tlsSlot != TLS_OUT_OF_INDEXES);
+    TlsFree(s_tlsSlot);
+    s_tlsSlot = TLS_OUT_OF_INDEXES;
+#endif
+}
+
+bool ThreadContextTLSEntry::IsProcessInitialized()
+{
+#ifdef _WIN32
+    return s_tlsSlot != TLS_OUT_OF_INDEXES;
+#else
+    return true;
+#endif
+}
+
+void ThreadContextTLSEntry::InitializeThread()
 {
-    ThreadContextTLSEntry * entry = s_tlvSlot;
+#ifdef _WIN32
+    Assert(s_tlsSlot != TLS_OUT_OF_INDEXES);
+    Assert(!TlsGetValue(s_tlsSlot));
+    TlsSetValue(s_tlsSlot, NULL);
+#endif
+}
 
-    if (entry != nullptr)
+void ThreadContextTLSEntry::CleanupThread()
+{
+    ASSERT_ENTRY_INITIALIZED();
+    ThreadContextTLSEntry* entry = ENTRY_FOR_CURRENT_THREAD();
+    if (entry != NULL)
     {
         HeapDelete(entry);
-        s_tlvSlot = nullptr;
+        TlsSetValue(s_tlsSlot, NULL);
     }
 }
 
 bool ThreadContextTLSEntry::TrySetThreadContext(ThreadContext * threadContext)
 {
     Assert(threadContext != NULL);
+    ASSERT_ENTRY_INITIALIZED();
 
     DWORD threadContextThreadId = threadContext->GetCurrentThreadId();
 
@@ -32,13 +82,15 @@ bool ThreadContextTLSEntry::TrySetThreadContext(ThreadContext * threadContext)
         return false;
     }
 
-    ThreadContextTLSEntry * entry = s_tlvSlot;
+    ThreadContextTLSEntry * entry = ENTRY_FOR_CURRENT_THREAD();
 
-    if (entry == nullptr)
+    if (entry == NULL)
     {
         Assert(!threadContext->IsThreadBound());
         entry = CreateEntryForCurrentThread();
-        s_tlvSlot = entry;
+#ifndef _WIN32
+        ENTRY_FOR_CURRENT_THREAD() = entry;
+#endif
     }
     else if (entry->threadContext != NULL && entry->threadContext != threadContext)
     {
@@ -67,12 +119,14 @@ void ThreadContextTLSEntry::SetThreadContext(ThreadContextTLSEntry * entry, Thre
 
 bool ThreadContextTLSEntry::ClearThreadContext(bool isValid)
 {
-    return ClearThreadContext(s_tlvSlot, isValid, false);
+    return ClearThreadContext(ENTRY_FOR_CURRENT_THREAD(), isValid, false);
 }
 
 bool ThreadContextTLSEntry::ClearThreadContext(ThreadContextTLSEntry * entry, bool isThreadContextValid, bool force)
 {
-    if (entry != nullptr)
+    ASSERT_ENTRY_INITIALIZED();
+
+    if (entry != NULL)
     {
         if (entry->threadContext != NULL && isThreadContextValid)
         {
@@ -100,15 +154,25 @@ void ThreadContextTLSEntry::Delete(ThreadContextTLSEntry * entry)
 
 ThreadContextTLSEntry * ThreadContextTLSEntry::GetEntryForCurrentThread()
 {
-    return s_tlvSlot;
+    ASSERT_ENTRY_INITIALIZED();
+#ifdef _WIN32
+    return reinterpret_cast<ThreadContextTLSEntry *>(TlsGetValue(s_tlsSlot));
+#else
+    return ENTRY_FOR_CURRENT_THREAD();
+#endif
 }
 
 ThreadContextTLSEntry * ThreadContextTLSEntry::CreateEntryForCurrentThread()
 {
+    ASSERT_ENTRY_INITIALIZED();
+#ifdef _WIN32
+    Assert(TlsGetValue(s_tlsSlot) == NULL);
+#endif
+
     ThreadContextTLSEntry * entry = HeapNewStructZ(ThreadContextTLSEntry);
 #pragma prefast(suppress:6001, "Memory from HeapNewStructZ are zero initialized")
     entry->prober.Initialize();
-    s_tlvSlot = entry;
+    TlsSetValue(s_tlsSlot, entry);
 
     return entry;
 }
@@ -120,8 +184,8 @@ ThreadContext * ThreadContextTLSEntry::GetThreadContext()
 
 ThreadContextId ThreadContextTLSEntry::GetCurrentThreadContextId()
 {
-    ThreadContextTLSEntry * entry = s_tlvSlot;
-    if (entry != nullptr && entry->GetThreadContext() != NULL)
+    ThreadContextTLSEntry * entry = ENTRY_FOR_CURRENT_THREAD();
+    if (entry != NULL && entry->GetThreadContext() != NULL)
     {
         return (ThreadContextId)entry->GetThreadContext();
     }

+ 7 - 1
lib/Runtime/Base/ThreadContextTlsEntry.h

@@ -7,6 +7,10 @@
 class ThreadContextTLSEntry
 {
 public:
+    static bool InitializeProcess();
+    static void CleanupProcess();
+    static bool IsProcessInitialized();
+    static void InitializeThread();
     static void CleanupThread();
     static void Delete(ThreadContextTLSEntry * entry);
     static bool TrySetThreadContext(ThreadContext * threadContext);
@@ -16,7 +20,9 @@ public:
     static ThreadContextTLSEntry * GetEntryForCurrentThread();
     static ThreadContextTLSEntry * CreateEntryForCurrentThread();
     static ThreadContextId GetThreadContextId(ThreadContext * threadContext);
-
+#ifdef _WIN32
+    static uint32 s_tlsSlot;
+#endif
     ThreadContext * GetThreadContext();
 
 private: