1
0
forked from 0ad/0ad

Remove topology.cpp. The data isn't useful to us, and it prevents some players from running the game.

Fixes #6028
Differential Revision: https://code.wildfiregames.com/D4402
This was SVN commit r26157.
This commit is contained in:
Stan 2022-01-03 10:29:34 +00:00
parent 273d336364
commit 7afe489214
5 changed files with 2 additions and 431 deletions

View File

@ -1,36 +0,0 @@
/* Copyright (C) 2010 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "lib/self_test.h"
#include "lib/sysdep/arch/x86_x64/topology.h"
class TestTopology : public CxxTest::TestSuite
{
public:
void test_run()
{
TS_ASSERT_LESS_THAN_EQUALS(1u, topology::NumPackages());
TS_ASSERT_LESS_THAN_EQUALS(1u, topology::CoresPerPackage());
TS_ASSERT_LESS_THAN_EQUALS(1u, topology::LogicalPerCore());
}
};

View File

@ -1,294 +0,0 @@
/* Copyright (C) 2020 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Detection of CPU topology
*/
#include "precompiled.h"
#include "lib/sysdep/arch/x86_x64/topology.h"
#include "lib/bits.h"
#include "lib/module_init.h"
#include "lib/sysdep/cpu.h" // ERR::CPU_FEATURE_MISSING
#include "lib/sysdep/os_cpu.h"
#include "lib/sysdep/numa.h"
#include "lib/sysdep/arch/x86_x64/x86_x64.h"
#include "lib/sysdep/arch/x86_x64/apic.h"
#include <bitset>
#include <vector>
namespace topology {
//---------------------------------------------------------------------------------------------------------------------
// detect *maximum* number of cores/packages.
// note: some of them may be disabled by the OS or BIOS.
// note: Intel Appnote 485 assures us that they are uniform across packages.
static size_t MaxCoresPerPackage()
{
// assume single-core unless one of the following applies:
size_t maxCoresPerPackage = 1;
x86_x64::CpuidRegs regs = { 0 };
switch(x86_x64::Vendor())
{
case x86_x64::VENDOR_INTEL:
regs.eax = 4;
regs.ecx = 0;
if(x86_x64::cpuid(&regs))
maxCoresPerPackage = bits(regs.eax, 26, 31)+1;
break;
case x86_x64::VENDOR_AMD:
regs.eax = 0x80000008;
if(x86_x64::cpuid(&regs))
maxCoresPerPackage = bits(regs.ecx, 0, 7)+1;
break;
default:
break;
}
return maxCoresPerPackage;
}
static size_t MaxLogicalPerCore()
{
struct IsHyperthreadingCapable
{
bool operator()() const
{
// definitely not
if(!x86_x64::Cap(x86_x64::CAP_HT))
return false;
// multi-core AMD systems falsely set the HT bit for reasons of
// compatibility. we'll just ignore it, because clearing it might
// confuse other callers.
if(x86_x64::Vendor() == x86_x64::VENDOR_AMD && x86_x64::Cap(x86_x64::CAP_AMD_CMP_LEGACY))
return false;
return true;
}
};
if(IsHyperthreadingCapable()())
{
x86_x64::CpuidRegs regs = { 0 };
regs.eax = 1;
if(!x86_x64::cpuid(&regs))
DEBUG_WARN_ERR(ERR::CPU_FEATURE_MISSING);
const size_t logicalPerPackage = bits(regs.ebx, 16, 23);
const size_t maxCoresPerPackage = MaxCoresPerPackage();
// cores ought to be uniform WRT # logical processors
ENSURE(logicalPerPackage % maxCoresPerPackage == 0);
const size_t maxLogicalPerCore = logicalPerPackage / maxCoresPerPackage;
return maxLogicalPerCore;
}
else
return 1;
}
//---------------------------------------------------------------------------------------------------------------------
// CPU topology interface
// APIC IDs consist of variable-length bit fields indicating the logical,
// core, package and cache IDs. Vol3a says they aren't guaranteed to be
// contiguous, but that also applies to the individual fields.
// for example, quad-core E5630 CPUs report 4-bit core IDs 0, 1, 6, 7.
struct ApicField // POD
{
size_t operator()(size_t bits) const
{
return (bits >> shift) & mask;
}
size_t mask; // zero for zero-width fields
size_t shift;
};
struct CpuTopology // POD
{
size_t numProcessors; // total reported by OS
ApicField logical;
ApicField core;
ApicField package;
// how many are actually enabled
size_t logicalPerCore;
size_t coresPerPackage;
size_t numPackages;
};
static CpuTopology cpuTopology;
static ModuleInitState cpuInitState;
static Status InitCpuTopology()
{
cpuTopology.numProcessors = os_cpu_NumProcessors();
const size_t maxLogicalPerCore = MaxLogicalPerCore();
const size_t maxCoresPerPackage = MaxCoresPerPackage();
const size_t maxPackages = 256; // "enough"
const size_t logicalWidth = ceil_log2(maxLogicalPerCore);
const size_t coreWidth = ceil_log2(maxCoresPerPackage);
const size_t packageWidth = ceil_log2(maxPackages);
cpuTopology.logical.mask = bit_mask<size_t>(logicalWidth);
cpuTopology.core.mask = bit_mask<size_t>(coreWidth);
cpuTopology.package.mask = bit_mask<size_t>(packageWidth);
cpuTopology.logical.shift = 0;
cpuTopology.core.shift = logicalWidth;
cpuTopology.package.shift = logicalWidth + coreWidth;
if(AreApicIdsReliable())
{
struct NumUniqueValuesInField
{
size_t operator()(const ApicField& apicField) const
{
std::bitset<os_cpu_MaxProcessors> values;
for(size_t processor = 0; processor < os_cpu_NumProcessors(); processor++)
{
const ApicId apicId = ApicIdFromProcessor(processor);
const size_t value = apicField(apicId);
values.set(value);
}
return values.count();
}
};
cpuTopology.logicalPerCore = NumUniqueValuesInField()(cpuTopology.logical);
cpuTopology.coresPerPackage = NumUniqueValuesInField()(cpuTopology.core);
cpuTopology.numPackages = NumUniqueValuesInField()(cpuTopology.package);
}
else // processor lacks an xAPIC, or IDs are invalid
{
struct MinPackages
{
size_t operator()(size_t maxCoresPerPackage, size_t maxLogicalPerCore) const
{
const size_t numNodes = numa_NumNodes();
const size_t logicalPerNode = PopulationCount(numa_ProcessorMaskFromNode(0));
// NB: some cores or logical processors may be disabled.
const size_t maxLogicalPerPackage = maxCoresPerPackage*maxLogicalPerCore;
const size_t minPackagesPerNode = DivideRoundUp(logicalPerNode, maxLogicalPerPackage);
return minPackagesPerNode*numNodes;
}
};
// we can't differentiate between cores and logical processors.
// since the former are less likely to be disabled, we seek the
// maximum feasible number of cores and minimal number of packages:
const size_t minPackages = MinPackages()(maxCoresPerPackage, maxLogicalPerCore);
for(size_t numPackages = minPackages; numPackages <= cpuTopology.numProcessors; numPackages++)
{
if(cpuTopology.numProcessors % numPackages != 0)
continue;
const size_t logicalPerPackage = cpuTopology.numProcessors / numPackages;
const size_t minCoresPerPackage = DivideRoundUp(logicalPerPackage, maxLogicalPerCore);
for(size_t coresPerPackage = maxCoresPerPackage; coresPerPackage >= minCoresPerPackage; coresPerPackage--)
{
if(logicalPerPackage % coresPerPackage != 0)
continue;
const size_t logicalPerCore = logicalPerPackage / coresPerPackage;
if(logicalPerCore <= maxLogicalPerCore)
{
ENSURE(cpuTopology.numProcessors == numPackages*coresPerPackage*logicalPerCore);
cpuTopology.logicalPerCore = logicalPerCore;
cpuTopology.coresPerPackage = coresPerPackage;
cpuTopology.numPackages = numPackages;
return INFO::OK;
}
}
}
DEBUG_WARN_ERR(ERR::LOGIC); // didn't find a feasible topology
}
return INFO::OK;
}
size_t NumPackages()
{
ModuleInit(&cpuInitState, InitCpuTopology);
return cpuTopology.numPackages;
}
size_t CoresPerPackage()
{
ModuleInit(&cpuInitState, InitCpuTopology);
return cpuTopology.coresPerPackage;
}
size_t LogicalPerCore()
{
ModuleInit(&cpuInitState, InitCpuTopology);
return cpuTopology.logicalPerCore;
}
size_t LogicalFromApicId(ApicId apicId)
{
const size_t contiguousId = ContiguousIdFromApicId(apicId);
return contiguousId % cpuTopology.logicalPerCore;
}
size_t CoreFromApicId(ApicId apicId)
{
const size_t contiguousId = ContiguousIdFromApicId(apicId);
return (contiguousId / cpuTopology.logicalPerCore) % cpuTopology.coresPerPackage;
}
size_t PackageFromApicId(ApicId apicId)
{
const size_t contiguousId = ContiguousIdFromApicId(apicId);
return contiguousId / (cpuTopology.logicalPerCore * cpuTopology.coresPerPackage);
}
ApicId ApicIdFromIndices(size_t idxLogical, size_t idxCore, size_t idxPackage)
{
ModuleInit(&cpuInitState, InitCpuTopology);
size_t contiguousId = 0;
ENSURE(idxPackage < cpuTopology.numPackages);
contiguousId += idxPackage;
contiguousId *= cpuTopology.coresPerPackage;
ENSURE(idxCore < cpuTopology.coresPerPackage);
contiguousId += idxCore;
contiguousId *= cpuTopology.logicalPerCore;
ENSURE(idxLogical < cpuTopology.logicalPerCore);
contiguousId += idxLogical;
ENSURE(contiguousId < cpuTopology.numProcessors);
return ApicIdFromContiguousId(contiguousId);
}
} // namespace topology

