Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3174ffaa authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched:
  sched: rt-group: refure unrunnable tasks
  sched: rt-group: clean up the ifdeffery
  sched: rt-group: make rt groups scheduling configurable
  sched: rt-group: interface
  sched: rt-group: deal with PI
  sched: fix incorrect irq lock usage in normalize_rt_tasks()
  sched: fair-group: separate tg->shares from task_group_lock
  hrtimer: more hrtimer_init_sleeper() fallout.
parents d7ab95f8 b68aa230
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line


Real-Time group scheduling.

The problem space:

In order to schedule multiple groups of realtime tasks each group must
be assigned a fixed portion of the CPU time available. Without a minimum
guarantee a realtime group can obviously fall short. A fuzzy upper limit
is of no use since it cannot be relied upon. Which leaves us with just
the single fixed portion.

CPU time is divided by means of specifying how much time can be spent
running in a given period. Say a frame fixed realtime renderer must
deliver 25 frames a second, which yields a period of 0.04s. Now say
it will also have to play some music and respond to input, leaving it
with around 80% for the graphics. We can then give this group a runtime
of 0.8 * 0.04s = 0.032s.

This way the graphics group will have a 0.04s period with a 0.032s runtime
limit.

Now if the audio thread needs to refill the DMA buffer every 0.005s, but
needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s
= 0.00015s.


The Interface:

system wide:

/proc/sys/kernel/sched_rt_period_ms
/proc/sys/kernel/sched_rt_runtime_us

CONFIG_FAIR_USER_SCHED

/sys/kernel/uids/<uid>/cpu_rt_runtime_us

or

CONFIG_FAIR_CGROUP_SCHED

/cgroup/<cgroup>/cpu.rt_runtime_us

[ time is specified in us because the interface is s32; this gives an
  operating range of ~35m to 1us ]

The period takes values in [ 1, INT_MAX ], runtime in [ -1, INT_MAX - 1 ].

A runtime of -1 specifies runtime == period, ie. no limit.

New groups get the period from /proc/sys/kernel/sched_rt_period_us and
a runtime of 0.

Settings are constrained to:

   \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period

in order to keep the configuration schedulable.
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ SUBSYS(ns)

/* */

#ifdef CONFIG_FAIR_CGROUP_SCHED
#ifdef CONFIG_CGROUP_SCHED
SUBSYS(cpu_cgroup)
#endif

+12 −6
Original line number Diff line number Diff line
@@ -590,7 +590,7 @@ struct user_struct {
	struct hlist_node uidhash_node;
	uid_t uid;

#ifdef CONFIG_FAIR_USER_SCHED
#ifdef CONFIG_USER_SCHED
	struct task_group *tg;
#ifdef CONFIG_SYSFS
	struct kobject kobj;
@@ -973,7 +973,7 @@ struct sched_rt_entity {
	unsigned long timeout;
	int nr_cpus_allowed;

#ifdef CONFIG_FAIR_GROUP_SCHED
#ifdef CONFIG_RT_GROUP_SCHED
	struct sched_rt_entity	*parent;
	/* rq on which this entity is (to be) queued: */
	struct rt_rq		*rt_rq;
@@ -1541,8 +1541,6 @@ extern unsigned int sysctl_sched_child_runs_first;
extern unsigned int sysctl_sched_features;
extern unsigned int sysctl_sched_migration_cost;
extern unsigned int sysctl_sched_nr_migrate;
extern unsigned int sysctl_sched_rt_period;
extern unsigned int sysctl_sched_rt_ratio;
#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_SMP)
extern unsigned int sysctl_sched_min_bal_int_shares;
extern unsigned int sysctl_sched_max_bal_int_shares;
@@ -1552,6 +1550,8 @@ int sched_nr_latency_handler(struct ctl_table *table, int write,
		struct file *file, void __user *buffer, size_t *length,
		loff_t *ppos);
#endif
extern unsigned int sysctl_sched_rt_period;
extern int sysctl_sched_rt_runtime;

extern unsigned int sysctl_sched_compat_yield;

@@ -2027,16 +2027,22 @@ extern int sched_mc_power_savings, sched_smt_power_savings;

extern void normalize_rt_tasks(void);

#ifdef CONFIG_FAIR_GROUP_SCHED
#ifdef CONFIG_GROUP_SCHED

extern struct task_group init_task_group;

extern struct task_group *sched_create_group(void);
extern void sched_destroy_group(struct task_group *tg);
extern void sched_move_task(struct task_struct *tsk);
#ifdef CONFIG_FAIR_GROUP_SCHED
extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
extern unsigned long sched_group_shares(struct task_group *tg);

#endif
#ifdef CONFIG_RT_GROUP_SCHED
extern int sched_group_set_rt_runtime(struct task_group *tg,
				      long rt_runtime_us);
extern long sched_group_rt_runtime(struct task_group *tg);
#endif
#endif

#ifdef CONFIG_TASK_XACCT
+17 −6
Original line number Diff line number Diff line
@@ -311,25 +311,36 @@ config CPUSETS

	  Say N if unsure.

config FAIR_GROUP_SCHED
	bool "Fair group CPU scheduler"
config GROUP_SCHED
	bool "Group CPU scheduler"
	default y
	help
	  This feature lets CPU scheduler recognize task groups and control CPU
	  bandwidth allocation to such task groups.

config FAIR_GROUP_SCHED
	bool "Group scheduling for SCHED_OTHER"
	depends on GROUP_SCHED
	default y

config RT_GROUP_SCHED
	bool "Group scheduling for SCHED_RR/FIFO"
	depends on EXPERIMENTAL
	depends on GROUP_SCHED
	default n

choice
	depends on FAIR_GROUP_SCHED
	depends on GROUP_SCHED
	prompt "Basis for grouping tasks"
	default FAIR_USER_SCHED
	default USER_SCHED

config FAIR_USER_SCHED
config 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.

config FAIR_CGROUP_SCHED
config CGROUP_SCHED
	bool "Control groups"
 	depends on CGROUPS
 	help
+4 −1
Original line number Diff line number Diff line
@@ -630,9 +630,12 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
	set_current_state(state);

	/* Setup the timer, when timeout != NULL */
	if (unlikely(timeout))
	if (unlikely(timeout)) {
		hrtimer_start(&timeout->timer, timeout->timer.expires,
			      HRTIMER_MODE_ABS);
		if (!hrtimer_active(&timeout->timer))
			timeout->task = NULL;
	}

	for (;;) {
		/* Try to acquire the lock: */
Loading