
From: Tengda Wu <wutengda2@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICAOAT -------------------------------- Measure the wakeup latency of tasks from sched_waking/sched_wakeup_new to running as a form of scheduling interference. Signed-off-by: Tengda Wu <wutengda2@huawei.com> Signed-off-by: Pu Lehui <pulehui@huawei.com> --- include/linux/cgroup.h | 17 +++++++++++++++++ include/linux/sched.h | 5 +++++ kernel/cgroup/ifs.c | 3 +++ kernel/sched/core.c | 3 +++ kernel/sched/stats.h | 29 ++++++++++++++++++++++++++++- 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 8fc762b3841c..5ac1b53c25e4 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -865,6 +865,7 @@ void cgroup_move_task_to_root(struct task_struct *tsk); enum ifs_types { IFS_SMT, IFS_RUNDELAY, + IFS_WAKELAT, IFS_THROTTLE, #ifdef CONFIG_SCHEDSTATS IFS_SLEEP, @@ -938,6 +939,21 @@ static inline void cgroup_ifs_account_rundelay(struct task_struct *task, cgroup_ifs_account_delta(this_cpu_ptr(ifs->pcpu), IFS_RUNDELAY, delta); } +static inline void cgroup_ifs_account_wakelat(struct task_struct *task, + u64 delta) +{ + struct cgroup_ifs *ifs; + + if (!cgroup_ifs_enabled()) + return; + + ifs = task_ifs(task); + if (!ifs) + return; + + cgroup_ifs_account_delta(this_cpu_ptr(ifs->pcpu), IFS_WAKELAT, delta); +} + static inline void cgroup_ifs_account_throttle(struct cgroup *cgrp, int cpu, u64 delta) { @@ -980,6 +996,7 @@ static inline void cgroup_ifs_account_smttime(struct task_struct *prev, struct task_struct *idle) {} static inline void cgroup_ifs_set_smt(cpumask_t *sibling) {} static inline void cgroup_ifs_account_rundelay(struct task_struct *task, u64 delta) {} +static inline void cgroup_ifs_account_wakelat(struct task_struct *task, u64 delta) {} static inline void cgroup_ifs_account_throttle(struct cgroup *cgrp, int cpu, u64 delta) {} #ifdef CONFIG_SCHEDSTATS static inline void cgroup_ifs_account_sleep(struct task_struct *task, u64 delta) {} diff --git a/include/linux/sched.h b/include/linux/sched.h index b31db870e23b..3979c34e9b83 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -390,7 +390,12 @@ struct sched_info { /* When were we last queued to run? */ unsigned long long last_queued; +#ifdef CONFIG_CGROUP_IFS + /* When were we last waking to run? */ + KABI_USE(1, unsigned long long last_waking) +#else KABI_RESERVE(1) +#endif KABI_RESERVE(2) #endif /* CONFIG_SCHED_INFO */ }; diff --git a/kernel/cgroup/ifs.c b/kernel/cgroup/ifs.c index dad42b38d16e..edebb5f00602 100644 --- a/kernel/cgroup/ifs.c +++ b/kernel/cgroup/ifs.c @@ -162,6 +162,9 @@ static const char *ifs_type_name(int type) case IFS_RUNDELAY: name = "rundelay"; break; + case IFS_WAKELAT: + name = "wakelat"; + break; case IFS_THROTTLE: name = "throttle"; break; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 082056ba8bdc..6c9da25a3d45 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4246,6 +4246,7 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) trace_sched_waking(p); ttwu_do_wakeup(p); + ifs_task_waking(p); goto out; } @@ -4261,6 +4262,7 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) break; trace_sched_waking(p); + ifs_task_waking(p); /* * Ensure we load p->on_rq _after_ p->state, otherwise it would @@ -4935,6 +4937,7 @@ void wake_up_new_task(struct task_struct *p) activate_task(rq, p, ENQUEUE_NOCLOCK); trace_sched_wakeup_new(p); + ifs_task_waking(p); check_preempt_curr(rq, p, WF_FORK); #ifdef CONFIG_SMP if (p->sched_class->task_woken) { diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h index 12966561d5d4..1b736b931247 100644 --- a/kernel/sched/stats.h +++ b/kernel/sched/stats.h @@ -2,6 +2,8 @@ #ifndef _KERNEL_STATS_H #define _KERNEL_STATS_H +#include <linux/sched/clock.h> + #ifdef CONFIG_SCHEDSTATS extern struct static_key_false sched_schedstats; @@ -148,8 +150,31 @@ static inline void ifs_account_rundelay(struct task_struct *task, u64 delta) cgroup_ifs_account_rundelay(task, delta); } + +static inline void ifs_task_waking(struct task_struct *t) +{ + if (t->sched_info.last_waking) + return; + + t->sched_info.last_waking = sched_clock(); +} + +static inline void ifs_task_arrive(struct task_struct *t) +{ + unsigned long long now, delta = 0; + + if (!t->sched_info.last_waking) + return; + + now = sched_clock(); + delta = now - t->sched_info.last_waking; + t->sched_info.last_waking = 0; + cgroup_ifs_account_wakelat(t, delta); +} #else static inline void ifs_account_rundelay(struct task_struct *task, u64 delta) {} +static inline void ifs_task_waking(struct task_struct *t) {} +static inline void ifs_task_arrive(struct task_struct *t) {} #endif #ifdef CONFIG_PSI @@ -336,8 +361,10 @@ sched_info_switch(struct rq *rq, struct task_struct *prev, struct task_struct *n if (prev != rq->idle) sched_info_depart(rq, prev); - if (next != rq->idle) + if (next != rq->idle) { sched_info_arrive(rq, next); + ifs_task_arrive(next); + } } #else /* !CONFIG_SCHED_INFO: */ -- 2.34.1