Skip to contentSkip to conversation

Fair group scheduler - various fixes

PATCH In review Srivatsa Vaddagiri 4 participants 16 messages Sep 24, 2007 – Sep 25, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Fair group scheduler - various fixes

Hello Ingo and Andrew,
Here are various patches to fair group scheduler code present in
sched-devel and in 2.6.23-rc7-mm1. These patches should apply against both sched-devel git tree and 2.6.23-rc7-mm1 (as they are both in sync now).

Pls consider for inclusion after review.

[there is still room for improving group fairness obtained on smp systems. By sending out these patches, i am hoping more folks can test and improve that aspect]

Ingo,
You may want to avoid picking Patch 5/5 as it makes sense only in
-mm tree atm.

Signature · 2 lines
Regards,
vatsa
#1 lore raw

PATCH 1/5 Revert recent removal of set_curr_task()

Quoted 2 lines · dimm

here is a few cleanup/simplification/optimization(s) based on the recent modifications in the sched-dev tree.

[refer http://marc.info/?l=linux-kernel&m=119014449807290]

[snip]

Quoted 2 lines

(3) rework enqueue/dequeue_entity() to get rid of
sched_class::set_curr_task()

Dmitry/Ingo,
I am sorry for not having reviewed this change properly, but I
think we need to revert this.

Some problems with current sched-devel code introduced by this change:

1. SCHED_NORMAL->SCHED_RT transition of current task
a. we reset current->se.exec_start to 0 (update_stats_curr_end)
and not initialize it again. As a result, update_curr_rt() can calculate bogus values

b. (for CONFIG_FAIR_GROUP_SCHED):
i) higher level entities of current task arent put back on their cfs_rq
ii) their corresponding cfs_rq->curr is not set to NULL
iii) update_stats_wait_start() not called for higher
level entities of current task.

These functions are usually accomplished by put_prev_entity()

2. SCHED_RT->SCHED_NORMAL
a. (minor) we don't initialize se->prev_sum_exec_runtime
in enqueue_entity() under if (set_curr) { } block. As a result the current task may get preempted almost immediately?

b. (for CONFIG_FAIR_GROUP_SCHED):
i) higher level entities of current task arent taken out of their cfs_rq
ii) their corresponding cfs_rq->curr is not set
iii) update_stats_wait_end() and update_stats_curr_start()
arent called for higher level entities of current task.

These functions are usually accomplished by set_next_entity()

(similar problems exist while changing groups)

In theory its possible to solve these problems w/o reintroducing set_curr_task(). I tried doing so, but found it clutters dequeue_entity and enqueue_entity a lot and makes it less readable. It will duplicate what put_prev_entity() and set_next_entity() are supposed to do. Moreoever it is slightly inefficient to do all these in dequeue_entity() if we consider that dequeue_entity can be called on current task for other reasons as well (like when it is abt to sleep or change its nice value).

Considering these, IMHO, it's best to re-introduce set_curr_task() and use put_prev_task/set_curr_task whenever the current task is changing policies/groups.

Let me know what you think.

--

Revert removal of set_curr_task.
Use put_prev_task/set_curr_task when changing groups/policies

---
 include/linux/sched.h   |    1 
 kernel/sched.c          |   34 ++++++++++++++++++------
 kernel/sched_fair.c     |   68 ++++++++++++++++++++++--------------------------
 kernel/sched_idletask.c |    5 +++
 kernel/sched_rt.c       |    8 +++++
 5 files changed, 72 insertions(+), 44 deletions(-)
include/linux/sched.h +1 -0
Index: current/include/linux/sched.h
===================================================================
@@ -870,6 +870,7 @@ struct sched_class {
 			struct sched_domain *sd, enum cpu_idle_type idle,
 			int *all_pinned, int *this_best_prio);
 
+	void (*set_curr_task) (struct rq *rq);
 	void (*task_tick) (struct rq *rq, struct task_struct *p);
 	void (*task_new) (struct rq *rq, struct task_struct *p);
 };
kernel/sched.c +26 -8
Index: current/kernel/sched.c
===================================================================
@@ -3916,7 +3916,7 @@ EXPORT_SYMBOL(sleep_on_timeout);
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
 	unsigned long flags;
-	int oldprio, on_rq;
+	int oldprio, on_rq, running;
 	struct rq *rq;
 
 	BUG_ON(prio < 0 || prio > MAX_PRIO);
