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:
Pawel Dziepak
2013-10-16 18:39:25 +02:00
parent ebec24f9e0
commit cf863a5040
4 changed files with 35 additions and 15 deletions
+1
View File
@@ -76,6 +76,7 @@ typedef struct cpu_ent {
//extern cpu_ent gCPU[MAX_BOOT_CPUS]; //extern cpu_ent gCPU[MAX_BOOT_CPUS];
extern cpu_ent gCPU[]; extern cpu_ent gCPU[];
extern uint32 gCPUCacheLevelCount;
#ifdef __cplusplus #ifdef __cplusplus
+6 -7
View File
@@ -131,7 +131,6 @@ static uint32 sHierarchyShift[CPU_TOPOLOGY_LEVELS];
/* Cache topology information */ /* Cache topology information */
static uint32 sCacheSharingMask[CPU_MAX_CACHE_LEVEL]; static uint32 sCacheSharingMask[CPU_MAX_CACHE_LEVEL];
static uint32 sCacheLevelCount;
static status_t static status_t
@@ -611,7 +610,7 @@ detect_amd_cache_topology(uint32 maxExtendedLeaf)
for (int i = 0; i < maxCacheLevel; i++) for (int i = 0; i < maxCacheLevel; i++)
sCacheSharingMask[i] = ~uint32(hierarchyLevels[i] - 1); 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++) for (int i = 0; i < maxCacheLevel; i++)
sCacheSharingMask[i] = ~uint32(hierarchyLevels[i] - 1); 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); = get_topology_level_id(topologyID, CPU_TOPOLOGY_PACKAGE);
unsigned int i; unsigned int i;
for (i = 0; i < sCacheLevelCount; i++) for (i = 0; i < gCPUCacheLevelCount; i++)
cpu->cache_id[i] = topologyID & sCacheSharingMask[i]; cpu->cache_id[i] = topologyID & sCacheSharingMask[i];
for (; i < CPU_MAX_CACHE_LEVEL; i++) for (; i < CPU_MAX_CACHE_LEVEL; i++)
cpu->cache_id[i] = -1; 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_CORE],
cpu->topology_id[CPU_TOPOLOGY_SMT]); cpu->topology_id[CPU_TOPOLOGY_SMT]);
if (sCacheLevelCount > 0) { if (gCPUCacheLevelCount > 0) {
char cacheLevels[256]; char cacheLevels[256];
unsigned int offset = 0; unsigned int offset = 0;
for (i = 0; i < sCacheLevelCount; i++) { for (i = 0; i < gCPUCacheLevelCount; i++) {
offset += snprintf(cacheLevels + offset, offset += snprintf(cacheLevels + offset,
sizeof(cacheLevels) - offset, sizeof(cacheLevels) - offset,
" L%d id %d%s", i + 1, cpu->cache_id[i], " L%d id %d%s", i + 1, cpu->cache_id[i],
i < sCacheLevelCount - 1 ? "," : ""); i < gCPUCacheLevelCount - 1 ? "," : "");
if (offset >= sizeof(cacheLevels)) if (offset >= sizeof(cacheLevels))
break; break;
+1
View File
@@ -21,6 +21,7 @@
/* global per-cpu structure */ /* global per-cpu structure */
cpu_ent gCPU[MAX_BOOT_CPUS]; cpu_ent gCPU[MAX_BOOT_CPUS];
uint32 gCPUCacheLevelCount;
static spinlock sSetCpuLock; static spinlock sSetCpuLock;
+27 -8
View File
@@ -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 void
scheduler_init(void) scheduler_init(void)
{ {
int32 cpuCount = smp_get_num_cpus(); int32 cpuCount = smp_get_num_cpus();
dprintf("scheduler_init: found %" B_PRId32 " logical cpu%s\n", cpuCount, dprintf("scheduler_init: found %" B_PRId32 " logical cpu%s and %" B_PRId32
cpuCount != 1 ? "s" : ""); " cache level%s\n", cpuCount, cpuCount != 1 ? "s" : "",
gCPUCacheLevelCount, gCPUCacheLevelCount != 1 ? "s" : "");
status_t result; status_t result;
#if 0 if (should_use_affine_scheduler(cpuCount)) {
dprintf("scheduler_init: using affine scheduler\n"); dprintf("scheduler_init: using affine scheduler\n");
result = scheduler_affine_init(); result = scheduler_affine_init();
#endif } else {
dprintf("scheduler_init: using simple scheduler\n"); dprintf("scheduler_init: using simple scheduler\n");
result = scheduler_simple_init(); result = scheduler_simple_init();
}
if (result != B_OK) if (result != B_OK)
panic("scheduler_init: failed to initialize scheduler\n"); panic("scheduler_init: failed to initialize scheduler\n");