View File

@ -1,85 +0,0 @@
/* Copyright (C) 2020 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* detection of CPU and cache topology.
* thread-safe, no explicit initialization is required.
*/
#ifndef INCLUDED_X86_X64_TOPOLOGY
#define INCLUDED_X86_X64_TOPOLOGY
#include "lib/sysdep/arch/x86_x64/apic.h" // ApicId
namespace topology {
//-----------------------------------------------------------------------------
// cpu
// the CPU topology, i.e. how many packages, cores and logical processors are
// actually present and enabled, is useful for parameterizing parallel
// algorithms, especially on NUMA systems.
//
// note: OS abstractions usually only mention "processors", which could be
// any mix of the above.
/**
* @return number of *enabled* CPU packages / sockets.
**/
LIB_API size_t NumPackages();
/**
* @return number of *enabled* CPU cores per package.
* (2 on dual-core systems)
**/
LIB_API size_t CoresPerPackage();
/**
* @return number of *enabled* logical processors (aka Hyperthreads)
* per core. (2 on P4 EE)
**/
LIB_API size_t LogicalPerCore();
/**
* @return index of processor package/socket in [0, NumPackages())
**/
LIB_API size_t PackageFromApicId(ApicId apicId);
/**
* @return index of processor core in [0, CoresPerPackage())
**/
LIB_API size_t CoreFromApicId(ApicId apicId);
/**
* @return index of logical processor in [0, LogicalPerCore())
**/
LIB_API size_t LogicalFromApicId(ApicId apicId);
/**
* @param idxPackage, idxCore, idxLogical return values of *FromApicId
* @return APIC ID (see note at AreApicIdsReliable)
**/
LIB_API ApicId ApicIdFromIndices(size_t idxPackage, size_t idxCore, size_t idxLogical);
} // namespace topology
#endif // #ifndef INCLUDED_X86_X64_TOPOLOGY

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,9 +25,6 @@
#include "lib/sysdep/cpu.h"
#include "lib/sysdep/numa.h"
#include "lib/sysdep/os_cpu.h"
#if ARCH_X86_X64
# include "lib/sysdep/arch/x86_x64/topology.h"
#endif
#if CONFIG2_AUDIO
#include "soundmanager/SoundManager.h"
#endif
@ -177,11 +174,6 @@ void RunHardwareDetection()
Script::SetProperty(rq, settings, "cpu_pagesize", (u32)os_cpu_PageSize());
Script::SetProperty(rq, settings, "cpu_largepagesize", (u32)os_cpu_LargePageSize());
Script::SetProperty(rq, settings, "cpu_numprocs", (u32)os_cpu_NumProcessors());
#if ARCH_X86_X64
Script::SetProperty(rq, settings, "cpu_numpackages", (u32)topology::NumPackages());
Script::SetProperty(rq, settings, "cpu_coresperpackage", (u32)topology::CoresPerPackage());
Script::SetProperty(rq, settings, "cpu_logicalpercore", (u32)topology::LogicalPerCore());
#endif
Script::SetProperty(rq, settings, "numa_numnodes", (u32)numa_NumNodes());
Script::SetProperty(rq, settings, "numa_factor", numa_Factor());

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,9 +25,6 @@
#include "lib/bits.h" // round_up
#include "lib/ogl.h"
#include "lib/posix/posix_utsname.h"
#if ARCH_X86_X64
#include "lib/sysdep/arch/x86_x64/topology.h"
#endif
#include "lib/sysdep/cpu.h"
#include "lib/sysdep/os_cpu.h"
#include "lib/sysdep/smbios.h"
@ -81,9 +78,6 @@ void WriteSystemInfo()
// CPU
fprintf(f, "CPU : %s, %s", un.machine, cpu_IdentifierString());
#if ARCH_X86_X64
fprintf(f, " (%dx%dx%d)", (int)topology::NumPackages(), (int)topology::CoresPerPackage(), (int)topology::LogicalPerCore());
#endif
double cpuClock = os_cpu_ClockFrequency(); // query OS (may fail)
#if ARCH_X86_X64
if(cpuClock <= 0.0)