@@ -3926,8 +3926,12 @@ void rt_mutex_setprio(struct task_struct
 
 	oldprio = p->prio;
 	on_rq = p->se.on_rq;
-	if (on_rq)
+	running = task_running(rq, p);
+	if (on_rq) {
 		dequeue_task(rq, p, 0);
+		if (running)
+			p->sched_class->put_prev_task(rq, p);
+	}
 
 	if (rt_prio(prio))
 		p->sched_class = &rt_sched_class;
@@ -3937,13 +3941,15 @@ void rt_mutex_setprio(struct task_struct
 	p->prio = prio;
 
 	if (on_rq) {
+		if (running)
+			p->sched_class->set_curr_task(rq);
 		enqueue_task(rq, p, 0);
 		/*
 		 * Reschedule if we are currently running on this runqueue and
 		 * our priority decreased, or if we are not currently running on
 		 * this runqueue and our priority is higher than the current's
 		 */
-		if (task_running(rq, p)) {
+		if (running) {
 			if (p->prio > oldprio)
 				resched_task(rq->curr);
 		} else {
@@ -4149,7 +4155,7 @@ __setscheduler(struct rq *rq, struct tas
 int sched_setscheduler(struct task_struct *p, int policy,
 		       struct sched_param *param)
 {
-	int retval, oldprio, oldpolicy = -1, on_rq;
+	int retval, oldprio, oldpolicy = -1, on_rq, running;
 	unsigned long flags;
 	struct rq *rq;
 
@@ -4231,20 +4237,26 @@ recheck:
 	}
 	update_rq_clock(rq);
 	on_rq = p->se.on_rq;
-	if (on_rq)
+	running = task_running(rq, p);
+	if (on_rq) {
 		deactivate_task(rq, p, 0);
+		if (running)
+			p->sched_class->put_prev_task(rq, p);
+	}
 
 	oldprio = p->prio;
 	__setscheduler(rq, p, policy, param->sched_priority);
 
 	if (on_rq) {
+		if (running)
+			p->sched_class->set_curr_task(rq);
 		activate_task(rq, p, 0);
 		/*
 		 * Reschedule if we are currently running on this runqueue and
 		 * our priority decreased, or if we are not currently running on
 		 * this runqueue and our priority is higher than the current's
 		 */
-		if (task_running(rq, p)) {
+		if (running) {
 			if (p->prio > oldprio)
 				resched_task(rq->curr);
 		} else {
@@ -6845,13 +6857,19 @@ static void sched_move_task(struct conta
 	running = task_running(rq, tsk);
 	on_rq = tsk->se.on_rq;
 
-	if (on_rq)
+	if (on_rq) {
 		dequeue_task(rq, tsk, 0);
+		if (unlikely(running))
+			tsk->sched_class->put_prev_task(rq, tsk);
+	}
 
 	set_task_cfs_rq(tsk);
 
-	if (on_rq)
+	if (on_rq) {
+		if (unlikely(running))
+			tsk->sched_class->set_curr_task(rq);
 		enqueue_task(rq, tsk, 0);
+	}
 
 done:
 	task_rq_unlock(rq, &flags);
kernel/sched_fair.c +32 -36

132 lines not on this page · raw message

kernel/sched_idletask.c +5 -0
Index: current/kernel/sched_idletask.c
===================================================================
@@ -50,6 +50,10 @@ static void task_tick_idle(struct rq *rq
 {
 }
 
+static void set_curr_task_idle(struct rq *rq)
+{
+}
+
 /*
  * Simple, special scheduling class for the per-CPU idle tasks:
  */
@@ -66,6 +70,7 @@ static struct sched_class idle_sched_cla
 
 	.load_balance		= load_balance_idle,
 
+	.set_curr_task          = set_curr_task_idle,
 	.task_tick		= task_tick_idle,
 	/* no .task_new for idle tasks */
 };
kernel/sched_rt.c +8 -0
Index: current/kernel/sched_rt.c
===================================================================
@@ -218,6 +218,13 @@ static void task_tick_rt(struct rq *rq, 
 	}
 }
 
+static void set_curr_task_rt(struct rq *rq)
+{
+	struct task_struct *p = rq->curr;
+
+	p->se.exec_start = rq->clock;
+}
+
 static struct sched_class rt_sched_class __read_mostly = {
 	.enqueue_task		= enqueue_task_rt,
 	.dequeue_task		= dequeue_task_rt,
@@ -230,5 +237,6 @@ static struct sched_class rt_sched_class
 
 	.load_balance		= load_balance_rt,
 
+	.set_curr_task          = set_curr_task_rt,
 	.task_tick		= task_tick_rt,
 };
Signature · 2 lines
Regards,
vatsa
#2 lore raw

Re: [PATCH 1/5] Revert recent removal of set_curr_task()

Quoted 6 lines · Srivatsa Vaddagiri
Quoted 2 lines

(3) rework enqueue/dequeue_entity() to get rid of
sched_class::set_curr_task()

Dmitry/Ingo,
I am sorry for not having reviewed this change properly, but I
think we need to revert this.

ah, i was wondering about that already. We can certainly skip that optimization.

Quoted 8 lines

In theory its possible to solve these problems w/o reintroducing set_curr_task(). I tried doing so, but found it clutters dequeue_entity and enqueue_entity a lot and makes it less readable. It will duplicate what put_prev_entity() and set_next_entity() are supposed to do. Moreoever it is slightly inefficient to do all these in dequeue_entity() if we consider that dequeue_entity can be called on current task for other reasons as well (like when it is abt to sleep or change its nice value).

yeah, it's not worth it. I'd go for keeping the code unified even if adds a few instructions runtime overhead, as i'd expect most distros to enable fair-group-scheduling by default in the future. (once all the containers infrastructure and tools has trickled down to them)

Ingo

#3 lore raw

PATCH 2/5 Fix minor bug in yield + add more debug o/p

In reply to Srivatsa Vaddagiri

- Fix a minor bug in yield (seen for CONFIG_FAIR_GROUP_SCHED)
- Print nr_running and load information for cfs_rq in /proc/sched_debug
- Print &rq->cfs statistics as well (usefull for group scheduling)

---
 kernel/sched_debug.c |    2 ++
 kernel/sched_fair.c  |    3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
kernel/sched_debug.c +2 -0
Index: current/kernel/sched_debug.c
===================================================================
@@ -136,6 +136,8 @@ void print_cfs_rq(struct seq_file *m, in
 			SPLIT_NS(spread0));
 	SEQ_printf(m, "  .%-30s: %ld\n", "spread0",
 			cfs_rq->nr_sync_min_vruntime);
+	SEQ_printf(m, "  .%-30s: %ld\n", "nr_running", cfs_rq->nr_running);
+	SEQ_printf(m, "  .%-30s: %ld\n", "load", cfs_rq->load.weight);
 }
 
 static void print_cpu(struct seq_file *m, int cpu)
kernel/sched_fair.c +2 -1
Index: current/kernel/sched_fair.c
===================================================================
@@ -726,7 +726,7 @@ static void dequeue_task_fair(struct rq 
  */
 static void yield_task_fair(struct rq *rq)
 {
-	struct cfs_rq *cfs_rq = &rq->cfs;
+	struct cfs_rq *cfs_rq = task_cfs_rq(rq->curr);
 	struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
 	struct sched_entity *rightmost, *se = &rq->curr->se;
 	struct rb_node *parent;
@@ -1025,6 +1025,7 @@ static void print_cfs_stats(struct seq_f
 {
 	struct cfs_rq *cfs_rq;
 
+	print_cfs_rq(m, cpu, &cpu_rq(cpu)->cfs);
 	for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq)
 		print_cfs_rq(m, cpu, cfs_rq);
 }
Signature · 2 lines
Regards,
vatsa
#4 lore raw

PATCH 3/5 Cleanup code under CONFIG_FAIR_GROUP_SCHED

In reply to Srivatsa Vaddagiri

With the view of supporting user-id based fair scheduling (and not just container-based fair scheduling), this patch renames several functions and makes them independent of whether they are being used for container or user-id based fair scheduling.

Also fix a problem reported by KAMEZAWA Hiroyuki (wrt allocating less-sized array for tg->cfs_rq[] and tf->se[]).

---
 include/linux/sched.h |   12 +++
 init/Kconfig          |   11 +--
 kernel/sched.c        |  172 ++++++++++++++++++--------------------------------
 kernel/sched_fair.c   |    5 +
 4 files changed, 83 insertions(+), 117 deletions(-)
include/linux/sched.h +12 -0
Index: current/include/linux/sched.h
===================================================================
@@ -135,6 +135,7 @@ extern unsigned long weighted_cpuload(co
 
 struct seq_file;
 struct cfs_rq;
+struct task_grp;
 #ifdef CONFIG_SCHED_DEBUG
 extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m);
 extern void proc_sched_set_task(struct task_struct *p);
@@ -1833,6 +1834,17 @@ extern int sched_mc_power_savings, sched
 
 extern void normalize_rt_tasks(void);
 
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+extern struct task_grp init_task_grp;
+
+extern struct task_grp *sched_create_group(void);
+extern void sched_destroy_group(struct task_grp *tg);
+extern void sched_move_task(struct task_struct *tsk);
+extern int sched_group_set_shares(struct task_grp *tg, unsigned long shares);
+
+#endif
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
init/Kconfig +5 -6
Index: current/init/Kconfig
===================================================================
@@ -282,13 +282,12 @@ config CPUSETS
 	  Say N if unsure.
 
 config FAIR_GROUP_SCHED
-	bool "Fair group scheduler"
-	depends on EXPERIMENTAL && CONTAINERS
+	bool "Fair group cpu scheduler"
+	default n
+	depends on EXPERIMENTAL
 	help
-	  This option enables you to group tasks and control CPU resource
-	  allocation to such groups.
-
-	  Say N if unsure.
+	  This feature lets cpu scheduler recognize task groups and control cpu
+	  bandwidth allocation to such task groups.
 
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"
kernel/sched.c +62 -110

279 lines not on this page · raw message

kernel/sched_fair.c +4 -1
Index: current/kernel/sched_fair.c
===================================================================
@@ -878,7 +878,10 @@ static int cfs_rq_best_prio(struct cfs_r
 	if (!cfs_rq->nr_running)
 		return MAX_PRIO;
 
-	curr = __pick_next_entity(cfs_rq);
+	curr = cfs_rq->curr;
+	if (!curr)
+		curr = __pick_next_entity(cfs_rq);
+
 	p = task_of(curr);
 
 	return p->prio;
Signature · 2 lines
Regards,
vatsa
#5 lore raw

Re: [PATCH 3/5] Cleanup code under CONFIG_FAIR_GROUP_SCHED

Quoted 25 lines · On Mon, 24 Sep 2007 22:09:37 +0530 Srivatsa Vaddagiri wrote:

With the view of supporting user-id based fair scheduling (and not just container-based fair scheduling), this patch renames several functions and makes them independent of whether they are being used for container or user-id based fair scheduling.

Also fix a problem reported by KAMEZAWA Hiroyuki (wrt allocating less-sized array for tg->cfs_rq[] and tf->se[]).

---
 include/linux/sched.h |   12 +++
 init/Kconfig          |   11 +--
 kernel/sched.c        |  172 ++++++++++++++++++--------------------------------
 kernel/sched_fair.c   |    5 +
 4 files changed, 83 insertions(+), 117 deletions(-)

Index: current/init/Kconfig
===================================================================

init/Kconfig config CPUSETS · line 285

Quoted 6 lines
init/Kconfig +1 -2
@@ -282,13 +282,12 @@ config CPUSETS
 	  Say N if unsure.
 
 config FAIR_GROUP_SCHED
-	bool "Fair group scheduler"
-	depends on EXPERIMENTAL && CONTAINERS
+	bool "Fair group cpu scheduler"

Can we have "CPU" instead of "cpu" ?

init/Kconfig config CPUSETS · line 293

Quoted 12 lines
init/Kconfig +4 -4
+	default n
+	depends on EXPERIMENTAL
 	help
-	  This option enables you to group tasks and control CPU resource
-	  allocation to such groups.
-
-	  Say N if unsure.
+	  This feature lets cpu scheduler recognize task groups and control cpu
+	  bandwidth allocation to such task groups.
 
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"

---
~Randy
Phaedrus says that Quality is about caring.

#6 lore raw

Re: [PATCH 3/5] Cleanup code under CONFIG_FAIR_GROUP_SCHED

Quoted 6 lines · Randy Dunlap

init/Kconfig config CPUSETS · line 285

Quoted 4 lines

config FAIR_GROUP_SCHED

init/Kconfig +1 -2
-	bool "Fair group scheduler"
-	depends on EXPERIMENTAL && CONTAINERS
+	bool "Fair group cpu scheduler"

Can we have "CPU" instead of "cpu" ?

Sounds good. Will add to my follow-on.patch (and will send out after others have had a chance to comment).

Signature · 2 lines
Regards,
vatsa
#7 lore raw

PATCH 4/5 Add fair-user scheduler

In reply to Srivatsa Vaddagiri

Enable user-id based fair group scheduling. This is usefull for anyone who wants to test the group scheduler w/o having to enable CONFIG_CGROUPS.

A separate scheduling group (i.e struct task_grp) is automatically created for every new user added to the system. Upon uid change for a task, it is made to move to the corresponding scheduling group.

A /proc tunable (/proc/root_user_share) is also provided to tune root user's quota of cpu bandwidth.

---
 include/linux/sched.h |    4 +++
 init/Kconfig          |   13 ++++++++++++
 kernel/sched.c        |    9 ++++++++
 kernel/sched_debug.c  |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/user.c         |   43 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 121 insertions(+)
include/linux/sched.h +4 -0
Index: linux-2.6.23-rc6/include/linux/sched.h
===================================================================
@@ -596,6 +596,10 @@ struct user_struct {
 	/* Hash table maintenance information */
 	struct hlist_node uidhash_node;
 	uid_t uid;
+
+#ifdef CONFIG_FAIR_USER_SCHED
+	struct task_grp *tg;
+#endif
 };
 
 extern struct user_struct *find_user(uid_t);
init/Kconfig +13 -0
Index: linux-2.6.23-rc6/init/Kconfig
===================================================================
@@ -289,6 +289,19 @@ config FAIR_GROUP_SCHED
 	  This feature lets cpu scheduler recognize task groups and control cpu
 	  bandwidth allocation to such task groups.
 
+choice
+	depends on FAIR_GROUP_SCHED
+	prompt "Basis for grouping tasks"
+	default FAIR_USER_SCHED
+
+ 	config FAIR_USER_SCHED
+ 		bool "user id"
+ 		help
+ 		  This option will choose userid as the basis for grouping
+		  tasks, thus providing equal cpu bandwidth to each user.
+
+endchoice
+
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"
 	default y
kernel/sched.c +9 -0
Index: linux-2.6.23-rc6/kernel/sched.c
===================================================================
@@ -199,7 +199,12 @@ struct task_grp init_task_grp =  {
 				.cfs_rq = init_cfs_rq_p,
 				 };
 
+#ifdef CONFIG_FAIR_USER_SCHED
+#define INIT_TASK_GRP_LOAD	2*NICE_0_LOAD
+#else
 #define INIT_TASK_GRP_LOAD	NICE_0_LOAD
+#endif
+
 static int init_task_grp_load = INIT_TASK_GRP_LOAD;
 
 /* return group to which a task belongs */
@@ -207,7 +212,11 @@ static inline struct task_grp *task_grp(
 {
 	struct task_grp *tg;
 
+#ifdef CONFIG_FAIR_USER_SCHED
+	tg = p->user->tg;
+#else
 	tg  = &init_task_grp;
+#endif
 
 	return tg;
 }
kernel/sched_debug.c +52 -0

64 lines not on this page · raw message

kernel/user.c +43 -0

75 lines not on this page · raw message

Signature · 2 lines
Regards,
vatsa
#8 lore raw

Re: [PATCH 4/5] Add fair-user scheduler

Quoted 16 lines · On Mon, 24 Sep 2007 22:10:59 +0530 Srivatsa Vaddagiri wrote:
---
 include/linux/sched.h |    4 +++
 init/Kconfig          |   13 ++++++++++++
 kernel/sched.c        |    9 ++++++++
 kernel/sched_debug.c  |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/user.c         |   43 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 121 insertions(+)

Index: linux-2.6.23-rc6/init/Kconfig
===================================================================

init/Kconfig +0 -0
@@ -289,6 +289,19 @@ config FAIR_GROUP_SCHED
 	  This feature lets cpu scheduler recognize task groups and control cpu
 	  bandwidth allocation to such task groups.
 

init/Kconfig config FAIR_GROUP_SCHED · line 301

Quoted 10 lines
init/Kconfig +10 -0
+choice
+	depends on FAIR_GROUP_SCHED
+	prompt "Basis for grouping tasks"
+	default FAIR_USER_SCHED
+
+ 	config FAIR_USER_SCHED
+ 		bool "user id"
+ 		help
+ 		  This option will choose userid as the basis for grouping
+		  tasks, thus providing equal cpu bandwidth to each user.

s/cpu/CPU/g please.

and the "bool", "help" and help text are indented by one tab too much.

init/Kconfig config FAIR_GROUP_SCHED · line 307

Quoted 6 lines
init/Kconfig +3 -0
+
+endchoice
+
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"
 	default y

---
~Randy
Phaedrus says that Quality is about caring.

#9 lore raw

Re: [PATCH 4/5] Add fair-user scheduler

Quoted 4 lines · Randy Dunlap
Quoted 4 lines
init/Kconfig +4 -0
+choice
+	depends on FAIR_GROUP_SCHED
+	prompt "Basis for grouping tasks"
+	default FAIR_USER_SCHED
Quoted 8 lines

init/Kconfig config FAIR_GROUP_SCHED · line 301

Quoted 6 lines
init/Kconfig +6 -0
+
+ 	config FAIR_USER_SCHED
+ 		bool "user id"
+ 		help
+ 		  This option will choose userid as the basis for grouping
+		  tasks, thus providing equal cpu bandwidth to each user.

s/cpu/CPU/g please.

ok, sure.

Quoted 1 line

and the "bool", "help" and help text are indented by one tab too much.

will take care.

Signature · 2 lines
Regards,
vatsa
#10 lore raw

Re: [PATCH 4/5] Add fair-user scheduler

In reply to Srivatsa Vaddagiri
Quoted 3 lines · Srivatsa Vaddagiri

Enable user-id based fair group scheduling. This is usefull for anyone who wants to test the group scheduler w/o having to enable CONFIG_CGROUPS.

excellent! I'll make this default-enabled.

Ingo

#11 lore raw

Re: [PATCH 4/5] Add fair-user scheduler

In reply to Srivatsa Vaddagiri
Quoted 103 lines · Srivatsa Vaddagiri

Enable user-id based fair group scheduling. This is usefull for anyone who wants to test the group scheduler w/o having to enable CONFIG_CGROUPS.

A separate scheduling group (i.e struct task_grp) is automatically created for every new user added to the system. Upon uid change for a task, it is made to move to the corresponding scheduling group.

A /proc tunable (/proc/root_user_share) is also provided to tune root user's quota of cpu bandwidth.

---
 include/linux/sched.h |    4 +++
 init/Kconfig          |   13 ++++++++++++
 kernel/sched.c        |    9 ++++++++
 kernel/sched_debug.c  |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/user.c         |   43 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 121 insertions(+)

Index: linux-2.6.23-rc6/include/linux/sched.h
===================================================================

include/linux/sched.h +4 -0
@@ -596,6 +596,10 @@ struct user_struct {
 	/* Hash table maintenance information */
 	struct hlist_node uidhash_node;
 	uid_t uid;
+
+#ifdef CONFIG_FAIR_USER_SCHED
+	struct task_grp *tg;
+#endif
 };
 
 extern struct user_struct *find_user(uid_t);

Index: linux-2.6.23-rc6/init/Kconfig
===================================================================

init/Kconfig +13 -0
@@ -289,6 +289,19 @@ config FAIR_GROUP_SCHED
 	  This feature lets cpu scheduler recognize task groups and control cpu
 	  bandwidth allocation to such task groups.
 
+choice
+	depends on FAIR_GROUP_SCHED
+	prompt "Basis for grouping tasks"
+	default FAIR_USER_SCHED
+
+ 	config FAIR_USER_SCHED
+ 		bool "user id"
+ 		help
+ 		  This option will choose userid as the basis for grouping
+		  tasks, thus providing equal cpu bandwidth to each user.
+
+endchoice
+
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"
 	default y

Index: linux-2.6.23-rc6/kernel/sched.c
===================================================================

kernel/sched.c +9 -0
@@ -199,7 +199,12 @@ struct task_grp init_task_grp =  {
 				.cfs_rq = init_cfs_rq_p,
 				 };
 
+#ifdef CONFIG_FAIR_USER_SCHED
+#define INIT_TASK_GRP_LOAD	2*NICE_0_LOAD
+#else
 #define INIT_TASK_GRP_LOAD	NICE_0_LOAD
+#endif
+
 static int init_task_grp_load = INIT_TASK_GRP_LOAD;
 
 /* return group to which a task belongs */
@@ -207,7 +212,11 @@ static inline struct task_grp *task_grp(
 {
 	struct task_grp *tg;
 
+#ifdef CONFIG_FAIR_USER_SCHED
+	tg = p->user->tg;
+#else
 	tg  = &init_task_grp;
+#endif
 
 	return tg;
 }

Index: linux-2.6.23-rc6/kernel/sched_debug.c
===================================================================

kernel/sched_debug.c +4 -0
@@ -214,6 +214,49 @@ static void sysrq_sched_debug_show(void)
 	sched_debug_show(NULL, NULL);
 }
 
+#ifdef CONFIG_FAIR_USER_SCHED
+
+static DEFINE_MUTEX(root_user_share_mutex);
+

kernel/sched_debug.c static void sysrq_sched_debug_show(void) · line 230

Quoted 10 lines
kernel/sched_debug.c +10 -0
+static int
+root_user_share_read_proc(char *page, char **start, off_t off, int count,
+				 int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", init_task_grp_load);
+
+	return len;
+}

or use this oneliner:

	return sprintf(page, "%d\n", init_task_grp_load);
Quoted 133 lines
kernel/sched_debug.c +38 -0
+
+static int
+root_user_share_write_proc(struct file *file, const char __user *buffer,
+				 unsigned long count, void *data)
+{
+	unsigned long shares;
+	char kbuf[sizeof(unsigned long)+1];
+	int rc = 0;
+
+	if (copy_from_user(kbuf, buffer, sizeof(kbuf)))
+		return -EFAULT;
+
+	shares = simple_strtoul(kbuf, NULL, 0);
+
+	if (!shares)
+		shares = NICE_0_LOAD;
+
+	mutex_lock(&root_user_share_mutex);
+
+	init_task_grp_load = shares;
+	rc = sched_group_set_shares(&init_task_grp, shares);
+
+	mutex_unlock(&root_user_share_mutex);
+
+	return (rc < 0 ? rc : count);
+}
+
+#endif	/* CONFIG_FAIR_USER_SCHED */
+
 static int sched_debug_open(struct inode *inode, struct file *filp)
 {
 	return single_open(filp, sched_debug_show, NULL);
@@ -236,6 +279,15 @@ static int __init init_sched_debug_procf
 
 	pe->proc_fops = &sched_debug_fops;
 
+#ifdef CONFIG_FAIR_USER_SCHED
+	pe = create_proc_entry("root_user_share", 0644, NULL);
+	if (!pe)
+		return -ENOMEM;
+
+	pe->read_proc = root_user_share_read_proc;
+	pe->write_proc = root_user_share_write_proc;
+#endif
+
 	return 0;
 }
 

Index: linux-2.6.23-rc6/kernel/user.c
===================================================================

kernel/user.c +43 -0
@@ -50,8 +50,41 @@ struct user_struct root_user = {
 	.uid_keyring	= &root_user_keyring,
 	.session_keyring = &root_session_keyring,
 #endif
+#ifdef CONFIG_FAIR_USER_SCHED
+	.tg		= &init_task_grp,
+#endif
 };
 
+#ifdef CONFIG_FAIR_USER_SCHED
+static void sched_destroy_user(struct user_struct *up)
+{
+	sched_destroy_group(up->tg);
+}
+
+static int sched_create_user(struct user_struct *up)
+{
+	int rc = 0;
+
+	up->tg = sched_create_group();
+	if (IS_ERR(up->tg))
+		rc = -ENOMEM;
+
+	return rc;
+}
+
+static void sched_switch_user(struct task_struct *p)
+{
+	sched_move_task(p);
+}
+
+#else	/* CONFIG_FAIR_USER_SCHED */
+
+static void sched_destroy_user(struct user_struct *up) { }
+static int sched_create_user(struct user_struct *up) { return 0; }
+static void sched_switch_user(struct task_struct *p) { }
+
+#endif	/* CONFIG_FAIR_USER_SCHED */
+
 /*
  * These routines must be called with the uidhash spinlock held!
  */
@@ -109,6 +142,7 @@ void free_uid(struct user_struct *up)
 	if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) {
 		uid_hash_remove(up);
 		spin_unlock_irqrestore(&uidhash_lock, flags);
+		sched_destroy_user(up);
 		key_put(up->uid_keyring);
 		key_put(up->session_keyring);
 		kmem_cache_free(uid_cachep, up);
@@ -150,6 +184,13 @@ struct user_struct * alloc_uid(struct us
 			return NULL;
 		}
 
+		if (sched_create_user(new) < 0) {
+			key_put(new->uid_keyring);
+			key_put(new->session_keyring);
+			kmem_cache_free(uid_cachep, new);
+			return NULL;
+		}
+
 		/*
 		 * Before adding this, check whether we raced
 		 * on adding the same user already..
@@ -157,6 +198,7 @@ struct user_struct * alloc_uid(struct us
 		spin_lock_irq(&uidhash_lock);
 		up = uid_hash_find(uid, hashent);
 		if (up) {
+			sched_destroy_user(new);
 			key_put(new->uid_keyring);
 			key_put(new->session_keyring);
 			kmem_cache_free(uid_cachep, new);
@@ -184,6 +226,7 @@ void switch_uid(struct user_struct *new_
 	atomic_dec(&old_user->processes);
 	switch_uid_keyring(new_user);
 	current->user = new_user;
+	sched_switch_user(current);
 
 	/*
 	 * We need to synchronize with __sigqueue_alloc()
#12 lore raw

Re: [PATCH 4/5] Add fair-user scheduler

Quoted 13 lines · roel

kernel/sched_debug.c static void sysrq_sched_debug_show(void) · line 230

Quoted 10 lines
kernel/sched_debug.c +10 -0
+static int
+root_user_share_read_proc(char *page, char **start, off_t off, int count,
+				 int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", init_task_grp_load);
+
+	return len;
+}

or use this oneliner:

Quoted 1 line
	return sprintf(page, "%d\n", init_task_grp_load);

Looks good. Will fix this in a follow-on.patch.

Thanks!

Signature · 2 lines
Regards,
vatsa
#13 lore raw

PATCH 5/5 Add fair "control groups" scheduler

In reply to Srivatsa Vaddagiri

Enable "cgroup" (formerly containers) based fair group scheduling. This will let administrator create arbitrary groups of tasks (using "cgroup" psuedo filesystem) and control their cpu bandwidth usage.

---
 include/linux/cgroup_subsys.h |    6 ++
 init/Kconfig                  |   24 +++++---
 kernel/sched.c                |  122 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 7 deletions(-)
include/linux/cgroup_subsys.h +6 -0
Index: current/include/linux/cgroup_subsys.h
===================================================================
@@ -36,3 +36,9 @@ SUBSYS(mem_cgroup)
 #endif
 
 /* */
+
+#ifdef CONFIG_FAIR_CGROUP_SCHED
+SUBSYS(cpu_cgroup)
+#endif
+
+/* */
init/Kconfig +17 -7
Index: current/init/Kconfig
===================================================================
@@ -327,13 +327,6 @@ config FAIR_GROUP_SCHED
 	  This feature lets cpu scheduler recognize task groups and control cpu
 	  bandwidth allocation to such task groups.
 
-config RESOURCE_COUNTERS
-	bool "Resource counters"
-	help
-	  This option enables controller independent resource accounting
-          infrastructure that works with cgroups
-	depends on CGROUPS
-
 choice
 	depends on FAIR_GROUP_SCHED
 	prompt "Basis for grouping tasks"
@@ -345,8 +338,25 @@ choice
  		  This option will choose userid as the basis for grouping
 		  tasks, thus providing equal cpu bandwidth to each user.
 
+	config FAIR_CGROUP_SCHED
+		bool "Control groups"
+		depends on CGROUPS
+		help
+		   This option allows you to create arbitrary task groups
+		   using the "cgroup" psuedo filesystem and control
+		   the cpu bandwidth allocated to each such task group.
+		   Refer to Documentation/cgroups.txt for more information
+		   on "cgroup" psuedo filesystem.
+
 endchoice
 
+config RESOURCE_COUNTERS
+	bool "Resource counters"
+	help
+	  This option enables controller independent resource accounting
+          infrastructure that works with cgroups
+	depends on CGROUPS
+
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"
 	default y
kernel/sched.c +122 -0

141 lines not on this page · raw message

Signature · 2 lines
Regards,
vatsa
#14 lore raw

Re: [PATCH 5/5] Add fair "control groups" scheduler

Quoted 26 lines · On Mon, 24 Sep 2007 22:11:59 +0530 Srivatsa Vaddagiri wrote:
 include/linux/cgroup_subsys.h |    6 ++
 init/Kconfig                  |   24 +++++---
 kernel/sched.c                |  122 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+), 7 deletions(-)

Index: current/init/Kconfig
===================================================================

init/Kconfig +0 -7
@@ -327,13 +327,6 @@ config FAIR_GROUP_SCHED
 	  This feature lets cpu scheduler recognize task groups and control cpu
 	  bandwidth allocation to such task groups.
 
-config RESOURCE_COUNTERS
-	bool "Resource counters"
-	help
-	  This option enables controller independent resource accounting
-          infrastructure that works with cgroups
-	depends on CGROUPS
-
 choice
 	depends on FAIR_GROUP_SCHED
 	prompt "Basis for grouping tasks"
@@ -345,8 +338,25 @@ choice
  		  This option will choose userid as the basis for grouping
 		  tasks, thus providing equal cpu bandwidth to each user.

init/Kconfig choice · line 349

Quoted 10 lines
init/Kconfig +9 -0
 
+	config FAIR_CGROUP_SCHED
+		bool "Control groups"
+		depends on CGROUPS
+		help
+		   This option allows you to create arbitrary task groups
+		   using the "cgroup" psuedo filesystem and control
+		   the cpu bandwidth allocated to each such task group.
+		   Refer to Documentation/cgroups.txt for more information
+		   on "cgroup" psuedo filesystem.

Too much indentation.

s/cpu/CPU/g please.

init/Kconfig choice · line 357

Quoted 8 lines
init/Kconfig +6 -0
+
 endchoice
 
+config RESOURCE_COUNTERS
+	bool "Resource counters"
+	help
+	  This option enables controller independent resource accounting
+          infrastructure that works with cgroups

Use tab + 2 spaces to indent help text.

init/Kconfig choice · line 362

Quoted 5 lines
init/Kconfig +2 -0
+	depends on CGROUPS
+
 config SYSFS_DEPRECATED
 	bool "Create deprecated sysfs files"
 	default y

---
~Randy
Phaedrus says that Quality is about caring.

#15 lore raw

Re: [PATCH 5/5] Add fair "control groups" scheduler

Quoted 12 lines · Randy Dunlap

init/Kconfig choice · line 349

Quoted 9 lines
init/Kconfig +9 -0
+	config FAIR_CGROUP_SCHED
+		bool "Control groups"
+		depends on CGROUPS
+		help
+		   This option allows you to create arbitrary task groups
+		   using the "cgroup" psuedo filesystem and control
+		   the cpu bandwidth allocated to each such task group.
+		   Refer to Documentation/cgroups.txt for more information
+		   on "cgroup" psuedo filesystem.

Too much indentation.

Quoted 1 line

s/cpu/CPU/g please.

will fix both.

Quoted 7 lines

init/Kconfig choice · line 357

Quoted 5 lines
init/Kconfig +5 -0
+config RESOURCE_COUNTERS
+	bool "Resource counters"
+	help
+	  This option enables controller independent resource accounting
+          infrastructure that works with cgroups

Use tab + 2 spaces to indent help text.

This one was there before in -mm ..I just moved it below in the Kconfig file. Neverthless will fix the coding-style here as well.

Thanks for your reviews!

Signature · 2 lines
Regards,
vatsa