Skip to content

Commit dddcab7

Browse files
author
Syed Rameez Mustafa
committed
sched: Introduce HMP scheduling
Add a snapshot of all changes associated with the HMP scheduler ported over to the latest kernel version. This will allow proper big Little scheduling for targets that will use this kernel version. The msm-4-4 snapshot is taken at commitcc60f0790f27 (sched: constrain HMP scheduler tunable range with in better way). Please note that this is not an exact snapshot; certain HMP related code has been removed. This includes redundant code, useless CONFIG options, rarely taken error code paths, runtime enable/disable support for the HMP scheduler. Change-Id: I923f35904008f1fb74ac9c1a39481810cdea5790 Signed-off-by: Syed Rameez Mustafa <[email protected]>
1 parent e47abbf commit dddcab7

File tree

23 files changed

+9438
-94
lines changed

23 files changed

+9438
-94
lines changed

Documentation/scheduler/sched-hmp.txt

Lines changed: 1432 additions & 0 deletions
Large diffs are not rendered by default.

include/linux/cpu.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ struct cpu {
2828
struct device dev;
2929
};
3030

31+
struct cpu_pstate_pwr {
32+
unsigned int freq;
33+
uint32_t power;
34+
};
35+
36+
struct cpu_pwr_stats {
37+
int cpu;
38+
long temp;
39+
struct cpu_pstate_pwr *ptable;
40+
bool throttling;
41+
int len;
42+
};
43+
44+
extern struct cpu_pwr_stats *get_cpu_pwr_stats(void);
45+
3146
extern void boot_cpu_init(void);
3247
extern void boot_cpu_state_init(void);
3348

include/linux/sched.h

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ extern unsigned long nr_iowait(void);
174174
extern unsigned long nr_iowait_cpu(int cpu);
175175
extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load);
176176

177+
extern void sched_update_nr_prod(int cpu, long delta, bool inc);
178+
extern void sched_get_nr_running_avg(int *avg, int *iowait_avg, int *big_avg);
179+
177180
extern void calc_global_load(unsigned long ticks);
178181

