aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c115
1 files changed, 59 insertions, 56 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index f8b8996228dd..2aaceebd484c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -306,52 +306,6 @@ static int init_task_group_load = INIT_TASK_GROUP_LOAD;
306 */ 306 */
307struct task_group init_task_group; 307struct task_group init_task_group;
308 308
309/* return group to which a task belongs */
310static inline struct task_group *task_group(struct task_struct *p)
311{
312 struct task_group *tg;
313
314#ifdef CONFIG_CGROUP_SCHED
315 tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
316 struct task_group, css);
317#else
318 tg = &init_task_group;
319#endif
320 return tg;
321}
322
323/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
324static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
325{
326 /*
327 * Strictly speaking this rcu_read_lock() is not needed since the
328 * task_group is tied to the cgroup, which in turn can never go away
329 * as long as there are tasks attached to it.
330 *
331 * However since task_group() uses task_subsys_state() which is an
332 * rcu_dereference() user, this quiets CONFIG_PROVE_RCU.
333 */
334 rcu_read_lock();
335#ifdef CONFIG_FAIR_GROUP_SCHED
336 p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
337 p->se.parent = task_group(p)->se[cpu];
338#endif
339
340#ifdef CONFIG_RT_GROUP_SCHED
341 p->rt.rt_rq = task_group(p)->rt_rq[cpu];
342 p->rt.parent = task_group(p)->rt_se[cpu];
343#endif
344 rcu_read_unlock();
345}
346
347#else
348
349static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
350static inline struct task_group *task_group(struct task_struct *p)
351{
352 return NULL;
353}
354
355#endif /* CONFIG_CGROUP_SCHED */ 309#endif /* CONFIG_CGROUP_SCHED */
356 310
357/* CFS-related fields in a runqueue */ 311/* CFS-related fields in a runqueue */
@@ -644,6 +598,49 @@ static inline int cpu_of(struct rq *rq)
644#define cpu_curr(cpu) (cpu_rq(cpu)->curr) 598#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
645#define raw_rq() (&__raw_get_cpu_var(runqueues)) 599#define raw_rq() (&__raw_get_cpu_var(runqueues))
646 600
601#ifdef CONFIG_CGROUP_SCHED
602
603/*
604 * Return the group to which this tasks belongs.
605 *
606 * We use task_subsys_state_check() and extend the RCU verification
607 * with lockdep_is_held(&task_rq(p)->lock) because cpu_cgroup_attach()
608 * holds that lock for each task it moves into the cgroup. Therefore
609 * by holding that lock, we pin the task to the current cgroup.
610 */
611static inline struct task_group *task_group(struct task_struct *p)
612{
613 struct cgroup_subsys_state *css;
614
615 css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
616 lockdep_is_held(&task_rq(p)->lock));
617 return container_of(css, struct task_group, css);
618}
619
620/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
621static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
622{
623#ifdef CONFIG_FAIR_GROUP_SCHED
624 p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
625 p->se.parent = task_group(p)->se[cpu];
626#endif
627
628#ifdef CONFIG_RT_GROUP_SCHED
629 p->rt.rt_rq = task_group(p)->rt_rq[cpu];
630 p->rt.parent = task_group(p)->rt_se[cpu];
631#endif
632}
633
634#else /* CONFIG_CGROUP_SCHED */
635
636static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
637static inline struct task_group *task_group(struct task_struct *p)
638{
639 return NULL;
640}
641
642#endif /* CONFIG_CGROUP_SCHED */
643
647inline void update_rq_clock(struct rq *rq) 644inline void update_rq_clock(struct rq *rq)
648{ 645{
649 if (!rq->skip_clock_update) 646 if (!rq->skip_clock_update)
@@ -4465,16 +4462,6 @@ recheck:
4465 } 4462 }
4466 4463
4467 if (user) { 4464 if (user) {
4468#ifdef CONFIG_RT_GROUP_SCHED
4469 /*
4470 * Do not allow realtime tasks into groups that have no runtime
4471 * assigned.
4472 */
4473 if (rt_bandwidth_enabled() && rt_policy(policy) &&
4474 task_group(p)->rt_bandwidth.rt_runtime == 0)
4475 return -EPERM;
4476#endif
4477
4478 retval = security_task_setscheduler(p, policy, param); 4465 retval = security_task_setscheduler(p, policy, param);
4479 if (retval) 4466 if (retval)
4480 return retval; 4467 return retval;
@@ -4490,6 +4477,22 @@ recheck:
4490 * runqueue lock must be held. 4477 * runqueue lock must be held.
4491 */ 4478 */
4492 rq = __task_rq_lock(p); 4479 rq = __task_rq_lock(p);
4480
4481#ifdef CONFIG_RT_GROUP_SCHED
4482 if (user) {
4483 /*
4484 * Do not allow realtime tasks into groups that have no runtime
4485 * assigned.
4486 */
4487 if (rt_bandwidth_enabled() && rt_policy(policy) &&
4488 task_group(p)->rt_bandwidth.rt_runtime == 0) {
4489 __task_rq_unlock(rq);
4490 raw_spin_unlock_irqrestore(&p->pi_lock, flags);
4491 return -EPERM;
4492 }
4493 }
4494#endif
4495
4493 /* recheck policy now with rq lock held */ 4496 /* recheck policy now with rq lock held */
4494 if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { 4497 if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
4495 policy = oldpolicy = -1; 4498 policy = oldpolicy = -1;