diff options
author | Sean Gillespie <segilles@microsoft.com> | 2017-06-01 10:17:35 -0700 |
---|---|---|
committer | Sean Gillespie <segilles@microsoft.com> | 2017-06-01 10:22:06 -0700 |
commit | 77eb339752afa774655d88121f4d8f5de05f6d0a (patch) | |
tree | c5c7d5e383cda13e29accbb86d620d69749973e7 /src/gc | |
parent | 0834425813497593ceda8bb0ae12dcc463011d7c (diff) | |
download | coreclr-77eb339752afa774655d88121f4d8f5de05f6d0a.tar.gz coreclr-77eb339752afa774655d88121f4d8f5de05f6d0a.tar.bz2 coreclr-77eb339752afa774655d88121f4d8f5de05f6d0a.zip |
[Local GC] Remove uses of g_SystemInfo from the GC (#11628)
* [Local GC] Don't use g_SystemInfo to infer the number of processors
* [Local GC] Avoid using g_SystemInfo.dwAllocationGranularity from within
the GC.
In a few places, the GC aligns the size of a request memory reservation
to the allocation granularity before calling
GCToOSInterface::VirtualReserve. Upon inspection, this isn't necessary.
* [Local GC] Remove uses of g_SystemInfo from the handle table
* Add new API on GCToOSInterface for querying the total number of procs on the machine
Diffstat (limited to 'src/gc')
-rw-r--r-- | src/gc/env/gcenv.os.h | 15 | ||||
-rw-r--r-- | src/gc/gc.cpp | 51 | ||||
-rw-r--r-- | src/gc/gc.h | 1 | ||||
-rw-r--r-- | src/gc/gccommon.cpp | 1 | ||||
-rw-r--r-- | src/gc/handletablecache.cpp | 2 | ||||
-rw-r--r-- | src/gc/handletablecore.cpp | 12 | ||||
-rw-r--r-- | src/gc/objecthandle.cpp | 4 | ||||
-rw-r--r-- | src/gc/unix/gcenv.unix.cpp | 12 | ||||
-rw-r--r-- | src/gc/windows/gcenv.windows.cpp | 9 |
9 files changed, 72 insertions, 35 deletions
diff --git a/src/gc/env/gcenv.os.h b/src/gc/env/gcenv.os.h index d3e40ac4ff..8c533222ef 100644 --- a/src/gc/env/gcenv.os.h +++ b/src/gc/env/gcenv.os.h @@ -158,6 +158,15 @@ public: // flags - flags to control special settings like write watching // Return: // Starting virtual address of the reserved range + // Notes: + // Previous uses of this API aligned the `size` parameter to the platform + // allocation granularity. This is not required by POSIX or Windows. Windows will + // round the size up to the nearest page boundary. POSIX does not specify what is done, + // but Linux probably also rounds up. If an implementation of GCToOSInterface needs to + // align to the allocation granularity, it will do so in its implementation. + // + // Windows guarantees that the returned mapping will be aligned to the allocation + // granularity. static void* VirtualReserve(size_t size, size_t alignment, uint32_t flags); // Release virtual memory range previously reserved using VirtualReserve @@ -357,6 +366,12 @@ public: // Return: // Time stamp in milliseconds static uint32_t GetLowPrecisionTimeStamp(); + + // Gets the total number of processors on the machine, not taking + // into account current process affinity. + // Return: + // Number of processors on the machine + static uint32_t GetTotalProcessorCount(); }; #endif // __GCENV_OS_H__ diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index 662a3b68b4..425639cde4 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -748,7 +748,7 @@ public: if (color == join_struct.lock_color) { respin: - int spin_count = 4096 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 4096 * g_num_processors; for (int j = 0; j < spin_count; j++) { if (color != join_struct.lock_color) @@ -849,7 +849,7 @@ respin: if (!join_struct.wait_done) { respin: - int spin_count = 2 * 4096 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 2 * 4096 * g_num_processors; for (int j = 0; j < spin_count; j++) { if (join_struct.wait_done) @@ -1042,7 +1042,7 @@ class exclusive_sync public: void init() { - spin_count = 32 * (g_SystemInfo.dwNumberOfProcessors - 1); + spin_count = 32 * (g_num_processors - 1); rwp_object = 0; needs_checking = 0; for (int i = 0; i < max_pending_allocs; i++) @@ -1498,7 +1498,7 @@ void WaitLongerNoInstru (int i) // if we're waiting for gc to finish, we should block immediately if (!g_TrapReturningThreads) { - if (g_SystemInfo.dwNumberOfProcessors > 1) + if (g_num_processors > 1) { YieldProcessor(); // indicate to the processor that we are spining if (i & 0x01f) @@ -1570,12 +1570,12 @@ retry: { if ((++i & 7) && !IsGCInProgress()) { - if (g_SystemInfo.dwNumberOfProcessors > 1) + if (g_num_processors > 1) { #ifndef MULTIPLE_HEAPS - int spin_count = 1024 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 1024 * g_num_processors; #else //!MULTIPLE_HEAPS - int spin_count = 32 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 32 * g_num_processors; #endif //!MULTIPLE_HEAPS for (int j = 0; j < spin_count; j++) { @@ -1686,7 +1686,7 @@ void WaitLonger (int i #ifdef SYNCHRONIZATION_STATS (spin_lock->num_switch_thread_w)++; #endif //SYNCHRONIZATION_STATS - if (g_SystemInfo.dwNumberOfProcessors > 1) + if (g_num_processors > 1) { YieldProcessor(); // indicate to the processor that we are spining if (i & 0x01f) @@ -1731,12 +1731,12 @@ retry: { if ((++i & 7) && !gc_heap::gc_started) { - if (g_SystemInfo.dwNumberOfProcessors > 1) + if (g_num_processors > 1) { #ifndef MULTIPLE_HEAPS - int spin_count = 1024 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 1024 * g_num_processors; #else //!MULTIPLE_HEAPS - int spin_count = 32 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 32 * g_num_processors; #endif //!MULTIPLE_HEAPS for (int j = 0; j < spin_count; j++) { @@ -4391,9 +4391,9 @@ static size_t get_valid_segment_size (BOOL large_seg=FALSE) if (!large_seg) #endif // BIT64 { - if (g_SystemInfo.dwNumberOfProcessors > 4) + if (g_num_processors > 4) initial_seg_size /= 2; - if (g_SystemInfo.dwNumberOfProcessors > 8) + if (g_num_processors > 8) initial_seg_size /= 2; } #endif //MULTIPLE_HEAPS @@ -5324,7 +5324,7 @@ void gc_heap::gc_thread_function () } else { - int spin_count = 32 * (g_SystemInfo.dwNumberOfProcessors - 1); + int spin_count = 32 * (g_num_processors - 1); // wait until RestartEE has progressed to a stage where we can restart user threads while (!gc_heap::internal_gc_done && !GCHeap::SafeToRestartManagedThreads()) @@ -6999,9 +6999,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) // it is impossible for alloc_size to overflow due bounds on each of // its components. size_t alloc_size = sizeof (uint8_t)*(sizeof(card_table_info) + cs + bs + cb + wws + st + ms); - size_t alloc_size_aligned = Align (alloc_size, g_SystemInfo.dwAllocationGranularity-1); - - uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size_aligned, 0, virtual_reserve_flags); + uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size, 0, virtual_reserve_flags); if (!mem) return 0; @@ -7015,7 +7013,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) if (!GCToOSInterface::VirtualCommit (mem, commit_size)) { dprintf (2, ("Card table commit failed")); - GCToOSInterface::VirtualRelease (mem, alloc_size_aligned); + GCToOSInterface::VirtualRelease (mem, alloc_size); return 0; } @@ -7025,7 +7023,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) card_table_lowest_address (ct) = start; card_table_highest_address (ct) = end; card_table_brick_table (ct) = (short*)((uint8_t*)ct + cs); - card_table_size (ct) = alloc_size_aligned; + card_table_size (ct) = alloc_size; card_table_next (ct) = 0; #ifdef CARD_BUNDLE @@ -7206,11 +7204,10 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, // it is impossible for alloc_size to overflow due bounds on each of // its components. size_t alloc_size = sizeof (uint8_t)*(sizeof(card_table_info) + cs + bs + cb + wws + st + ms); - size_t alloc_size_aligned = Align (alloc_size, g_SystemInfo.dwAllocationGranularity-1); dprintf (GC_TABLE_LOG, ("card table: %Id; brick table: %Id; card bundle: %Id; sw ww table: %Id; seg table: %Id; mark array: %Id", cs, bs, cb, wws, st, ms)); - uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size_aligned, 0, virtual_reserve_flags); + uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size, 0, virtual_reserve_flags); if (!mem) { @@ -7407,7 +7404,7 @@ fail: #endif //delete (uint32_t*)((uint8_t*)ct - sizeof(card_table_info)); - if (!GCToOSInterface::VirtualRelease (mem, alloc_size_aligned)) + if (!GCToOSInterface::VirtualRelease (mem, alloc_size)) { dprintf (GC_TABLE_LOG, ("GCToOSInterface::VirtualRelease failed")); assert (!"release failed"); @@ -10247,9 +10244,9 @@ retry: { while (gc_done_event_lock >= 0) { - if (g_SystemInfo.dwNumberOfProcessors > 1) + if (g_num_processors > 1) { - int spin_count = 32 * g_SystemInfo.dwNumberOfProcessors; + int spin_count = 32 * g_num_processors; for (int j = 0; j < spin_count; j++) { if (gc_done_event_lock < 0) @@ -33437,6 +33434,8 @@ HRESULT GCHeap::Initialize () g_gc_pFreeObjectMethodTable = GCToEEInterface::GetFreeObjectMethodTable(); + g_num_processors = GCToOSInterface::GetTotalProcessorCount(); + assert(g_num_processors != 0); //Initialize the static members. #ifdef TRACE_GC @@ -33477,7 +33476,7 @@ HRESULT GCHeap::Initialize () gc_heap::mem_one_percent = gc_heap::total_physical_mem / 100; #ifndef MULTIPLE_HEAPS - gc_heap::mem_one_percent /= g_SystemInfo.dwNumberOfProcessors; + gc_heap::mem_one_percent /= g_num_processors; #endif //!MULTIPLE_HEAPS // We should only use this if we are in the "many process" mode which really is only applicable @@ -33489,7 +33488,7 @@ HRESULT GCHeap::Initialize () int available_mem_th = 10; if (gc_heap::total_physical_mem >= ((uint64_t)80 * 1024 * 1024 * 1024)) { - int adjusted_available_mem_th = 3 + (int)((float)47 / (float)(g_SystemInfo.dwNumberOfProcessors)); + int adjusted_available_mem_th = 3 + (int)((float)47 / (float)(g_num_processors)); available_mem_th = min (available_mem_th, adjusted_available_mem_th); } diff --git a/src/gc/gc.h b/src/gc/gc.h index 64c287e8be..822fd42a54 100644 --- a/src/gc/gc.h +++ b/src/gc/gc.h @@ -116,6 +116,7 @@ extern "C" uint8_t* g_gc_highest_address; extern "C" GCHeapType g_gc_heap_type; extern "C" uint32_t g_max_generation; extern "C" MethodTable* g_gc_pFreeObjectMethodTable; +extern "C" uint32_t g_num_processors; ::IGCHandleManager* CreateGCHandleManager(); diff --git a/src/gc/gccommon.cpp b/src/gc/gccommon.cpp index 1e5383843b..932f4a2c33 100644 --- a/src/gc/gccommon.cpp +++ b/src/gc/gccommon.cpp @@ -44,6 +44,7 @@ uint8_t* g_gc_highest_address = 0; GCHeapType g_gc_heap_type = GC_HEAP_INVALID; uint32_t g_max_generation = max_generation; MethodTable* g_gc_pFreeObjectMethodTable = nullptr; +uint32_t g_num_processors = 0; #ifdef GC_CONFIG_DRIVEN void record_global_mechanism (int mech_index) diff --git a/src/gc/handletablecache.cpp b/src/gc/handletablecache.cpp index aaf3370bd6..498e688677 100644 --- a/src/gc/handletablecache.cpp +++ b/src/gc/handletablecache.cpp @@ -57,7 +57,7 @@ void SpinUntil(void *pCond, BOOL fNonZero) #endif //_DEBUG // on MP machines, allow ourselves some spin time before sleeping - uint32_t uNonSleepSpins = 8 * (g_SystemInfo.dwNumberOfProcessors - 1); + static uint32_t uNonSleepSpins = 8 * (GCToOSInterface::GetCurrentProcessCpuCount() - 1); // spin until the specificed condition is met while ((*(uintptr_t *)pCond != 0) != (fNonZero != 0)) diff --git a/src/gc/handletablecore.cpp b/src/gc/handletablecore.cpp index a0ffb37d05..4548237eda 100644 --- a/src/gc/handletablecore.cpp +++ b/src/gc/handletablecore.cpp @@ -516,14 +516,14 @@ BOOL SegmentInitialize(TableSegment *pSegment, HandleTable *pTable) #ifndef FEATURE_REDHAWK // todo: implement SafeInt // Prefast overflow sanity check the addition - if (!ClrSafeInt<uint32_t>::addition(dwCommit, g_SystemInfo.dwPageSize, dwCommit)) + if (!ClrSafeInt<uint32_t>::addition(dwCommit, OS_PAGE_SIZE, dwCommit)) { return FALSE; } #endif // !FEATURE_REDHAWK // Round down to the dwPageSize - dwCommit &= ~(g_SystemInfo.dwPageSize - 1); + dwCommit &= ~(OS_PAGE_SIZE - 1); // commit the header if (!GCToOSInterface::VirtualCommit(pSegment, dwCommit)) @@ -1443,7 +1443,7 @@ uint32_t SegmentInsertBlockFromFreeListWorker(TableSegment *pSegment, uint32_t u void * pvCommit = pSegment->rgValue + (uCommitLine * HANDLE_HANDLES_PER_BLOCK); // we should commit one more page of handles - uint32_t dwCommit = g_SystemInfo.dwPageSize; + uint32_t dwCommit = OS_PAGE_SIZE; // commit the memory if (!GCToOSInterface::VirtualCommit(pvCommit, dwCommit)) @@ -1808,7 +1808,7 @@ BOOL DoesSegmentNeedsToTrimExcessPages(TableSegment *pSegment) if (uEmptyLine < uDecommitLine) { // derive some useful info about the page size - uintptr_t dwPageRound = (uintptr_t)g_SystemInfo.dwPageSize - 1; + uintptr_t dwPageRound = (uintptr_t)OS_PAGE_SIZE - 1; uintptr_t dwPageMask = ~dwPageRound; // compute the address corresponding to the empty line @@ -1852,7 +1852,7 @@ void SegmentTrimExcessPages(TableSegment *pSegment) if (uEmptyLine < uDecommitLine) { // derive some useful info about the page size - uintptr_t dwPageRound = (uintptr_t)g_SystemInfo.dwPageSize - 1; + uintptr_t dwPageRound = (uintptr_t)OS_PAGE_SIZE - 1; uintptr_t dwPageMask = ~dwPageRound; // compute the address corresponding to the empty line @@ -1874,7 +1874,7 @@ void SegmentTrimExcessPages(TableSegment *pSegment) pSegment->bCommitLine = (uint8_t)((dwLo - (size_t)pSegment->rgValue) / HANDLE_BYTES_PER_BLOCK); // compute the address for the new decommit line - size_t dwDecommitAddr = dwLo - g_SystemInfo.dwPageSize; + size_t dwDecommitAddr = dwLo - OS_PAGE_SIZE; // assume a decommit line of zero until we know otheriwse uDecommitLine = 0; diff --git a/src/gc/objecthandle.cpp b/src/gc/objecthandle.cpp index 7df915fb72..838947dba1 100644 --- a/src/gc/objecthandle.cpp +++ b/src/gc/objecthandle.cpp @@ -563,10 +563,10 @@ int getNumberOfSlots() return 1; #ifdef FEATURE_REDHAWK - return g_SystemInfo.dwNumberOfProcessors; + return GCToOSInterface::GetCurrentProcessCpuCount(); #else return (CPUGroupInfo::CanEnableGCCPUGroups() ? CPUGroupInfo::GetNumActiveProcessors() : - g_SystemInfo.dwNumberOfProcessors); + GCToOSInterface::GetCurrentProcessCpuCount()); #endif } diff --git a/src/gc/unix/gcenv.unix.cpp b/src/gc/unix/gcenv.unix.cpp index 71c3caee6a..eafd141fd5 100644 --- a/src/gc/unix/gcenv.unix.cpp +++ b/src/gc/unix/gcenv.unix.cpp @@ -710,6 +710,18 @@ bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThr return (st == 0); } +// Gets the total number of processors on the machine, not taking +// into account current process affinity. +// Return: +// Number of processors on the machine +uint32_t GCToOSInterface::GetTotalProcessorCount() +{ + // Calculated in GCToOSInterface::Initialize using + // sysconf(_SC_NPROCESSORS_ONLN) + return g_logicalCpuCount; +} + + // Initialize the critical section void CLRCriticalSection::Initialize() { diff --git a/src/gc/windows/gcenv.windows.cpp b/src/gc/windows/gcenv.windows.cpp index 3749f06a68..c543b0413a 100644 --- a/src/gc/windows/gcenv.windows.cpp +++ b/src/gc/windows/gcenv.windows.cpp @@ -603,6 +603,15 @@ bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThr return true; } +// Gets the total number of processors on the machine, not taking +// into account current process affinity. +// Return: +// Number of processors on the machine +uint32_t GCToOSInterface::GetTotalProcessorCount() +{ + return g_SystemInfo.dwNumberOfProcessors; +} + // Initialize the critical section void CLRCriticalSection::Initialize() { |