mirror of https://github.com/OpenIPC/firmware.git
440 lines
13 KiB
Diff
440 lines
13 KiB
Diff
diff -drupN a/kernel/sched/sched.h b/kernel/sched/sched.h
|
|
--- a/kernel/sched/sched.h 2018-08-06 17:23:04.000000000 +0300
|
|
+++ b/kernel/sched/sched.h 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -39,8 +39,10 @@ extern long calc_load_fold_active(struct
|
|
|
|
#ifdef CONFIG_SMP
|
|
extern void cpu_load_update_active(struct rq *this_rq);
|
|
+extern void check_for_migration(struct rq *rq, struct task_struct *p);
|
|
#else
|
|
static inline void cpu_load_update_active(struct rq *this_rq) { }
|
|
+static inline void check_for_migration(struct rq *rq, struct task_struct *p) { }
|
|
#endif
|
|
|
|
#ifdef CONFIG_SCHED_SMT
|
|
@@ -410,6 +412,7 @@ struct cfs_rq {
|
|
unsigned long runnable_load_avg;
|
|
#ifdef CONFIG_FAIR_GROUP_SCHED
|
|
unsigned long tg_load_avg_contrib;
|
|
+ unsigned long propagate_avg;
|
|
#endif
|
|
atomic_long_t removed_load_avg, removed_util_avg;
|
|
#ifndef CONFIG_64BIT
|
|
@@ -453,6 +456,9 @@ struct cfs_rq {
|
|
u64 throttled_clock_task_time;
|
|
int throttled, throttle_count;
|
|
struct list_head throttled_list;
|
|
+#ifdef CONFIG_SCHED_WALT
|
|
+ u64 cumulative_runnable_avg;
|
|
+#endif /* CONFIG_SCHED_WALT */
|
|
#endif /* CONFIG_CFS_BANDWIDTH */
|
|
#endif /* CONFIG_FAIR_GROUP_SCHED */
|
|
};
|
|
@@ -539,6 +545,12 @@ struct dl_rq {
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
+struct max_cpu_capacity {
|
|
+ raw_spinlock_t lock;
|
|
+ unsigned long val;
|
|
+ int cpu;
|
|
+};
|
|
+
|
|
/*
|
|
* We add the notion of a root-domain which will be used to define per-domain
|
|
* variables. Each exclusive cpuset essentially defines an island domain by
|
|
@@ -557,6 +569,9 @@ struct root_domain {
|
|
/* Indicate more than one runnable task for any CPU */
|
|
bool overload;
|
|
|
|
+ /* Indicate one or more cpus over-utilized (tipping point) */
|
|
+ bool overutilized;
|
|
+
|
|
/*
|
|
* The bit corresponding to a CPU gets set here if such CPU has more
|
|
* than one runnable -deadline task (as it is below for RT tasks).
|
|
@@ -586,7 +601,11 @@ struct root_domain {
|
|
cpumask_var_t rto_mask;
|
|
struct cpupri cpupri;
|
|
|
|
- unsigned long max_cpu_capacity;
|
|
+ /* Maximum cpu capacity in the system. */
|
|
+ struct max_cpu_capacity max_cpu_capacity;
|
|
+
|
|
+ /* First cpu with maximum and minimum original capacity */
|
|
+ int max_cap_orig_cpu, min_cap_orig_cpu;
|
|
};
|
|
|
|
extern struct root_domain def_root_domain;
|
|
@@ -620,6 +639,7 @@ struct rq {
|
|
#endif
|
|
#define CPU_LOAD_IDX_MAX 5
|
|
unsigned long cpu_load[CPU_LOAD_IDX_MAX];
|
|
+ unsigned int misfit_task;
|
|
#ifdef CONFIG_NO_HZ_COMMON
|
|
#ifdef CONFIG_SMP
|
|
unsigned long last_load_update_tick;
|
|
@@ -629,6 +649,14 @@ struct rq {
|
|
#ifdef CONFIG_NO_HZ_FULL
|
|
unsigned long last_sched_tick;
|
|
#endif
|
|
+
|
|
+#ifdef CONFIG_CPU_QUIET
|
|
+ /* time-based average load */
|
|
+ u64 nr_last_stamp;
|
|
+ u64 nr_running_integral;
|
|
+ seqcount_t ave_seqcnt;
|
|
+#endif
|
|
+
|
|
/* capture load from *all* tasks on this cpu: */
|
|
struct load_weight load;
|
|
unsigned long nr_load_updates;
|
|
@@ -641,6 +669,7 @@ struct rq {
|
|
#ifdef CONFIG_FAIR_GROUP_SCHED
|
|
/* list of leaf cfs_rq on this cpu: */
|
|
struct list_head leaf_cfs_rq_list;
|
|
+ struct list_head *tmp_alone_branch;
|
|
#endif /* CONFIG_FAIR_GROUP_SCHED */
|
|
|
|
/*
|
|
@@ -674,6 +703,7 @@ struct rq {
|
|
/* For active balancing */
|
|
int active_balance;
|
|
int push_cpu;
|
|
+ struct task_struct *push_task;
|
|
struct cpu_stop_work active_balance_work;
|
|
/* cpu of this runqueue: */
|
|
int cpu;
|
|
@@ -690,6 +720,20 @@ struct rq {
|
|
u64 max_idle_balance_cost;
|
|
#endif
|
|
|
|
+#ifdef CONFIG_SCHED_WALT
|
|
+ u64 cumulative_runnable_avg;
|
|
+ u64 window_start;
|
|
+ u64 curr_runnable_sum;
|
|
+ u64 prev_runnable_sum;
|
|
+ u64 nt_curr_runnable_sum;
|
|
+ u64 nt_prev_runnable_sum;
|
|
+ u64 cur_irqload;
|
|
+ u64 avg_irqload;
|
|
+ u64 irqload_ts;
|
|
+ u64 cum_window_demand;
|
|
+#endif /* CONFIG_SCHED_WALT */
|
|
+
|
|
+
|
|
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
|
u64 prev_irq_time;
|
|
#endif
|
|
@@ -728,6 +772,9 @@ struct rq {
|
|
/* try_to_wake_up() stats */
|
|
unsigned int ttwu_count;
|
|
unsigned int ttwu_local;
|
|
+#ifdef CONFIG_SMP
|
|
+ struct eas_stats eas_stats;
|
|
+#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_SMP
|
|
@@ -737,6 +784,7 @@ struct rq {
|
|
#ifdef CONFIG_CPU_IDLE
|
|
/* Must be inspected within a rcu lock section */
|
|
struct cpuidle_state *idle_state;
|
|
+ int idle_state_idx;
|
|
#endif
|
|
};
|
|
|
|
@@ -886,6 +934,8 @@ DECLARE_PER_CPU(int, sd_llc_id);
|
|
DECLARE_PER_CPU(struct sched_domain_shared *, sd_llc_shared);
|
|
DECLARE_PER_CPU(struct sched_domain *, sd_numa);
|
|
DECLARE_PER_CPU(struct sched_domain *, sd_asym);
|
|
+DECLARE_PER_CPU(struct sched_domain *, sd_ea);
|
|
+DECLARE_PER_CPU(struct sched_domain *, sd_scs);
|
|
|
|
struct sched_group_capacity {
|
|
atomic_t ref;
|
|
@@ -893,7 +943,9 @@ struct sched_group_capacity {
|
|
* CPU capacity of this group, SCHED_CAPACITY_SCALE being max capacity
|
|
* for a single CPU.
|
|
*/
|
|
- unsigned int capacity;
|
|
+ unsigned long capacity;
|
|
+ unsigned long max_capacity; /* Max per-cpu capacity in group */
|
|
+ unsigned long min_capacity; /* Min per-CPU capacity in group */
|
|
unsigned long next_update;
|
|
int imbalance; /* XXX unrelated to capacity but shared group state */
|
|
|
|
@@ -906,6 +958,7 @@ struct sched_group {
|
|
|
|
unsigned int group_weight;
|
|
struct sched_group_capacity *sgc;
|
|
+ const struct sched_group_energy *sge;
|
|
|
|
/*
|
|
* The CPUs this group covers.
|
|
@@ -1214,6 +1267,7 @@ extern const u32 sched_prio_to_wmult[40]
|
|
#else
|
|
#define ENQUEUE_MIGRATED 0x00
|
|
#endif
|
|
+#define ENQUEUE_WAKEUP_NEW 0x40
|
|
|
|
#define RETRY_TASK ((void *)-1UL)
|
|
|
|
@@ -1304,6 +1358,7 @@ extern const struct sched_class idle_sch
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
+extern void init_max_cpu_capacity(struct max_cpu_capacity *mcc);
|
|
extern void update_group_capacity(struct sched_domain *sd, int cpu);
|
|
|
|
extern void trigger_load_balance(struct rq *rq);
|
|
@@ -1324,6 +1379,17 @@ static inline struct cpuidle_state *idle
|
|
SCHED_WARN_ON(!rcu_read_lock_held());
|
|
return rq->idle_state;
|
|
}
|
|
+
|
|
+static inline void idle_set_state_idx(struct rq *rq, int idle_state_idx)
|
|
+{
|
|
+ rq->idle_state_idx = idle_state_idx;
|
|
+}
|
|
+
|
|
+static inline int idle_get_state_idx(struct rq *rq)
|
|
+{
|
|
+ WARN_ON(!rcu_read_lock_held());
|
|
+ return rq->idle_state_idx;
|
|
+}
|
|
#else
|
|
static inline void idle_set_state(struct rq *rq,
|
|
struct cpuidle_state *idle_state)
|
|
@@ -1334,6 +1400,15 @@ static inline struct cpuidle_state *idle
|
|
{
|
|
return NULL;
|
|
}
|
|
+
|
|
+static inline void idle_set_state_idx(struct rq *rq, int idle_state_idx)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline int idle_get_state_idx(struct rq *rq)
|
|
+{
|
|
+ return -1;
|
|
+}
|
|
#endif
|
|
|
|
extern void sysrq_sched_debug_show(void);
|
|
@@ -1388,7 +1463,7 @@ static inline void sched_update_tick_dep
|
|
static inline void sched_update_tick_dependency(struct rq *rq) { }
|
|
#endif
|
|
|
|
-static inline void add_nr_running(struct rq *rq, unsigned count)
|
|
+static inline void __add_nr_running(struct rq *rq, unsigned count)
|
|
{
|
|
unsigned prev_nr = rq->nr_running;
|
|
|
|
@@ -1404,13 +1479,50 @@ static inline void add_nr_running(struct
|
|
sched_update_tick_dependency(rq);
|
|
}
|
|
|
|
-static inline void sub_nr_running(struct rq *rq, unsigned count)
|
|
+static inline void __sub_nr_running(struct rq *rq, unsigned count)
|
|
{
|
|
rq->nr_running -= count;
|
|
/* Check if we still need preemption */
|
|
sched_update_tick_dependency(rq);
|
|
}
|
|
|
|
+#ifdef CONFIG_CPU_QUIET
|
|
+#define NR_AVE_SCALE(x) ((x) << FSHIFT)
|
|
+static inline u64 do_nr_running_integral(struct rq *rq)
|
|
+{
|
|
+ s64 nr, deltax;
|
|
+ u64 nr_running_integral = rq->nr_running_integral;
|
|
+
|
|
+ deltax = rq->clock_task - rq->nr_last_stamp;
|
|
+ nr = NR_AVE_SCALE(rq->nr_running);
|
|
+
|
|
+ nr_running_integral += nr * deltax;
|
|
+
|
|
+ return nr_running_integral;
|
|
+}
|
|
+
|
|
+static inline void add_nr_running(struct rq *rq, unsigned count)
|
|
+{
|
|
+ write_seqcount_begin(&rq->ave_seqcnt);
|
|
+ rq->nr_running_integral = do_nr_running_integral(rq);
|
|
+ rq->nr_last_stamp = rq->clock_task;
|
|
+ __add_nr_running(rq, count);
|
|
+ write_seqcount_end(&rq->ave_seqcnt);
|
|
+}
|
|
+
|
|
+static inline void sub_nr_running(struct rq *rq, unsigned count)
|
|
+{
|
|
+ write_seqcount_begin(&rq->ave_seqcnt);
|
|
+ rq->nr_running_integral = do_nr_running_integral(rq);
|
|
+ rq->nr_last_stamp = rq->clock_task;
|
|
+ __sub_nr_running(rq, count);
|
|
+ write_seqcount_end(&rq->ave_seqcnt);
|
|
+}
|
|
+#else
|
|
+#define add_nr_running __add_nr_running
|
|
+#define sub_nr_running __sub_nr_running
|
|
+#endif
|
|
+
|
|
static inline void rq_last_tick_reset(struct rq *rq)
|
|
{
|
|
#ifdef CONFIG_NO_HZ_FULL
|
|
@@ -1472,6 +1584,26 @@ unsigned long arch_scale_freq_capacity(s
|
|
}
|
|
#endif
|
|
|
|
+#ifndef arch_scale_max_freq_capacity
|
|
+static __always_inline
|
|
+unsigned long arch_scale_max_freq_capacity(struct sched_domain *sd, int cpu)
|
|
+{
|
|
+ return SCHED_CAPACITY_SCALE;
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifndef arch_scale_min_freq_capacity
|
|
+static __always_inline
|
|
+unsigned long arch_scale_min_freq_capacity(struct sched_domain *sd, int cpu)
|
|
+{
|
|
+ /*
|
|
+ * Multiplied with any capacity value, this scale factor will return
|
|
+ * 0, which represents an un-capped state
|
|
+ */
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
#ifndef arch_scale_cpu_capacity
|
|
static __always_inline
|
|
unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
|
|
@@ -1483,10 +1615,87 @@ unsigned long arch_scale_cpu_capacity(st
|
|
}
|
|
#endif
|
|
|
|
+#ifdef CONFIG_SMP
|
|
+static inline unsigned long capacity_of(int cpu)
|
|
+{
|
|
+ return cpu_rq(cpu)->cpu_capacity;
|
|
+}
|
|
+
|
|
+static inline unsigned long capacity_orig_of(int cpu)
|
|
+{
|
|
+ return cpu_rq(cpu)->cpu_capacity_orig;
|
|
+}
|
|
+
|
|
+extern unsigned int sysctl_sched_use_walt_cpu_util;
|
|
+extern unsigned int walt_ravg_window;
|
|
+extern bool walt_disabled;
|
|
+
|
|
+/*
|
|
+ * cpu_util returns the amount of capacity of a CPU that is used by CFS
|
|
+ * tasks. The unit of the return value must be the one of capacity so we can
|
|
+ * compare the utilization with the capacity of the CPU that is available for
|
|
+ * CFS task (ie cpu_capacity).
|
|
+ *
|
|
+ * cfs_rq.avg.util_avg is the sum of running time of runnable tasks plus the
|
|
+ * recent utilization of currently non-runnable tasks on a CPU. It represents
|
|
+ * the amount of utilization of a CPU in the range [0..capacity_orig] where
|
|
+ * capacity_orig is the cpu_capacity available at the highest frequency
|
|
+ * (arch_scale_freq_capacity()).
|
|
+ * The utilization of a CPU converges towards a sum equal to or less than the
|
|
+ * current capacity (capacity_curr <= capacity_orig) of the CPU because it is
|
|
+ * the running time on this CPU scaled by capacity_curr.
|
|
+ *
|
|
+ * Nevertheless, cfs_rq.avg.util_avg can be higher than capacity_curr or even
|
|
+ * higher than capacity_orig because of unfortunate rounding in
|
|
+ * cfs.avg.util_avg or just after migrating tasks and new task wakeups until
|
|
+ * the average stabilizes with the new running time. We need to check that the
|
|
+ * utilization stays within the range of [0..capacity_orig] and cap it if
|
|
+ * necessary. Without utilization capping, a group could be seen as overloaded
|
|
+ * (CPU0 utilization at 121% + CPU1 utilization at 80%) whereas CPU1 has 20% of
|
|
+ * available capacity. We allow utilization to overshoot capacity_curr (but not
|
|
+ * capacity_orig) as it useful for predicting the capacity required after task
|
|
+ * migrations (scheduler-driven DVFS).
|
|
+ */
|
|
+static inline unsigned long __cpu_util(int cpu, int delta)
|
|
+{
|
|
+ unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;
|
|
+ unsigned long capacity = capacity_orig_of(cpu);
|
|
+
|
|
+#ifdef CONFIG_SCHED_WALT
|
|
+ if (!walt_disabled && sysctl_sched_use_walt_cpu_util)
|
|
+ util = div64_u64(cpu_rq(cpu)->cumulative_runnable_avg,
|
|
+ walt_ravg_window >> SCHED_CAPACITY_SHIFT);
|
|
+#endif
|
|
+ delta += util;
|
|
+ if (delta < 0)
|
|
+ return 0;
|
|
+
|
|
+ return (delta >= capacity) ? capacity : delta;
|
|
+}
|
|
+
|
|
+static inline unsigned long cpu_util(int cpu)
|
|
+{
|
|
+ return __cpu_util(cpu, 0);
|
|
+}
|
|
+
|
|
+static inline unsigned long cpu_util_freq(int cpu)
|
|
+{
|
|
+ unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;
|
|
+ unsigned long capacity = capacity_orig_of(cpu);
|
|
+
|
|
+#ifdef CONFIG_SCHED_WALT
|
|
+ if (!walt_disabled && sysctl_sched_use_walt_cpu_util)
|
|
+ util = div64_u64(cpu_rq(cpu)->prev_runnable_sum,
|
|
+ walt_ravg_window >> SCHED_CAPACITY_SHIFT);
|
|
+#endif
|
|
+ return (util >= capacity) ? capacity : util;
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
static inline void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
|
|
{
|
|
rq->rt_avg += rt_delta * arch_scale_freq_capacity(NULL, cpu_of(rq));
|
|
- sched_avg_update(rq);
|
|
}
|
|
#else
|
|
static inline void sched_rt_avg_update(struct rq *rq, u64 rt_delta) { }
|
|
@@ -1521,6 +1730,9 @@ task_rq_unlock(struct rq *rq, struct tas
|
|
raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
|
|
}
|
|
|
|
+extern struct rq *lock_rq_of(struct task_struct *p, struct rq_flags *flags);
|
|
+extern void unlock_rq_of(struct rq *rq, struct task_struct *p, struct rq_flags *flags);
|
|
+
|
|
#ifdef CONFIG_SMP
|
|
#ifdef CONFIG_PREEMPT
|
|
|
|
@@ -1593,7 +1805,8 @@ static inline int double_lock_balance(st
|
|
static inline void double_unlock_balance(struct rq *this_rq, struct rq *busiest)
|
|
__releases(busiest->lock)
|
|
{
|
|
- raw_spin_unlock(&busiest->lock);
|
|
+ if (this_rq != busiest)
|
|
+ raw_spin_unlock(&busiest->lock);
|
|
lock_set_subclass(&this_rq->lock.dep_map, 0, _RET_IP_);
|
|
}
|
|
|
|
@@ -1809,6 +2022,17 @@ static inline void cpufreq_update_util(s
|
|
static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags) {}
|
|
#endif /* CONFIG_CPU_FREQ */
|
|
|
|
+#ifdef CONFIG_SCHED_WALT
|
|
+
|
|
+static inline bool
|
|
+walt_task_in_cum_window_demand(struct rq *rq, struct task_struct *p)
|
|
+{
|
|
+ return cpu_of(rq) == task_cpu(p) &&
|
|
+ (p->on_rq || p->last_sleep_ts >= rq->window_start);
|
|
+}
|
|
+
|
|
+#endif /* CONFIG_SCHED_WALT */
|
|
+
|
|
#ifdef arch_scale_freq_capacity
|
|
#ifndef arch_scale_freq_invariant
|
|
#define arch_scale_freq_invariant() (true)
|