From 92e026f5b5dcbb0487eaada1f545f6a0cf0d2bca Mon Sep 17 00:00:00 2001 From: Bin Lai Date: Sat, 2 Jul 2022 18:48:25 +0800 Subject: [PATCH] sli: fix rq_clock warning caused by sli In order to reduce the critical section, we invoke sli_update_tick() to do sli statistics after release the rq lock. But there is a race condition that could led the rq_clock warning. Warning generates like following: CPU0 CPU1 rq_lock() update_rq_clock() rq_unlock() rq_lock() sli_update_tick() load balance Although, CPU0 had updated the rq_clock(). But CPU1 may concurrently do the load balance and acquire CPU0's rq lock, and the CPU0's clock_update_flags would be cleared. It means that caller should update the rq clock before actually use it. Unfortunately, CPU0 cann't observed it. So the warning was produced by sli when it invoke rq_clock(). Therefore, we must move the sli_check_longsys() in the front of rq_unlock(). Signed-off-by: Bin Lai --- include/linux/sli.h | 1 + kernel/cgroup/sli.c | 12 +++--------- kernel/sched/core.c | 6 ++++++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/linux/sli.h b/include/linux/sli.h index 370c6fb79..32c901b87 100755 --- a/include/linux/sli.h +++ b/include/linux/sli.h @@ -132,6 +132,7 @@ int sli_schedlat_max_show(struct seq_file *m, struct cgroup *cgrp); ssize_t cgroup_sli_control_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off); int cgroup_sli_control_show(struct seq_file *sf, void *v); +void sli_check_longsys(struct task_struct *tsk); void sli_update_tick(struct task_struct *tsk); struct sli_notify_ctx* sctx_alloc(void); diff --git a/kernel/cgroup/sli.c b/kernel/cgroup/sli.c index 42f7a2af8..be0b3f0db 100755 --- a/kernel/cgroup/sli.c +++ b/kernel/cgroup/sli.c @@ -531,11 +531,13 @@ out: rcu_read_unlock(); } -#ifdef CONFIG_SCHED_INFO void sli_check_longsys(struct task_struct *tsk) { long delta; + if (!static_branch_likely(&sli_enabled)) + return; + if (tsk->sched_class != &fair_sched_class) return ; @@ -559,7 +561,6 @@ void sli_check_longsys(struct task_struct *tsk) delta = rq_clock(task_rq(tsk)) - tsk->sched_info.kernel_exec_start; sli_schedlat_stat(tsk, SCHEDLAT_LONGSYS, delta); } -#endif static void sli_proactive_monitor_work(struct work_struct *work) { @@ -642,13 +643,6 @@ void sli_update_tick(struct task_struct *tsk) { struct cgroup *cgrp; - if (!static_branch_likely(&sli_enabled)) - return; - -#ifdef CONFIG_SCHED_INFO - sli_check_longsys(tsk); -#endif - if (!static_branch_likely(&sli_monitor_enabled)) return; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 28699c824..3c2730edd 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3697,6 +3697,9 @@ void scheduler_tick(void) calc_global_load_tick(rq); psi_task_tick(rq); +#ifdef CONFIG_CGROUP_SLI + sli_check_longsys(curr); +#endif rq_unlock(rq, &rf); perf_event_task_tick(); @@ -3786,6 +3789,9 @@ static void sched_tick_remote(struct work_struct *work) curr->sched_class->task_tick(rq, curr, 0); calc_load_nohz_remote(rq); +#ifdef CONFIG_CGROUP_SLI + sli_check_longsys(curr); +#endif out_unlock: rq_unlock_irq(rq, &rf); out_requeue: