Skip to contentSkip to conversation

autogroup: sched_setscheduler() fails

DISCUSSION Applied Bharata B Rao 6 participants 40 messages Jan 10, 2011 – Mar 1, 2011

lore
Share & tools
lore
#0 lore raw

Hi,

With autogroup ON, sched_setscheduler() fails when I try to change the scheduling policy of a normal task to either RR or FIFO.

sched_setscheduler() returns -EPERM when it finds that the group doesn't have any rt bandwidth. This is expected because with autogroup, the task is in an autogroup for which task_group(p)->rt_bandwidth.rt_runtime is 0.

I guess the task needs to be moved to appropriate cgroup (from its current autogroup) when such policy change is requested, but I wasn't sure if group change from sched_setscheduler() can be achieved easily.

Regards,
Bharata.

#1 lore raw
Quoted 5 lines · Bharata B Rao

Hi,

With autogroup ON, sched_setscheduler() fails when I try to change the scheduling policy of a normal task to either RR or FIFO.

Quoted 7 lines

sched_setscheduler() returns -EPERM when it finds that the group doesn't have any rt bandwidth. This is expected because with autogroup, the task is in an autogroup for which task_group(p)->rt_bandwidth.rt_runtime is 0.

I guess the task needs to be moved to appropriate cgroup (from its current autogroup) when such policy change is requested, but I wasn't sure if group change from sched_setscheduler() can be achieved easily.

Right, autogroup should be excluding CONFIG_RT_GROUP_SCHED, since it doesn't currently support it.

sched: SCHED_AUTOGROUP selection excludes RT_GROUP_SCHED

Autogroup does not support realtime task groups, so make selection of SCHED_AUTOGROUP exclude RT_GROUP_SCHED.

---
 init/Kconfig |    5 +++++
 1 file changed, 5 insertions(+)
init/Kconfig +5 -0
Index: linux-2.6/init/Kconfig
===================================================================
@@ -699,6 +699,7 @@ config RT_GROUP_SCHED
 	bool "Group scheduling for SCHED_RR/FIFO"
 	depends on EXPERIMENTAL
 	depends on CGROUP_SCHED
+	depends on !SCHED_AUTOGROUP
 	default n
 	help
 	  This feature lets you explicitly allocate real CPU bandwidth
@@ -807,6 +808,10 @@ config SCHED_AUTOGROUP
 	  desktop applications.  Task group autogeneration is currently based
 	  upon task session.
 
+	  Note: SCHED_AUTOGROUP does not support realtime tasks, and prevents
+	  enabling RT_GROUP_SCHED.  If you intend to use group scheduling for
+	  realtime tasks, do not enable this option.
+
 config MM_OWNER
 	bool
 
#2 lore raw
Quoted 29 lines · Mike Galbraith

Right, autogroup should be excluding CONFIG_RT_GROUP_SCHED, since it doesn't currently support it.

sched: SCHED_AUTOGROUP selection excludes RT_GROUP_SCHED

Autogroup does not support realtime task groups, so make selection of SCHED_AUTOGROUP exclude RT_GROUP_SCHED.

---
 init/Kconfig |    5 +++++
 1 file changed, 5 insertions(+)

Index: linux-2.6/init/Kconfig
===================================================================

init/Kconfig +1 -0
@@ -699,6 +699,7 @@ config RT_GROUP_SCHED
        bool "Group scheduling for SCHED_RR/FIFO"
        depends on EXPERIMENTAL
        depends on CGROUP_SCHED
+       depends on !SCHED_AUTOGROUP
        default n
        help
          This feature lets you explicitly allocate real CPU bandwidth

init/Kconfig config SCHED_AUTOGROUP · line 817

Quoted 10 lines
init/Kconfig +4 -0
@@ -807,6 +808,10 @@ config SCHED_AUTOGROUP
          desktop applications.  Task group autogeneration is currently based
          upon task session.
 
+         Note: SCHED_AUTOGROUP does not support realtime tasks, and prevents
+         enabling RT_GROUP_SCHED.  If you intend to use group scheduling for
+         realtime tasks, do not enable this option.
+
 config MM_OWNER
        bool
 

Uhm, no. The right way is to put tasks back into the root group and then perform sched_setscheduler().

#3 lore raw
Quoted 8 lines · Peter Zijlstra
Quoted 4 lines · Mike Galbraith

Autogroup does not support realtime task groups, so make selection of SCHED_AUTOGROUP exclude RT_GROUP_SCHED.

Uhm, no. The right way is to put tasks back into the root group and then perform sched_setscheduler().

I think that would take more lines, this look like a right way too?

sched, autogroup: move tasks to the appropriate runqueue on policy change.

If CONFIG_RT_GROUP_SCHED is set, sched_setscheduler() fails due to autogroup not allocating rt_runtime. Fool __sched_setscheduler() into proceeding on, and move tasks to the appropriate runqueue upon policy change.

---
 kernel/sched.c           |    9 ++++++---
 kernel/sched_autogroup.c |   18 ++++++++++++++++++
 kernel/sched_autogroup.h |    1 +
 3 files changed, 25 insertions(+), 3 deletions(-)
