mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Peter Williams <pwil3058@bigpond.net.au>
To: Mike Galbraith <efault@gmx.de>
Cc: Con Kolivas <kernel@kolivas.org>,
	Peter Williams <pwil3058@bigpond.net.au>,
	Linux Kernel <linux-kernel@vger.kernel.org>,
	Kingsley Cheung <kingsley@aurema.com>,
	Ingo Molnar <mingo@elte.hu>,
	Rene Herman <rene.herman@keyaccess.nl>
Subject: [RFC 3/5] sched: Add CPU rate hard caps
Date: Fri, 26 May 2006 14:20:51 +1000	[thread overview]
Message-ID: <20060526042051.2886.70594.sendpatchset@heathwren.pw.nest> (raw)
In-Reply-To: <20060526042021.2886.4957.sendpatchset@heathwren.pw.nest>

This patch implements hard CPU rate caps per task as a proportion of a
single CPU's capacity expressed in parts per thousand.

Signed-off-by: Peter Williams <pwil3058@bigpond.com.au>
 include/linux/sched.h |    8 ++
 kernel/Kconfig.caps   |   14 +++-
 kernel/sched.c        |  154 ++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 168 insertions(+), 8 deletions(-)

Index: MM-2.6.17-rc4-mm3/include/linux/sched.h
===================================================================
--- MM-2.6.17-rc4-mm3.orig/include/linux/sched.h	2006-05-26 10:46:35.000000000 +1000
+++ MM-2.6.17-rc4-mm3/include/linux/sched.h	2006-05-26 11:00:07.000000000 +1000
@@ -796,6 +796,10 @@ struct task_struct {
 #ifdef CONFIG_CPU_RATE_CAPS
 	unsigned long long avg_cpu_per_cycle, avg_cycle_length;
 	unsigned int cpu_rate_cap;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	unsigned int cpu_rate_hard_cap;
+	struct timer_list sinbin_timer;
+#endif
 #endif
 	enum sleep_type sleep_type;
 
@@ -994,6 +998,10 @@ struct task_struct {
 #ifdef CONFIG_CPU_RATE_CAPS
 unsigned int get_cpu_rate_cap(const struct task_struct *);
 int set_cpu_rate_cap(struct task_struct *, unsigned int);
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+unsigned int get_cpu_rate_hard_cap(const struct task_struct *);
+int set_cpu_rate_hard_cap(struct task_struct *, unsigned int);
+#endif
 #endif
 
 static inline pid_t process_group(struct task_struct *tsk)
Index: MM-2.6.17-rc4-mm3/kernel/Kconfig.caps
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/Kconfig.caps	2006-05-26 10:45:26.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/Kconfig.caps	2006-05-26 11:00:07.000000000 +1000
@@ -3,11 +3,21 @@
 #
 
 config CPU_RATE_CAPS
-	bool "Support (soft) CPU rate caps"
+	bool "Support CPU rate caps"
 	default n
 	---help---
-	  Say y here if you wish to be able to put a (soft) upper limit on
+	  Say y here if you wish to be able to put a soft upper limit on
 	  the rate of CPU usage by individual tasks.  A task which has been
 	  allocated a soft CPU rate cap will be limited to that rate of CPU
 	  usage unless there is spare CPU resources available after the needs
 	  of uncapped tasks are met.
+
+config CPU_RATE_HARD_CAPS
+	bool "Support CPU rate hard caps"
+	depends on CPU_RATE_CAPS
+	default n
+	---help---
+	  Say y here if you wish to be able to put a hard upper limit on
+	  the rate of CPU usage by individual tasks.  A task which has been
+	  allocated a hard CPU rate cap will be limited to that rate of CPU
+	  usage regardless of whether there is spare CPU resources available.
Index: MM-2.6.17-rc4-mm3/kernel/sched.c
===================================================================
--- MM-2.6.17-rc4-mm3.orig/kernel/sched.c	2006-05-26 11:00:02.000000000 +1000
+++ MM-2.6.17-rc4-mm3/kernel/sched.c	2006-05-26 13:50:11.000000000 +1000
@@ -201,21 +201,33 @@ static inline unsigned int task_timeslic
 
 #ifdef CONFIG_CPU_RATE_CAPS
 #define CAP_STATS_OFFSET 8
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+static void sinbin_release_fn(unsigned long arg);
+#define min_cpu_rate_cap(p) min((p)->cpu_rate_cap, (p)->cpu_rate_hard_cap)
+#else
+#define min_cpu_rate_cap(p) (p)->cpu_rate_cap
+#endif
 #define task_has_cap(p) unlikely((p)->flags & PF_HAS_CAP)
 /* this assumes that p is not a real time task */
 #define task_is_background(p) unlikely((p)->cpu_rate_cap == 0)
 #define task_being_capped(p) unlikely((p)->prio >= CAPPED_PRIO)
-#define cap_load_weight(p) (((p)->cpu_rate_cap * SCHED_LOAD_SCALE) / 1000)
+#define cap_load_weight(p) ((min_cpu_rate_cap(p) * SCHED_LOAD_SCALE) / 1000)
 
 static void init_cpu_rate_caps(task_t *p)
 {
 	p->cpu_rate_cap = 1000;
 	p->flags &= ~PF_HAS_CAP;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	p->cpu_rate_hard_cap = 1000;
+	init_timer(&p->sinbin_timer);
+	p->sinbin_timer.function = sinbin_release_fn;
+	p->sinbin_timer.data = (unsigned long) p;
+#endif
 }
 
 static inline void set_cap_flag(task_t *p)
 {
-	if (p->cpu_rate_cap < 1000 && !has_rt_policy(p))
+	if (min_cpu_rate_cap(p) < 1000 && !has_rt_policy(p))
 		p->flags |= PF_HAS_CAP;
 	else
 		p->flags &= ~PF_HAS_CAP;
@@ -223,7 +235,7 @@ static inline void set_cap_flag(task_t *
 
 static inline int task_exceeding_cap(const task_t *p)
 {
-	return (p->avg_cpu_per_cycle * 1000) > (p->avg_cycle_length * p->cpu_rate_cap);
+	return (p->avg_cpu_per_cycle * 1000) > (p->avg_cycle_length * min_cpu_rate_cap(p));
 }
 
 #ifdef CONFIG_SCHED_SMT
@@ -257,7 +269,7 @@ static int task_exceeding_cap_now(const 
 
 	delta = (now > p->timestamp) ? (now - p->timestamp) : 0;
 	lhs = (p->avg_cpu_per_cycle + delta) * 1000;
-	rhs = (p->avg_cycle_length + delta) * p->cpu_rate_cap;
+	rhs = (p->avg_cycle_length + delta) * min_cpu_rate_cap(p);
 
 	return lhs > rhs;
 }
@@ -266,6 +278,10 @@ static inline void init_cap_stats(task_t
 {
 	p->avg_cpu_per_cycle = 0;
 	p->avg_cycle_length = 0;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	init_timer(&p->sinbin_timer);
+	p->sinbin_timer.data = (unsigned long) p;
+#endif
 }
 
 static inline void inc_cap_stats_cycle(task_t *p, unsigned long long now)
@@ -1213,6 +1229,64 @@ static void deactivate_task(struct task_
 	p->array = NULL;
 }
 
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+#define task_has_hard_cap(p) unlikely((p)->cpu_rate_hard_cap < 1000)
+
+/*
+ * Release a task from the sinbin
+ */
+static void sinbin_release_fn(unsigned long arg)
+{
+	unsigned long flags;
+	struct task_struct *p = (struct task_struct*)arg;
+	struct runqueue *rq = task_rq_lock(p, &flags);
+
+	p->prio = effective_prio(p);
+
+	__activate_task(p, rq);
+
+	task_rq_unlock(rq, &flags);
+}
+
+static unsigned long reqd_sinbin_ticks(const task_t *p)
+{
+	unsigned long long res;
+
+	res = p->avg_cpu_per_cycle * 1000;
+
+	if (res > p->avg_cycle_length * p->cpu_rate_hard_cap) {
+		(void)do_div(res, p->cpu_rate_hard_cap);
+		res -= p->avg_cpu_per_cycle;
+		/*
+		 * IF it was available we'd also subtract
+		 * the average sleep per cycle here
+		 */
+		res >>= CAP_STATS_OFFSET;
+		(void)do_div(res, (1000000000 / HZ));
+
+		return res ? : 1;
+	}
+
+	return 0;
+}
+
+static void sinbin_task(task_t *p, unsigned long durn)
+{
+	if (durn == 0)
+		return;
+	deactivate_task(p, task_rq(p));
+	p->sinbin_timer.expires = jiffies + durn;
+	add_timer(&p->sinbin_timer);
+}
+#else
+#define task_has_hard_cap(p) 0
+#define reqd_sinbin_ticks(p) 0
+
+static inline void sinbin_task(task_t *p, unsigned long durn)
+{
+}
+#endif
+
 /*
  * resched_task - mark a task 'to be rescheduled now'.
  *
@@ -3508,9 +3582,16 @@ need_resched_nonpreemptible:
 		}
 	}
 
-	/* do this now so that stats are correct for SMT code */
-	if (task_has_cap(prev))
+	if (task_has_cap(prev)) {
 		inc_cap_stats_both(prev, now);
+		if (task_has_hard_cap(prev) && !prev->state &&
+		    !rt_task(prev) && !signal_pending(prev)) {
+			unsigned long sinbin_ticks = reqd_sinbin_ticks(prev);
+
+			if (sinbin_ticks)
+				sinbin_task(prev, sinbin_ticks);
+		}
+	}
 
 	cpu = smp_processor_id();
 	if (unlikely(!rq->nr_running)) {
@@ -4539,6 +4620,67 @@ out:
 }
 
 EXPORT_SYMBOL(set_cpu_rate_cap);
+
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+unsigned int get_cpu_rate_hard_cap(const struct task_struct *p)
+{
+	return p->cpu_rate_hard_cap;
+}
+
+EXPORT_SYMBOL(get_cpu_rate_hard_cap);
+
+/*
+ * Require: 1 <= new_cap <= 1000
+ */
+int set_cpu_rate_hard_cap(struct task_struct *p, unsigned int new_cap)
+{
+	int is_allowed;
+	unsigned long flags;
+	struct runqueue *rq;
+	int delta;
+
+	if (new_cap > 1000 && new_cap > 0)
+		return -EINVAL;
+	is_allowed = capable(CAP_SYS_NICE);
+	/*
+	 * We have to be careful, if called from /proc code,
+	 * the task might be in the middle of scheduling on another CPU.
+	 */
+	rq = task_rq_lock(p, &flags);
+	delta = new_cap - p->cpu_rate_hard_cap;
+	if (!is_allowed) {
+		/*
+		 * Ordinary users can set/change caps on their own tasks
+		 * provided that the new setting is MORE constraining
+		 */
+		if (((current->euid != p->uid) && (current->uid != p->uid)) || (delta > 0)) {
+			task_rq_unlock(rq, &flags);
+			return -EPERM;
+		}
+	}
+	/*
+	 * The RT tasks don't have caps, but we still allow the caps to be
+	 * set - but as expected it wont have any effect on scheduling until
+	 * the task becomes SCHED_NORMAL/SCHED_BATCH:
+	 */
+	p->cpu_rate_hard_cap = new_cap;
+
+	if (has_rt_policy(p))
+		goto out;
+
+	if (p->array)
+		dec_raw_weighted_load(rq, p);
+	set_load_weight(p);
+	if (p->array)
+		inc_raw_weighted_load(rq, p);
+out:
+	task_rq_unlock(rq, &flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(set_cpu_rate_hard_cap);
+#endif
 #endif
 
 long sched_setaffinity(pid_t pid, cpumask_t new_mask)

-- 
Peter Williams                                   pwil3058@bigpond.net.au

"Learning, n. The kind of ignorance distinguishing the studious."
 -- Ambrose Bierce

  parent reply	other threads:[~2006-05-26  4:21 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-26  4:20 [RFC 0/5] sched: Add CPU rate caps Peter Williams
2006-05-26  4:20 ` [RFC 1/5] sched: Fix priority inheritence before CPU rate soft caps Peter Williams
2006-05-26  4:20 ` [RFC 2/5] sched: Add " Peter Williams
2006-05-26 10:48   ` Con Kolivas
2006-05-26 11:15     ` Mike Galbraith
2006-05-26 11:17       ` Con Kolivas
2006-05-26 11:30         ` Mike Galbraith
2006-05-26 13:55     ` Peter Williams
2006-05-27  6:31   ` Balbir Singh
2006-05-27  7:03     ` Peter Williams
2006-05-28  0:11       ` Peter Williams
2006-05-28  7:38         ` Balbir Singh
2006-05-28 13:35           ` Peter Williams
2006-05-28 14:42             ` Balbir Singh
2006-05-28 23:27               ` Peter Williams
2006-05-31 13:17                 ` Kirill Korotaev
2006-05-31 23:39                   ` Peter Williams
2006-06-01  8:09                     ` Kirill Korotaev
2006-06-01 23:38                       ` Peter Williams
2006-06-02  1:35                         ` Peter Williams
2006-05-26  4:20 ` Peter Williams [this message]
2006-05-26  6:58   ` [RFC 3/5] sched: Add CPU rate hard caps Kari Hurtta
2006-05-27  1:00     ` Peter Williams
2006-05-26 11:00   ` Con Kolivas
2006-05-26 13:59     ` Peter Williams
2006-05-26 14:12       ` Con Kolivas
2006-05-26 14:23       ` Mike Galbraith
2006-05-27  0:16         ` Peter Williams
2006-05-27  9:28           ` Mike Galbraith
2006-05-28  2:09             ` Peter Williams
2006-05-27  6:48   ` Balbir Singh
2006-05-27  8:44     ` Peter Williams
2006-05-31 13:10       ` Kirill Korotaev
2006-05-31 15:59         ` Balbir Singh
2006-05-31 18:09           ` Mike Galbraith
2006-06-01  7:41           ` Kirill Korotaev
2006-06-01  8:34             ` Balbir Singh
2006-06-01 18:43               ` [ckrm-tech] " Chandra Seetharaman
2006-06-01 23:26                 ` Peter Williams
2006-06-02  2:02                   ` Chandra Seetharaman
2006-06-02  3:21                     ` Peter Williams
2006-06-02  8:32                       ` Balbir Singh
2006-06-02 13:30                         ` Peter Williams
2006-06-02 18:58                           ` Balbir Singh
2006-06-02 23:49                             ` Peter Williams
2006-06-03  4:59                               ` Balbir Singh
2006-06-02 19:06                       ` Chandra Seetharaman
2006-06-03  0:04                         ` Peter Williams
2006-06-02  0:36                 ` Con Kolivas
2006-06-02  2:03                   ` [ckrm-tech] " Chandra Seetharaman
2006-06-02  5:55                 ` [ckrm-tech] [RFC 3/5] " Peter Williams
2006-06-02  7:47                   ` Kirill Korotaev
2006-06-02 13:34                     ` Peter Williams
2006-06-05 22:11                     ` Sam Vilain
2006-06-06  8:24                       ` Kirill Korotaev
2006-06-06  9:13                         ` Con Kolivas
2006-06-06  9:28                           ` Kirill Korotaev
2006-06-02  8:46                   ` Mike Galbraith
2006-06-02 13:18                     ` Peter Williams
2006-06-02 14:47                       ` Mike Galbraith
2006-06-03  0:08                         ` Peter Williams
2006-06-03  6:02                           ` Mike Galbraith
2006-06-03 11:03                             ` Peter Williams
2006-06-06 11:26                         ` Srivatsa Vaddagiri
2006-06-02  7:34                 ` Kirill Korotaev
2006-06-02 21:23                   ` Shailabh Nagar
2006-06-01 23:47               ` Sam Vilain
2006-06-01 23:43           ` Peter Williams
2006-05-31 23:28         ` Peter Williams
2006-06-01  7:44           ` Kirill Korotaev
2006-06-01 23:21             ` Peter Williams
2006-05-26  4:21 ` [RFC 4/5] sched: Add procfs interface for CPU rate soft caps Peter Williams
2006-05-26  4:21 ` [RFC 5/5] sched: Add procfs interface for CPU rate hard caps Peter Williams
2006-05-26  8:04 ` [RFC 0/5] sched: Add CPU rate caps Mike Galbraith
2006-05-26 16:11   ` Björn Steinbrink
2006-05-28 22:46     ` Sam Vilain
2006-05-28 23:30       ` Peter Williams
2006-05-29  3:09         ` Sam Vilain
2006-05-29  3:41           ` Peter Williams
2006-05-29 21:16             ` Sam Vilain
2006-05-29 23:12               ` Peter Williams
2006-05-30  2:07                 ` Sam Vilain
2006-05-30  2:45                   ` Peter Williams
2006-05-30 22:05                     ` Sam Vilain
2006-05-30 23:22                       ` Peter Williams
2006-05-30 23:25                       ` Peter Williams
2006-06-05 23:56                       ` Peter Williams
2006-05-27  0:16   ` Peter Williams
2006-05-26 10:41 ` Con Kolivas
2006-05-27  1:28   ` Peter Williams
2006-05-27  1:42     ` Con Kolivas
2006-05-26 11:09 ` Con Kolivas
2006-05-26 14:00   ` Peter Williams
2006-05-26 11:29 ` Balbir Singh
2006-05-27  1:40   ` Peter Williams
2006-06-01 21:03 [RFC 3/5] sched: Add CPU rate hard caps Al Boldi
2006-06-02  1:33 ` Peter Williams
2006-06-02 11:23   ` Matt Helsley
2006-06-02 13:16     ` Peter Williams
2006-06-06 10:47     ` Srivatsa Vaddagiri

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=20060526042051.2886.70594.sendpatchset@heathwren.pw.nest \
    --to=pwil3058@bigpond.net.au \
    --cc=efault@gmx.de \
    --cc=kernel@kolivas.org \
    --cc=kingsley@aurema.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rene.herman@keyaccess.nl \
    /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

all inboxes | Powered by JetHome®