diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index 2432cce524..e8fe6bc490 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -76,6 +76,7 @@ typedef struct cpu_ent { //extern cpu_ent gCPU[MAX_BOOT_CPUS]; extern cpu_ent gCPU[]; +extern uint32 gCPUCacheLevelCount; #ifdef __cplusplus diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 7ea90bf672..91cc6bf31a 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -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; diff --git a/src/system/kernel/cpu.cpp b/src/system/kernel/cpu.cpp index 44bff7e25d..1dfbc4dcc1 100644 --- a/src/system/kernel/cpu.cpp +++ b/src/system/kernel/cpu.cpp @@ -21,6 +21,7 @@ /* global per-cpu structure */ cpu_ent gCPU[MAX_BOOT_CPUS]; +uint32 gCPUCacheLevelCount; static spinlock sSetCpuLock; diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index ba6a00825f..fd843119c3 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -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");