added 3 changesets to branch 'refs/remotes/pdziepak-github/scheduler' old head: b3723fdada15080f9d8cad90d57c7689bb029bed new head: 7ce234bf2444831f6340230e9e42900ce25c0173 overview: https://github.com/pdziepak/Haiku/compare/b3723fd...7ce234b ---------------------------------------------------------------------------- cb3f258: kernel: Make get_cpu_topology() return a pointer to const The client code is not supposed to change the topology info. It would be also nice if cpu_topology_node::children was an array of pointers to const but that would require several const_casts in the topology tree generation code so it's probably not worth it. 23bf5fe: kernel: Propagate scheduler modes to cpu{freq, idle} modules 7ce234b: scheduler: Fix unassigning threads from core being disabled [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 10 files changed, 94 insertions(+), 42 deletions(-) headers/os/drivers/cpufreq.h | 8 +++- headers/os/drivers/cpuidle.h | 8 +++- headers/private/kernel/cpu.h | 8 +++- headers/private/kernel/kscheduler.h | 6 --- .../cpufreq/intel_pstates/intel_pstates.cpp | 25 +++++++++--- .../cpuidle/intel_cstates/intel_cstates.cpp | 41 +++++++++++++++----- src/system/kernel/cpu.cpp | 22 ++++++++--- src/system/kernel/int.cpp | 2 +- src/system/kernel/scheduler/scheduler.cpp | 12 ++++-- src/system/kernel/scheduler/scheduler_cpu.cpp | 4 +- ############################################################################ Commit: cb3f258a7eb27f8e2d1e64499091139bfc7ff431 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Dec 17 21:08:18 2013 UTC kernel: Make get_cpu_topology() return a pointer to const The client code is not supposed to change the topology info. It would be also nice if cpu_topology_node::children was an array of pointers to const but that would require several const_casts in the topology tree generation code so it's probably not worth it. ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index 7b4d51f..73614ab 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -105,7 +105,7 @@ cpu_ent *get_cpu_struct(void); extern inline cpu_ent *get_cpu_struct(void) { return &gCPU[smp_get_current_cpu()]; } status_t cpu_build_topology_tree(void); -cpu_topology_node* get_cpu_topology(void); +const cpu_topology_node* get_cpu_topology(void); status_t increase_cpu_performance(int delta, bool allowBoost); status_t decrease_cpu_performance(int delta); diff --git a/src/system/kernel/cpu.cpp b/src/system/kernel/cpu.cpp index 3a3df3a..2adc443 100644 --- a/src/system/kernel/cpu.cpp +++ b/src/system/kernel/cpu.cpp @@ -274,7 +274,7 @@ cpu_build_topology_tree(void) } -cpu_topology_node* +const cpu_topology_node* get_cpu_topology(void) { return &sCPUTopology; diff --git a/src/system/kernel/int.cpp b/src/system/kernel/int.cpp index 9fd6d2e..6601f3a 100644 --- a/src/system/kernel/int.cpp +++ b/src/system/kernel/int.cpp @@ -391,7 +391,7 @@ restore_interrupts(cpu_status status) static uint32 assign_cpu(void) { - cpu_topology_node* node; + const cpu_topology_node* node; do { int32 nextID = atomic_add(&sLastCPU, 1); node = get_cpu_topology(); diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 18c8784..4801cde 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -751,7 +751,7 @@ scheduler_set_cpu_enabled(int32 cpuID, bool enabled) static void -traverse_topology_tree(cpu_topology_node* node, int packageID, int coreID) +traverse_topology_tree(const cpu_topology_node* node, int packageID, int coreID) { switch (node->level) { case CPU_TOPOLOGY_SMT: @@ -805,7 +805,7 @@ build_topology_mappings(int32& cpuCount, int32& coreCount, int32& packageCount) } } - cpu_topology_node* root = get_cpu_topology(); + const cpu_topology_node* root = get_cpu_topology(); traverse_topology_tree(root, 0, 0); cpuToCoreDeleter.Detach(); ############################################################################ Commit: 23bf5fe778cc85fe6bd5ed5a262be27414c3ff8d Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Dec 17 22:26:37 2013 UTC kernel: Propagate scheduler modes to cpu{freq, idle} modules ---------------------------------------------------------------------------- diff --git a/headers/os/drivers/cpufreq.h b/headers/os/drivers/cpufreq.h index ad36f99..3eb04b7 100644 --- a/headers/os/drivers/cpufreq.h +++ b/headers/os/drivers/cpufreq.h @@ -8,6 +8,8 @@ #include <module.h> +#include <scheduler.h> + #define CPUFREQ_MODULES_PREFIX "power/cpufreq" @@ -19,8 +21,10 @@ typedef struct cpufreq_module_info { float rank; - status_t (*increase_performance)(int delta, bool allowBoost); - status_t (*decrease_performance)(int delta); + void (*cpufreq_set_scheduler_mode)(enum scheduler_mode mode); + + status_t (*cpufreq_increase_performance)(int delta); + status_t (*cpufreq_decrease_performance)(int delta); } cpufreq_module_info; diff --git a/headers/os/drivers/cpuidle.h b/headers/os/drivers/cpuidle.h index c22b3e6..2373978 100644 --- a/headers/os/drivers/cpuidle.h +++ b/headers/os/drivers/cpuidle.h @@ -8,6 +8,8 @@ #include <module.h> +#include <scheduler.h> + #define CPUIDLE_MODULES_PREFIX "power/cpuidle" @@ -17,8 +19,10 @@ typedef struct cpuidle_module_info { float rank; - void (*idle)(void); - void (*wait)(int32* variable, int32 test); + void (*cpuidle_set_scheduler_mode)(enum scheduler_mode mode); + + void (*cpuidle_idle)(void); + void (*cpuidle_wait)(int32* variable, int32 test); } cpuidle_module_info; diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index 73614ab..17b056a 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -16,6 +16,8 @@ #include <timer.h> #include <arch/cpu.h> +#include <scheduler.h> + struct kernel_args; @@ -107,7 +109,9 @@ extern inline cpu_ent *get_cpu_struct(void) { return &gCPU[smp_get_current_cpu() status_t cpu_build_topology_tree(void); const cpu_topology_node* get_cpu_topology(void); -status_t increase_cpu_performance(int delta, bool allowBoost); +void cpu_set_scheduler_mode(enum scheduler_mode mode); + +status_t increase_cpu_performance(int delta); status_t decrease_cpu_performance(int delta); void cpu_idle(void); diff --git a/headers/private/kernel/kscheduler.h b/headers/private/kernel/kscheduler.h index 16316e8..bfc6e02 100644 --- a/headers/private/kernel/kscheduler.h +++ b/headers/private/kernel/kscheduler.h @@ -18,12 +18,6 @@ struct scheduling_analysis; struct SchedulerListener; -enum scheduler_mode { - SCHEDULER_MODE_LOW_LATENCY, - SCHEDULER_MODE_POWER_SAVING, -}; - - #ifdef __cplusplus extern "C" { #endif diff --git a/src/add-ons/kernel/power/cpufreq/intel_pstates/intel_pstates.cpp b/src/add-ons/kernel/power/cpufreq/intel_pstates/intel_pstates.cpp index f7f7fe1..5b545fc 100644 --- a/src/add-ons/kernel/power/cpufreq/intel_pstates/intel_pstates.cpp +++ b/src/add-ons/kernel/power/cpufreq/intel_pstates/intel_pstates.cpp @@ -25,6 +25,8 @@ static uint16 sMinPState; static uint16 sMaxPState; static uint16 sBoostPState; +static bool sAvoidBoost; + struct CPUEntry { CPUEntry(); @@ -32,7 +34,7 @@ struct CPUEntry { uint16 fCurrentPState; bigtime_t fLastUpdate; -}; +} CACHE_LINE_ALIGN; static CPUEntry* sCPUEntries; @@ -44,6 +46,13 @@ CPUEntry::CPUEntry() } +static void +pstates_set_scheduler_mode(scheduler_mode mode) +{ + sAvoidBoost = mode == SCHEDULER_MODE_POWER_SAVING; +} + + static int measure_pstate(CPUEntry* entry) { @@ -83,7 +92,7 @@ set_pstate(uint16 pstate) static status_t -increase_performance(int delta, bool allowBoost) +pstates_increase_performance(int delta) { CPUEntry* entry = &sCPUEntries[smp_get_current_cpu()]; @@ -93,7 +102,7 @@ increase_performance(int delta, bool allowBoost) int pState = measure_pstate(entry); pState += (sBoostPState - pState) * delta / kCPUPerformanceScaleMax; - if (!allowBoost) + if (sAvoidBoost && pState < (sMaxPState + sBoostPState) / 2) pState = min_c(pState, sMaxPState); set_pstate(pState); @@ -102,7 +111,7 @@ increase_performance(int delta, bool allowBoost) static status_t -decrease_performance(int delta) +pstates_decrease_performance(int delta) { CPUEntry* entry = &sCPUEntries[smp_get_current_cpu()]; @@ -184,6 +193,8 @@ init_pstates() if (sCPUEntries == NULL) return B_NO_MEMORY; + pstates_set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY); + call_all_cpus_sync(set_normal_pstate, NULL); return B_OK; } @@ -224,8 +235,10 @@ static cpufreq_module_info sIntelPStates = { 1.0f, - increase_performance, - decrease_performance, + pstates_set_scheduler_mode, + + pstates_increase_performance, + pstates_decrease_performance, }; diff --git a/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp b/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp index d401b45..c90b010 100644 --- a/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp +++ b/src/add-ons/kernel/power/cpuidle/intel_cstates/intel_cstates.cpp @@ -27,17 +27,19 @@ #define INTEL_CSTATES_MODULE_NAME CPUIDLE_MODULES_PREFIX "/intel_cstates/v1" -#define TIME_STEP 250 +#define BASE_TIME_STEP 500 struct CState { uint32 fCode; int fSubStatesCount; - int fSubStatesStep; }; static CState sCStates[CPUIDLE_CSTATE_MAX]; static int sCStateCount; +static int sTimeStep = BASE_TIME_STEP; +static bool sEnableWait = false; + static bigtime_t* sIdleTime; @@ -56,18 +58,31 @@ x86_mwait(uint32 eax, uint32 ecx) static void -idle(void) +cstates_set_scheduler_mode(scheduler_mode mode) +{ + if (mode == SCHEDULER_MODE_POWER_SAVING) { + sTimeStep = BASE_TIME_STEP / 4; + sEnableWait = true; + } else { + sTimeStep = BASE_TIME_STEP; + sEnableWait = false; + } +} + + +static void +cstates_idle(void) { ASSERT(thread_get_current_thread()->pinned_to_cpu > 0); int32 cpu = smp_get_current_cpu(); bigtime_t idleTime = sIdleTime[cpu]; - int state = min_c(idleTime / TIME_STEP, sCStateCount - 1); + int state = min_c(idleTime / sTimeStep, sCStateCount - 1); ASSERT(state >= 0 && state < sCStateCount); - int subState = idleTime % TIME_STEP; - subState /= sCStates[state].fSubStatesStep; + int subState = idleTime % sTimeStep; + subState /= sTimeStep / sCStates[state].fSubStatesCount; ASSERT(subState >= 0 && subState < sCStates[state].fSubStatesCount); @@ -84,8 +99,11 @@ idle(void) static void -wait(int32* variable, int32 test) +cstates_wait(int32* variable, int32 test) { + if (!sEnableWait) + return; + InterruptsLocker _; x86_monitor(variable, 0, 0); if (*variable != test) @@ -133,7 +151,6 @@ init_cstates() sCStates[sCStateCount].fCode = sCStateCount * 0x10; sCStates[sCStateCount].fSubStatesCount = subStates; - sCStates[sCStateCount].fSubStatesStep = TIME_STEP / subStates; sCStateCount++; } @@ -145,6 +162,8 @@ init_cstates() return B_NO_MEMORY; memset(sIdleTime, 0, sizeof(bigtime_t) * smp_get_num_cpus()); + cstates_set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY); + dprintf("using Intel C-States: C0%s\n", cStates); return B_OK; } @@ -183,8 +202,10 @@ static cpuidle_module_info sIntelCStates = { 0.8f, - idle, - wait + cstates_set_scheduler_mode, + + cstates_idle, + cstates_wait }; diff --git a/src/system/kernel/cpu.cpp b/src/system/kernel/cpu.cpp index 2adc443..a0ffcaf 100644 --- a/src/system/kernel/cpu.cpp +++ b/src/system/kernel/cpu.cpp @@ -281,11 +281,21 @@ get_cpu_topology(void) } +void +cpu_set_scheduler_mode(enum scheduler_mode mode) +{ + if (sCPUPerformanceModule != NULL) + sCPUPerformanceModule->cpufreq_set_scheduler_mode(mode); + if (sCPUIdleModule != NULL) + sCPUIdleModule->cpuidle_set_scheduler_mode(mode); +} + + status_t -increase_cpu_performance(int delta, bool allowBoost) +increase_cpu_performance(int delta) { if (sCPUPerformanceModule != NULL) - return sCPUPerformanceModule->increase_performance(delta, allowBoost); + return sCPUPerformanceModule->cpufreq_increase_performance(delta); return B_NOT_SUPPORTED; } @@ -294,7 +304,7 @@ status_t decrease_cpu_performance(int delta) { if (sCPUPerformanceModule != NULL) - return sCPUPerformanceModule->decrease_performance(delta); + return sCPUPerformanceModule->cpufreq_decrease_performance(delta); return B_NOT_SUPPORTED; } @@ -308,7 +318,7 @@ cpu_idle(void) #endif if (sCPUIdleModule != NULL) - sCPUIdleModule->idle(); + sCPUIdleModule->cpuidle_idle(); else arch_cpu_idle(); } @@ -318,7 +328,7 @@ void cpu_wait(int32* variable, int32 test) { if (sCPUIdleModule != NULL) - sCPUIdleModule->wait(variable, test); + sCPUIdleModule->cpuidle_wait(variable, test); else arch_cpu_pause(); } diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 4801cde..5484b45 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -996,7 +996,11 @@ _user_estimate_max_scheduling_latency(thread_id id) status_t _user_set_scheduler_mode(int32 mode) { - return scheduler_set_operation_mode(static_cast<scheduler_mode>(mode)); + scheduler_mode schedulerMode = static_cast<scheduler_mode>(mode); + status_t error = scheduler_set_operation_mode(schedulerMode); + if (error == B_OK) + cpu_set_scheduler_mode(schedulerMode); + return error; } diff --git a/src/system/kernel/scheduler/scheduler_cpu.cpp b/src/system/kernel/scheduler/scheduler_cpu.cpp index c78d62a..3c8203a 100644 --- a/src/system/kernel/scheduler/scheduler_cpu.cpp +++ b/src/system/kernel/scheduler/scheduler_cpu.cpp @@ -215,13 +215,11 @@ CPUEntry::_RequestPerformanceLevel(ThreadData* threadData) decrease_cpu_performance(delta); } else { - bool allowBoost = !gCurrentMode->avoid_boost; - int32 delta = load - kTargetLoad; delta *= kMaxLoad - kTargetLoad; delta /= kCPUPerformanceScaleMax; - increase_cpu_performance(delta, allowBoost); + increase_cpu_performance(delta); } } ############################################################################ Commit: 7ce234bf2444831f6340230e9e42900ce25c0173 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Dec 17 23:03:56 2013 UTC scheduler: Fix unassigning threads from core being disabled ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 5484b45..b6d303b 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -677,7 +677,7 @@ scheduler_set_cpu_enabled(int32 cpuID, bool enabled) gIdlePackageList.Remove(package); // get rid of threads - thread_map(unassign_thread, &core->fCoreID); + thread_map(unassign_thread, core); core->fThreadCount = 0; while (core->fRunQueue.PeekMaximum() != NULL) {