kernel/sched.c +6 -3
Index: linux-2.6/kernel/sched.c
===================================================================
@@ -4571,6 +4571,8 @@ void rt_mutex_setprio(struct task_struct
 
 	p->prio = prio;
 
+	autogroup_setscheduler(p, on_rq);
+
 	if (running)
 		p->sched_class->set_curr_task(rq);
 	if (on_rq) {
@@ -4738,7 +4740,7 @@ static struct task_struct *find_process_
 
 /* Actually do priority change: must hold rq lock. */
 static void
-__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
+__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio, int on_rq)
 {
 	BUG_ON(p->se.on_rq);
 
@@ -4752,6 +4754,7 @@ __setscheduler(struct rq *rq, struct tas
 	else
 		p->sched_class = &fair_sched_class;
 	set_load_weight(p);
+	autogroup_setscheduler(p, on_rq);
 }
 
 /*
@@ -4900,7 +4903,7 @@ recheck:
 
 	oldprio = p->prio;
 	prev_class = p->sched_class;
-	__setscheduler(rq, p, policy, param->sched_priority);
+	__setscheduler(rq, p, policy, param->sched_priority, on_rq);
 
 	if (running)
 		p->sched_class->set_curr_task(rq);
@@ -8116,7 +8119,7 @@ static void normalize_task(struct rq *rq
 	on_rq = p->se.on_rq;
 	if (on_rq)
 		deactivate_task(rq, p, 0);
-	__setscheduler(rq, p, SCHED_NORMAL, 0);
+	__setscheduler(rq, p, SCHED_NORMAL, 0, on_rq);
 	if (on_rq) {
 		activate_task(rq, p, 0);
 		resched_task(rq->curr);
kernel/sched_autogroup.c +18 -0
Index: linux-2.6/kernel/sched_autogroup.c
===================================================================
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+
 /* Allocates GFP_KERNEL, cannot be called under any spinlock */
 void sched_autogroup_create_attach(struct task_struct *p)
 {
kernel/sched_autogroup.h +1 -0
Index: linux-2.6/kernel/sched_autogroup.h
===================================================================
@@ -15,6 +15,7 @@ autogroup_task_group(struct task_struct
 
 static inline void autogroup_init(struct task_struct *init_task) {  }
 static inline void autogroup_free(struct task_group *tg) { }
+static inline void autogroup_setscheduler(struct task_struct *p, int on_rq) { }
 
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg)
#4 lore raw
Quoted 23 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 163

Quoted 10 lines
kernel/sched_autogroup.c +9 -0
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+

IIUC, with the above changes you are actually queing the task into rt_rq of an autogroup. But the task's autogroup interface (/proc/<pid>/autogroup) allows you to control the bandwidth of only cfs_rq tasks, while the rt tasks in the group get RUNTIME_INF bandwidth.

I think what we need is a real group change here (which is difficult I think) and not just sched_class change.

Regards,
Bharata.

#5 lore raw
Quoted 40 lines · Bharata B Rao
Quoted 23 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 163

Quoted 10 lines
kernel/sched_autogroup.c +9 -0
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+

IIUC, with the above changes you are actually queing the task into rt_rq of an autogroup. But the task's autogroup interface (/proc/<pid>/autogroup) allows you to control the bandwidth of only cfs_rq tasks, while the rt tasks in the group get RUNTIME_INF bandwidth.

Quoted 2 lines

I think what we need is a real group change here (which is difficult I think) and not just sched_class change.

Unless I fscked up, set_task_rq() is the group change. As soon as the task's class changes, it'll be moved to the root_task_group.

-Mike

#6 lore raw
Quoted 41 lines · Mike Galbraith
Quoted 40 lines · Bharata B Rao
Quoted 23 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 163

Quoted 10 lines
kernel/sched_autogroup.c +9 -0
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+

IIUC, with the above changes you are actually queing the task into rt_rq of an autogroup. But the task's autogroup interface (/proc/<pid>/autogroup) allows you to control the bandwidth of only cfs_rq tasks, while the rt tasks in the group get RUNTIME_INF bandwidth.

Quoted 5 lines
Quoted 2 lines

I think what we need is a real group change here (which is difficult I think) and not just sched_class change.

Unless I fscked up, set_task_rq() is the group change. As soon as the task's class changes, it'll be moved to the root_task_group.

Ok, this is what I understand, may be Peter Z can confirm...

set_task_rq() just changes the task's cfs_rq and rt_rq as per its task_group(). The normal way to change a task's group is to first change its cgroup pointer (task->cgroups, see cgroup_attach_task()) After this you change the runqueues by calling set_task_rq() which now refers to new group's runqueues.

In your code, I don't see where you really change task's group. AFAICS, it continues to remain in the same autogroup.

Regards,
Bharata.

#7 lore raw
Quoted 5 lines · Bharata B Rao
Quoted 2 lines

Unless I fscked up, set_task_rq() is the group change.  As soon as the task's class changes, it'll be moved to the root_task_group.

Ok, this is what I understand, may be Peter Z can confirm...

Quoted 8 lines

set_task_rq() just changes the task's cfs_rq and rt_rq as per its task_group(). The normal way to change a task's group is to first change its cgroup pointer (task->cgroups, see cgroup_attach_task()) After this you change the runqueues by calling set_task_rq() which now refers to new group's runqueues.

In your code, I don't see where you really change task's group. AFAICS, it continues to remain in the same autogroup.

IMHO, task->cgroups will not change when autogroup take effect. IOW, autogroup will only take effect when task belongs to root_task_group.

Thanks,
Yong

Quoted 9 lines

Regards,
Bharata.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Signature · 1 line
Only stand for myself
#8 lore raw
Quoted 13 lines · Yong Zhang
Quoted 11 lines · Bharata B Rao
Quoted 2 lines

Unless I fscked up, set_task_rq() is the group change.  As soon as the task's class changes, it'll be moved to the root_task_group.

Ok, this is what I understand, may be Peter Z can confirm...

set_task_rq() just changes the task's cfs_rq and rt_rq as per its task_group(). The normal way to change a task's group is to first change its cgroup pointer (task->cgroups, see cgroup_attach_task()) After this you change the runqueues by calling set_task_rq() which now refers to new group's runqueues.

Quoted 4 lines
Quoted 2 lines

In your code, I don't see where you really change task's group. AFAICS, it continues to remain in the same autogroup.

IMHO, task->cgroups will not change when autogroup take effect.

Yes and I believe this is cause for some of the weird semantics I see with autogroup and cgroups. I am not sure if this has already been discussed ealier, may be I need to go back and check the archives, but consider this:

I have cpu cgroup mounted at /cgroup and see that all the tasks in the system are listed in /cgroup/tasks file.

Now I start a task like this:

# ./while1 &
[1] 2761

and see that this task belongs to root cgroup.

# grep 2761 /cgroup/tasks
2671

But we know that this task really belongs to an autogroup and is not sitting directly on root_task_group.

# cat /proc/2761/autogroup 
/autogroup-49 nice 0

So we have a task in an autogroup (which is a sub group of root_task_group) but is being shown as part of root_task_group. Is this by design ?

Now say I create a sub cgroup and move this task to it.

# mkdir /cgroup/1
# echo 2671 > /cgroup/1/tasks

So now the task moved to a real cgroup.

# cat /cgroup/1/tasks 
2761

But the /proc/2761/autogroup isn't updated. It still shows /autogroup-49 nice 0

May be this was all discussed earlier as I noted in the beginning, but I find this semantics a bit unusual.

Regards,
Bharata.

#9 lore raw
Quoted 12 lines · Bharata B Rao
Quoted 1 line · Yong Zhang

IMHO, task->cgroups will not change when autogroup take effect.

Yes and I believe this is cause for some of the weird semantics I see with autogroup and cgroups. I am not sure if this has already been discussed ealier, may be I need to go back and check the archives, but consider this:

I have cpu cgroup mounted at /cgroup and see that all the tasks in the system are listed in /cgroup/tasks file.

Quoted 6 lines

Now I start a task like this:

# ./while1 &
[1] 2761

and see that this task belongs to root cgroup.

Yes, cgroups sees cgroup associations, not autogroup associations.

Quoted 5 lines
# grep 2761 /cgroup/tasks
2671

But we know that this task really belongs to an autogroup and is not sitting directly on root_task_group.

Yup, cgroups doesn't want it, so autogroup (if enabled) claims it.

Quoted 5 lines
# cat /proc/2761/autogroup 
/autogroup-49 nice 0

So we have a task in an autogroup (which is a sub group of root_task_group) but is being shown as part of root_task_group. Is this by design ?

Yes, it's supposed to be transparent to cgroups.

Quoted 5 lines

Now say I create a sub cgroup and move this task to it.

# mkdir /cgroup/1
# echo 2671 > /cgroup/1/tasks
Quoted 7 lines

So now the task moved to a real cgroup.

# cat /cgroup/1/tasks 
2761

But the /proc/2761/autogroup isn't updated. It still shows /autogroup-49 nice 0

The proc interface shows task->autogroup associations, which always exist. This is autogroups' view of the world, just as cgroup/tasks is cgroups' view of it's world.

Quoted 2 lines

May be this was all discussed earlier as I noted in the beginning, but I find this semantics a bit unusual.

Makes perfect sense to me.

-Mike

#10 lore raw
Quoted 30 lines · Mike Galbraith
Quoted 12 lines · Bharata B Rao
Quoted 1 line · Yong Zhang

IMHO, task->cgroups will not change when autogroup take effect.

Yes and I believe this is cause for some of the weird semantics I see with autogroup and cgroups. I am not sure if this has already been discussed ealier, may be I need to go back and check the archives, but consider this:

I have cpu cgroup mounted at /cgroup and see that all the tasks in the system are listed in /cgroup/tasks file.

Quoted 6 lines

Now I start a task like this:

# ./while1 &
[1] 2761

and see that this task belongs to root cgroup.

Yes, cgroups sees cgroup associations, not autogroup associations.

Quoted 5 lines
# grep 2761 /cgroup/tasks
2671

But we know that this task really belongs to an autogroup and is not sitting directly on root_task_group.

Yup, cgroups doesn't want it, so autogroup (if enabled) claims it.

Quoted 7 lines
Quoted 5 lines
# cat /proc/2761/autogroup 
/autogroup-49 nice 0

So we have a task in an autogroup (which is a sub group of root_task_group) but is being shown as part of root_task_group. Is this by design ?

Yes, it's supposed to be transparent to cgroups.

If cgroups doesn't want that task and if its transparent to cgroups, why is it shown as part of /cgroups/tasks ? The task really doesn't belong in there. Its not on the runqueue of root_task_group.

So basically I feel that a task consumed by autogroup shouldn't ideally be shown in root cgroup's tasks file.

Regards,
Bharata.

#11 lore raw
Quoted 4 lines · Bharata B Rao
Quoted 1 line · Mike Galbraith

Yes, it's supposed to be transparent to cgroups.

Quoted 8 lines

If cgroups doesn't want that task and if its transparent to cgroups, why is it shown as part of /cgroups/tasks ? The task really doesn't belong in there. Its not on the runqueue of root_task_group.

So basically I feel that a task consumed by autogroup shouldn't ideally be shown in root cgroup's tasks file.

From cgroups' viewpoint, root is where it's at. The task isn't consumed

by autogroup either, it's only borrowed until cgroups claims it.

Would you prefer that when you mount /cgroups, you see a nearly empty root task list because box was booted with autogroup enabled? Should tasks appear and disappear on the fly while you're watching?

The goal is peaceful coexistence. The user can turn either or both both on/off at his/her whim.

-Mike

#12 lore raw
Quoted 9 lines · Mike Galbraith
Quoted 8 lines · Bharata B Rao
Quoted 1 line · Mike Galbraith

Yes, it's supposed to be transparent to cgroups.

If cgroups doesn't want that task and if its transparent to cgroups, why is it shown as part of /cgroups/tasks ? The task really doesn't belong in there. Its not on the runqueue of root_task_group.

Quoted 8 lines
Quoted 4 lines

So basically I feel that a task consumed by autogroup shouldn't ideally be shown in root cgroup's tasks file.

From cgroups' viewpoint, root is where it's at. The task isn't consumed

by autogroup either, it's only borrowed until cgroups claims it.

Would you prefer that when you mount /cgroups, you see a nearly empty root task list because box was booted with autogroup enabled?

If I had my way, I would say yes :) I would even say make autogroups visible so that we know exactly what it is. Let 'auto' in autogroups mean only 'automatic' and not necessarily 'hidden'.

Quoted 2 lines

Should
tasks appear and disappear on the fly while you're watching?

Why would they unless we explicitly move them ?

Anyway I guess you would have gone through these questions already. Thanks for patiently answering :)

Regards,
Bharata.

#13 lore raw
In reply to Bharata B Rao
Quoted 45 lines · Bharata B Rao
Quoted 44 lines · Mike Galbraith
Quoted 42 lines · Bharata B Rao
Quoted 23 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 163

Quoted 10 lines
kernel/sched_autogroup.c +9 -0
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+

IIUC, with the above changes you are actually queing the task into rt_rq of an autogroup. But the task's autogroup interface (/proc/<pid>/autogroup) allows you to control the bandwidth of only cfs_rq tasks, while the rt tasks in the group get RUNTIME_INF bandwidth.

I think what we need is a real group change here (which is difficult I think) and not just sched_class change.

Quoted 7 lines
Quoted 2 lines

Unless I fscked up, set_task_rq() is the group change. As soon as the task's class changes, it'll be moved to the root_task_group.

Ok, this is what I understand, may be Peter Z can confirm...

set_task_rq() just changes the task's cfs_rq and rt_rq as per its task_group().

Exactly. When you call task_group() for an RT task, it returns &root_task_group, so a task making the transition to RT will be dequeued from it's autogroup cfs_rq, and enqueued in root_task_group's rt_rq.

Quoted 4 lines

The normal way to change a task's group is to first
change its cgroup pointer (task->cgroups, see cgroup_attach_task()) After this you change the runqueues by calling set_task_rq() which now refers to new group's runqueues.

Autogroup doesn't need to do cgroup stuff. If a task is in a cgroup, it's autogroup remains intact, but is ignored. Move it back to root, and it's autogroup will be used again.

-Mike

#14 lore raw
Quoted 49 lines · Mike Galbraith
Quoted 48 lines · Bharata B Rao
Quoted 46 lines · Mike Galbraith
Quoted 40 lines · Bharata B Rao
Quoted 23 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 163

Quoted 10 lines
kernel/sched_autogroup.c +9 -0
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+

IIUC, with the above changes you are actually queing the task into rt_rq of an autogroup. But the task's autogroup interface (/proc/<pid>/autogroup) allows you to control the bandwidth of only cfs_rq tasks, while the rt tasks in the group get RUNTIME_INF bandwidth.

Quoted 2 lines

I think what we need is a real group change here (which is difficult I think) and not just sched_class change.

Unless I fscked up, set_task_rq() is the group change. As soon as the task's class changes, it'll be moved to the root_task_group.

Quoted 8 lines
Quoted 4 lines

Ok, this is what I understand, may be Peter Z can confirm...

set_task_rq() just changes the task's cfs_rq and rt_rq as per its task_group().

Exactly. When you call task_group() for an RT task, it returns &root_task_group, so a task making the transition to RT will be dequeued from it's autogroup cfs_rq, and enqueued in root_task_group's rt_rq.

Oh yes, forgot that addition to task_group() for a moment!

Regards,
Bharata.

#15 lore raw
In reply to Mike Galbraith
Quoted 41 lines · Mike Galbraith
Quoted 40 lines · Bharata B Rao
Quoted 23 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
 	tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * HACK: autogroup RT tasks run in the root task group.
+	 * This fools __sched_setscheduler() into proceeding on
+	 * so we can move the task to the appropriate runqueue
+	 * upon scheduling policy change.
+	 */
+	tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
 	return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
 	autogroup_kref_put(prev);
 }

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 163

