From: Frederic Weisbecker <fweisbec@gmail.com>
To: LKML <linux-kernel@vger.kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
Frederic Weisbecker <fweisbec@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
Ingo Molnar <mingo@elte.hu>, Steven Rostedt <rostedt@goodmis.org>,
Lai Jiangshan <laijs@cn.fujitsu.com>,
Andrew Morton <akpm@linux-foundation.org>,
Anton Blanchard <anton@au1.ibm.com>,
Tim Pepper <lnxninja@linux.vnet.ibm.com>
Subject: [RFC PATCH 15/15] nohz_task: Procfs interface
Date: Mon, 20 Dec 2010 16:24:22 +0100 [thread overview]
Message-ID: <1292858662-5650-16-git-send-email-fweisbec@gmail.com> (raw)
In-Reply-To: <1292858662-5650-1-git-send-email-fweisbec@gmail.com>
This implements the /proc/pid/nohz file that enables the
nohz attribute of a task.
Synchronization is enforced so that:
- A CPU can have only one nohz task
- A nohz task can be only affine to a single CPU
For now this is only possible to write on /proc/self but probably
allowing it from another task would be a good idea and wouldn't
increase so much the complexity of the code.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Anton Blanchard <anton@au1.ibm.com>
Cc: Tim Pepper <lnxninja@linux.vnet.ibm.com>
---
fs/proc/base.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/sched.h | 1 +
include/linux/tick.h | 1 +
kernel/sched.c | 43 ++++++++++++++++++++++++
kernel/time/Kconfig | 6 ++--
kernel/time/tick-sched.c | 12 +++++++
6 files changed, 140 insertions(+), 3 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1828451..9a01978 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -83,6 +83,7 @@
#include <linux/pid_namespace.h>
#include <linux/fs_struct.h>
#include <linux/slab.h>
+#include <linux/tick.h>
#include "internal.h"
/* NOTE:
@@ -1295,6 +1296,82 @@ static const struct file_operations proc_sessionid_operations = {
};
#endif
+#ifdef CONFIG_NO_HZ_TASK
+static ssize_t proc_nohz_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ char buffer[PROC_NUMBUF];
+ int val = 0;
+ size_t len;
+
+ if (!task)
+ return -ESRCH;
+
+ if (test_tsk_thread_flag(task, TIF_NOHZ))
+ val = 1;
+
+ put_task_struct(task);
+
+ len = snprintf(buffer, sizeof(buffer), "%d\n", val);
+
+ return simple_read_from_buffer(buf, count, ppos, buffer, len);
+}
+
+
+static ssize_t proc_nohz_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct task_struct *task;
+ char buffer[PROC_NUMBUF];
+ long val;
+ int err = 0;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if (count > sizeof(buffer) - 1)
+ count = sizeof(buffer) - 1;
+
+ if (copy_from_user(buffer, buf, count)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ err = strict_strtol(strstrip(buffer), 0, &val);
+
+ if (err || (val != 0 && val != 1)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ rcu_read_lock();
+ task = pid_task(proc_pid(inode), PIDTYPE_PID);
+ if (task != current) {
+ rcu_read_unlock();
+ err = -EPERM;
+ goto out;
+ }
+ rcu_read_unlock();
+
+ if (val == 1)
+ err = tick_nohz_task_set();
+ else
+ tick_nohz_task_clear();
+
+out:
+ return err < 0 ? err : count;
+}
+
+
+static const struct file_operations proc_nohz_operations = {
+ .read = proc_nohz_read,
+ .write = proc_nohz_write,
+ .llseek = generic_file_llseek,
+};
+#endif /* CONFIG_NO_HZ_TASK */
+
+
#ifdef CONFIG_FAULT_INJECTION
static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
@@ -2784,6 +2861,9 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
REG("sessionid", S_IRUGO, proc_sessionid_operations),
#endif
+#ifdef CONFIG_NO_HZ_TASK
+ REG("nohz", S_IWUSR|S_IRUGO, proc_nohz_operations),
+#endif
#ifdef CONFIG_FAULT_INJECTION
REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f80088a..0e2e5c9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2552,6 +2552,7 @@ extern void task_oncpu_function_call(struct task_struct *p,
#ifdef CONFIG_NO_HZ_TASK
extern void smp_send_update_nohz_task_cpu(int cpu);
extern int nohz_task_can_stop_tick(void);
+extern int sched_task_set_nohz(void);
#else
static inline void smp_send_update_nohz_task_cpu(int cpu) { }
static inline int nohz_task_can_stop_tick(void) { return 0; }
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 37af961..5364438 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -137,6 +137,7 @@ extern void tick_nohz_task_enter_kernel(void);
extern void tick_nohz_task_exit_kernel(void);
extern void tick_nohz_task_enter_exception(struct pt_regs *regs);
extern void tick_nohz_task_exit_exception(struct pt_regs *regs);
+extern int tick_nohz_task_set(void);
extern void tick_nohz_task_clear(void);
extern int tick_nohz_task_mode(void);
diff --git a/kernel/sched.c b/kernel/sched.c
index bd0a41f..d553a47 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2491,6 +2491,49 @@ void smp_send_update_nohz_task_cpu(int cpu)
smp_call_function_single(cpu, nohz_task_cpu_update,
NULL, 0);
}
+
+int sched_task_set_nohz(void)
+{
+ int cpu;
+ struct rq *rq;
+ int err = -EBUSY;
+ unsigned long flags;
+
+ get_online_cpus();
+
+ /* We need to serialize against set_cpus_allowed() */
+ rq = task_rq_lock(current, &flags);
+
+ /* A nohz task must be affine to a single cpu */
+ if (!cpumask_weight(¤t->cpus_allowed) == 1)
+ goto out;
+
+ cpu = smp_processor_id();
+
+ if (!cpu_online(cpu))
+ goto out;
+
+ /* A CPU must have a single nohz task */
+ if (cpu_has_nohz_task(cpu))
+ goto out;
+
+ /*
+ * We need to keep at least one CPU without nohz task
+ * for several background jobs.
+ */
+ if (cpumask_weight(cpu_online_mask) -
+ cpumask_weight(cpu_has_nohz_task_mask) == 1)
+ goto out;
+
+ set_cpu_has_nohz_task(cpu, 1);
+ set_thread_flag(TIF_NOHZ);
+ err = 0;
+out:
+ task_rq_unlock(rq, &flags);
+ put_online_cpus();
+
+ return err;
+}
#endif
static inline void ttwu_activate(struct task_struct *p, struct rq *rq,
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index a460cee..dfb10db 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -31,6 +31,6 @@ config NO_HZ_TASK
bool "Tickless task"
depends on HAVE_NO_HZ_TASK && NO_HZ && SMP && HIGH_RES_TIMERS
help
- When a task runs alone on a CPU and switches into this mode,
- the timer interrupt will only trigger when it is strictly
- needed.
+ This implements the /proc/self/nohz interface. When a task
+ runs alone on a CPU and switches into this mode, the timer
+ interrupt will only trigger when it is strictly needed.
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 06379eb..f408803 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -720,6 +720,18 @@ void tick_check_idle(int cpu)
}
#ifdef CONFIG_NO_HZ_TASK
+int tick_nohz_task_set(void)
+{
+ /*
+ * Only current can set this from procfs, so no possible
+ * race.
+ */
+ if (test_thread_flag(TIF_NOHZ))
+ return 0;
+
+ return sched_task_set_nohz();
+}
+
void tick_nohz_task_clear(void)
{
int cpu = raw_smp_processor_id();
--
1.7.3.2
next prev parent reply other threads:[~2010-12-20 15:25 UTC|newest]
Thread overview: 98+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-20 15:24 [RFC PATCH 00/15] Nohz task support Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 01/15] nohz_task: New mask for cpus having nohz task Frederic Weisbecker
2010-12-24 8:00 ` Lai Jiangshan
2010-12-24 8:19 ` Dario Faggioli
2010-12-24 12:29 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 02/15] nohz_task: Avoid nohz task cpu as non-idle timer target Frederic Weisbecker
2010-12-20 15:47 ` Peter Zijlstra
2010-12-20 16:06 ` Steven Rostedt
2010-12-20 16:12 ` Peter Zijlstra
2010-12-21 0:20 ` Frederic Weisbecker
2010-12-21 7:51 ` Peter Zijlstra
2010-12-21 13:58 ` Frederic Weisbecker
2010-12-21 0:13 ` Frederic Weisbecker
2010-12-21 7:50 ` Peter Zijlstra
2010-12-21 13:52 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 03/15] nohz_task: Make tick stop and restart callable outside idle Frederic Weisbecker
2010-12-20 15:48 ` Peter Zijlstra
2010-12-20 16:19 ` Steven Rostedt
2010-12-20 16:25 ` Peter Zijlstra
2010-12-21 1:34 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 04/15] nohz_task: Stop the tick when the nohz task runs alone Frederic Weisbecker
2010-12-20 15:51 ` Peter Zijlstra
2010-12-20 23:37 ` Frederic Weisbecker
2010-12-21 7:35 ` Peter Zijlstra
2010-12-21 13:22 ` Frederic Weisbecker
2010-12-21 14:34 ` Steven Rostedt
2010-12-21 15:14 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 05/15] nohz_task: Restart the tick when another task compete on the cpu Frederic Weisbecker
2010-12-20 15:53 ` Peter Zijlstra
2010-12-20 23:39 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 06/15] nohz_task: Keep the tick if rcu needs it Frederic Weisbecker
2010-12-20 15:58 ` Peter Zijlstra
2010-12-20 23:49 ` Frederic Weisbecker
2010-12-21 0:12 ` Jonathan Corbet
2010-12-21 2:10 ` Frederic Weisbecker
2010-12-21 8:10 ` Paul E. McKenney
2010-12-20 15:24 ` [RFC PATCH 07/15] nohz_task: Restart tick when RCU forces nohz task cpu quiescent state Frederic Weisbecker
2010-12-20 16:02 ` Peter Zijlstra
2010-12-20 23:52 ` Frederic Weisbecker
2010-12-21 7:41 ` Peter Zijlstra
2010-12-21 13:28 ` Frederic Weisbecker
2010-12-21 15:35 ` Paul E. McKenney
2010-12-20 15:24 ` [RFC PATCH 08/15] smp: Don't warn if irq are disabled but we don't wait for the ipi Frederic Weisbecker
2010-12-20 16:03 ` Peter Zijlstra
2010-12-21 0:02 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 09/15] rcu: Make rcu_enter,exit_nohz() callable from irq Frederic Weisbecker
2010-12-21 19:26 ` Paul E. McKenney
2010-12-21 19:27 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 10/15] nohz_task: Enter in extended quiescent state when in userspace Frederic Weisbecker
2010-12-20 16:18 ` Peter Zijlstra
2010-12-21 1:27 ` Frederic Weisbecker
2010-12-21 8:04 ` Peter Zijlstra
2010-12-21 14:06 ` Frederic Weisbecker
2010-12-21 19:28 ` Paul E. McKenney
2010-12-21 21:49 ` Frederic Weisbecker
2010-12-22 2:20 ` Paul E. McKenney
2010-12-20 15:24 ` [RFC PATCH 11/15] x86: Nohz task support Frederic Weisbecker
2010-12-20 16:23 ` Peter Zijlstra
2010-12-21 1:30 ` Frederic Weisbecker
2010-12-21 8:05 ` Peter Zijlstra
2010-12-21 14:19 ` Frederic Weisbecker
2010-12-21 15:12 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 12/15] clocksource: Ignore nohz task cpu in clocksource watchdog Frederic Weisbecker
2010-12-20 16:27 ` Peter Zijlstra
2010-12-21 1:40 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 13/15] sched: Protect nohz task cpu affinity Frederic Weisbecker
2010-12-20 16:28 ` Peter Zijlstra
2010-12-20 17:05 ` Steven Rostedt
2010-12-21 1:55 ` Frederic Weisbecker
2010-12-20 15:24 ` [RFC PATCH 14/15] nohz_task: Clear nohz task attribute on exit() Frederic Weisbecker
2010-12-20 16:30 ` Peter Zijlstra
2010-12-21 1:48 ` Frederic Weisbecker
2010-12-21 8:07 ` Peter Zijlstra
2010-12-21 14:22 ` Frederic Weisbecker
2010-12-20 15:24 ` Frederic Weisbecker [this message]
2010-12-20 15:42 ` [RFC PATCH 15/15] nohz_task: Procfs interface Peter Zijlstra
2010-12-20 15:57 ` Frederic Weisbecker
2010-12-20 16:16 ` Peter Zijlstra
2010-12-21 1:24 ` Frederic Weisbecker
2010-12-21 8:14 ` Peter Zijlstra
2010-12-21 14:00 ` Avi Kivity
2010-12-21 17:05 ` Frederic Weisbecker
2010-12-21 18:17 ` Avi Kivity
2010-12-21 21:08 ` Frederic Weisbecker
2010-12-22 9:22 ` Avi Kivity
2010-12-22 9:51 ` Peter Zijlstra
2010-12-22 20:41 ` Frederic Weisbecker
2010-12-21 14:26 ` Frederic Weisbecker
2010-12-20 15:44 ` [RFC PATCH 00/15] Nohz task support Steven Rostedt
2010-12-20 23:33 ` Frederic Weisbecker
2010-12-21 1:36 ` Steven Rostedt
2010-12-21 2:15 ` Frederic Weisbecker
2010-12-21 7:34 ` Peter Zijlstra
2010-12-21 13:13 ` Frederic Weisbecker
2010-12-21 13:56 ` Avi Kivity
2010-12-21 17:01 ` Frederic Weisbecker
2010-12-20 16:35 ` Peter Zijlstra
2010-12-21 1:53 ` Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1292858662-5650-16-git-send-email-fweisbec@gmail.com \
--to=fweisbec@gmail.com \
--cc=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=anton@au1.ibm.com \
--cc=laijs@cn.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lnxninja@linux.vnet.ibm.com \
--cc=mingo@elte.hu \
--cc=paulmck@linux.vnet.ibm.com \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome