Loading include/linux/sched.h +3 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,9 @@ extern u64 nr_running_integral(unsigned int cpu); #endif extern void sched_update_nr_prod(int cpu, long delta, bool inc); extern void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg); extern void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg, unsigned int *max_nr, unsigned int *big_max_nr); extern void calc_global_load(unsigned long ticks); Loading include/trace/events/sched.h +10 −4 Original line number Diff line number Diff line Loading @@ -1312,24 +1312,30 @@ TRACE_EVENT(sched_wake_idle_without_ipi, TRACE_EVENT(sched_get_nr_running_avg, TP_PROTO(int avg, int big_avg, int iowait_avg), TP_PROTO(int avg, int big_avg, int iowait_avg, unsigned int max_nr, unsigned int big_max_nr), TP_ARGS(avg, big_avg, iowait_avg), TP_ARGS(avg, big_avg, iowait_avg, max_nr, big_max_nr), TP_STRUCT__entry( __field( int, avg ) __field( int, big_avg ) __field( int, iowait_avg ) __field( unsigned int, max_nr ) __field( unsigned int, big_max_nr ) ), TP_fast_assign( __entry->avg = avg; __entry->big_avg = big_avg; __entry->iowait_avg = iowait_avg; __entry->max_nr = max_nr; __entry->big_max_nr = big_max_nr; ), TP_printk("avg=%d big_avg=%d iowait_avg=%d", __entry->avg, __entry->big_avg, __entry->iowait_avg) TP_printk("avg=%d big_avg=%d iowait_avg=%d max_nr=%u big_max_nr=%u", __entry->avg, __entry->big_avg, __entry->iowait_avg, __entry->max_nr, __entry->big_max_nr) ); TRACE_EVENT(core_ctl_eval_need, Loading kernel/sched/core_ctl.c +22 −28 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ struct cluster_data { cpumask_t cpu_mask; unsigned int need_cpus; unsigned int task_thres; unsigned int max_nr; s64 need_ts; struct list_head lru; bool pending; Loading @@ -60,6 +61,7 @@ struct cpu_data { struct cluster_data *cluster; struct list_head sib; bool isolated_by_us; unsigned int max_nr; }; static DEFINE_PER_CPU(struct cpu_data, cpu_state); Loading Loading @@ -429,7 +431,6 @@ static struct kobj_type ktype_core_ctl = { #define RQ_AVG_TOLERANCE 2 #define RQ_AVG_DEFAULT_MS 20 #define NR_RUNNING_TOLERANCE 5 static unsigned int rq_avg_period_ms = RQ_AVG_DEFAULT_MS; static s64 rq_avg_timestamp_ms; Loading @@ -437,6 +438,7 @@ static s64 rq_avg_timestamp_ms; static void update_running_avg(bool trigger_update) { int avg, iowait_avg, big_avg, old_nrrun; int old_max_nr, max_nr, big_max_nr; s64 now; unsigned long flags; struct cluster_data *cluster; Loading @@ -450,40 +452,23 @@ static void update_running_avg(bool trigger_update) return; } rq_avg_timestamp_ms = now; sched_get_nr_running_avg(&avg, &iowait_avg, &big_avg); sched_get_nr_running_avg(&avg, &iowait_avg, &big_avg, &max_nr, &big_max_nr); spin_unlock_irqrestore(&state_lock, flags); /* * Round up to the next integer if the average nr running tasks * is within NR_RUNNING_TOLERANCE/100 of the next integer. * If normal rounding up is used, it will allow a transient task * to trigger online event. By the time core is onlined, the task * has finished. * Rounding to closest suffers same problem because scheduler * might only provide running stats per jiffy, and a transient * task could skew the number for one jiffy. If core control * samples every 2 jiffies, it will observe 0.5 additional running * average which rounds up to 1 task. */ avg = (avg + NR_RUNNING_TOLERANCE) / 100; big_avg = (big_avg + NR_RUNNING_TOLERANCE) / 100; for_each_cluster(cluster, index) { if (!cluster->inited) continue; old_nrrun = cluster->nrrun; /* * Big cluster only need to take care of big tasks, but if * there are not enough big cores, big tasks need to be run * on little as well. Thus for little's runqueue stat, it * has to use overall runqueue average, or derive what big * tasks would have to be run on little. The latter approach * is not easy to get given core control reacts much slower * than scheduler, and can't predict scheduler's behavior. */ old_max_nr = cluster->max_nr; cluster->nrrun = cluster->is_big_cluster ? big_avg : avg; if (cluster->nrrun != old_nrrun) { cluster->max_nr = cluster->is_big_cluster ? big_max_nr : max_nr; if (cluster->nrrun != old_nrrun || cluster->max_nr != old_max_nr) { if (trigger_update) apply_need(cluster); else Loading @@ -493,6 +478,7 @@ static void update_running_avg(bool trigger_update) return; } #define MAX_NR_THRESHOLD 4 /* adjust needed CPUs based on current runqueue information */ static unsigned int apply_task_need(const struct cluster_data *cluster, unsigned int new_need) Loading @@ -503,7 +489,15 @@ static unsigned int apply_task_need(const struct cluster_data *cluster, /* only unisolate more cores if there are tasks to run */ if (cluster->nrrun > new_need) return new_need + 1; new_need = new_need + 1; /* * We don't want tasks to be overcrowded in a cluster. * If any CPU has more than MAX_NR_THRESHOLD in the last * window, bring another CPU to help out. */ if (cluster->max_nr > MAX_NR_THRESHOLD) new_need = new_need + 1; return new_need; } Loading kernel/sched/hmp.c +1 −1 Original line number Diff line number Diff line Loading @@ -1602,7 +1602,7 @@ unsigned int nr_eligible_big_tasks(int cpu) int nr_big = rq->hmp_stats.nr_big_tasks; int nr = rq->nr_running; if (cpu_max_possible_capacity(cpu) != max_possible_capacity) if (!is_max_capacity_cpu(cpu)) return nr_big; return nr; Loading kernel/sched/sched.h +7 −0 Original line number Diff line number Diff line Loading @@ -1225,6 +1225,11 @@ static inline bool hmp_capable(void) return max_possible_capacity != min_max_possible_capacity; } static inline bool is_max_capacity_cpu(int cpu) { return cpu_max_possible_capacity(cpu) == max_possible_capacity; } /* * 'load' is in reference to "best cpu" at its best frequency. * Scale that in reference to a given cpu, accounting for how bad it is Loading Loading @@ -1601,6 +1606,8 @@ static inline unsigned int nr_eligible_big_tasks(int cpu) return 0; } static inline bool is_max_capacity_cpu(int cpu) { return true; } static inline int pct_task_load(struct task_struct *p) { return 0; } static inline int cpu_capacity(int cpu) Loading Loading
include/linux/sched.h +3 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,9 @@ extern u64 nr_running_integral(unsigned int cpu); #endif extern void sched_update_nr_prod(int cpu, long delta, bool inc); extern void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg); extern void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg, unsigned int *max_nr, unsigned int *big_max_nr); extern void calc_global_load(unsigned long ticks); Loading
include/trace/events/sched.h +10 −4 Original line number Diff line number Diff line Loading @@ -1312,24 +1312,30 @@ TRACE_EVENT(sched_wake_idle_without_ipi, TRACE_EVENT(sched_get_nr_running_avg, TP_PROTO(int avg, int big_avg, int iowait_avg), TP_PROTO(int avg, int big_avg, int iowait_avg, unsigned int max_nr, unsigned int big_max_nr), TP_ARGS(avg, big_avg, iowait_avg), TP_ARGS(avg, big_avg, iowait_avg, max_nr, big_max_nr), TP_STRUCT__entry( __field( int, avg ) __field( int, big_avg ) __field( int, iowait_avg ) __field( unsigned int, max_nr ) __field( unsigned int, big_max_nr ) ), TP_fast_assign( __entry->avg = avg; __entry->big_avg = big_avg; __entry->iowait_avg = iowait_avg; __entry->max_nr = max_nr; __entry->big_max_nr = big_max_nr; ), TP_printk("avg=%d big_avg=%d iowait_avg=%d", __entry->avg, __entry->big_avg, __entry->iowait_avg) TP_printk("avg=%d big_avg=%d iowait_avg=%d max_nr=%u big_max_nr=%u", __entry->avg, __entry->big_avg, __entry->iowait_avg, __entry->max_nr, __entry->big_max_nr) ); TRACE_EVENT(core_ctl_eval_need, Loading
kernel/sched/core_ctl.c +22 −28 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ struct cluster_data { cpumask_t cpu_mask; unsigned int need_cpus; unsigned int task_thres; unsigned int max_nr; s64 need_ts; struct list_head lru; bool pending; Loading @@ -60,6 +61,7 @@ struct cpu_data { struct cluster_data *cluster; struct list_head sib; bool isolated_by_us; unsigned int max_nr; }; static DEFINE_PER_CPU(struct cpu_data, cpu_state); Loading Loading @@ -429,7 +431,6 @@ static struct kobj_type ktype_core_ctl = { #define RQ_AVG_TOLERANCE 2 #define RQ_AVG_DEFAULT_MS 20 #define NR_RUNNING_TOLERANCE 5 static unsigned int rq_avg_period_ms = RQ_AVG_DEFAULT_MS; static s64 rq_avg_timestamp_ms; Loading @@ -437,6 +438,7 @@ static s64 rq_avg_timestamp_ms; static void update_running_avg(bool trigger_update) { int avg, iowait_avg, big_avg, old_nrrun; int old_max_nr, max_nr, big_max_nr; s64 now; unsigned long flags; struct cluster_data *cluster; Loading @@ -450,40 +452,23 @@ static void update_running_avg(bool trigger_update) return; } rq_avg_timestamp_ms = now; sched_get_nr_running_avg(&avg, &iowait_avg, &big_avg); sched_get_nr_running_avg(&avg, &iowait_avg, &big_avg, &max_nr, &big_max_nr); spin_unlock_irqrestore(&state_lock, flags); /* * Round up to the next integer if the average nr running tasks * is within NR_RUNNING_TOLERANCE/100 of the next integer. * If normal rounding up is used, it will allow a transient task * to trigger online event. By the time core is onlined, the task * has finished. * Rounding to closest suffers same problem because scheduler * might only provide running stats per jiffy, and a transient * task could skew the number for one jiffy. If core control * samples every 2 jiffies, it will observe 0.5 additional running * average which rounds up to 1 task. */ avg = (avg + NR_RUNNING_TOLERANCE) / 100; big_avg = (big_avg + NR_RUNNING_TOLERANCE) / 100; for_each_cluster(cluster, index) { if (!cluster->inited) continue; old_nrrun = cluster->nrrun; /* * Big cluster only need to take care of big tasks, but if * there are not enough big cores, big tasks need to be run * on little as well. Thus for little's runqueue stat, it * has to use overall runqueue average, or derive what big * tasks would have to be run on little. The latter approach * is not easy to get given core control reacts much slower * than scheduler, and can't predict scheduler's behavior. */ old_max_nr = cluster->max_nr; cluster->nrrun = cluster->is_big_cluster ? big_avg : avg; if (cluster->nrrun != old_nrrun) { cluster->max_nr = cluster->is_big_cluster ? big_max_nr : max_nr; if (cluster->nrrun != old_nrrun || cluster->max_nr != old_max_nr) { if (trigger_update) apply_need(cluster); else Loading @@ -493,6 +478,7 @@ static void update_running_avg(bool trigger_update) return; } #define MAX_NR_THRESHOLD 4 /* adjust needed CPUs based on current runqueue information */ static unsigned int apply_task_need(const struct cluster_data *cluster, unsigned int new_need) Loading @@ -503,7 +489,15 @@ static unsigned int apply_task_need(const struct cluster_data *cluster, /* only unisolate more cores if there are tasks to run */ if (cluster->nrrun > new_need) return new_need + 1; new_need = new_need + 1; /* * We don't want tasks to be overcrowded in a cluster. * If any CPU has more than MAX_NR_THRESHOLD in the last * window, bring another CPU to help out. */ if (cluster->max_nr > MAX_NR_THRESHOLD) new_need = new_need + 1; return new_need; } Loading
kernel/sched/hmp.c +1 −1 Original line number Diff line number Diff line Loading @@ -1602,7 +1602,7 @@ unsigned int nr_eligible_big_tasks(int cpu) int nr_big = rq->hmp_stats.nr_big_tasks; int nr = rq->nr_running; if (cpu_max_possible_capacity(cpu) != max_possible_capacity) if (!is_max_capacity_cpu(cpu)) return nr_big; return nr; Loading
kernel/sched/sched.h +7 −0 Original line number Diff line number Diff line Loading @@ -1225,6 +1225,11 @@ static inline bool hmp_capable(void) return max_possible_capacity != min_max_possible_capacity; } static inline bool is_max_capacity_cpu(int cpu) { return cpu_max_possible_capacity(cpu) == max_possible_capacity; } /* * 'load' is in reference to "best cpu" at its best frequency. * Scale that in reference to a given cpu, accounting for how bad it is Loading Loading @@ -1601,6 +1606,8 @@ static inline unsigned int nr_eligible_big_tasks(int cpu) return 0; } static inline bool is_max_capacity_cpu(int cpu) { return true; } static inline int pct_task_load(struct task_struct *p) { return 0; } static inline int cpu_capacity(int cpu) Loading