Quoted 10 lines
kernel/sched_autogroup.c +9 -0
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+	if (p->sched_class->task_move_group)
+		p->sched_class->task_move_group(p, on_rq);
+	else
+		set_task_rq(p, task_cpu(p));
+}
+

IIUC, with the above changes you are actually queing the task into rt_rq of an autogroup. But the task's autogroup interface (/proc/<pid>/autogroup) allows you to control the bandwidth of only cfs_rq tasks, while the rt tasks in the group get RUNTIME_INF bandwidth.

Quoted 5 lines
Quoted 2 lines

I think what we need is a real group change here (which is difficult I think) and not just sched_class change.

Unless I fscked up, set_task_rq() is the group change. As soon as the task's class changes, it'll be moved to the root_task_group.

But it'd be better to not touch anything, just deflect RT tasks away from useless queues from the start.

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, sched_setscheduler() fails due to autogroup not allocating rt_runtime. Squirrel allocated but useless rt_se and rt_rq away for group destruction time, and deflect RT tasks to the root task group.

---
 kernel/sched_autogroup.c |   13 +++++++++++++
 kernel/sched_autogroup.h |    4 ++++
 2 files changed, 17 insertions(+)
kernel/sched_autogroup.c +13 -0
Index: linux-2.6/kernel/sched_autogroup.c
===================================================================
@@ -27,6 +27,11 @@ static inline void autogroup_destroy(str
 {
 	struct autogroup *ag = container_of(kref, struct autogroup, kref);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+	ag->tg->rt_se = ag->rt_se;
+	ag->tg->rt_rq = ag->rt_rq;
+	ag->tg->rt_bandwidth.rt_runtime = 0;
+#endif
 	sched_destroy_group(ag->tg);
 }
 
@@ -72,6 +77,14 @@ static inline struct autogroup *autogrou
 	init_rwsem(&ag->lock);
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/* Sorry, we don't do RT, go away. */
+	ag->rt_se = tg->rt_se;
+	ag->rt_rq = tg->rt_rq;
+	tg->rt_se = root_task_group.rt_se;
+	tg->rt_rq = root_task_group.rt_rq;
+	tg->rt_bandwidth.rt_runtime = root_task_group.rt_bandwidth.rt_runtime;
+#endif
 	tg->autogroup = ag;
 
 	return ag;
kernel/sched_autogroup.h +4 -0
Index: linux-2.6/kernel/sched_autogroup.h
===================================================================
@@ -6,6 +6,10 @@ struct autogroup {
 	struct rw_semaphore	lock;
 	unsigned long		id;
 	int			nice;
+#ifdef CONFIG_RT_GROUP_SCHED
+	struct sched_rt_entity **rt_se;
+	struct rt_rq **rt_rq;
+#endif
 };
 
 static inline struct task_group *
#16 lore raw
Quoted 34 lines · Mike Galbraith

But it'd be better to not touch anything, just deflect RT tasks away from useless queues from the start.

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, sched_setscheduler() fails due to autogroup not allocating rt_runtime.  Squirrel allocated but useless rt_se and rt_rq away for group destruction time, and deflect RT tasks to the root task group.

---
 kernel/sched_autogroup.c |   13 +++++++++++++
 kernel/sched_autogroup.h |    4 ++++

 2 files changed, 17 insertions(+)

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +5 -0
@@ -27,6 +27,11 @@ static inline void autogroup_destroy(str
  {
        struct autogroup *ag = container_of(kref, struct autogroup, kref);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       ag->tg->rt_se = ag->rt_se;
+       ag->tg->rt_rq = ag->rt_rq;
+       ag->tg->rt_bandwidth.rt_runtime = 0;
+#endif
        sched_destroy_group(ag->tg);
  }
 

kernel/sched_autogroup.c static inline struct autogroup *autogrou · line 86

Quoted 10 lines
kernel/sched_autogroup.c +7 -0
@@ -72,6 +77,14 @@ static inline struct autogroup *autogrou
        init_rwsem(&ag->lock);
        ag->id = atomic_inc_return(&autogroup_seq_nr);
        ag->tg = tg;
+#ifdef CONFIG_RT_GROUP_SCHED
+       /* Sorry, we don't do RT, go away. */
+       ag->rt_se = tg->rt_se;
+       ag->rt_rq = tg->rt_rq;
+       tg->rt_se = root_task_group.rt_se;
+       tg->rt_rq = root_task_group.rt_rq;
+       tg->rt_bandwidth.rt_runtime = root_task_group.rt_bandwidth.rt_runtime;

Setting rt_runtime both in this patch and the previous one will make tune other's rt_runtime/rt_period trouble, I guess.

Thanks,
Yong

Signature · 1 line
Only stand for myself
#17 lore raw
Quoted 2 lines · Yong Zhang

Setting rt_runtime both in this patch and the previous one will make tune other's rt_runtime/rt_period trouble, I guess.

Hrmph, how annoying. I'll take another look at rt_runtime.

-Mike

#18 lore raw
In reply to Yong Zhang

(mailer switched me to work account again. grrrr, switch yet again:)

Quoted 2 lines · Yong Zhang

Setting rt_runtime both in this patch and the previous one will make tune other's rt_runtime/rt_period trouble, I guess.

Yeah, as in making it impossible to allocate even 1 usec :) We need zero bandwidth though, so tell __sched_setscheduler() that autogroups having zero allocated is perfectly fine.

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

---
 kernel/sched.c           |    3 ++-
 kernel/sched_autogroup.c |   27 +++++++++++++++++++++++++++
 kernel/sched_autogroup.h |    4 ++++
 3 files changed, 33 insertions(+), 1 deletion(-)
kernel/sched_autogroup.c +27 -0
Index: linux-2.6/kernel/sched_autogroup.c
===================================================================
@@ -27,6 +27,11 @@ static inline void autogroup_destroy(str
 {
 	struct autogroup *ag = container_of(kref, struct autogroup, kref);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+	/* We've redirected RT tasks to the root task group... */
+	ag->tg->rt_se = NULL;
+	ag->tg->rt_rq = NULL;
+#endif
 	sched_destroy_group(ag->tg);
 }
 
@@ -55,6 +60,10 @@ static inline struct autogroup *autogrou
 	return ag;
 }
 
+#ifdef CONFIG_RT_GROUP_SCHED
+static void free_rt_sched_group(struct task_group *tg);
+#endif
+
 static inline struct autogroup *autogroup_create(void)
 {
 	struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
@@ -72,6 +81,19 @@ static inline struct autogroup *autogrou
 	init_rwsem(&ag->lock);
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * Autogroup RT tasks are redirected to the root task group
+	 * so we don't have to move tasks around upon policy change,
+	 * or flail around trying to allocate bandwidth on the fly.
+	 * A bandwidth exception in __sched_setscheduler() allows
+	 * the policy change to proceed.  Thereafter, task_group()
+	 * returns &root_task_group, so zero bandwidth is required.
+	 */
+	free_rt_sched_group(tg);
+	tg->rt_se = root_task_group.rt_se;
+	tg->rt_rq = root_task_group.rt_rq;
+#endif
 	tg->autogroup = ag;
 
 	return ag;
@@ -106,6 +128,11 @@ task_wants_autogroup(struct task_struct
 	return true;
 }
 
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+	return tg != &root_task_group && tg->autogroup;
+}
+
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg)
 {
kernel/sched_autogroup.h +4 -0
Index: linux-2.6/kernel/sched_autogroup.h
===================================================================
@@ -15,6 +15,10 @@ autogroup_task_group(struct task_struct
 
 static inline void autogroup_init(struct task_struct *init_task) {  }
 static inline void autogroup_free(struct task_group *tg) { }
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+	return 0;
+}
 
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg)
kernel/sched.c +2 -1
Index: linux-2.6/kernel/sched.c
===================================================================
@@ -4874,7 +4874,8 @@ recheck:
 		 * assigned.
 		 */
 		if (rt_bandwidth_enabled() && rt_policy(policy) &&
-				task_group(p)->rt_bandwidth.rt_runtime == 0) {
+				task_group(p)->rt_bandwidth.rt_runtime == 0 &&
+				!task_group_is_autogroup(task_group(p))) {
 			__task_rq_unlock(rq);
 			raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 			return -EPERM;
#19 lore raw
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime.  Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

This looks more clear ;)

