summaryrefslogtreecommitdiff
path: root/src/gc
diff options
context:
space:
mode:
authorSean Gillespie <segilles@microsoft.com>2017-06-01 10:17:35 -0700
committerSean Gillespie <segilles@microsoft.com>2017-06-01 10:22:06 -0700
commit77eb339752afa774655d88121f4d8f5de05f6d0a (patch)
treec5c7d5e383cda13e29accbb86d620d69749973e7 /src/gc
parent0834425813497593ceda8bb0ae12dcc463011d7c (diff)
downloadcoreclr-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.h15
-rw-r--r--src/gc/gc.cpp51
-rw-r--r--src/gc/gc.h1
-rw-r--r--src/gc/gccommon.cpp1
-rw-r--r--src/gc/handletablecache.cpp2
-rw-r--r--src/gc/handletablecore.cpp12
-rw-r--r--src/gc/objecthandle.cpp4
-rw-r--r--src/gc/unix/gcenv.unix.cpp12
-rw-r--r--src/gc/windows/gcenv.windows.cpp9
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()
{