aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2015-05-13 16:35:16 -0400
committerTejun Heo <tj@kernel.org>2015-05-26 20:35:00 -0400
commit7d7efec368d537226142cbe559f45797f18672f9 (patch)
tree8b391dada2b97b66f9fbd4315b397516f13199de /kernel
parent8ab456ac3697dbd1d3eae5d5817dba941faf89ee (diff)
sched, cgroup: reorganize threadgroup locking
threadgroup_change_begin/end() are used to mark the beginning and end of threadgroup modifying operations to allow code paths which require a threadgroup to stay stable across blocking operations to synchronize against those sections using threadgroup_lock/unlock(). It's currently implemented as a general mechanism in sched.h using per-signal_struct rwsem; however, this never grew non-cgroup use cases and becomes noop if !CONFIG_CGROUPS. It turns out that cgroups is gonna be better served with a different sycnrhonization scheme and is a bit silly to keep cgroups specific details as a general mechanism. What's general here is identifying the places where threadgroups are modified. This patch restructures threadgroup locking so that threadgroup_change_begin/end() become a place where subsystems which need to sycnhronize against threadgroup changes can hook into. cgroup_threadgroup_change_begin/end() which operate on the per-signal_struct rwsem are created and threadgroup_lock/unlock() are moved to cgroup.c and made static. This is pure reorganization which doesn't cause any functional changes. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index b91177f93416..980b1f52f39f 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -848,6 +848,48 @@ static struct css_set *find_css_set(struct css_set *old_cset,
848 return cset; 848 return cset;
849} 849}
850 850
851void cgroup_threadgroup_change_begin(struct task_struct *tsk)
852{
853 down_read(&tsk->signal->group_rwsem);
854}
855
856void cgroup_threadgroup_change_end(struct task_struct *tsk)
857{
858 up_read(&tsk->signal->group_rwsem);
859}
860
861/**
862 * threadgroup_lock - lock threadgroup
863 * @tsk: member task of the threadgroup to lock
864 *
865 * Lock the threadgroup @tsk belongs to. No new task is allowed to enter
866 * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or
867 * change ->group_leader/pid. This is useful for cases where the threadgroup
868 * needs to stay stable across blockable operations.
869 *
870 * fork and exit explicitly call threadgroup_change_{begin|end}() for
871 * synchronization. While held, no new task will be added to threadgroup
872 * and no existing live task will have its PF_EXITING set.
873 *
874 * de_thread() does threadgroup_change_{begin|end}() when a non-leader
875 * sub-thread becomes a new leader.
876 */
877static void threadgroup_lock(struct task_struct *tsk)
878{
879 down_write(&tsk->signal->group_rwsem);
880}
881
882/**
883 * threadgroup_unlock - unlock threadgroup
884 * @tsk: member task of the threadgroup to unlock
885 *
886 * Reverse threadgroup_lock().
887 */
888static inline void threadgroup_unlock(struct task_struct *tsk)
889{
890 up_write(&tsk->signal->group_rwsem);
891}
892
851static struct cgroup_root *cgroup_root_from_kf(struct kernfs_root *kf_root) 893static struct cgroup_root *cgroup_root_from_kf(struct kernfs_root *kf_root)
852{ 894{
853 struct cgroup *root_cgrp = kf_root->kn->priv; 895 struct cgroup *root_cgrp = kf_root->kn->priv;