And a little comment below

kernel/sched_autogroup.c task_wants_autogroup(struct task_struct · line 133

Quoted 13 lines

---
 kernel/sched.c           |    3 ++- kernel/sched_autogroup.c |   27 +++++++++++++++++++++++++++ kernel/sched_autogroup.h |    4 ++++

 3 files changed, 33 insertions(+), 1 deletion(-)
kernel/sched_autogroup.c +3 -0
@@ -106,6 +128,11 @@ task_wants_autogroup(struct task_struct
        return true;
  }
 
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+       return tg != &root_task_group && tg->autogroup;

Isn't just checking tg->autogroup sufficient?

if tg == &root_task_group

Quoted 8 lines
kernel/sched.c +0 -0
@@ -4874,7 +4874,8 @@ recheck:
                 * assigned.
                 */

               if (rt_bandwidth_enabled() && rt_policy(policy) &&
-                               task_group(p)->rt_bandwidth.rt_runtime == 0) {
+                               task_group(p)->rt_bandwidth.rt_runtime == 0 &&

this check will fail.

Thanks,
Yong

Signature · 1 line
Only stand for myself
#20 lore raw
Quoted 24 lines · Yong Zhang
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime.  Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

This looks more clear ;)

And a little comment below

Quoted 10 lines

---
 kernel/sched.c           |    3 ++- kernel/sched_autogroup.c |   27 +++++++++++++++++++++++++++ kernel/sched_autogroup.h |    4 ++++

 3 files changed, 33 insertions(+), 1 deletion(-)
kernel/sched_autogroup.c +0 -0
@@ -106,6 +128,11 @@ task_wants_autogroup(struct task_struct
        return true;
  }
 
Quoted 5 lines

kernel/sched_autogroup.c task_wants_autogroup(struct task_struct · line 133

Quoted 3 lines
kernel/sched_autogroup.c +3 -0
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+       return tg != &root_task_group && tg->autogroup;

Isn't just checking tg->autogroup sufficient?

But if task_group_is_autogroup() will be called in other place in the future, checking (tg != &root_task_group) is needed.

Quoted 20 lines

if tg == &root_task_group

Quoted 8 lines
kernel/sched.c +0 -0
@@ -4874,7 +4874,8 @@ recheck:
                 * assigned.
                 */

               if (rt_bandwidth_enabled() && rt_policy(policy) &&
-                               task_group(p)->rt_bandwidth.rt_runtime == 0) {
+                               task_group(p)->rt_bandwidth.rt_runtime == 0 &&

this check will fail.

Thanks,
Yong

--
Only stand for myself

Signature · 1 line
Only stand for myself
#21 lore raw
In reply to Yong Zhang
Quoted 32 lines · Yong Zhang
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

This looks more clear ;)

And a little comment below

kernel/sched_autogroup.c task_wants_autogroup(struct task_struct · line 133

Quoted 13 lines
---
 kernel/sched.c           |    3 ++-
 kernel/sched_autogroup.c |   27 +++++++++++++++++++++++++++
 kernel/sched_autogroup.h |    4 ++++
 3 files changed, 33 insertions(+), 1 deletion(-)
kernel/sched_autogroup.c +3 -0
@@ -106,6 +128,11 @@ task_wants_autogroup(struct task_struct
       return true;
 }
 
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+       return tg != &root_task_group && tg->autogroup;

Isn't just checking tg->autogroup sufficient?

if tg == &root_task_group

Quoted 10 lines

kernel/sched.c recheck: · line 4877

Quoted 8 lines
kernel/sched.c +1 -1
@@ -4874,7 +4874,8 @@ recheck:
                * assigned.
                */
               if (rt_bandwidth_enabled() && rt_policy(policy) &&
-                               task_group(p)->rt_bandwidth.rt_runtime == 0) {
+                               task_group(p)->rt_bandwidth.rt_runtime == 0 &&

this check will fail.

Yes, it's intended to fail. I intend to make it explicit throughout autogroup that root_task_group is not an autogroup, and will drop the test for root_task_group then.

-Mike

#22 lore raw
In reply to Mike Galbraith
Quoted 17 lines · Mike Galbraith

(mailer switched me to work account again. grrrr, switch yet again:)

Quoted 2 lines · Yong Zhang

Setting rt_runtime both in this patch and the previous one will make tune other's rt_runtime/rt_period trouble, I guess.

Yeah, as in making it impossible to allocate even 1 usec :) We need zero bandwidth though, so tell __sched_setscheduler() that autogroups having zero allocated is perfectly fine.

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Quoted 9 lines
---
 kernel/sched.c           |    3 ++-
 kernel/sched_autogroup.c |   27 +++++++++++++++++++++++++++
 kernel/sched_autogroup.h |    4 ++++
 3 files changed, 33 insertions(+), 1 deletion(-)

Works fine here.

Thanks,
Bharata.

#23 lore raw
In reply to Mike Galbraith
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

#24 lore raw
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

why isnt rt_runtime_us residing in a separate (new) subsystem ?

Signature · 1 line
torben Hohn
#25 lore raw
Quoted 11 lines · torbenh
Quoted 10 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Quoted 6 lines
Quoted 1 line

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

Quoted 1 line

why isnt rt_runtime_us residing in a separate (new) subsystem ?

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

-Mike

#26 lore raw
Quoted 14 lines · Mike Galbraith
Quoted 13 lines · torbenh
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

Quoted 7 lines
Quoted 4 lines

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

but i can not get the same behaviour as if CONFIG_RT_GROUP_SCHED was off. iE N cgroups with different cpu.share values, but each with rt_runtime_us=950000

if the rt_runtime_us was in a different subsystem, its my understanding that i could leave rt_runtime_us alone, and have all tasks in the root group in the rt_runtime subsystem.

Quoted 5 lines
Quoted 2 lines

why isnt rt_runtime_us residing in a separate (new) subsystem ?

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

sure it belongs to the user. but what if user wants to have different cpu.shares, but full rt_runtime_us for all tasks ?

i can not have 2 sibling cgroups, whose rt_runtime_us adds up to over the rt_period ...

Quoted 8 lines

-Mike

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 1 line
torben Hohn
#27 lore raw
Quoted 20 lines · torbenh
Quoted 19 lines · Mike Galbraith
Quoted 17 lines · torbenh
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

Quoted 6 lines
Quoted 2 lines

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

but i can not get the same behaviour as if CONFIG_RT_GROUP_SCHED was off. iE N cgroups with different cpu.share values, but each with rt_runtime_us=950000

? if CONFIG_RT_GROUP_SCHED was a noop, it wouldn't exist.

Quoted 3 lines

if the rt_runtime_us was in a different subsystem, its my understanding that i could leave rt_runtime_us alone, and have all tasks in the root group in the rt_runtime subsystem.

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

Quoted 5 lines
Quoted 2 lines

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

sure it belongs to the user. but what if user wants to have different cpu.shares, but full rt_runtime_us for all tasks ?

Then the user doesn't want CONFIG_RT_GROUP_SCHED set.

-Mike

#28 lore raw
Quoted 36 lines · Mike Galbraith
Quoted 20 lines · torbenh
Quoted 19 lines · Mike Galbraith
Quoted 17 lines · torbenh
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

Quoted 6 lines
Quoted 2 lines

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

but i can not get the same behaviour as if CONFIG_RT_GROUP_SCHED was off. iE N cgroups with different cpu.share values, but each with rt_runtime_us=950000

? if CONFIG_RT_GROUP_SCHED was a noop, it wouldn't exist.

Quoted 3 lines

if the rt_runtime_us was in a different subsystem, its my understanding that i could leave rt_runtime_us alone, and have all tasks in the root group in the rt_runtime subsystem.

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

sure it belongs to the user. but what if user wants to have different cpu.shares, but full rt_runtime_us for all tasks ?

Then the user doesn't want CONFIG_RT_GROUP_SCHED set.

many users dont configure their kernels themselves. and this setting is not dynamic.

i guess its highly unlikely any normal user wants CONFIG_RT_GROUP_SCHED. but maybe distros will turn it on.

Signature · 1 line
torben Hohn
#29 lore raw
In reply to Mike Galbraith
Quoted 28 lines · Mike Galbraith
Quoted 20 lines · torbenh
Quoted 19 lines · Mike Galbraith
Quoted 17 lines · torbenh
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

Quoted 6 lines
Quoted 2 lines

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

but i can not get the same behaviour as if CONFIG_RT_GROUP_SCHED was off. iE N cgroups with different cpu.share values, but each with rt_runtime_us=950000

Quoted 7 lines

? if CONFIG_RT_GROUP_SCHED was a noop, it wouldn't exist.

Quoted 3 lines

if the rt_runtime_us was in a different subsystem, its my understanding that i could leave rt_runtime_us alone, and have all tasks in the root group in the rt_runtime subsystem.

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

but distros turn it on.
we could prevent debian from turning it on.
now opensuse 11.4 has turned it on.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

sure it belongs to the user. but what if user wants to have different cpu.shares, but full rt_runtime_us for all tasks ?

Then the user doesn't want CONFIG_RT_GROUP_SCHED set.

but distros force it onto the user.
if systemd shows up, and puts things into different cgroups, we end up with a pretty fragmented rt_runtime_us.

Quoted 8 lines

-Mike

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 1 line
torben Hohn
#30 lore raw
Quoted 35 lines · torbenh
Quoted 34 lines · Mike Galbraith
Quoted 20 lines · torbenh
Quoted 19 lines · Mike Galbraith
Quoted 17 lines · torbenh
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

Quoted 6 lines
Quoted 2 lines

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

but i can not get the same behaviour as if CONFIG_RT_GROUP_SCHED was off. iE N cgroups with different cpu.share values, but each with rt_runtime_us=950000

? if CONFIG_RT_GROUP_SCHED was a noop, it wouldn't exist.

Quoted 3 lines

if the rt_runtime_us was in a different subsystem, its my understanding that i could leave rt_runtime_us alone, and have all tasks in the root group in the rt_runtime subsystem.

Quoted 5 lines
Quoted 1 line

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

but distros turn it on.
we could prevent debian from turning it on.
now opensuse 11.4 has turned it on.

If you or anyone else turns on RT_GROUP_SCHED, you will count your beans, and pay up front, or you will not play. That's a very sensible policy for realtime.

Quoted 11 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

sure it belongs to the user. but what if user wants to have different cpu.shares, but full rt_runtime_us for all tasks ?

Then the user doesn't want CONFIG_RT_GROUP_SCHED set.

but distros force it onto the user.
if systemd shows up, and puts things into different cgroups, we end up with a pretty fragmented rt_runtime_us.

If systemd deals with it at all, seems to me it can only make a mess of it. But who knows, maybe they made a clever allocator. If they didn't, they'll need an escape hatch methinks.

-Mike

#31 lore raw
Quoted 38 lines · Mike Galbraith
Quoted 37 lines · torbenh
Quoted 35 lines · Mike Galbraith
Quoted 20 lines · torbenh
Quoted 19 lines · Mike Galbraith
Quoted 17 lines · torbenh
Quoted 11 lines · Peter Zijlstra
Quoted 8 lines · Mike Galbraith

sched, autogroup: fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure.

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

Thanks, applied!

while this behaviour is certeinly necessary, i think this is a hack. it fixes the problem for autogroups.
But its not fixed for things which want to control the cfs shares via normal cgroups.

Quoted 6 lines
Quoted 2 lines

You mean automated control ala systemd? For a static set of groups, it works fine. I was wondering how systemd would deal with it.

but i can not get the same behaviour as if CONFIG_RT_GROUP_SCHED was off. iE N cgroups with different cpu.share values, but each with rt_runtime_us=950000

? if CONFIG_RT_GROUP_SCHED was a noop, it wouldn't exist.

Quoted 3 lines

if the rt_runtime_us was in a different subsystem, its my understanding that i could leave rt_runtime_us alone, and have all tasks in the root group in the rt_runtime subsystem.

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

Quoted 7 lines
Quoted 3 lines

but distros turn it on.
we could prevent debian from turning it on.
now opensuse 11.4 has turned it on.

If you or anyone else turns on RT_GROUP_SCHED, you will count your beans, and pay up front, or you will not play. That's a very sensible policy for realtime.

this probably means that generic computer distros should not turn this option on ?

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

The allocation problem was shamelessly punted back to the user, where I think it truly belongs.

sure it belongs to the user. but what if user wants to have different cpu.shares, but full rt_runtime_us for all tasks ?

Then the user doesn't want CONFIG_RT_GROUP_SCHED set.

Quoted 7 lines
Quoted 3 lines

but distros force it onto the user.
if systemd shows up, and puts things into different cgroups, we end up with a pretty fragmented rt_runtime_us.

If systemd deals with it at all, seems to me it can only make a mess of it. But who knows, maybe they made a clever allocator. If they didn't, they'll need an escape hatch methinks.

the problem is that audio applications can not really pre allocate their cpu needs. user can add processing plugins until he pushes his machine to the limit. (or the cgroup where his process is running in)

we dont really have a mechanism for plugins to publish their needed cycles.

Signature · 1 line
torben Hohn
#32 lore raw
Quoted 11 lines · torbenh
Quoted 9 lines · Mike Galbraith
Quoted 7 lines · torbenh
Quoted 1 line · Mike Galbraith

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

but distros turn it on.
we could prevent debian from turning it on.
now opensuse 11.4 has turned it on.

Quoted 6 lines
Quoted 3 lines

If you or anyone else turns on RT_GROUP_SCHED, you will count your beans, and pay up front, or you will not play. That's a very sensible policy for realtime.

this probably means that generic computer distros should not turn this option on ?

Yeah, agreed, not for a great default config, but only because newfangled automation thingies can't (possibly?) deal with it sanely.

Quoted 10 lines
Quoted 3 lines

If systemd deals with it at all, seems to me it can only make a mess of it. But who knows, maybe they made a clever allocator. If they didn't, they'll need an escape hatch methinks.

the problem is that audio applications can not really pre allocate their cpu needs. user can add processing plugins until he pushes his machine to the limit. (or the cgroup where his process is running in)

we dont really have a mechanism for plugins to publish their needed cycles.

I can't see how it could matter what any individual group of arbitrary groups N (who can appear/disappear in the blink of an eye) advertises as it's wish of the instant. "Hard" + "Arbitrary" doesn't compute for me.

-Mike

#33 lore raw

sorry... i cced the old ML addresses :S
fixing the CC now.

Quoted 16 lines · Mike Galbraith
Quoted 15 lines · torbenh
Quoted 12 lines · Mike Galbraith
Quoted 7 lines · torbenh
Quoted 1 line · Mike Galbraith

Sounds like you just want to turn CONFIG_RT_GROUP_SCHED off.

but distros turn it on.
we could prevent debian from turning it on.
now opensuse 11.4 has turned it on.

If you or anyone else turns on RT_GROUP_SCHED, you will count your beans, and pay up front, or you will not play. That's a very sensible policy for realtime.

Quoted 5 lines
Quoted 2 lines

this probably means that generic computer distros should not turn this option on ?

Yeah, agreed, not for a great default config, but only because newfangled automation thingies can't (possibly?) deal with it sanely.

but this is excactly the reason, why i would advocate rt_runtime to be in a separate cgroups system.
any admin who wants to limit RT runtime could still do it. people who dont care, and just want their cfs slices configured, can still do it.

Quoted 9 lines
Quoted 9 lines
Quoted 4 lines

If systemd deals with it at all, seems to me it can only make a mess of it. But who knows, maybe they made a clever allocator. If they didn't, they'll need an escape hatch methinks.

the problem is that audio applications can not really pre allocate their cpu needs. user can add processing plugins until he pushes his machine to the limit. (or the cgroup where his process is running in)

Quoted 6 lines
Quoted 2 lines

we dont really have a mechanism for plugins to publish their needed cycles.

I can't see how it could matter what any individual group of arbitrary groups N (who can appear/disappear in the blink of an eye) advertises as it's wish of the instant. "Hard" + "Arbitrary" doesn't compute for me.

i dont really understnad this statement.

Quoted 8 lines

-Mike

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 1 line
torben Hohn
#34 lore raw
Quoted 1 line · torbenh

i dont really understnad this statement.

Doesn't matter, we're thinking about different subjects. You're thinking of an unborn mechanism, I'm thinking of the living one.

-Mike

#35 lore raw

P.S. Kindly do not CC closed lists. Closed list readers only see your part of any conversation, and anyone replying to you is rewarded with bounce spam for their trouble.

#36 lore raw
Quoted 3 lines · Mike Galbraith

P.S. Kindly do not CC closed lists. Closed list readers only see your part of any conversation, and anyone replying to you is rewarded with bounce spam for their trouble.

yeah. sorry. i thought the lists were open.
there doesnt seem to be interest in it anyways.

i guess i rest my case, and wait for things to fall apart.

Signature · 1 line
torben Hohn
#37 lore raw

[tip:sched/urgent] sched, autogroup: Fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure

In reply to Mike Galbraith
Commit-ID:  f44937718ce3b8360f72f6c68c9481712517a867
Gitweb:     http://git.kernel.org/tip/f44937718ce3b8360f72f6c68c9481712517a867
Author:     Mike Galbraith <[email protected]>
AuthorDate: Thu, 13 Jan 2011 04:54:50 +0100
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 18 Jan 2011 15:09:42 +0100

sched, autogroup: Fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure

If CONFIG_RT_GROUP_SCHED is set, __sched_setscheduler() fails due to autogroup not allocating rt_runtime. Free unused/unusable rt_se and rt_rq, redirect RT tasks to the root task group, and tell __sched_setscheduler() that it's ok.

LKML-Reference: <[email protected]>

---
 kernel/sched.c           |    3 ++-
 kernel/sched_autogroup.c |   27 +++++++++++++++++++++++++++
 kernel/sched_autogroup.h |    4 ++++
 3 files changed, 33 insertions(+), 1 deletions(-)
kernel/sched.c +2 -1
index a0eb094..6cbff6b 100644
@@ -4871,7 +4871,8 @@ recheck:
 		 * assigned.
 		 */
 		if (rt_bandwidth_enabled() && rt_policy(policy) &&
-				task_group(p)->rt_bandwidth.rt_runtime == 0) {
+				task_group(p)->rt_bandwidth.rt_runtime == 0 &&
+				!task_group_is_autogroup(task_group(p))) {
 			__task_rq_unlock(rq);
 			raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 			return -EPERM;
kernel/sched_autogroup.c +27 -0
index 938d52f..9fb6562 100644
@@ -27,6 +27,11 @@ static inline void autogroup_destroy(struct kref *kref)
 {
 	struct autogroup *ag = container_of(kref, struct autogroup, kref);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+	/* We've redirected RT tasks to the root task group... */
+	ag->tg->rt_se = NULL;
+	ag->tg->rt_rq = NULL;
+#endif
 	sched_destroy_group(ag->tg);
 }
 
@@ -55,6 +60,10 @@ static inline struct autogroup *autogroup_task_get(struct task_struct *p)
 	return ag;
 }
 
+#ifdef CONFIG_RT_GROUP_SCHED
+static void free_rt_sched_group(struct task_group *tg);
+#endif
+
 static inline struct autogroup *autogroup_create(void)
 {
 	struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
@@ -72,6 +81,19 @@ static inline struct autogroup *autogroup_create(void)
 	init_rwsem(&ag->lock);
 	ag->id = atomic_inc_return(&autogroup_seq_nr);
 	ag->tg = tg;
+#ifdef CONFIG_RT_GROUP_SCHED
+	/*
+	 * Autogroup RT tasks are redirected to the root task group
+	 * so we don't have to move tasks around upon policy change,
+	 * or flail around trying to allocate bandwidth on the fly.
+	 * A bandwidth exception in __sched_setscheduler() allows
+	 * the policy change to proceed.  Thereafter, task_group()
+	 * returns &root_task_group, so zero bandwidth is required.
+	 */
+	free_rt_sched_group(tg);
+	tg->rt_se = root_task_group.rt_se;
+	tg->rt_rq = root_task_group.rt_rq;
+#endif
 	tg->autogroup = ag;
 
 	return ag;
@@ -106,6 +128,11 @@ task_wants_autogroup(struct task_struct *p, struct task_group *tg)
 	return true;
 }
 
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+	return tg != &root_task_group && tg->autogroup;
+}
+
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg)
 {
kernel/sched_autogroup.h +4 -0
index 5358e24..7b859ff 100644
@@ -15,6 +15,10 @@ autogroup_task_group(struct task_struct *p, struct task_group *tg);
 
 static inline void autogroup_init(struct task_struct *init_task) {  }
 static inline void autogroup_free(struct task_group *tg) { }
+static inline bool task_group_is_autogroup(struct task_group *tg)
+{
+	return 0;
+}
 
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg)
#38 lore raw
In reply to Mike Galbraith
Quoted 21 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
        ag->id = atomic_inc_return(&autogroup_seq_nr);
        ag->tg = tg;
        tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * HACK: autogroup RT tasks run in the root task group.
+        * This fools __sched_setscheduler() into proceeding on
+        * so we can move the task to the appropriate runqueue
+        * upon scheduling policy change.
+        */
+       tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
        return ag;
 

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 159

Quoted 8 lines
kernel/sched_autogroup.c +5 -0
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
        autogroup_kref_put(prev);
  }
 
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+       if (p->sched_class->task_move_group)
+               p->sched_class->task_move_group(p, on_rq);

