Re: [PATCH 0/4] sched: Add CPU rate caps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Peter Williams wrote:
Andrew Morton wrote:
On Sun, 18 Jun 2006 18:26:38 +1000
Peter Williams <[email protected]> wrote:
5. Code size measurements:

Vanilla kernel:

   text    data     bss     dec     hex filename
  33800    4689     296   38785    9781 sched.o
   2554      79       0    2633     a49 mutex.o
  12076    2632       0   14708    3974 base.o

Patches applied:

   text    data     bss     dec     hex filename
  36870    4721     296   41887    a39f sched.o
   2630      79       0    2709     a95 mutex.o
  13011    2920       0   15931    3e3b base.o

Indicating that the size cost of the patch proper is about
3 kilobytes and the procfs costs about another 1.2 kilobytes.


hm.  That seems rather a lot.  I guess it's not a simple thing to do.

I suspect that a large part of that is the functions that set the caps (i.e. the equivalents of set_user_nice()) one for soft and one for hard caps. The actual capping mechanisms are quite simple.

This contribution may not be as large as I thought.  Realizing that the
function to set soft caps and the function to set hard caps duplicate a
lot of code I've modified them to share code rather than duplicate.
I've also made the functions for getting caps inline and they should
just be optimized away to a field reference.  But the reduction in code
size is only about 285 bytes.

Before:
   text    data     bss     dec     hex filename
  32820    4913     672   38405    9605 kernel/sched.o

After:
   text    data     bss     dec     hex filename
  32535    4913     672   38120    94e8 kernel/sched.o

Noting that these values were less than those in the original mail, I've
also checked the size for when the patches are excluded.

   text    data     bss     dec     hex filename
  30061    4881     672   35614    8b1e kernel/sched.o

The numbers in the e-mail were from a different computer with gcc-4.0.2
installed while these are generated with gcc-4.1.1 (also that build
would not have had CONFIG_SCHED_SMT or CONFIG_SCHED_MC set).  But the
end result is that the cost is still of the order of 2.5 kilobytes.

A patch to make these changes is attached.

Signed-off-by: Peter Williams <[email protected]>

Peter
--
Peter Williams                                   [email protected]

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

---
 include/linux/sched.h |   24 +++++++++++--
 kernel/sched.c        |   90 ++++++++++----------------------------------------
 2 files changed, 38 insertions(+), 76 deletions(-)

Index: MM-2.6.17-rc6-mm2/include/linux/sched.h
===================================================================
--- MM-2.6.17-rc6-mm2.orig/include/linux/sched.h	2006-06-19 13:57:18.000000000 +1000
+++ MM-2.6.17-rc6-mm2/include/linux/sched.h	2006-06-19 14:28:25.000000000 +1000
@@ -1022,11 +1022,27 @@ 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);
+int set_cpu_rate_cap_low(struct task_struct *, unsigned int, int);
+
+static inline unsigned int get_cpu_rate_cap(const struct task_struct *p)
+{
+	return p->cpu_rate_cap;
+}
+
+static inline int set_cpu_rate_cap(struct task_struct *p, unsigned int newcap)
+{
+	return set_cpu_rate_cap_low(p, newcap, 0);
+}
 #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);
+static inline unsigned int get_cpu_rate_hard_cap(const struct task_struct *p)
+{
+	return p->cpu_rate_hard_cap;
+}
+
+static inline int set_cpu_rate_hard_cap(struct task_struct *p, unsigned int newcap)
+{
+	return set_cpu_rate_cap_low(p, newcap, 1);
+}
 #endif
 #endif
 
Index: MM-2.6.17-rc6-mm2/kernel/sched.c
===================================================================
--- MM-2.6.17-rc6-mm2.orig/kernel/sched.c	2006-06-19 13:57:18.000000000 +1000
+++ MM-2.6.17-rc6-mm2/kernel/sched.c	2006-06-19 14:28:25.000000000 +1000
@@ -4614,17 +4614,11 @@ out_unlock:
 }
 
 #ifdef CONFIG_CPU_RATE_CAPS
-unsigned int get_cpu_rate_cap(const struct task_struct *p)
-{
-	return p->cpu_rate_cap;
-}
-
-EXPORT_SYMBOL(get_cpu_rate_cap);
-
 /*
- * Require: 0 <= new_cap <= CPU_CAP_ONE
+ * Require: 0 <= new_cap <= CPU_CAP_ONE for hard == 0
+ *          1 <= new_cap <= CPU_CAP_ONE otherwise
  */
-int set_cpu_rate_cap(struct task_struct *p, unsigned int new_cap)
+int set_cpu_rate_cap_low(struct task_struct *p, unsigned int new_cap, int hard)
 {
 	int is_allowed;
 	unsigned long flags;
@@ -4634,13 +4628,21 @@ int set_cpu_rate_cap(struct task_struct 
 
 	if (new_cap > CPU_CAP_ONE)
 		return -EINVAL;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	if (hard && new_cap < 1)
+		return -EINVAL;
+#endif
 	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);
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	delta = new_cap - (hard ? p->cpu_rate_hard_cap : p->cpu_rate_cap);
+#else
 	delta = new_cap - p->cpu_rate_cap;
+#endif
 	if (!is_allowed) {
 		/*
 		 * Ordinary users can set/change caps on their own tasks
@@ -4656,7 +4658,12 @@ int set_cpu_rate_cap(struct task_struct 
 	 * set - but as expected it wont have any effect on scheduling until
 	 * the task becomes SCHED_NORMAL/SCHED_BATCH:
 	 */
-	p->cpu_rate_cap = new_cap;
+#ifdef CONFIG_CPU_RATE_HARD_CAPS
+	if (hard)
+		p->cpu_rate_hard_cap = new_cap;
+	else
+#endif
+		p->cpu_rate_cap = new_cap;
 
 	if (has_rt_policy(p))
 		goto out;
@@ -4680,68 +4687,7 @@ out:
 	return 0;
 }
 
-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 <= CPU_CAP_ONE
- */
-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 > CPU_CAP_ONE || new_cap < 1)
-		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
+EXPORT_SYMBOL(set_cpu_rate_cap_low);
 #endif
 
 long sched_setaffinity(pid_t pid, cpumask_t new_mask)

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux