diff options
Diffstat (limited to 'src/utilcode/util.cpp')
-rw-r--r-- | src/utilcode/util.cpp | 246 |
1 files changed, 26 insertions, 220 deletions
diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp index 33722e5297..c215a49213 100644 --- a/src/utilcode/util.cpp +++ b/src/utilcode/util.cpp @@ -19,9 +19,6 @@ #include "cor.h" #include "corinfo.h" -#ifndef FEATURE_CORECLR -#include "metahost.h" -#endif // !FEATURE_CORECLR const char g_RTMVersion[]= "v1.0.3705"; @@ -882,6 +879,27 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, #endif } +#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL) +// Calculate greatest common divisor +DWORD GCD(DWORD u, DWORD v) +{ + while (v != 0) + { + DWORD dwTemp = v; + v = u % v; + u = dwTemp; + } + + return u; +} + +// Calculate least common multiple +DWORD LCM(DWORD u, DWORD v) +{ + return u / GCD(u, v) * v; +} +#endif + /*static*/ BOOL CPUGroupInfo::InitCPUGroupInfoArray() { CONTRACTL @@ -943,11 +961,13 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, m_CPUGroupInfoArray[i].nr_active = (WORD)pRecord->Group.GroupInfo[i].ActiveProcessorCount; m_CPUGroupInfoArray[i].active_mask = pRecord->Group.GroupInfo[i].ActiveProcessorMask; m_nProcessors += m_CPUGroupInfoArray[i].nr_active; - dwWeight *= (DWORD)m_CPUGroupInfoArray[i].nr_active; + dwWeight = LCM(dwWeight, (DWORD)m_CPUGroupInfoArray[i].nr_active); } - //NOTE: the weight setting should work fine with 4 CPU groups upto 64 LPs each. the minimum number of threads - // per group before the weight overflow is 2^32/(2^6x2^6x2^6) = 2^14 (i.e. 16K threads) + // The number of threads per group that can be supported will depend on the number of CPU groups + // and the number of LPs within each processor group. For example, when the number of LPs in + // CPU groups is the same and is 64, the number of threads per group before weight overflow + // would be 2^32/2^6 = 2^26 (64M threads) for (DWORD i = 0; i < m_nGroups; i++) { m_CPUGroupInfoArray[i].groupWeight = dwWeight / (DWORD)m_CPUGroupInfoArray[i].nr_active; @@ -3322,114 +3342,6 @@ BOOL FileExists(LPCWSTR filename) return TRUE; } -#ifndef FEATURE_CORECLR -// Current users for FileLock are ngen and ngen service - -FileLockHolder::FileLockHolder() -{ - _hLock = INVALID_HANDLE_VALUE; -} - -FileLockHolder::~FileLockHolder() -{ - Release(); -} - -// the amount of time we want to wait -#define FILE_LOCK_RETRY_TIME 100 - -void FileLockHolder::Acquire(LPCWSTR lockName, HANDLE hInterrupt, BOOL* pInterrupted) -{ - WRAPPER_NO_CONTRACT; - - DWORD dwErr = 0; - DWORD dwAccessDeniedRetry = 0; - const DWORD MAX_ACCESS_DENIED_RETRIES = 10; - - if (pInterrupted) - { - *pInterrupted = FALSE; - } - - _ASSERTE(_hLock == INVALID_HANDLE_VALUE); - - for (;;) { - _hLock = WszCreateFile(lockName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); - if (_hLock != INVALID_HANDLE_VALUE) { - return; - } - - dwErr = GetLastError(); - // Logically we should only expect ERROR_SHARING_VIOLATION, but Windows can also return - // ERROR_ACCESS_DENIED for underlying NtStatus DELETE_PENDING. That happens when another process - // (gacutil.exe or indexer) have the file opened. Unfortunately there is no public API that would - // allow us to detect this NtStatus and distinguish it from 'real' access denied (candidates are - // RtlGetLastNtStatus that is not documented on MSDN and NtCreateFile that is internal and can change - // at any time), so we retry on access denied, but only for a limited number of times. - if (dwErr == ERROR_SHARING_VIOLATION || - (dwErr == ERROR_ACCESS_DENIED && ++dwAccessDeniedRetry <= MAX_ACCESS_DENIED_RETRIES)) - { - // Somebody is holding the lock. Let's sleep, and come back again. - if (hInterrupt) - { - _ASSERTE(pInterrupted && - "If you can be interrupted, you better want to know if you actually were interrupted"); - if (WaitForSingleObject(hInterrupt, FILE_LOCK_RETRY_TIME) == WAIT_OBJECT_0) - { - if (pInterrupted) - { - *pInterrupted = TRUE; - } - - // We've been interrupted, so return without acquiring - return; - } - } - else - { - ClrSleepEx(FILE_LOCK_RETRY_TIME, FALSE); - } - } - else { - ThrowHR(HRESULT_FROM_WIN32(dwErr)); - } - } -} - - -HRESULT FileLockHolder::AcquireNoThrow(LPCWSTR lockName, HANDLE hInterrupt, BOOL* pInterrupted) -{ - HRESULT hr = S_OK; - - EX_TRY - { - Acquire(lockName, hInterrupt, pInterrupted); - } - EX_CATCH_HRESULT(hr); - - return hr; -} - -BOOL FileLockHolder::IsTaken(LPCWSTR lockName) -{ - - // We don't want to do an acquire the lock to know if its taken, so we want to see if the file - // exists. However, in situations like unplugging a machine, a DELETE_ON_CLOSE still leaves the file - // around. We try to delete it here. If the lock is acquired, DeleteFile will fail, as the file is - // not opened with SHARE_DELETE. - WszDeleteFile(lockName); - - return FileExists(lockName); -} - -void FileLockHolder::Release() -{ - if (_hLock != INVALID_HANDLE_VALUE) { - CloseHandle(_hLock); - _hLock = INVALID_HANDLE_VALUE; - } -} -#endif // FEATURE_CORECLR //====================================================================== // This function returns true, if it can determine that the instruction pointer @@ -3587,59 +3499,6 @@ RUNTIMEVERSIONINFO RUNTIMEVERSIONINFO::notDefined; BOOL IsV2RuntimeLoaded(void) { -#ifndef FEATURE_CORECLR - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - ReleaseHolder<ICLRMetaHost> pMetaHost(NULL); - ReleaseHolder<IEnumUnknown> pEnum(NULL); - ReleaseHolder<IUnknown> pUnk(NULL); - ReleaseHolder<ICLRRuntimeInfo> pRuntime(NULL); - HRESULT hr; - - HModuleHolder hModule = WszLoadLibrary(MSCOREE_SHIM_W); - if (hModule == NULL) - return FALSE; - - CLRCreateInstanceFnPtr pfnCLRCreateInstance = (CLRCreateInstanceFnPtr)::GetProcAddress(hModule, "CLRCreateInstance"); - if (pfnCLRCreateInstance == NULL) - return FALSE; - - hr = (*pfnCLRCreateInstance)(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID *)&pMetaHost); - if (FAILED(hr)) - return FALSE; - - hr = pMetaHost->EnumerateLoadedRuntimes(GetCurrentProcess(), &pEnum); - if (FAILED(hr)) - return FALSE; - - while (pEnum->Next(1, &pUnk, NULL) == S_OK) - { - hr = pUnk->QueryInterface(IID_ICLRRuntimeInfo, (void **)&pRuntime); - if (FAILED(hr)) - continue; - - WCHAR wszVersion[30]; - DWORD cchVersion = _countof(wszVersion); - hr = pRuntime->GetVersionString(wszVersion, &cchVersion); - if (FAILED(hr)) - continue; - - // Is it a V2 runtime? - if ((cchVersion < 3) || - ((wszVersion[0] != W('v')) && (wszVersion[0] != W('V'))) || - (wszVersion[1] != W('2')) || - (wszVersion[2] != W('.'))) - continue; - - return TRUE; - } -#endif // FEATURE_CORECLR return FALSE; } @@ -3650,11 +3509,6 @@ BOOL IsClrHostedLegacyComObject(REFCLSID rclsid) // let's simply check for all CLSIDs that are known to be runtime implemented and capped to 2.0 return ( rclsid == CLSID_ComCallUnmarshal || -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - rclsid == CLSID_CorRuntimeHost || - rclsid == CLSID_CLRRuntimeHost || - rclsid == CLSID_CLRProfiling || -#endif rclsid == CLSID_CorMetaDataDispenser || rclsid == CLSID_CorMetaDataDispenserRuntime || rclsid == CLSID_TypeNameFactory); @@ -3663,54 +3517,6 @@ BOOL IsClrHostedLegacyComObject(REFCLSID rclsid) -#if !defined(FEATURE_CORECLR) && !defined(SELF_NO_HOST) && !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) - -namespace UtilCode -{ - -#pragma warning(push) -#pragma warning(disable:4996) // For use of deprecated LoadLibraryShim - - // When a NULL version is passed to LoadLibraryShim, this told the shim to bind the already-loaded - // runtime or to the latest runtime. In hosted environments, we already know a runtime (or two) is - // loaded, and since we are no longer guaranteed that a call to mscoree!LoadLibraryShim with a NULL - // version will return the correct runtime, this code uses the ClrCallbacks infrastructure - // available to get the ICLRRuntimeInfo for the runtime in which this code is hosted, and then - // calls ICLRRuntimeInfo::LoadLibrary to make sure that the load occurs within the context of the - // correct runtime. - HRESULT LoadLibraryShim(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll) - { - HRESULT hr = S_OK; - - if (szVersion != NULL) - { // If a version is provided, then we just fall back to the legacy function to allow - // it to construct the explicit path and load from that location. - //@TODO: Can we verify that all callers of LoadLibraryShim in hosted environments always pass null and eliminate this code? - return ::LoadLibraryShim(szDllName, szVersion, pvReserved, phModDll); - } - - // - // szVersion is NULL, which means we should load the DLL from the hosted environment's directory. - // - - typedef ICLRRuntimeInfo *GetCLRRuntime_t(); - GetCLRRuntime_t *pfnGetCLRRuntime = - reinterpret_cast<GetCLRRuntime_t *>((*GetClrCallbacks().m_pfnGetCLRFunction)("GetCLRRuntime")); - if (pfnGetCLRRuntime == NULL) - return E_UNEXPECTED; - - ICLRRuntimeInfo* pRI = (*pfnGetCLRRuntime)(); - if (pRI == NULL) - return E_UNEXPECTED; - - return pRI->LoadLibrary(szDllName, phModDll); - } - -#pragma warning(pop) - -} - -#endif //!FEATURE_CORECLR && !SELF_NO_HOST && !FEATURE_UTILCODE_NO_DEPENDENCIES namespace Clr { |