From 087e750df2a13801d0f144cdcfa6c1c3e16067c2 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 23 Jul 2016 07:23:21 -0700 Subject: [PATCH] GC update from CoreRT (#6429) https://github.com/dotnet/corert/tree/master/src/Native/gc 91d7a9c8e2b393314422b6106adedec683c0ae51 --- src/gc/env/gcenv.base.h | 23 +++ src/gc/gc.cpp | 36 ++-- src/gc/sample/gcenv.unix.cpp | 435 +------------------------------------------ 3 files changed, 41 insertions(+), 453 deletions(-) diff --git a/src/gc/env/gcenv.base.h b/src/gc/env/gcenv.base.h index 83726f4..97f1661 100644 --- a/src/gc/env/gcenv.base.h +++ b/src/gc/env/gcenv.base.h @@ -176,6 +176,12 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter); #endif // _MSC_VER +typedef struct _PROCESSOR_NUMBER { + uint16_t Group; + uint8_t Number; + uint8_t Reserved; +} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; + #endif // _INC_WINDOWS // ----------------------------------------------------------------------------------------------------------- @@ -600,4 +606,21 @@ public: }; #endif // STRESS_HEAP +class NumaNodeInfo +{ +public: + static bool CanEnableGCNumaAware(); + static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number); + static bool GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, uint16_t * node_no); +}; + +class CPUGroupInfo +{ +public: + static bool CanEnableGCCPUGroups(); + static uint32_t GetNumActiveProcessors(); + static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number); +}; + + #endif // __GCENV_BASE_INCLUDED__ diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index af2d1e7..3300421 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -2271,7 +2271,7 @@ SPTR_IMPL_NS(PTR_gc_heap, SVR, gc_heap, g_heaps); size_t* gc_heap::g_promoted; #ifdef MH_SC_MARK -BOOL* gc_heap::g_mark_stack_busy; +int* gc_heap::g_mark_stack_busy; #endif //MH_SC_MARK @@ -4921,7 +4921,7 @@ public: return TRUE; } - static void init_cpu_mapping(gc_heap *heap, int heap_number) + static void init_cpu_mapping(gc_heap * /*heap*/, int heap_number) { if (GCToOSInterface::CanGetCurrentProcessorNumber()) { @@ -4942,8 +4942,10 @@ public: sniff_buffer[(1 + heap_number*n_sniff_buffers + sniff_index)*HS_CACHE_LINE_SIZE] &= 1; } - static int select_heap(alloc_context* acontext, int hint) + static int select_heap(alloc_context* acontext, int /*hint*/) { + UNREFERENCED_PARAMETER(acontext); // only referenced by dprintf + if (GCToOSInterface::CanGetCurrentProcessorNumber()) return proc_no_to_heap_no[GCToOSInterface::GetCurrentProcessorNumber() % gc_heap::n_heaps]; @@ -5103,7 +5105,7 @@ void gc_heap::destroy_thread_support () } } -#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL) +#if !defined(FEATURE_PAL) void set_thread_group_affinity_for_heap(int heap_number, GCThreadAffinity* affinity) { affinity->Group = GCThreadAffinity::None; @@ -5183,7 +5185,7 @@ void set_thread_affinity_mask_for_heap(int heap_number, GCThreadAffinity* affini } } } -#endif // !FEATURE_REDHAWK && !FEATURE_CORECLR +#endif // !FEATURE_PAL bool gc_heap::create_gc_thread () { @@ -5193,7 +5195,7 @@ bool gc_heap::create_gc_thread () affinity.Group = GCThreadAffinity::None; affinity.Processor = GCThreadAffinity::None; -#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL) +#if !defined(FEATURE_PAL) if (!gc_thread_no_affinitize_p) { //We are about to set affinity for GC threads, it is a good place to setup NUMA and @@ -5204,7 +5206,7 @@ bool gc_heap::create_gc_thread () else set_thread_affinity_mask_for_heap(heap_number, &affinity); } -#endif // !FEATURE_REDHAWK && !FEATURE_PAL +#endif // !FEATURE_PAL return GCToOSInterface::CreateThread(gc_thread_stub, this, &affinity); } @@ -13179,7 +13181,7 @@ try_again: org_hp->alloc_context_count--; max_hp->alloc_context_count++; acontext->alloc_heap = GCHeap::GetHeap(max_hp->heap_number); -#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL) +#if !defined(FEATURE_PAL) if (CPUGroupInfo::CanEnableGCCPUGroups()) { //only set ideal processor when max_hp and org_hp are in the same cpu //group. DO NOT MOVE THREADS ACROSS CPU GROUPS @@ -13213,7 +13215,7 @@ try_again: org_hp->heap_number)); } } -#endif // !FEATURE_REDHAWK && !FEATURE_PAL +#endif // !FEATURE_PAL dprintf (3, ("Switching context %p (home heap %d) ", acontext, acontext->home_heap->pGenGCHeap->heap_number)); @@ -13232,7 +13234,7 @@ try_again: acontext->alloc_count++; } -gc_heap* gc_heap::balance_heaps_loh (alloc_context* acontext, size_t size) +gc_heap* gc_heap::balance_heaps_loh (alloc_context* acontext, size_t /*size*/) { gc_heap* org_hp = acontext->alloc_heap->pGenGCHeap; //dprintf (1, ("LA: %Id", size)); @@ -17762,8 +17764,8 @@ gc_heap::mark_steal() if (((size_t)o > 4) && !partial_object_p (o)) { //this is a normal object, not a partial mark tuple - //success = (FastInterlockCompareExchangePointer (&ref_mark_stack (hp, level), 0, o)==o); - success = (FastInterlockCompareExchangePointer (&ref_mark_stack (hp, level), 4, o)==o); + //success = (Interlocked::CompareExchangePointer (&ref_mark_stack (hp, level), 0, o)==o); + success = (Interlocked::CompareExchangePointer (&ref_mark_stack (hp, level), (uint8_t*)4, o)==o); #ifdef SNOOP_STATS snoop_stat.interlocked_count++; if (success) @@ -17798,7 +17800,7 @@ gc_heap::mark_steal() if (o && start) { //steal the object - success = (FastInterlockCompareExchangePointer (&ref_mark_stack (hp, level+1), stolen, next)==next); + success = (Interlocked::CompareExchangePointer (&ref_mark_stack (hp, level+1), (uint8_t*)stolen, next)==next); #ifdef SNOOP_STATS snoop_stat.interlocked_count++; if (success) @@ -23303,13 +23305,8 @@ uint8_t* tree_search (uint8_t* tree, uint8_t* old_address) #ifdef FEATURE_BASICFREEZE bool gc_heap::frozen_object_p (Object* obj) { -#ifdef MULTIPLE_HEAPS - ptrdiff_t delta = 0; - heap_segment* pSegment = segment_of ((uint8_t*)obj, delta); -#else //MULTIPLE_HEAPS heap_segment* pSegment = gc_heap::find_segment ((uint8_t*)obj, FALSE); _ASSERTE(pSegment); -#endif //MULTIPLE_HEAPS return heap_segment_read_only_p(pSegment); } @@ -23326,6 +23323,7 @@ void gc_heap::relocate_address (uint8_t** pold_address THREAD_NUMBER_DCL) if (!((old_address >= gc_low) && (old_address < gc_high))) #ifdef MULTIPLE_HEAPS { + UNREFERENCED_PARAMETER(thread); if (old_address == 0) return; gc_heap* hp = heap_of (old_address); @@ -35426,7 +35424,7 @@ int GCHeap::GetHomeHeapNumber () { if (pThread) { - GCHeap *hp = pThread->GetAllocContext()->home_heap; + GCHeap *hp = GCToEEInterface::GetAllocContext(pThread)->home_heap; if (hp == gc_heap::g_heaps[i]->vm_heap) return i; } } diff --git a/src/gc/sample/gcenv.unix.cpp b/src/gc/sample/gcenv.unix.cpp index c8663fb..a5e9e83 100644 --- a/src/gc/sample/gcenv.unix.cpp +++ b/src/gc/sample/gcenv.unix.cpp @@ -11,437 +11,4 @@ #include "gcenv.h" #include "gc.h" -#include -#include - -int32_t FastInterlockIncrement(int32_t volatile *lpAddend) -{ - return __sync_add_and_fetch(lpAddend, 1); -} - -int32_t FastInterlockDecrement(int32_t volatile *lpAddend) -{ - return __sync_sub_and_fetch(lpAddend, 1); -} - -int32_t FastInterlockExchange(int32_t volatile *Target, int32_t Value) -{ - return __sync_swap(Target, Value); -} - -int32_t FastInterlockCompareExchange(int32_t volatile *Destination, int32_t Exchange, int32_t Comparand) -{ - return __sync_val_compare_and_swap(Destination, Comparand, Exchange); -} - -int32_t FastInterlockExchangeAdd(int32_t volatile *Addend, int32_t Value) -{ - return __sync_fetch_and_add(Addend, Value); -} - -void * _FastInterlockExchangePointer(void * volatile *Target, void * Value) -{ - return __sync_swap(Target, Value); -} - -void * _FastInterlockCompareExchangePointer(void * volatile *Destination, void * Exchange, void * Comparand) -{ - return __sync_val_compare_and_swap(Destination, Comparand, Exchange); -} - -void FastInterlockOr(uint32_t volatile *p, uint32_t msk) -{ - __sync_fetch_and_or(p, msk); -} - -void FastInterlockAnd(uint32_t volatile *p, uint32_t msk) -{ - __sync_fetch_and_and(p, msk); -} - - -void UnsafeInitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection) -{ - pthread_mutex_init(&lpCriticalSection->mutex, NULL); -} - -void UnsafeEEEnterCriticalSection(CRITICAL_SECTION *lpCriticalSection) -{ - pthread_mutex_lock(&lpCriticalSection->mutex); -} - -void UnsafeEELeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection) -{ - pthread_mutex_unlock(&lpCriticalSection->mutex); -} - -void UnsafeDeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection) -{ - pthread_mutex_destroy(&lpCriticalSection->mutex); -} - -#if 0 -void CLREventStatic::CreateManualEvent(bool bInitialState) -{ - // TODO: Implement - m_fInitialized = true; -} - -void CLREventStatic::CreateAutoEvent(bool bInitialState) -{ - // TODO: Implement - m_fInitialized = true; -} - -void CLREventStatic::CreateOSManualEvent(bool bInitialState) -{ - CreateManualEvent(bInitialState); -} - -void CLREventStatic::CreateOSAutoEvent (bool bInitialState) -{ - CreateAutoEvent(bInitialState); -} - -void CLREventStatic::CloseEvent() -{ - if (m_fInitialized) - { - // TODO: Implement - m_fInitialized = false; - } -} - -bool CLREventStatic::IsValid() const -{ - return m_fInitialized; -} - -bool CLREventStatic::Set() -{ - if (!m_fInitialized) - return false; - // TODO: Implement - return true; -} - -bool CLREventStatic::Reset() -{ - if (!m_fInitialized) - return false; - // TODO: Implement - return true; -} - -uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable) -{ - DWORD result = WAIT_FAILED; - - if (m_fInitialized) - { - bool disablePreemptive = false; - Thread * pCurThread = GetThread(); - - if (NULL != pCurThread) - { - if (pCurThread->PreemptiveGCDisabled()) - { - pCurThread->EnablePreemptiveGC(); - disablePreemptive = true; - } - } - - // TODO: Implement - result = WAIT_OBJECT_0; - - if (disablePreemptive) - { - pCurThread->DisablePreemptiveGC(); - } - } - - return result; -} -#endif // 0 - -bool __SwitchToThread(uint32_t dwSleepMSec, uint32_t dwSwitchCount) -{ - return sched_yield() == 0; -} - -static int W32toUnixAccessControl(uint32_t flProtect) -{ - int prot = 0; - - switch (flProtect & 0xff) - { - case PAGE_NOACCESS: - prot = PROT_NONE; - break; - case PAGE_READWRITE: - prot = PROT_READ | PROT_WRITE; - break; - default: - _ASSERTE(false); - break; - } - return prot; -} - -MethodTable * g_pFreeObjectMethodTable; - -GCSystemInfo g_SystemInfo; - -void InitializeSystemInfo() -{ - // TODO: Implement - g_SystemInfo.dwNumberOfProcessors = 4; - - g_SystemInfo.dwPageSize = OS_PAGE_SIZE; - g_SystemInfo.dwAllocationGranularity = OS_PAGE_SIZE; -} - -int32_t g_TrapReturningThreads; - -bool g_fFinalizerRunOnShutDown; - -#if 0 -#ifdef _MSC_VER -__declspec(thread) -#else -__thread -#endif -Thread * pCurrentThread; - -Thread * GetThread() -{ - return pCurrentThread; -} - -Thread * g_pThreadList = NULL; - -Thread * ThreadStore::GetThreadList(Thread * pThread) -{ - if (pThread == NULL) - return g_pThreadList; - - return pThread->m_pNext; -} - -void ThreadStore::AttachCurrentThread(bool fAcquireThreadStoreLock) -{ - // TODO: Locks - - Thread * pThread = new Thread(); - pThread->GetAllocContext()->init(); - pCurrentThread = pThread; - - pThread->m_pNext = g_pThreadList; - g_pThreadList = pThread; -} -#endif // 0 - -#if 0 -void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) -{ - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); - - // TODO: Implement -} - -void GCToEEInterface::RestartEE(bool bFinishedGC) -{ - // TODO: Implement - - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); -} - -void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) -{ - // TODO: Implement - Scan stack roots -} - -void GCToEEInterface::GcStartWork(int condemned, int max_gen) -{ -} - -void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) -{ -} - -void GCToEEInterface::GcBeforeBGCSweepWork() -{ -} - -void GCToEEInterface::GcDone(int condemned) -{ -} - -void FinalizerThread::EnableFinalization() -{ - // Signal to finalizer thread that there are objects to finalize - // TODO: Implement for finalization -} - -bool IsGCSpecialThread() -{ - // TODO: Implement for background GC - return false; -} - -#endif // 0 - -WINBASEAPI -UINT -WINAPI -GetWriteWatch( - DWORD dwFlags, - PVOID lpBaseAddress, - SIZE_T dwRegionSize, - PVOID *lpAddresses, - uintptr_t * lpdwCount, - uint32_t * lpdwGranularity - ) -{ - // TODO: Implement for background GC - *lpAddresses = NULL; - *lpdwCount = 0; - // Until it is implemented, return non-zero value as an indicator of failure - return 1; -} - -WINBASEAPI -UINT -WINAPI -ResetWriteWatch( - LPVOID lpBaseAddress, - SIZE_T dwRegionSize - ) -{ - // TODO: Implement for background GC - // Until it is implemented, return non-zero value as an indicator of failure - return 1; -} - -const int tccSecondsToMillieSeconds = 1000; -const int tccSecondsToMicroSeconds = 1000000; -const int tccMillieSecondsToMicroSeconds = 1000; // 10^3 - -WINBASEAPI -DWORD -WINAPI -GetTickCount() -{ - // TODO: More efficient, platform-specific implementation - struct timeval tv; - if (gettimeofday(&tv, NULL) == -1) - { - _ASSERTE(!"gettimeofday() failed"); - return 0; - } - return (tv.tv_sec * tccSecondsToMillieSeconds) + (tv.tv_usec / tccMillieSecondsToMicroSeconds); -} - -WINBASEAPI -BOOL -WINAPI -QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount) -{ - // TODO: More efficient, platform-specific implementation - struct timeval tv; - if (gettimeofday(&tv, NULL) == -1) - { - _ASSERTE(!"gettimeofday() failed"); - return FALSE; - } - lpPerformanceCount->QuadPart = - (int64_t) tv.tv_sec * (int64_t) tccSecondsToMicroSeconds + (int64_t) tv.tv_usec; - return TRUE; -} - -WINBASEAPI -BOOL -WINAPI -QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency) -{ - lpFrequency->QuadPart = (int64_t) tccSecondsToMicroSeconds; - return TRUE; -} - -WINBASEAPI -DWORD -WINAPI -GetCurrentThreadId( - void) -{ - // TODO: Implement - return 1; -} - -WINBASEAPI -void -WINAPI -YieldProcessor() -{ - // TODO: Implement -} - -WINBASEAPI -void -WINAPI -DebugBreak() -{ - // TODO: Implement -} - -WINBASEAPI -void -WINAPI -MemoryBarrier() -{ - // TODO: Implement -} - -// File I/O - Used for tracking only - -WINBASEAPI -BOOL -WINAPI -FlushFileBuffers( - HANDLE hFile) -{ - // TODO: Reimplement callers using CRT - return FALSE; -} - -WINBASEAPI -BOOL -WINAPI -WriteFile( - HANDLE hFile, - LPCVOID lpBuffer, - DWORD nNumberOfBytesToWrite, - DWORD * lpNumberOfBytesWritten, - PVOID lpOverlapped) -{ - // TODO: Reimplement callers using CRT - return FALSE; -} - -WINBASEAPI -BOOL -WINAPI -CloseHandle( - HANDLE hObject) -{ - // TODO: Reimplement callers using CRT - return FALSE; -} - -WINBASEAPI -DWORD -WINAPI -GetLastError() -{ - return 1; -} +// TODO: Implement -- 2.7.4