This will be called even if we don't change the sched_class in which case it is not necessary.

Thanks,
Yong

Signature · 1 line
Only stand for myself
#39 lore raw
Quoted 25 lines · Yong Zhang
Quoted 24 lines · Mike Galbraith

Index: linux-2.6/kernel/sched_autogroup.c
===================================================================

kernel/sched_autogroup.c +9 -0
@@ -73,6 +73,15 @@ static inline struct autogroup *autogrou
       ag->id = atomic_inc_return(&autogroup_seq_nr);
       ag->tg = tg;
       tg->autogroup = ag;
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * HACK: autogroup RT tasks run in the root task group.
+        * This fools __sched_setscheduler() into proceeding on
+        * so we can move the task to the appropriate runqueue
+        * upon scheduling policy change.
+        */
+       tg->rt_bandwidth.rt_runtime = RUNTIME_INF;
+#endif
 
       return ag;
 
@@ -143,6 +152,15 @@ autogroup_move_group(struct task_struct
       autogroup_kref_put(prev);
 }
 
Quoted 8 lines

kernel/sched_autogroup.c autogroup_move_group(struct task_struct · line 159

Quoted 5 lines
kernel/sched_autogroup.c +5 -0
+static inline void
+autogroup_setscheduler(struct task_struct *p, int on_rq)
+{
+       if (p->sched_class->task_move_group)
+               p->sched_class->task_move_group(p, on_rq);

This will be called even if we don't change the sched_class in which case it is not necessary.

Yes. It'll also piddle around with tasks it shouldn't. I sent what I hope is a better solution a few minutes ago. This one works, but probably upset Peter's tummy mightily :)

-Mike