From 7e9bce2d25ce84fe737b2a711d8160bb250ba769 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Thu, 15 Dec 2016 14:26:48 -0800 Subject: [PATCH] Switch GCSample to the canonical GCToOSInterface implementation (#8653) --- src/gc/gcenv.unix.cpp | 2 - src/gc/gcenv.windows.cpp | 6 +- src/gc/sample/CMakeLists.txt | 4 +- src/gc/sample/GCSample.vcxproj | 7 +- src/gc/sample/GCSample.vcxproj.filters | 2 +- src/gc/sample/gcenv.ee.cpp | 6 + src/gc/sample/gcenv.unix.cpp | 14 - src/gc/sample/gcenv.windows.cpp | 453 ------------------------- 8 files changed, 14 insertions(+), 480 deletions(-) delete mode 100644 src/gc/sample/gcenv.unix.cpp delete mode 100644 src/gc/sample/gcenv.windows.cpp diff --git a/src/gc/gcenv.unix.cpp b/src/gc/gcenv.unix.cpp index 8263ded173c8..0235952e28ea 100644 --- a/src/gc/gcenv.unix.cpp +++ b/src/gc/gcenv.unix.cpp @@ -6,8 +6,6 @@ #include "env/gcenv.base.h" #include "env/gcenv.os.h" -#error This file should not be compiled! - // Initialize the interface implementation // Return: // true if it has succeeded, false if it has failed diff --git a/src/gc/gcenv.windows.cpp b/src/gc/gcenv.windows.cpp index 33776550f954..a636478245d5 100644 --- a/src/gc/gcenv.windows.cpp +++ b/src/gc/gcenv.windows.cpp @@ -12,10 +12,6 @@ #include "env/gcenv.base.h" #include "env/gcenv.os.h" -#ifndef FEATURE_STANDALONE_GC -#error This file should only be compiled for a standalone GC -#endif // FEATURE_STANDALONE_GC - GCSystemInfo g_SystemInfo; typedef BOOL (WINAPI *PGET_PROCESS_MEMORY_INFO)(HANDLE handle, PROCESS_MEMORY_COUNTERS* memCounters, uint32_t cb); @@ -422,7 +418,7 @@ size_t GCToOSInterface::GetVirtualMemoryLimit() MEMORYSTATUSEX memStatus; if (::GlobalMemoryStatusEx(&memStatus)) { - return memStatus.ullAvailVirtual; + return (size_t)memStatus.ullAvailVirtual; } return 0; diff --git a/src/gc/sample/CMakeLists.txt b/src/gc/sample/CMakeLists.txt index 572fba371f51..9552cc51e2eb 100644 --- a/src/gc/sample/CMakeLists.txt +++ b/src/gc/sample/CMakeLists.txt @@ -22,11 +22,11 @@ set(SOURCES if(WIN32) list(APPEND SOURCES - gcenv.windows.cpp) + ../gcenv.windows.cpp) add_definitions(-DUNICODE=1) else() list(APPEND SOURCES - gcenv.unix.cpp) + ../gcenv.unix.cpp) endif() _add_executable(gcsample diff --git a/src/gc/sample/GCSample.vcxproj b/src/gc/sample/GCSample.vcxproj index b196e1f34c37..1716f462ee89 100644 --- a/src/gc/sample/GCSample.vcxproj +++ b/src/gc/sample/GCSample.vcxproj @@ -84,10 +84,12 @@ - + + NotUsing + @@ -96,8 +98,7 @@ - Create - Create + Create diff --git a/src/gc/sample/GCSample.vcxproj.filters b/src/gc/sample/GCSample.vcxproj.filters index e46c05456540..f6aacfd0c726 100644 --- a/src/gc/sample/GCSample.vcxproj.filters +++ b/src/gc/sample/GCSample.vcxproj.filters @@ -59,7 +59,7 @@ Source Files - + Source Files diff --git a/src/gc/sample/gcenv.ee.cpp b/src/gc/sample/gcenv.ee.cpp index 51a735cbd147..ac227b48231f 100644 --- a/src/gc/sample/gcenv.ee.cpp +++ b/src/gc/sample/gcenv.ee.cpp @@ -9,6 +9,12 @@ #include "gcenv.h" #include "gc.h" +MethodTable * g_pFreeObjectMethodTable; + +int32_t g_TrapReturningThreads; + +bool g_fFinalizerRunOnShutDown; + EEConfig * g_pConfig; bool CLREventStatic::CreateManualEventNoThrow(bool bInitialState) diff --git a/src/gc/sample/gcenv.unix.cpp b/src/gc/sample/gcenv.unix.cpp deleted file mode 100644 index a5e9e83ee2e7..000000000000 --- a/src/gc/sample/gcenv.unix.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -// -// Implementation of the GC environment -// - -#include "common.h" - -#include "gcenv.h" -#include "gc.h" - -// TODO: Implement diff --git a/src/gc/sample/gcenv.windows.cpp b/src/gc/sample/gcenv.windows.cpp deleted file mode 100644 index a14019df7cd5..000000000000 --- a/src/gc/sample/gcenv.windows.cpp +++ /dev/null @@ -1,453 +0,0 @@ -// 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. - -// -// Implementation of the GC environment -// - -#include "common.h" - -#include "windows.h" - -#include "gcenv.h" -#include "gc.h" - -MethodTable * g_pFreeObjectMethodTable; - -int32_t g_TrapReturningThreads; - -bool g_fFinalizerRunOnShutDown; - -GCSystemInfo g_SystemInfo; - -static LARGE_INTEGER g_performanceFrequency; - -// Initialize the interface implementation -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::Initialize() -{ - if (!::QueryPerformanceFrequency(&g_performanceFrequency)) - { - return false; - } - - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - - g_SystemInfo.dwNumberOfProcessors = systemInfo.dwNumberOfProcessors; - g_SystemInfo.dwPageSize = systemInfo.dwPageSize; - g_SystemInfo.dwAllocationGranularity = systemInfo.dwAllocationGranularity; - - return true; -} - -// Shutdown the interface implementation -void GCToOSInterface::Shutdown() -{ -} - -// Get numeric id of the current thread if possible on the -// current platform. It is indended for logging purposes only. -// Return: -// Numeric id of the current thread or 0 if the -uint64_t GCToOSInterface::GetCurrentThreadIdForLogging() -{ - return ::GetCurrentThreadId(); -} - -// Get id of the process -// Return: -// Id of the current process -uint32_t GCToOSInterface::GetCurrentProcessId() -{ - return ::GetCurrentProcessId(); -} - -// Set ideal affinity for the current thread -// Parameters: -// affinity - ideal processor affinity for the thread -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity) -{ - bool success = true; - -#if !defined(FEATURE_CORESYSTEM) - SetThreadIdealProcessor(GetCurrentThread(), (DWORD)affinity->Processor); -#else - PROCESSOR_NUMBER proc; - - if (affinity->Group != -1) - { - proc.Group = (WORD)affinity->Group; - proc.Number = (BYTE)affinity->Processor; - proc.Reserved = 0; - - success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); - } - else - { - if (GetThreadIdealProcessorEx(GetCurrentThread(), &proc)) - { - proc.Number = affinity->Processor; - success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); - } - } -#endif - - return success; -} - -// Get the number of the current processor -uint32_t GCToOSInterface::GetCurrentProcessorNumber() -{ - _ASSERTE(GCToOSInterface::CanGetCurrentProcessorNumber()); - return ::GetCurrentProcessorNumber(); -} - -// Check if the OS supports getting current processor number -bool GCToOSInterface::CanGetCurrentProcessorNumber() -{ - return true; -} - -// Flush write buffers of processors that are executing threads of the current process -void GCToOSInterface::FlushProcessWriteBuffers() -{ - ::FlushProcessWriteBuffers(); -} - -// Break into a debugger -void GCToOSInterface::DebugBreak() -{ - ::DebugBreak(); -} - -// Get number of logical processors -uint32_t GCToOSInterface::GetLogicalCpuCount() -{ - return g_SystemInfo.dwNumberOfProcessors; -} - -// Causes the calling thread to sleep for the specified number of milliseconds -// Parameters: -// sleepMSec - time to sleep before switching to another thread -void GCToOSInterface::Sleep(uint32_t sleepMSec) -{ - ::Sleep(sleepMSec); -} - -// Causes the calling thread to yield execution to another thread that is ready to run on the current processor. -// Parameters: -// switchCount - number of times the YieldThread was called in a loop -void GCToOSInterface::YieldThread(uint32_t switchCount) -{ - SwitchToThread(); -} - -// Reserve virtual memory range. -// Parameters: -// address - starting virtual address, it can be NULL to let the function choose the starting address -// size - size of the virtual memory range -// alignment - requested memory alignment -// flags - flags to control special settings like write watching -// Return: -// Starting virtual address of the reserved range -void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags) -{ - DWORD memFlags = (flags & VirtualReserveFlags::WriteWatch) ? (MEM_RESERVE | MEM_WRITE_WATCH) : MEM_RESERVE; - return ::VirtualAlloc(0, size, memFlags, PAGE_READWRITE); -} - -// Release virtual memory range previously reserved using VirtualReserve -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualRelease(void* address, size_t size) -{ - UNREFERENCED_PARAMETER(size); - return !!::VirtualFree(address, 0, MEM_RELEASE); -} - -// Commit virtual memory range. It must be part of a range reserved using VirtualReserve. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualCommit(void* address, size_t size) -{ - return ::VirtualAlloc(address, size, MEM_COMMIT, PAGE_READWRITE) != NULL; -} - -// Decomit virtual memory range. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualDecommit(void* address, size_t size) -{ - return !!::VirtualFree(address, size, MEM_DECOMMIT); -} - -// Reset virtual memory range. Indicates that data in the memory range specified by address and size is no -// longer of interest, but it should not be decommitted. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -// unlock - true if the memory range should also be unlocked -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) -{ - bool success = ::VirtualAlloc(address, size, MEM_RESET, PAGE_READWRITE) != NULL; - if (success && unlock) - { - // Remove the page range from the working set - ::VirtualUnlock(address, size); - } - - return success; -} - -// Check if the OS supports write watching -bool GCToOSInterface::SupportsWriteWatch() -{ - return false; -} - -// Reset the write tracking state for the specified virtual memory range. -// Parameters: -// address - starting virtual address -// size - size of the virtual memory range -void GCToOSInterface::ResetWriteWatch(void* address, size_t size) -{ -} - -// Retrieve addresses of the pages that are written to in a region of virtual memory -// Parameters: -// resetState - true indicates to reset the write tracking state -// address - starting virtual address -// size - size of the virtual memory range -// pageAddresses - buffer that receives an array of page addresses in the memory region -// pageAddressesCount - on input, size of the lpAddresses array, in array elements -// on output, the number of page addresses that are returned in the array. -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, void** pageAddresses, uintptr_t* pageAddressesCount) -{ - return false; -} - -// Get size of the largest cache on the processor die -// Parameters: -// trueSize - true to return true cache size, false to return scaled up size based on -// the processor architecture -// Return: -// Size of the cache -size_t GCToOSInterface::GetLargestOnDieCacheSize(bool trueSize) -{ - // TODO: implement - return 0; -} - -// Get affinity mask of the current process -// Parameters: -// processMask - affinity mask for the specified process -// systemMask - affinity mask for the system -// Return: -// true if it has succeeded, false if it has failed -// Remarks: -// A process affinity mask is a bit vector in which each bit represents the processors that -// a process is allowed to run on. A system affinity mask is a bit vector in which each bit -// represents the processors that are configured into a system. -// A process affinity mask is a subset of the system affinity mask. A process is only allowed -// to run on the processors configured into a system. Therefore, the process affinity mask cannot -// specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor. -bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processMask, uintptr_t* systemMask) -{ - return false; -} - -// Get number of processors assigned to the current process -// Return: -// The number of processors -uint32_t GCToOSInterface::GetCurrentProcessCpuCount() -{ - return g_SystemInfo.dwNumberOfProcessors; -} - -// Return the size of the user-mode portion of the virtual address space of this process. -// Return: -// non zero if it has succeeded, 0 if it has failed -size_t GCToOSInterface::GetVirtualMemoryLimit() -{ - MEMORYSTATUSEX memStatus; - - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - BOOL fRet = GlobalMemoryStatusEx(&memStatus); - _ASSERTE(fRet); - - return (size_t)memStatus.ullTotalVirtual; -} - -// Get the physical memory that this process can use. -// Return: -// non zero if it has succeeded, 0 if it has failed -uint64_t GCToOSInterface::GetPhysicalMemoryLimit() -{ - MEMORYSTATUSEX memStatus; - - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - BOOL fRet = GlobalMemoryStatusEx(&memStatus); - _ASSERTE(fRet); - - return memStatus.ullTotalPhys; -} - -// Get memory status -// Parameters: -// memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory -// that is in use (0 indicates no memory use and 100 indicates full memory use). -// available_physical - The amount of physical memory currently available, in bytes. -// available_page_file - The maximum amount of memory the current process can commit, in bytes. -void GCToOSInterface::GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) -{ - MEMORYSTATUSEX memStatus; - - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - BOOL fRet = GlobalMemoryStatusEx(&memStatus); - _ASSERTE (fRet); - - // If the machine has more RAM than virtual address limit, let us cap it. - // The GC can never use more than virtual address limit. - if (memStatus.ullAvailPhys > memStatus.ullTotalVirtual) - { - memStatus.ullAvailPhys = memStatus.ullAvailVirtual; - } - - if (memory_load != NULL) - *memory_load = memStatus.dwMemoryLoad; - if (available_physical != NULL) - *available_physical = memStatus.ullAvailPhys; - if (available_page_file != NULL) - *available_page_file = memStatus.ullAvailPageFile; -} - -// Get a high precision performance counter -// Return: -// The counter value -int64_t GCToOSInterface::QueryPerformanceCounter() -{ - LARGE_INTEGER ts; - if (!::QueryPerformanceCounter(&ts)) - { - _ASSERTE(!"Fatal Error - cannot query performance counter."); - abort(); - } - - return ts.QuadPart; -} - -// Get a frequency of the high precision performance counter -// Return: -// The counter frequency -int64_t GCToOSInterface::QueryPerformanceFrequency() -{ - return g_performanceFrequency.QuadPart; -} - -// Get a time stamp with a low precision -// Return: -// Time stamp in milliseconds -uint32_t GCToOSInterface::GetLowPrecisionTimeStamp() -{ - return ::GetTickCount(); -} - -// Parameters of the GC thread stub -struct GCThreadStubParam -{ - GCThreadFunction GCThreadFunction; - void* GCThreadParam; -}; - -// GC thread stub to convert GC thread function to an OS specific thread function -static DWORD __stdcall GCThreadStub(void* param) -{ - GCThreadStubParam *stubParam = (GCThreadStubParam*)param; - GCThreadFunction function = stubParam->GCThreadFunction; - void* threadParam = stubParam->GCThreadParam; - - delete stubParam; - - function(threadParam); - - return 0; -} - -// Create a new thread -// Parameters: -// function - the function to be executed by the thread -// param - parameters of the thread -// affinity - processor affinity of the thread -// Return: -// true if it has succeeded, false if it has failed -bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity) -{ - DWORD thread_id; - - GCThreadStubParam* stubParam = new (nothrow) GCThreadStubParam(); - if (stubParam == NULL) - { - return false; - } - - stubParam->GCThreadFunction = function; - stubParam->GCThreadParam = param; - - HANDLE gc_thread = ::CreateThread(NULL, 0, GCThreadStub, stubParam, CREATE_SUSPENDED, &thread_id); - - if (!gc_thread) - { - delete stubParam; - return false; - } - - SetThreadPriority(gc_thread, /* THREAD_PRIORITY_ABOVE_NORMAL );*/ THREAD_PRIORITY_HIGHEST ); - - ResumeThread(gc_thread); - - CloseHandle(gc_thread); - - return true; -} - -// Initialize the critical section -void CLRCriticalSection::Initialize() -{ - ::InitializeCriticalSection(&m_cs); -} - -// Destroy the critical section -void CLRCriticalSection::Destroy() -{ - ::DeleteCriticalSection(&m_cs); -} - -// Enter the critical section. Blocks until the section can be entered. -void CLRCriticalSection::Enter() -{ - ::EnterCriticalSection(&m_cs); -} - -// Leave the critical section -void CLRCriticalSection::Leave() -{ - ::LeaveCriticalSection(&m_cs); -}