// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // ==++== // // // // // ==--== #include "stdafx.h" #include "mscoree.h" #include "clrinternal.h" #include "hostimpl.h" #include "predeftlsslot.h" #include "unsafe.h" // to avoid to include clrhost.h in this file #ifdef FAILPOINTS_ENABLED extern int RFS_HashStack(); #endif static DWORD TlsIndex = TLS_OUT_OF_INDEXES; static PTLS_CALLBACK_FUNCTION Callbacks[MAX_PREDEFINED_TLS_SLOT]; #ifdef SELF_NO_HOST HANDLE (*g_fnGetExecutableHeapHandle)(); #endif extern LPVOID* (*__ClrFlsGetBlock)(); // // FLS getter to avoid unnecessary indirection via execution engine. // LPVOID* ClrFlsGetBlockDirect() { return (LPVOID*)UnsafeTlsGetValue(TlsIndex); } // // utility functions for tls functionality // static void **CheckThreadState(DWORD slot, BOOL force = TRUE) { // Treat as a runtime assertion, since the invariant spans many DLLs. _ASSERTE(slot < MAX_PREDEFINED_TLS_SLOT); // Ensure we have a TLS Index if (TlsIndex == TLS_OUT_OF_INDEXES) { DWORD tmp = UnsafeTlsAlloc(); if (InterlockedCompareExchange((LONG*)&TlsIndex, tmp, TLS_OUT_OF_INDEXES) != (LONG) TLS_OUT_OF_INDEXES) { // We lost the race with another thread. UnsafeTlsFree(tmp); } // Switch to faster TLS getter now that the TLS slot is initialized __ClrFlsGetBlock = ClrFlsGetBlockDirect; } _ASSERTE(TlsIndex != TLS_OUT_OF_INDEXES); void **pTlsData = (void **)TlsGetValue(TlsIndex); if (pTlsData == 0 && force) { // !!! Contract uses our TLS support. Contract may be used before our host support is set up. // !!! To better support contract, we call into OS for memory allocation. pTlsData = (void**) ::HeapAlloc(GetProcessHeap(),0,MAX_PREDEFINED_TLS_SLOT*sizeof(void*)); if (pTlsData == NULL) { // workaround! We don't want exceptions being thrown during ClrInitDebugState. Just return NULL out of TlsSetValue. // ClrInitDebugState will do a confirming FlsGet to see if the value stuck. // If this is for the stack probe, and we failed to allocate memory for it, we won't // put in a guard page. if (slot == TlsIdx_ClrDebugState || slot == TlsIdx_StackProbe) { return NULL; } RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); } for (int i=0; i(ppvException); *ppException = NULL; } // UtilExecutionEngine::GetLastThrownObjectExceptionFromThread