scheduler_affine: Use CPU topology tree to create ID mappings
This commit is contained in:
@@ -1108,12 +1108,34 @@ static scheduler_ops kAffineOps = {
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static void
|
||||||
scheduler_affine_init()
|
traverse_topology_tree(cpu_topology_node* node, int packageID, int coreID)
|
||||||
{
|
{
|
||||||
int32 cpuCount = smp_get_num_cpus();
|
switch (node->level) {
|
||||||
|
case CPU_TOPOLOGY_SMT:
|
||||||
|
sCPUToCore[node->id] = coreID;
|
||||||
|
sCPUToPackage[node->id] = packageID;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case CPU_TOPOLOGY_CORE:
|
||||||
|
coreID = node->id;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU_TOPOLOGY_PACKAGE:
|
||||||
|
packageID = node->id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0; i < node->children_count; i++)
|
||||||
|
traverse_topology_tree(node->children[i], packageID, coreID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
build_topology_mappings(int32& cpuCount, int32& coreCount, int32& packageCount)
|
||||||
|
{
|
||||||
|
cpuCount = smp_get_num_cpus();
|
||||||
|
|
||||||
// create logical processor to core and package mappings
|
|
||||||
sCPUToCore = new(std::nothrow) int32[cpuCount];
|
sCPUToCore = new(std::nothrow) int32[cpuCount];
|
||||||
if (sCPUToCore == NULL)
|
if (sCPUToCore == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -1124,74 +1146,40 @@ scheduler_affine_init()
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
ArrayDeleter<int32> cpuToPackageDeleter(sCPUToPackage);
|
ArrayDeleter<int32> cpuToPackageDeleter(sCPUToPackage);
|
||||||
|
|
||||||
int32 coreCount = 0;
|
coreCount = 0;
|
||||||
for (int32 i = 0; i < cpuCount; i++) {
|
for (int32 i = 0; i < cpuCount; i++) {
|
||||||
if (gCPU[i].topology_id[CPU_TOPOLOGY_SMT] == 0)
|
if (gCPU[i].topology_id[CPU_TOPOLOGY_SMT] == 0)
|
||||||
sCPUToCore[i] = coreCount++;
|
coreCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packageCount = 0;
|
||||||
|
for (int32 i = 0; i < cpuCount; i++) {
|
||||||
|
if (gCPU[i].topology_id[CPU_TOPOLOGY_SMT] == 0
|
||||||
|
&& gCPU[i].topology_id[CPU_TOPOLOGY_CORE] == 0) {
|
||||||
|
packageCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_topology_node* root = get_cpu_topology();
|
||||||
|
traverse_topology_tree(root, 0, 0);
|
||||||
|
|
||||||
|
cpuToCoreDeleter.Detach();
|
||||||
|
cpuToPackageDeleter.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
scheduler_affine_init()
|
||||||
|
{
|
||||||
|
// create logical processor to core and package mappings
|
||||||
|
int32 cpuCount, coreCount, packageCount;
|
||||||
|
status_t result = build_topology_mappings(cpuCount, coreCount,
|
||||||
|
packageCount);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
sRunQueueCount = coreCount;
|
sRunQueueCount = coreCount;
|
||||||
|
|
||||||
int32 packageCount = 0;
|
|
||||||
for (int32 i = 0; i < cpuCount; i++) {
|
|
||||||
if (gCPU[i].topology_id[CPU_TOPOLOGY_SMT] == 0
|
|
||||||
&& gCPU[i].topology_id[CPU_TOPOLOGY_CORE] == 0) {
|
|
||||||
sCPUToPackage[i] = packageCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Nasty O(n^2), solutions with better complexity will require
|
|
||||||
// creating helper data structures. This code is run only once, so it
|
|
||||||
// probably won't be a problem until we support systems with large
|
|
||||||
// number of processors.
|
|
||||||
for (int32 i = 0; i < cpuCount; i++) {
|
|
||||||
if (gCPU[i].topology_id[CPU_TOPOLOGY_SMT] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int32 j = 0; j < cpuCount; j++) {
|
|
||||||
bool sameCore = true;
|
|
||||||
for (int32 k = 0; k < CPU_TOPOLOGY_LEVELS && sameCore; k++) {
|
|
||||||
if (k == CPU_TOPOLOGY_SMT && gCPU[j].topology_id[k] == 0)
|
|
||||||
continue;
|
|
||||||
if (k == CPU_TOPOLOGY_SMT && gCPU[j].topology_id[k] != 0) {
|
|
||||||
sameCore = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gCPU[i].topology_id[k] != gCPU[j].topology_id[k])
|
|
||||||
sameCore = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sameCore)
|
|
||||||
sCPUToCore[i] = sCPUToCore[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Another O(n^2), something has to be done with that... (i.e.
|
|
||||||
// build a tree representing the topology and then use it to create
|
|
||||||
// these mappings.
|
|
||||||
for (int32 i = 0; i < cpuCount; i++) {
|
|
||||||
if (gCPU[i].topology_id[CPU_TOPOLOGY_SMT] == 0
|
|
||||||
&& gCPU[i].topology_id[CPU_TOPOLOGY_CORE] == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 j = 0; j < cpuCount; j++) {
|
|
||||||
bool samePackage = true;
|
|
||||||
for (int32 k = 0; k < CPU_TOPOLOGY_LEVELS && samePackage; k++) {
|
|
||||||
if (k < CPU_TOPOLOGY_PACKAGE) {
|
|
||||||
if (gCPU[j].topology_id[k] == 0)
|
|
||||||
continue;
|
|
||||||
samePackage = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
samePackage = gCPU[i].topology_id[k] == gCPU[j].topology_id[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samePackage)
|
|
||||||
sCPUToPackage[i] = sCPUToPackage[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create package heap and idle package stack
|
// create package heap and idle package stack
|
||||||
sPackageEntries = new(std::nothrow) PackageEntry[packageCount];
|
sPackageEntries = new(std::nothrow) PackageEntry[packageCount];
|
||||||
if (sPackageEntries == NULL)
|
if (sPackageEntries == NULL)
|
||||||
@@ -1202,7 +1190,7 @@ scheduler_affine_init()
|
|||||||
if (sPackageUsageHeap == NULL)
|
if (sPackageUsageHeap == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
ObjectDeleter<AffinePackageHeap> packageHeapDeleter(sPackageUsageHeap);
|
ObjectDeleter<AffinePackageHeap> packageHeapDeleter(sPackageUsageHeap);
|
||||||
status_t result = sPackageUsageHeap->GrowHeap(packageCount);
|
result = sPackageUsageHeap->GrowHeap(packageCount);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@@ -1309,7 +1297,5 @@ scheduler_affine_init()
|
|||||||
packageEntriesDeleter.Detach();
|
packageEntriesDeleter.Detach();
|
||||||
packageHeapDeleter.Detach();
|
packageHeapDeleter.Detach();
|
||||||
packageListDeleter.Detach();
|
packageListDeleter.Detach();
|
||||||
cpuToPackageDeleter.Detach();
|
|
||||||
cpuToCoreDeleter.Detach();
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user