Loading arch/arm64/configs/sdm855-perf_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_CORE_CTL=y Loading arch/arm64/configs/sdm855_defconfig +5 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_CGROUP_DEBUG=y Loading Loading @@ -487,6 +488,8 @@ CONFIG_DEBUG_MEMORY_INIT=y CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_WQ_WATCHDOG=y CONFIG_PANIC_TIMEOUT=5 CONFIG_PANIC_ON_SCHED_BUG=y CONFIG_PANIC_ON_RT_THROTTLING=y CONFIG_SCHEDSTATS=y CONFIG_SCHED_STACK_END_CHECK=y # CONFIG_DEBUG_PREEMPT is not set Loading @@ -503,7 +506,8 @@ CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_IPC_LOGGING=y CONFIG_FUNCTION_TRACER=y CONFIG_TRACER_SNAPSHOT=y CONFIG_IRQSOFF_TRACER=y CONFIG_PREEMPT_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_MEMTEST=y CONFIG_BUG_ON_DATA_CORRUPTION=y Loading kernel/sched/core.c +6 −0 Original line number Diff line number Diff line Loading @@ -3300,6 +3300,9 @@ static noinline void __schedule_bug(struct task_struct *prev) if (panic_on_warn) panic("scheduling while atomic\n"); #ifdef CONFIG_PANIC_ON_SCHED_BUG BUG(); #endif dump_stack(); add_taint(TAINT_WARN, LOCKDEP_STILL_OK); } Loading Loading @@ -6473,6 +6476,9 @@ void ___might_sleep(const char *file, int line, int preempt_offset) print_ip_sym(preempt_disable_ip); pr_cont("\n"); } #ifdef CONFIG_PANIC_ON_SCHED_BUG BUG(); #endif dump_stack(); add_taint(TAINT_WARN, LOCKDEP_STILL_OK); } Loading kernel/sched/fair.c +0 −7 Original line number Diff line number Diff line Loading @@ -4968,8 +4968,6 @@ static inline void hrtick_update(struct rq *rq) #endif #ifdef CONFIG_SMP static bool cpu_overutilized(int cpu); static unsigned long cpu_util(int cpu); static bool sd_overutilized(struct sched_domain *sd) Loading Loading @@ -5507,11 +5505,6 @@ unsigned long capacity_curr_of(int cpu) return cap_scale(max_cap, scale_freq); } static inline bool energy_aware(void) { return sched_feat(ENERGY_AWARE); } /* * Externally visible function. Let's keep the one above * so that the check is inlined/optimized in the sched paths. Loading kernel/sched/rt.c +178 −5 Original line number Diff line number Diff line Loading @@ -905,6 +905,66 @@ static inline int rt_se_prio(struct sched_rt_entity *rt_se) return rt_task_of(rt_se)->prio; } static void dump_throttled_rt_tasks(struct rt_rq *rt_rq) { struct rt_prio_array *array = &rt_rq->active; struct sched_rt_entity *rt_se; char buf[500]; char *pos = buf; char *end = buf + sizeof(buf); int idx; struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); pos += snprintf(pos, sizeof(buf), "sched: RT throttling activated for rt_rq %pK (cpu %d)\n", rt_rq, cpu_of(rq_of_rt_rq(rt_rq))); pos += snprintf(pos, end - pos, "rt_period_timer: expires=%lld now=%llu period=%llu\n", hrtimer_get_expires_ns(&rt_b->rt_period_timer), ktime_get_ns(), sched_rt_period(rt_rq)); if (bitmap_empty(array->bitmap, MAX_RT_PRIO)) goto out; pos += snprintf(pos, end - pos, "potential CPU hogs:\n"); #ifdef CONFIG_SCHED_INFO if (sched_info_on()) pos += snprintf(pos, end - pos, "current %s (%d) is running for %llu nsec\n", current->comm, current->pid, rq_clock(rq_of_rt_rq(rt_rq)) - current->sched_info.last_arrival); #endif idx = sched_find_first_bit(array->bitmap); while (idx < MAX_RT_PRIO) { list_for_each_entry(rt_se, array->queue + idx, run_list) { struct task_struct *p; if (!rt_entity_is_task(rt_se)) continue; p = rt_task_of(rt_se); if (pos < end) pos += snprintf(pos, end - pos, "\t%s (%d)\n", p->comm, p->pid); } idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx + 1); } out: #ifdef CONFIG_PANIC_ON_RT_THROTTLING /* * Use pr_err() in the BUG() case since printk_sched() will * not get flushed and deadlock is not a concern. */ pr_err("%s", buf); BUG(); #else printk_deferred("%s", buf); #endif } static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) { u64 runtime = sched_rt_runtime(rt_rq); Loading @@ -928,8 +988,14 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) * but accrue some time due to boosting. */ if (likely(rt_b->rt_runtime)) { static bool once; rt_rq->rt_throttled = 1; printk_deferred_once("sched: RT throttling activated\n"); if (!once) { once = true; dump_throttled_rt_tasks(rt_rq); } } else { /* * In case we did anyway, make it go away, Loading Loading @@ -1422,9 +1488,10 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags, * This test is optimistic, if we get it wrong the load-balancer * will have to sort it out. */ if (curr && unlikely(rt_task(curr)) && if (energy_aware() || (curr && unlikely(rt_task(curr)) && (curr->nr_cpus_allowed < 2 || curr->prio <= p->prio)) { curr->prio <= p->prio))) { int target = find_lowest_rq(p); /* Loading Loading @@ -1636,12 +1703,112 @@ static struct task_struct *pick_highest_pushable_task(struct rq *rq, int cpu) static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask); static int rt_energy_aware_wake_cpu(struct task_struct *task) { struct sched_domain *sd; struct sched_group *sg, *sg_target = NULL; struct cpumask *lowest_mask = this_cpu_cpumask_var_ptr(local_cpu_mask); int cpu, best_cpu = -1; struct cpumask search_cpu, backup_search_cpu; unsigned long cpu_capacity, capacity = ULONG_MAX; unsigned long util, best_cpu_util = ULONG_MAX; unsigned long best_cpu_util_cum = ULONG_MAX; unsigned long util_cum; unsigned long tutil = task_util(task); int best_cpu_idle_idx = INT_MAX; int cpu_idle_idx = -1; rcu_read_lock(); sd = rcu_dereference(per_cpu(sd_ea, task_cpu(task))); if (!sd) { rcu_read_unlock(); return best_cpu; } sg = sd->groups; do { cpu = group_first_cpu(sg); cpu_capacity = capacity_orig_of(cpu); if (cpu_capacity < capacity) { capacity = cpu_capacity; sg_target = sg; } } while (sg = sg->next, sg != sd->groups); rcu_read_unlock(); cpumask_and(&search_cpu, lowest_mask, sched_group_span(sg_target)); cpumask_copy(&backup_search_cpu, lowest_mask); cpumask_andnot(&backup_search_cpu, &backup_search_cpu, &search_cpu); retry: for_each_cpu(cpu, &search_cpu) { if (cpu_isolated(cpu)) continue; if (sched_cpu_high_irqload(cpu)) continue; util = cpu_util(cpu); if (__cpu_overutilized(cpu, util + tutil)) continue; /* Find the least loaded CPU */ if (util > best_cpu_util) continue; /* * If the previous CPU has same load, keep it as * best_cpu. */ if (best_cpu_util == util && best_cpu == task_cpu(task)) continue; /* * If candidate CPU is the previous CPU, select it. * Otherwise, if its load is same with best_cpu and in * a shallower C-state, select it. If all above * conditions are same, select the least cumulative * window demand CPU. */ if (sysctl_sched_cstate_aware) cpu_idle_idx = idle_get_state_idx(cpu_rq(cpu)); util_cum = cpu_util_cum(cpu, 0); if (cpu != task_cpu(task) && best_cpu_util == util) { if (best_cpu_idle_idx < cpu_idle_idx) continue; if (best_cpu_idle_idx == cpu_idle_idx && best_cpu_util_cum < util_cum) continue; } best_cpu_idle_idx = cpu_idle_idx; best_cpu_util_cum = util_cum; best_cpu_util = util; best_cpu = cpu; } if (best_cpu != -1) { return best_cpu; } else if (!cpumask_empty(&backup_search_cpu)) { cpumask_copy(&search_cpu, &backup_search_cpu); cpumask_clear(&backup_search_cpu); goto retry; } else { return best_cpu; } } static int find_lowest_rq(struct task_struct *task) { struct sched_domain *sd; struct cpumask *lowest_mask = this_cpu_cpumask_var_ptr(local_cpu_mask); int this_cpu = smp_processor_id(); int cpu = task_cpu(task); int cpu = -1; /* Make sure the mask is initialized first */ if (unlikely(!lowest_mask)) Loading @@ -1653,6 +1820,12 @@ static int find_lowest_rq(struct task_struct *task) if (!cpupri_find(&task_rq(task)->rd->cpupri, task, lowest_mask)) return -1; /* No targets found */ if (energy_aware()) cpu = rt_energy_aware_wake_cpu(task); if (cpu == -1) cpu = task_cpu(task); /* * At this point we have built a mask of cpus representing the * lowest priority tasks in the system. Now we want to elect Loading Loading
arch/arm64/configs/sdm855-perf_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_CORE_CTL=y Loading
arch/arm64/configs/sdm855_defconfig +5 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_CGROUP_DEBUG=y Loading Loading @@ -487,6 +488,8 @@ CONFIG_DEBUG_MEMORY_INIT=y CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_WQ_WATCHDOG=y CONFIG_PANIC_TIMEOUT=5 CONFIG_PANIC_ON_SCHED_BUG=y CONFIG_PANIC_ON_RT_THROTTLING=y CONFIG_SCHEDSTATS=y CONFIG_SCHED_STACK_END_CHECK=y # CONFIG_DEBUG_PREEMPT is not set Loading @@ -503,7 +506,8 @@ CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_IPC_LOGGING=y CONFIG_FUNCTION_TRACER=y CONFIG_TRACER_SNAPSHOT=y CONFIG_IRQSOFF_TRACER=y CONFIG_PREEMPT_TRACER=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_MEMTEST=y CONFIG_BUG_ON_DATA_CORRUPTION=y Loading
kernel/sched/core.c +6 −0 Original line number Diff line number Diff line Loading @@ -3300,6 +3300,9 @@ static noinline void __schedule_bug(struct task_struct *prev) if (panic_on_warn) panic("scheduling while atomic\n"); #ifdef CONFIG_PANIC_ON_SCHED_BUG BUG(); #endif dump_stack(); add_taint(TAINT_WARN, LOCKDEP_STILL_OK); } Loading Loading @@ -6473,6 +6476,9 @@ void ___might_sleep(const char *file, int line, int preempt_offset) print_ip_sym(preempt_disable_ip); pr_cont("\n"); } #ifdef CONFIG_PANIC_ON_SCHED_BUG BUG(); #endif dump_stack(); add_taint(TAINT_WARN, LOCKDEP_STILL_OK); } Loading
kernel/sched/fair.c +0 −7 Original line number Diff line number Diff line Loading @@ -4968,8 +4968,6 @@ static inline void hrtick_update(struct rq *rq) #endif #ifdef CONFIG_SMP static bool cpu_overutilized(int cpu); static unsigned long cpu_util(int cpu); static bool sd_overutilized(struct sched_domain *sd) Loading Loading @@ -5507,11 +5505,6 @@ unsigned long capacity_curr_of(int cpu) return cap_scale(max_cap, scale_freq); } static inline bool energy_aware(void) { return sched_feat(ENERGY_AWARE); } /* * Externally visible function. Let's keep the one above * so that the check is inlined/optimized in the sched paths. Loading
kernel/sched/rt.c +178 −5 Original line number Diff line number Diff line Loading @@ -905,6 +905,66 @@ static inline int rt_se_prio(struct sched_rt_entity *rt_se) return rt_task_of(rt_se)->prio; } static void dump_throttled_rt_tasks(struct rt_rq *rt_rq) { struct rt_prio_array *array = &rt_rq->active; struct sched_rt_entity *rt_se; char buf[500]; char *pos = buf; char *end = buf + sizeof(buf); int idx; struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); pos += snprintf(pos, sizeof(buf), "sched: RT throttling activated for rt_rq %pK (cpu %d)\n", rt_rq, cpu_of(rq_of_rt_rq(rt_rq))); pos += snprintf(pos, end - pos, "rt_period_timer: expires=%lld now=%llu period=%llu\n", hrtimer_get_expires_ns(&rt_b->rt_period_timer), ktime_get_ns(), sched_rt_period(rt_rq)); if (bitmap_empty(array->bitmap, MAX_RT_PRIO)) goto out; pos += snprintf(pos, end - pos, "potential CPU hogs:\n"); #ifdef CONFIG_SCHED_INFO if (sched_info_on()) pos += snprintf(pos, end - pos, "current %s (%d) is running for %llu nsec\n", current->comm, current->pid, rq_clock(rq_of_rt_rq(rt_rq)) - current->sched_info.last_arrival); #endif idx = sched_find_first_bit(array->bitmap); while (idx < MAX_RT_PRIO) { list_for_each_entry(rt_se, array->queue + idx, run_list) { struct task_struct *p; if (!rt_entity_is_task(rt_se)) continue; p = rt_task_of(rt_se); if (pos < end) pos += snprintf(pos, end - pos, "\t%s (%d)\n", p->comm, p->pid); } idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx + 1); } out: #ifdef CONFIG_PANIC_ON_RT_THROTTLING /* * Use pr_err() in the BUG() case since printk_sched() will * not get flushed and deadlock is not a concern. */ pr_err("%s", buf); BUG(); #else printk_deferred("%s", buf); #endif } static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) { u64 runtime = sched_rt_runtime(rt_rq); Loading @@ -928,8 +988,14 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) * but accrue some time due to boosting. */ if (likely(rt_b->rt_runtime)) { static bool once; rt_rq->rt_throttled = 1; printk_deferred_once("sched: RT throttling activated\n"); if (!once) { once = true; dump_throttled_rt_tasks(rt_rq); } } else { /* * In case we did anyway, make it go away, Loading Loading @@ -1422,9 +1488,10 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags, * This test is optimistic, if we get it wrong the load-balancer * will have to sort it out. */ if (curr && unlikely(rt_task(curr)) && if (energy_aware() || (curr && unlikely(rt_task(curr)) && (curr->nr_cpus_allowed < 2 || curr->prio <= p->prio)) { curr->prio <= p->prio))) { int target = find_lowest_rq(p); /* Loading Loading @@ -1636,12 +1703,112 @@ static struct task_struct *pick_highest_pushable_task(struct rq *rq, int cpu) static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask); static int rt_energy_aware_wake_cpu(struct task_struct *task) { struct sched_domain *sd; struct sched_group *sg, *sg_target = NULL; struct cpumask *lowest_mask = this_cpu_cpumask_var_ptr(local_cpu_mask); int cpu, best_cpu = -1; struct cpumask search_cpu, backup_search_cpu; unsigned long cpu_capacity, capacity = ULONG_MAX; unsigned long util, best_cpu_util = ULONG_MAX; unsigned long best_cpu_util_cum = ULONG_MAX; unsigned long util_cum; unsigned long tutil = task_util(task); int best_cpu_idle_idx = INT_MAX; int cpu_idle_idx = -1; rcu_read_lock(); sd = rcu_dereference(per_cpu(sd_ea, task_cpu(task))); if (!sd) { rcu_read_unlock(); return best_cpu; } sg = sd->groups; do { cpu = group_first_cpu(sg); cpu_capacity = capacity_orig_of(cpu); if (cpu_capacity < capacity) { capacity = cpu_capacity; sg_target = sg; } } while (sg = sg->next, sg != sd->groups); rcu_read_unlock(); cpumask_and(&search_cpu, lowest_mask, sched_group_span(sg_target)); cpumask_copy(&backup_search_cpu, lowest_mask); cpumask_andnot(&backup_search_cpu, &backup_search_cpu, &search_cpu); retry: for_each_cpu(cpu, &search_cpu) { if (cpu_isolated(cpu)) continue; if (sched_cpu_high_irqload(cpu)) continue; util = cpu_util(cpu); if (__cpu_overutilized(cpu, util + tutil)) continue; /* Find the least loaded CPU */ if (util > best_cpu_util) continue; /* * If the previous CPU has same load, keep it as * best_cpu. */ if (best_cpu_util == util && best_cpu == task_cpu(task)) continue; /* * If candidate CPU is the previous CPU, select it. * Otherwise, if its load is same with best_cpu and in * a shallower C-state, select it. If all above * conditions are same, select the least cumulative * window demand CPU. */ if (sysctl_sched_cstate_aware) cpu_idle_idx = idle_get_state_idx(cpu_rq(cpu)); util_cum = cpu_util_cum(cpu, 0); if (cpu != task_cpu(task) && best_cpu_util == util) { if (best_cpu_idle_idx < cpu_idle_idx) continue; if (best_cpu_idle_idx == cpu_idle_idx && best_cpu_util_cum < util_cum) continue; } best_cpu_idle_idx = cpu_idle_idx; best_cpu_util_cum = util_cum; best_cpu_util = util; best_cpu = cpu; } if (best_cpu != -1) { return best_cpu; } else if (!cpumask_empty(&backup_search_cpu)) { cpumask_copy(&search_cpu, &backup_search_cpu); cpumask_clear(&backup_search_cpu); goto retry; } else { return best_cpu; } } static int find_lowest_rq(struct task_struct *task) { struct sched_domain *sd; struct cpumask *lowest_mask = this_cpu_cpumask_var_ptr(local_cpu_mask); int this_cpu = smp_processor_id(); int cpu = task_cpu(task); int cpu = -1; /* Make sure the mask is initialized first */ if (unlikely(!lowest_mask)) Loading @@ -1653,6 +1820,12 @@ static int find_lowest_rq(struct task_struct *task) if (!cpupri_find(&task_rq(task)->rd->cpupri, task, lowest_mask)) return -1; /* No targets found */ if (energy_aware()) cpu = rt_energy_aware_wake_cpu(task); if (cpu == -1) cpu = task_cpu(task); /* * At this point we have built a mask of cpus representing the * lowest priority tasks in the system. Now we want to elect Loading