diff --git a/tcmalloc/internal/cache_topology.cc b/tcmalloc/internal/cache_topology.cc index 94882ca6e..8e06f9c0b 100644 --- a/tcmalloc/internal/cache_topology.cc +++ b/tcmalloc/internal/cache_topology.cc @@ -55,7 +55,13 @@ int BuildCpuToL3CacheMap_FindFirstNumberInBuf(absl::string_view current) { } void CacheTopology::Init() { - cpu_count_ = NumCPUs(); + const auto maybe_numcpus = NumCPUsMaybe(); + if (!maybe_numcpus.has_value()) { + l3_count_ = 1; + return; + } + + cpu_count_ = *maybe_numcpus; for (int cpu = 0; cpu < cpu_count_; ++cpu) { const int fd = OpenSysfsCacheList(cpu); if (fd == -1) { diff --git a/tcmalloc/internal/cache_topology.h b/tcmalloc/internal/cache_topology.h index f49929a4c..6f0d93503 100644 --- a/tcmalloc/internal/cache_topology.h +++ b/tcmalloc/internal/cache_topology.h @@ -43,7 +43,9 @@ class CacheTopology { unsigned GetL3FromCpuId(int cpu) const { TC_ASSERT_GE(cpu, 0); TC_ASSERT_LT(cpu, cpu_count_); - return l3_cache_index_[cpu]; + unsigned l3 = l3_cache_index_[cpu]; + TC_ASSERT_LT(l3, l3_count_); + return l3; } private: diff --git a/tcmalloc/internal/parameter_accessors.h b/tcmalloc/internal/parameter_accessors.h index 58414f81d..39bd9a5f6 100644 --- a/tcmalloc/internal/parameter_accessors.h +++ b/tcmalloc/internal/parameter_accessors.h @@ -75,6 +75,8 @@ ABSL_ATTRIBUTE_WEAK void TCMalloc_Internal_SetMaxTotalThreadCacheBytes( ABSL_ATTRIBUTE_WEAK void TCMalloc_Internal_SetPeakSamplingHeapGrowthFraction( double v); ABSL_ATTRIBUTE_WEAK void TCMalloc_Internal_SetPerCpuCachesEnabled(bool v); +ABSL_ATTRIBUTE_WEAK void +TCMalloc_Internal_SetPerCpuCachesEnabledNoBuildRequirement(bool v); ABSL_ATTRIBUTE_WEAK void TCMalloc_Internal_SetProfileSamplingInterval( int64_t v); ABSL_ATTRIBUTE_WEAK void TCMalloc_Internal_SetBackgroundProcessActionsEnabled( diff --git a/tcmalloc/internal/percpu.cc b/tcmalloc/internal/percpu.cc index d3a9d0b3c..40b113456 100644 --- a/tcmalloc/internal/percpu.cc +++ b/tcmalloc/internal/percpu.cc @@ -116,7 +116,12 @@ int VirtualCpu::Synchronize() { } static void InitPerCpu() { - TC_CHECK(NumCPUs() <= std::numeric_limits::max()); + const auto maybe_numcpus = NumCPUsMaybe(); + if (!maybe_numcpus.has_value()) { + init_status = kSlowMode; + return; + } + TC_CHECK(*maybe_numcpus <= std::numeric_limits::max()); // Based on the results of successfully initializing the first thread, mark // init_status to initialize all subsequent threads. diff --git a/tcmalloc/parameters.cc b/tcmalloc/parameters.cc index d01cd512b..e958ed947 100644 --- a/tcmalloc/parameters.cc +++ b/tcmalloc/parameters.cc @@ -570,6 +570,10 @@ void TCMalloc_Internal_SetPerCpuCachesEnabled(bool v) { } #endif // !TCMALLOC_DEPRECATED_PERTHREAD + TCMalloc_Internal_SetPerCpuCachesEnabledNoBuildRequirement(v); +} + +void TCMalloc_Internal_SetPerCpuCachesEnabledNoBuildRequirement(bool v) { Parameters::per_cpu_caches_enabled_.store(v, std::memory_order_relaxed); } diff --git a/tcmalloc/parameters.h b/tcmalloc/parameters.h index 60f7bbdef..0e31d782e 100644 --- a/tcmalloc/parameters.h +++ b/tcmalloc/parameters.h @@ -213,7 +213,8 @@ class Parameters { friend void ::TCMalloc_Internal_SetMaxPerCpuCacheSize(int32_t v); friend void ::TCMalloc_Internal_SetMaxTotalThreadCacheBytes(int64_t v); friend void ::TCMalloc_Internal_SetPeakSamplingHeapGrowthFraction(double v); - friend void ::TCMalloc_Internal_SetPerCpuCachesEnabled(bool v); + friend void ::TCMalloc_Internal_SetPerCpuCachesEnabledNoBuildRequirement( + bool v); friend void ::TCMalloc_Internal_SetProfileSamplingInterval(int64_t v); friend void ::TCMalloc_Internal_SetHugePageFillerSkipSubreleaseInterval( diff --git a/tcmalloc/static_vars.cc b/tcmalloc/static_vars.cc index 83afd9f8f..8cef0c621 100644 --- a/tcmalloc/static_vars.cc +++ b/tcmalloc/static_vars.cc @@ -39,6 +39,7 @@ #include "tcmalloc/internal/logging.h" #include "tcmalloc/internal/mincore.h" #include "tcmalloc/internal/numa.h" +#include "tcmalloc/internal/parameter_accessors.h" #include "tcmalloc/internal/percpu.h" #include "tcmalloc/internal/sysinfo.h" #include "tcmalloc/malloc_extension.h" @@ -162,7 +163,9 @@ ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE void Static::SlowInitIfNecessary() { TC_CHECK(sizemap_.Init(SizeMap::CurrentClasses().classes)); // Verify we can determine the number of CPUs now, since we will need it // later for per-CPU caches and initializing the cache topology. - (void)NumCPUs(); + if (ABSL_PREDICT_FALSE(!NumCPUsMaybe().has_value())) { + TCMalloc_Internal_SetPerCpuCachesEnabledNoBuildRequirement(false); + } (void)subtle::percpu::IsFast(); numa_topology_.Init(); CacheTopology::Instance().Init();