Skip to content

Commit

Permalink
Port GC changes from dotnet/corert (dotnet#36197)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkotas authored May 11, 2020
1 parent d48be10 commit 993db61
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 50 deletions.
1 change: 1 addition & 0 deletions src/coreclr/src/gc/env/etmdummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
#define FireEtwGCMarkWithType(HeapNum, ClrInstanceID, Type, Bytes) 0
#define FireEtwGCJoin_V2(Heap, JoinTime, JoinType, ClrInstanceID, JoinID) 0
#define FireEtwGCPerHeapHistory_V3(ClrInstanceID, FreeListAllocated, FreeListRejected, EndOfSegAllocated, CondemnedAllocated, PinnedAllocated, PinnedAllocatedAdvance, RunningFreeListEfficiency, CondemnReasons0, CondemnReasons1, CompactMechanisms, ExpandMechanisms, HeapIndex, ExtraGen0Commit, Count, Values_Len_, Values) 0
#define FireEtwGCGlobalHeapHistory_V2(FinalYoungestDesired, NumHeaps, CondemnedGeneration, Gen0ReductionCount, Reason, GlobalMechanisms, ClrInstanceID, PauseMode, MemoryPressure) 0
#define FireEtwGCGlobalHeapHistory_V3(FinalYoungestDesired, NumHeaps, CondemnedGeneration, Gen0ReductionCount, Reason, GlobalMechanisms, ClrInstanceID, PauseMode, MemoryPressure, CondemnReasons0, CondemnReasons1) 0
#define FireEtwDebugIPCEventStart() 0
#define FireEtwDebugIPCEventEnd() 0
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/src/gc/env/gcenv.os.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ struct VirtualReserveFlags
// are run on process exit, potentially concurrently with other threads that may still be
// operating on the static event. To avoid these sorts of unsafety, GCEvent chooses to
// not have a destructor at all. The cost of this is leaking a small amount of memory, but
// this is not a problem since a majority of the uses of GCEvent are static. See CoreCLR#11111
// for more details on the hazards of static destructors.
// this is not a problem since a majority of the uses of GCEvent are static.
// See https://github.com/dotnet/runtime/issues/7919 for more details on the hazards of
// static destructors.
class GCEvent {
private:
class Impl;
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/src/gc/env/volatile.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
#error The Volatile type is currently only defined for Visual C++ and GNU C++
#endif

#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64)
#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM or ARM64 CPUs
#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) && !defined(HOST_WASM)
#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM, ARM64 or Wasm
#endif

#if defined(__GNUC__)
Expand Down
48 changes: 2 additions & 46 deletions src/coreclr/src/gc/unix/cgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Module Name:
#define CGROUP1_CFS_PERIOD_FILENAME "/cpu.cfs_period_us"
#define CGROUP2_CPU_MAX_FILENAME "/cpu.max"

extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val);

class CGroup
{
// the cgroup version number or 0 to indicate cgroups are not found or not enabled
Expand Down Expand Up @@ -420,52 +422,6 @@ class CGroup
return result;
}

static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val)
{
bool result = false;
char *line = nullptr;
size_t lineLen = 0;
char* endptr = nullptr;
uint64_t num = 0, l, multiplier;
FILE* file = nullptr;

if (val == nullptr)
goto done;

file = fopen(filename, "r");
if (file == nullptr)
goto done;

if (getline(&line, &lineLen, file) == -1)
goto done;

errno = 0;
num = strtoull(line, &endptr, 0);
if (line == endptr || errno != 0)
goto done;

multiplier = 1;
switch(*endptr)
{
case 'g':
case 'G': multiplier = 1024;
case 'm':
case 'M': multiplier = multiplier*1024;
case 'k':
case 'K': multiplier = multiplier*1024;
}

*val = num * multiplier;
result = true;
if (*val/multiplier != num)
result = false;
done:
if (file)
fclose(file);
free(line);
return result;
}

static bool GetCGroup1CpuLimit(uint32_t *val)
{
long long quota;
Expand Down
89 changes: 89 additions & 0 deletions src/coreclr/src/gc/unix/gcenv.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,52 @@ bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size,
return false;
}

bool ReadMemoryValueFromFile(const char* filename, uint64_t* val)
{
bool result = false;
char* line = nullptr;
size_t lineLen = 0;
char* endptr = nullptr;
uint64_t num = 0, l, multiplier;
FILE* file = nullptr;

if (val == nullptr)
goto done;

file = fopen(filename, "r");
if (file == nullptr)
goto done;

if (getline(&line, &lineLen, file) == -1)
goto done;

errno = 0;
num = strtoull(line, &endptr, 0);
if (line == endptr || errno != 0)
goto done;

multiplier = 1;
switch (*endptr)
{
case 'g':
case 'G': multiplier = 1024;
case 'm':
case 'M': multiplier = multiplier * 1024;
case 'k':
case 'K': multiplier = multiplier * 1024;
}

*val = num * multiplier;
result = true;
if (*val / multiplier != num)
result = false;
done:
if (file)
fclose(file);
free(line);
return result;
}

static size_t GetLogicalProcessorCacheSizeFromOS()
{
size_t cacheSize = 0;
Expand All @@ -789,6 +835,49 @@ static size_t GetLogicalProcessorCacheSizeFromOS()
cacheSize = std::max(cacheSize, ( size_t) sysconf(_SC_LEVEL4_CACHE_SIZE));
#endif

#if defined(HOST_ARM64)
if (cacheSize == 0)
{
size_t size;

if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size))
cacheSize = std::max(cacheSize, size);
if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index1/size", &size))
cacheSize = std::max(cacheSize, size);
if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index2/size", &size))
cacheSize = std::max(cacheSize, size);
if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index3/size", &size))
cacheSize = std::max(cacheSize, size);
if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size))
cacheSize = std::max(cacheSize, size);
}

if (cacheSize == 0)
{
// It is currently expected to be missing cache size info
//
// _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64
//
// /sys/devices/system/cpu/cpu*/cache/index*/ is also not yet present in most systems.
// Arm64 patch is in Linux kernel tip.
//
// midr_el1 is available in "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1",
// but without an exhaustive list of ARM64 processors any decode of midr_el1
// Would likely be incomplete

// Published information on ARM64 architectures is limited.
// If we use recent high core count chips as a guide for state of the art, we find
// total L3 cache to be 1-2MB/core. As always, there are exceptions.

// Estimate cache size based on CPU count
// Assume lower core count are lighter weight parts which are likely to have smaller caches
// Assume L3$/CPU grows linearly from 256K to 1.5M/CPU as logicalCPUs grows from 2 to 12 CPUs
DWORD logicalCPUs = g_totalCpuCount;

cacheSize = logicalCPUs * std::min(1536, std::max(256, (int)logicalCPUs * 128)) * 1024;
}
#endif

#if HAVE_SYSCTLBYNAME
if (cacheSize == 0)
{
Expand Down

0 comments on commit 993db61

Please sign in to comment.