lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 18 Apr 2023 10:51:55 -1000
From:   Tejun Heo <tj@...nel.org>
To:     jiangshanlai@...il.com
Cc:     torvalds@...ux-foundation.org, peterz@...radead.org,
        linux-kernel@...r.kernel.org, kernel-team@...a.com,
        Tejun Heo <tj@...nel.org>
Subject: [PATCH 1/5] workqueue, sched: Notify workqueue of scheduling of RUNNING tasks

When a workqueue kworker goes to sleep, wq_worker_sleeping() is called so
that workqueue can manage concurrency. This patch renames
wq_worker_sleeping() to wq_worker_stopping() can calls it whenever a kworker
is scheduled out whether it's going to sleep or not.

Workqueue will use the schedule-out event of running tasks to automatically
detect CPU hogging work items and exclude them from concurrency management
so that they can't stall other work items.

This patch just moves the task_is_running() test from sched_submit_work() to
wq_worker_stopping(). No behavior change is intended. While at it, remove
the already outdated comment which doesn't cover the io_wq case.

Signed-off-by: Tejun Heo <tj@...nel.org>
Cc: Lai Jiangshan <jiangshanlai@...il.com>
Cc: Peter Zijlstra <peterz@...radead.org>
---
 kernel/sched/core.c         | 18 ++++++------------
 kernel/workqueue.c          | 13 ++++++++-----
 kernel/workqueue_internal.h |  2 +-
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 0d18c3969f90..1d83ff00d587 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6650,22 +6650,16 @@ void __noreturn do_task_dead(void)
 
 static inline void sched_submit_work(struct task_struct *tsk)
 {
-	unsigned int task_flags;
+	unsigned int task_flags = tsk->flags;
+
+	if (task_flags & PF_WQ_WORKER)
+		wq_worker_stopping(tsk);
 
 	if (task_is_running(tsk))
 		return;
 
-	task_flags = tsk->flags;
-	/*
-	 * If a worker goes to sleep, notify and ask workqueue whether it
-	 * wants to wake up a task to maintain concurrency.
-	 */
-	if (task_flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
-		if (task_flags & PF_WQ_WORKER)
-			wq_worker_sleeping(tsk);
-		else
-			io_wq_worker_sleeping(tsk);
-	}
+	if (task_flags & PF_IO_WORKER)
+		io_wq_worker_sleeping(tsk);
 
 	/*
 	 * spinlock and rwlock must not flush block requests.  This will
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b8b541caed48..6199fbf10cec 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -886,17 +886,20 @@ void wq_worker_running(struct task_struct *task)
 }
 
 /**
- * wq_worker_sleeping - a worker is going to sleep
- * @task: task going to sleep
+ * wq_worker_stopping - a worker is stopping
+ * @task: task stopping
  *
- * This function is called from schedule() when a busy worker is
- * going to sleep.
+ * This function is called from schedule() when a busy worker is going off the
+ * CPU.
  */
-void wq_worker_sleeping(struct task_struct *task)
+void wq_worker_stopping(struct task_struct *task)
 {
 	struct worker *worker = kthread_data(task);
 	struct worker_pool *pool;
 
+	if (task_is_running(task))
+		return;
+
 	/*
 	 * Rescuers, which may not have all the fields set up like normal
 	 * workers, also reach here, let's not access anything before
diff --git a/kernel/workqueue_internal.h b/kernel/workqueue_internal.h
index e00b1204a8e9..b3b4b2b41d93 100644
--- a/kernel/workqueue_internal.h
+++ b/kernel/workqueue_internal.h
@@ -75,7 +75,7 @@ static inline struct worker *current_wq_worker(void)
  * sched/ and workqueue.c.
  */
 void wq_worker_running(struct task_struct *task);
-void wq_worker_sleeping(struct task_struct *task);
+void wq_worker_stopping(struct task_struct *task);
 work_func_t wq_worker_last_func(struct task_struct *task);
 
 #endif /* _KERNEL_WORKQUEUE_INTERNAL_H */
-- 
2.40.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