kernel: Decide whether to use simple or affine scheduler
Simple scheduler is used when we do not have to worry about cache affinity (i.e. single core with or without SMT, multicore with all cache levels shared). When we replace gSchedulerLock with more fine grained locking affine scheduler should also be chosen when logical CPU count is high (regardless of cache).
This commit is contained in:
@@ -76,6 +76,7 @@ typedef struct cpu_ent {
|
||||
|
||||
//extern cpu_ent gCPU[MAX_BOOT_CPUS];
|
||||
extern cpu_ent gCPU[];
|
||||
extern uint32 gCPUCacheLevelCount;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -131,7 +131,6 @@ static uint32 sHierarchyShift[CPU_TOPOLOGY_LEVELS];
|
||||
|
||||
/* Cache topology information */
|
||||
static uint32 sCacheSharingMask[CPU_MAX_CACHE_LEVEL];
|
||||
static uint32 sCacheLevelCount;
|
||||
|
||||
|
||||
static status_t
|
||||
@@ -611,7 +610,7 @@ detect_amd_cache_topology(uint32 maxExtendedLeaf)
|
||||
|
||||
for (int i = 0; i < maxCacheLevel; i++)
|
||||
sCacheSharingMask[i] = ~uint32(hierarchyLevels[i] - 1);
|
||||
sCacheLevelCount = maxCacheLevel;
|
||||
gCPUCacheLevelCount = maxCacheLevel;
|
||||
}
|
||||
|
||||
|
||||
@@ -725,7 +724,7 @@ detect_intel_cache_topology(uint32 maxBasicLeaf)
|
||||
for (int i = 0; i < maxCacheLevel; i++)
|
||||
sCacheSharingMask[i] = ~uint32(hierarchyLevels[i] - 1);
|
||||
|
||||
sCacheLevelCount = maxCacheLevel;
|
||||
gCPUCacheLevelCount = maxCacheLevel;
|
||||
}
|
||||
|
||||
|
||||
@@ -789,7 +788,7 @@ detect_cpu_topology(int currentCPU, cpu_ent* cpu, uint32 maxBasicLeaf,
|
||||
= get_topology_level_id(topologyID, CPU_TOPOLOGY_PACKAGE);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sCacheLevelCount; i++)
|
||||
for (i = 0; i < gCPUCacheLevelCount; i++)
|
||||
cpu->cache_id[i] = topologyID & sCacheSharingMask[i];
|
||||
for (; i < CPU_MAX_CACHE_LEVEL; i++)
|
||||
cpu->cache_id[i] = -1;
|
||||
@@ -800,14 +799,14 @@ detect_cpu_topology(int currentCPU, cpu_ent* cpu, uint32 maxBasicLeaf,
|
||||
cpu->topology_id[CPU_TOPOLOGY_CORE],
|
||||
cpu->topology_id[CPU_TOPOLOGY_SMT]);
|
||||
|
||||
if (sCacheLevelCount > 0) {
|
||||
if (gCPUCacheLevelCount > 0) {
|
||||
char cacheLevels[256];
|
||||
unsigned int offset = 0;
|
||||
for (i = 0; i < sCacheLevelCount; i++) {
|
||||
for (i = 0; i < gCPUCacheLevelCount; i++) {
|
||||
offset += snprintf(cacheLevels + offset,
|
||||
sizeof(cacheLevels) - offset,
|
||||
" L%d id %d%s", i + 1, cpu->cache_id[i],
|
||||
i < sCacheLevelCount - 1 ? "," : "");
|
||||
i < gCPUCacheLevelCount - 1 ? "," : "");
|
||||
|
||||
if (offset >= sizeof(cacheLevels))
|
||||
break;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
/* global per-cpu structure */
|
||||
cpu_ent gCPU[MAX_BOOT_CPUS];
|
||||
uint32 gCPUCacheLevelCount;
|
||||
|
||||
static spinlock sSetCpuLock;
|
||||
|
||||
|
||||
@@ -59,20 +59,39 @@ scheduler_remove_listener(struct SchedulerListener* listener)
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
should_use_affine_scheduler(int32 cpuCount)
|
||||
{
|
||||
if (cpuCount < 2)
|
||||
return false;
|
||||
|
||||
for (int32 i = 1; i < cpuCount; i++) {
|
||||
for (int32 j = 0; j < gCPUCacheLevelCount; j++) {
|
||||
if (gCPU[i].cache_id[j] != gCPU[i - 1].cache_id[j])
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scheduler_init(void)
|
||||
{
|
||||
int32 cpuCount = smp_get_num_cpus();
|
||||
dprintf("scheduler_init: found %" B_PRId32 " logical cpu%s\n", cpuCount,
|
||||
cpuCount != 1 ? "s" : "");
|
||||
dprintf("scheduler_init: found %" B_PRId32 " logical cpu%s and %" B_PRId32
|
||||
" cache level%s\n", cpuCount, cpuCount != 1 ? "s" : "",
|
||||
gCPUCacheLevelCount, gCPUCacheLevelCount != 1 ? "s" : "");
|
||||
|
||||
status_t result;
|
||||
#if 0
|
||||
dprintf("scheduler_init: using affine scheduler\n");
|
||||
result = scheduler_affine_init();
|
||||
#endif
|
||||
dprintf("scheduler_init: using simple scheduler\n");
|
||||
result = scheduler_simple_init();
|
||||
if (should_use_affine_scheduler(cpuCount)) {
|
||||
dprintf("scheduler_init: using affine scheduler\n");
|
||||
result = scheduler_affine_init();
|
||||
} else {
|
||||
dprintf("scheduler_init: using simple scheduler\n");
|
||||
result = scheduler_simple_init();
|
||||
}
|
||||
|
||||
if (result != B_OK)
|
||||
panic("scheduler_init: failed to initialize scheduler\n");
|
||||
|
||||
Reference in New Issue
Block a user