179182
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
@@ -315,6 +318,25 @@ extern char ___assert_task_state[1 - 2*!!(
315318
/* Task command name length */
316319
#define TASK_COMM_LEN 16
317320

321+
extern const char *sched_window_reset_reasons[];
322+
323+
enum task_event {
324+
PUT_PREV_TASK = 0,
325+
PICK_NEXT_TASK = 1,
326+
TASK_WAKE = 2,
327+
TASK_MIGRATE = 3,
328+
TASK_UPDATE = 4,
329+
IRQ_UPDATE = 5,
330+
};
331+
332+
/* Note: this need to be in sync with migrate_type_names array */
333+
enum migrate_types {
334+
GROUP_TO_RQ,
335+
RQ_TO_GROUP,
336+
RQ_TO_RQ,
337+
GROUP_TO_GROUP,
338+
};
339+
318340
#include <linux/spinlock.h>
319341

320342
/*
@@ -1335,6 +1357,47 @@ struct sched_statistics {
13351357
};
13361358
#endif
13371359

1360+
#define RAVG_HIST_SIZE_MAX 5
1361+
#define NUM_BUSY_BUCKETS 10
1362+
1363+
/* ravg represents frequency scaled cpu-demand of tasks */
1364+
struct ravg {
1365+
/*
1366+
* 'mark_start' marks the beginning of an event (task waking up, task
1367+
* starting to execute, task being preempted) within a window
1368+
*
1369+
* 'sum' represents how runnable a task has been within current
1370+
* window. It incorporates both running time and wait time and is
1371+
* frequency scaled.
1372+
*
1373+
* 'sum_history' keeps track of history of 'sum' seen over previous
1374+
* RAVG_HIST_SIZE windows. Windows where task was entirely sleeping are
1375+
* ignored.
1376+
*
1377+
* 'demand' represents maximum sum seen over previous
1378+
* sysctl_sched_ravg_hist_size windows. 'demand' could drive frequency
1379+
* demand for tasks.
1380+
*
1381+
* 'curr_window' represents task's contribution to cpu busy time
1382+
* statistics (rq->curr_runnable_sum) in current window
1383+
*
1384+
* 'prev_window' represents task's contribution to cpu busy time
1385+
* statistics (rq->prev_runnable_sum) in previous window
1386+
*
1387+
* 'pred_demand' represents task's current predicted cpu busy time
1388+
*
1389+
* 'busy_buckets' groups historical busy time into different buckets
1390+
* used for prediction
1391+
*/
1392+
u64 mark_start;
1393+
u32 sum, demand;
1394+
u32 sum_history[RAVG_HIST_SIZE_MAX];
1395+
u32 curr_window, prev_window;
1396+
u16 active_windows;
1397+
u32 pred_demand;
1398+
u8 busy_buckets[NUM_BUSY_BUCKETS];
1399+
};
1400+
13381401
struct sched_entity {
13391402
struct load_weight load; /* for load-balancing */
13401403
struct rb_node run_node;
@@ -1505,6 +1568,20 @@ struct task_struct {
15051568
const struct sched_class *sched_class;
15061569
struct sched_entity se;
15071570
struct sched_rt_entity rt;
1571+
#ifdef CONFIG_SCHED_HMP
1572+
struct ravg ravg;
1573+
/*
1574+
* 'init_load_pct' represents the initial task load assigned to children
1575+
* of this task
1576+
*/
1577+
u32 init_load_pct;
1578+
u64 last_wake_ts;
1579+
u64 last_switch_out_ts;
1580+
u64 last_cpu_selected_ts;
1581+
struct related_thread_group *grp;
1582+
struct list_head grp_list;
1583+
u64 cpu_cycles;
1584+
#endif
15081585
#ifdef CONFIG_CGROUP_SCHED
15091586
struct task_group *sched_task_group;
15101587
#endif
@@ -2254,6 +2331,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
22542331
/*
22552332
* Per process flags
22562333
*/
2334+
#define PF_WAKE_UP_IDLE 0x00000002 /* try to wake up on an idle CPU */
22572335
#define PF_EXITING 0x00000004 /* getting shut down */
22582336
#define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */
22592337
#define PF_VCPU 0x00000010 /* I'm a virtual CPU */
@@ -2436,6 +2514,93 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p,
24362514
}
24372515
#endif
24382516

2517+
struct sched_load {
2518+
unsigned long prev_load;
2519+
unsigned long new_task_load;
2520+
unsigned long predicted_load;
2521+
};
2522+
2523+
extern int sched_set_wake_up_idle(struct task_struct *p, int wake_up_idle);
2524+
extern u32 sched_get_wake_up_idle(struct task_struct *p);
2525+
2526+
struct cpu_cycle_counter_cb {
2527+
u64 (*get_cpu_cycle_counter)(int cpu);
2528+
};
2529+
2530+
#ifdef CONFIG_SCHED_HMP
2531+
extern int sched_set_window(u64 window_start, unsigned int window_size);
2532+
extern unsigned long sched_get_busy(int cpu);
2533+
extern void sched_get_cpus_busy(struct sched_load *busy,
2534+
const struct cpumask *query_cpus);
2535+
extern void sched_set_io_is_busy(int val);
2536+
extern int sched_set_boost(int enable);
2537+
extern int sched_set_init_task_load(struct task_struct *p, int init_load_pct);
2538+
extern u32 sched_get_init_task_load(struct task_struct *p);
2539+
extern int sched_set_static_cpu_pwr_cost(int cpu, unsigned int cost);
2540+
extern unsigned int sched_get_static_cpu_pwr_cost(int cpu);
2541+
extern int sched_set_static_cluster_pwr_cost(int cpu, unsigned int cost);
2542+
extern unsigned int sched_get_static_cluster_pwr_cost(int cpu);
2543+
extern int sched_update_freq_max_load(const cpumask_t *cpumask);
2544+
extern void sched_update_cpu_freq_min_max(const cpumask_t *cpus,
2545+
u32 fmin, u32 fmax);
2546+
extern void sched_set_cpu_cstate(int cpu, int cstate,
2547+
int wakeup_energy, int wakeup_latency);
2548+
extern void sched_set_cluster_dstate(const cpumask_t *cluster_cpus, int dstate,
2549+
int wakeup_energy, int wakeup_latency);
2550+
extern int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb);
2551+
extern u64 sched_ktime_clock(void);
2552+
extern int sched_set_group_id(struct task_struct *p, unsigned int group_id);
2553+
extern unsigned int sched_get_group_id(struct task_struct *p);
2554+
2555+
#else /* CONFIG_SCHED_HMP */
2556+
static inline u64 sched_ktime_clock(void)
2557+
{
2558+
return 0;
2559+
}
2560+
2561+
static inline int
2562+
register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb)
2563+
{
2564+
return 0;
2565+
}
2566+
2567+
static inline int sched_set_window(u64 window_start, unsigned int window_size)
2568+
{
2569+
return -EINVAL;
2570+
}
2571+
static inline unsigned long sched_get_busy(int cpu)
2572+
{
2573+
return 0;
2574+
}
2575+
static inline void sched_get_cpus_busy(struct sched_load *busy,
2576+
const struct cpumask *query_cpus) {};
2577+
2578+
static inline void sched_set_io_is_busy(int val) {};
2579+
2580+
static inline int sched_set_boost(int enable)
2581+
{
2582+
return -EINVAL;
2583+
}
2584+
2585+
static inline int sched_update_freq_max_load(const cpumask_t *cpumask)
2586+
{
2587+
return 0;
2588+
}
2589+
2590+
static inline void sched_update_cpu_freq_min_max(const cpumask_t *cpus,
2591+
u32 fmin, u32 fmax) { }
2592+
2593+
static inline void
2594+
sched_set_cpu_cstate(int cpu, int cstate, int wakeup_energy, int wakeup_latency)
2595+
{
2596+
}
2597+
2598+
static inline void sched_set_cluster_dstate(const cpumask_t *cluster_cpus,
2599+
int dstate, int wakeup_energy, int wakeup_latency)
2600+
{
2601+
}
2602+
#endif /* CONFIG_SCHED_HMP */
2603+
24392604
#ifdef CONFIG_NO_HZ_COMMON
24402605
void calc_load_enter_idle(void);
24412606
void calc_load_exit_idle(void);
@@ -2444,6 +2609,14 @@ static inline void calc_load_enter_idle(void) { }
24442609
static inline void calc_load_exit_idle(void) { }
24452610
#endif /* CONFIG_NO_HZ_COMMON */
24462611

2612+
static inline void set_wake_up_idle(bool enabled)
2613+
{
2614+
if (enabled)
2615+
current->flags |= PF_WAKE_UP_IDLE;
2616+
else
2617+
current->flags &= ~PF_WAKE_UP_IDLE;
2618+
}
2619+
24472620
/*
24482621
* Do not use outside of architecture code which knows its limitations.
24492622
*
@@ -2461,6 +2634,7 @@ extern u64 sched_clock_cpu(int cpu);
24612634

24622635

24632636
extern void sched_clock_init(void);
2637+
extern int sched_clock_initialized(void);
24642638

24652639
#ifndef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
24662640
static inline void sched_clock_tick(void)
@@ -2537,7 +2711,7 @@ extern unsigned long long
25372711
task_sched_runtime(struct task_struct *task);
25382712

25392713
/* sched_exec is called by processes performing an exec */
2540-
#ifdef CONFIG_SMP
2714+
#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_HMP)
25412715
extern void sched_exec(void);
25422716
#else
25432717
#define sched_exec() {}
@@ -2670,6 +2844,7 @@ extern void xtime_update(unsigned long ticks);
26702844

26712845
extern int wake_up_state(struct task_struct *tsk, unsigned int state);
26722846
extern int wake_up_process(struct task_struct *tsk);
2847+
extern int wake_up_process_no_notif(struct task_struct *tsk);
26732848
extern void wake_up_new_task(struct task_struct *tsk);
26742849
#ifdef CONFIG_SMP
26752850
extern void kick_process(struct task_struct *tsk);
@@ -2678,6 +2853,12 @@ extern void wake_up_new_task(struct task_struct *tsk);
26782853
#endif
26792854
extern int sched_fork(unsigned long clone_flags, struct task_struct *p);
26802855
extern void sched_dead(struct task_struct *p);
2856+
#ifdef CONFIG_SCHED_HMP
2857+
extern void sched_exit(struct task_struct *p);
2858+
#else
2859+
static inline void sched_exit(struct task_struct *p) { }
2860+
#endif
2861+
26812862

26822863
extern void proc_caches_init(void);
26832864
extern void flush_signals(struct task_struct *);
@@ -3506,6 +3687,8 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
35063687

35073688
#endif /* CONFIG_SMP */
35083689

3690+
extern struct atomic_notifier_head load_alert_notifier_head;
3691+
35093692
extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
35103693
extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
35113694

include/linux/sched/sysctl.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,32 @@ extern unsigned int sysctl_sched_latency;
1818
extern unsigned int sysctl_sched_min_granularity;
1919
extern unsigned int sysctl_sched_wakeup_granularity;
2020
extern unsigned int sysctl_sched_child_runs_first;
21+
extern unsigned int sysctl_sched_wake_to_idle;
22+
23+
#ifdef CONFIG_SCHED_HMP
24+
extern int sysctl_sched_freq_inc_notify;
25+
extern int sysctl_sched_freq_dec_notify;
26+
extern unsigned int sysctl_sched_window_stats_policy;
27+
extern unsigned int sysctl_sched_ravg_hist_size;
28+
extern unsigned int sysctl_sched_cpu_high_irqload;
29+
extern unsigned int sysctl_sched_init_task_load_pct;
30+
extern unsigned int sysctl_sched_spill_nr_run;
31+
extern unsigned int sysctl_sched_spill_load_pct;
32+
extern unsigned int sysctl_sched_upmigrate_pct;
33+
extern unsigned int sysctl_sched_downmigrate_pct;
34+
extern unsigned int sysctl_early_detection_duration;
35+
extern unsigned int sysctl_sched_boost;
36+
extern unsigned int sysctl_sched_small_wakee_task_load_pct;
37+
extern unsigned int sysctl_sched_big_waker_task_load_pct;
38+
extern unsigned int sysctl_sched_select_prev_cpu_us;
39+
extern unsigned int sysctl_sched_enable_colocation;
40+
extern unsigned int sysctl_sched_restrict_cluster_spill;
41+
extern unsigned int sysctl_sched_new_task_windows;
42+
extern unsigned int sysctl_sched_pred_alert_freq;
43+
extern unsigned int sysctl_sched_freq_aggregate;
44+
extern unsigned int sysctl_sched_enable_thread_grouping;
45+
extern unsigned int sysctl_sched_freq_aggregate_threshold_pct;
46+
#endif /* CONFIG_SCHED_HMP */
2147

2248
enum sched_tunable_scaling {
2349
SCHED_TUNABLESCALING_NONE,
@@ -43,6 +69,18 @@ int sched_proc_update_handler(struct ctl_table *table, int write,
4369
loff_t *ppos);
4470
#endif
4571

72+
extern int sched_migrate_notify_proc_handler(struct ctl_table *table,
73+
int write, void __user *buffer, size_t *lenp, loff_t *ppos);
74+
75+
extern int sched_hmp_proc_update_handler(struct ctl_table *table,
76+
int write, void __user *buffer, size_t *lenp, loff_t *ppos);
77+
78+
extern int sched_boost_handler(struct ctl_table *table, int write,
79+
void __user *buffer, size_t *lenp, loff_t *ppos);
80+
81+
extern int sched_window_update_handler(struct ctl_table *table,
82+
int write, void __user *buffer, size_t *lenp, loff_t *ppos);
83+
4684
/*
4785
* control realtime throttling:
4886
*

include/linux/tick.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ static inline void tick_handover_do_timer(void) { }
2727
static inline void tick_cleanup_dead_cpu(int cpu) { }
2828
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
2929

30+
extern u64 jiffy_to_ktime_ns(u64 *now, u64 *jiffy_ktime_ns);
31+
3032
#if defined(CONFIG_GENERIC_CLOCKEVENTS) && defined(CONFIG_SUSPEND)
3133
extern void tick_freeze(void);
3234
extern void tick_unfreeze(void);

0 commit comments

Comments
 (0)