aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/cgroup.h
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-06-08 05:40:42 -0400
committerIngo Molnar <mingo@elte.hu>2010-06-08 12:44:04 -0400
commitdc61b1d65e353d638b2445f71fb8e5b5630f2415 (patch)
tree07d79b2d385a380207cd889ac764b57190421fd1 /include/linux/cgroup.h
parent3975d16760d4be7402d1067c548c30c427971331 (diff)
sched: Fix PROVE_RCU vs cpu_cgroup
PROVE_RCU has a few issues with the cpu_cgroup because the scheduler typically holds rq->lock around the css rcu derefs but the generic cgroup code doesn't (and can't) know about that lock. Provide means to add extra checks to the css dereference and use that in the scheduler to annotate its users. The addition of rq->lock to these checks is correct because the cgroup_subsys::attach() method takes the rq->lock for each task it moves, therefore by holding that lock, we ensure the task is pinned to the current cgroup and the RCU derefence is valid. That leaves one genuine race in __sched_setscheduler() where we used task_group() without holding any of the required locks and thus raced with the cgroup code. Solve this by moving the check under the appropriate lock. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/cgroup.h')
-rw-r--r--include/linux/cgroup.h20
1 files changed, 14 insertions, 6 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 0c621604baa1..e3d00fdb858d 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -525,13 +525,21 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state(
525 return cgrp->subsys[subsys_id]; 525 return cgrp->subsys[subsys_id];
526} 526}
527 527
528static inline struct cgroup_subsys_state *task_subsys_state( 528/*
529 struct task_struct *task, int subsys_id) 529 * function to get the cgroup_subsys_state which allows for extra
530 * rcu_dereference_check() conditions, such as locks used during the
531 * cgroup_subsys::attach() methods.
532 */
533#define task_subsys_state_check(task, subsys_id, __c) \
534 rcu_dereference_check(task->cgroups->subsys[subsys_id], \
535 rcu_read_lock_held() || \
536 lockdep_is_held(&task->alloc_lock) || \
537 cgroup_lock_is_held() || (__c))
538
539static inline struct cgroup_subsys_state *
540task_subsys_state(struct task_struct *task, int subsys_id)
530{ 541{
531 return rcu_dereference_check(task->cgroups->subsys[subsys_id], 542 return task_subsys_state_check(task, subsys_id, false);
532 rcu_read_lock_held() ||
533 lockdep_is_held(&task->alloc_lock) ||
534 cgroup_lock_is_held());
535} 543}
536 544
537static inline struct cgroup* task_cgroup(struct task_struct *task, 545static inline struct cgroup* task_cgroup(struct task_struct *task,