@@ -274,9 +274,7 @@ struct task_group {
274274
275275#define root_task_group init_task_group
276276
277- /* task_group_lock serializes add/remove of task groups and also changes to
278- * a task group's cpu shares.
279- */
277+ /* task_group_lock serializes the addition/removal of task groups */
280278static DEFINE_SPINLOCK (task_group_lock );
281279
282280#ifdef CONFIG_FAIR_GROUP_SCHED
@@ -344,6 +342,7 @@ struct cfs_rq {
344342 * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
345343 * list is used during load balance.
346344 */
345+ int on_list ;
347346 struct list_head leaf_cfs_rq_list ;
348347 struct task_group * tg ; /* group that "owns" this runqueue */
349348
@@ -1547,7 +1546,7 @@ static unsigned long cpu_avg_load_per_task(int cpu)
15471546
15481547#ifdef CONFIG_FAIR_GROUP_SCHED
15491548
1550- static void update_cfs_load (struct cfs_rq * cfs_rq );
1549+ static void update_cfs_load (struct cfs_rq * cfs_rq , int lb );
15511550static void update_cfs_shares (struct cfs_rq * cfs_rq );
15521551
15531552/*
@@ -1570,7 +1569,7 @@ static int tg_shares_up(struct task_group *tg, void *data)
15701569 raw_spin_lock_irqsave (& rq -> lock , flags );
15711570
15721571 update_rq_clock (rq );
1573- update_cfs_load (cfs_rq );
1572+ update_cfs_load (cfs_rq , 1 );
15741573
15751574 load_avg = div64_u64 (cfs_rq -> load_avg , cfs_rq -> load_period + 1 );
15761575 load_avg -= cfs_rq -> load_contribution ;
@@ -7688,15 +7687,13 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
76887687
76897688#ifdef CONFIG_FAIR_GROUP_SCHED
76907689static void init_tg_cfs_entry (struct task_group * tg , struct cfs_rq * cfs_rq ,
7691- struct sched_entity * se , int cpu , int add ,
7690+ struct sched_entity * se , int cpu ,
76927691 struct sched_entity * parent )
76937692{
76947693 struct rq * rq = cpu_rq (cpu );
76957694 tg -> cfs_rq [cpu ] = cfs_rq ;
76967695 init_cfs_rq (cfs_rq , rq );
76977696 cfs_rq -> tg = tg ;
7698- if (add )
7699- list_add (& cfs_rq -> leaf_cfs_rq_list , & rq -> leaf_cfs_rq_list );
77007697
77017698 tg -> se [cpu ] = se ;
77027699 /* se could be NULL for init_task_group */
@@ -7716,7 +7713,7 @@ static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
77167713
77177714#ifdef CONFIG_RT_GROUP_SCHED
77187715static void init_tg_rt_entry (struct task_group * tg , struct rt_rq * rt_rq ,
7719- struct sched_rt_entity * rt_se , int cpu , int add ,
7716+ struct sched_rt_entity * rt_se , int cpu ,
77207717 struct sched_rt_entity * parent )
77217718{
77227719 struct rq * rq = cpu_rq (cpu );
@@ -7725,8 +7722,6 @@ static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
77257722 init_rt_rq (rt_rq , rq );
77267723 rt_rq -> tg = tg ;
77277724 rt_rq -> rt_runtime = tg -> rt_bandwidth .rt_runtime ;
7728- if (add )
7729- list_add (& rt_rq -> leaf_rt_rq_list , & rq -> leaf_rt_rq_list );
77307725
77317726 tg -> rt_se [cpu ] = rt_se ;
77327727 if (!rt_se )
@@ -7835,15 +7830,15 @@ void __init sched_init(void)
78357830 * We achieve this by letting init_task_group's tasks sit
78367831 * directly in rq->cfs (i.e init_task_group->se[] = NULL).
78377832 */
7838- init_tg_cfs_entry (& init_task_group , & rq -> cfs , NULL , i , 1 , NULL );
7833+ init_tg_cfs_entry (& init_task_group , & rq -> cfs , NULL , i , NULL );
78397834#endif
78407835#endif /* CONFIG_FAIR_GROUP_SCHED */
78417836
78427837 rq -> rt .rt_runtime = def_rt_bandwidth .rt_runtime ;
78437838#ifdef CONFIG_RT_GROUP_SCHED
78447839 INIT_LIST_HEAD (& rq -> leaf_rt_rq_list );
78457840#ifdef CONFIG_CGROUP_SCHED
7846- init_tg_rt_entry (& init_task_group , & rq -> rt , NULL , i , 1 , NULL );
7841+ init_tg_rt_entry (& init_task_group , & rq -> rt , NULL , i , NULL );
78477842#endif
78487843#endif
78497844
@@ -8119,7 +8114,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
81198114 if (!se )
81208115 goto err_free_rq ;
81218116
8122- init_tg_cfs_entry (tg , cfs_rq , se , i , 0 , parent -> se [i ]);
8117+ init_tg_cfs_entry (tg , cfs_rq , se , i , parent -> se [i ]);
81238118 }
81248119
81258120 return 1 ;
@@ -8130,15 +8125,22 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
81308125 return 0 ;
81318126}
81328127
8133- static inline void register_fair_sched_group (struct task_group * tg , int cpu )
8134- {
8135- list_add_rcu (& tg -> cfs_rq [cpu ]-> leaf_cfs_rq_list ,
8136- & cpu_rq (cpu )-> leaf_cfs_rq_list );
8137- }
8138-
81398128static inline void unregister_fair_sched_group (struct task_group * tg , int cpu )
81408129{
8141- list_del_rcu (& tg -> cfs_rq [cpu ]-> leaf_cfs_rq_list );
8130+ struct rq * rq = cpu_rq (cpu );
8131+ unsigned long flags ;
8132+ int i ;
8133+
8134+ /*
8135+ * Only empty task groups can be destroyed; so we can speculatively
8136+ * check on_list without danger of it being re-added.
8137+ */
8138+ if (!tg -> cfs_rq [cpu ]-> on_list )
8139+ return ;
8140+
8141+ raw_spin_lock_irqsave (& rq -> lock , flags );
8142+ list_del_leaf_cfs_rq (tg -> cfs_rq [i ]);
8143+ raw_spin_unlock_irqrestore (& rq -> lock , flags );
81428144}
81438145#else /* !CONFG_FAIR_GROUP_SCHED */
81448146static inline void free_fair_sched_group (struct task_group * tg )
@@ -8151,10 +8153,6 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
81518153 return 1 ;
81528154}
81538155
8154- static inline void register_fair_sched_group (struct task_group * tg , int cpu )
8155- {
8156- }
8157-
81588156static inline void unregister_fair_sched_group (struct task_group * tg , int cpu )
81598157{
81608158}
@@ -8209,7 +8207,7 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
82098207 if (!rt_se )
82108208 goto err_free_rq ;
82118209
8212- init_tg_rt_entry (tg , rt_rq , rt_se , i , 0 , parent -> rt_se [i ]);
8210+ init_tg_rt_entry (tg , rt_rq , rt_se , i , parent -> rt_se [i ]);
82138211 }
82148212
82158213 return 1 ;
@@ -8219,17 +8217,6 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
82198217err :
82208218 return 0 ;
82218219}
8222-
8223- static inline void register_rt_sched_group (struct task_group * tg , int cpu )
8224- {
8225- list_add_rcu (& tg -> rt_rq [cpu ]-> leaf_rt_rq_list ,
8226- & cpu_rq (cpu )-> leaf_rt_rq_list );
8227- }
8228-
8229- static inline void unregister_rt_sched_group (struct task_group * tg , int cpu )
8230- {
8231- list_del_rcu (& tg -> rt_rq [cpu ]-> leaf_rt_rq_list );
8232- }
82338220#else /* !CONFIG_RT_GROUP_SCHED */
82348221static inline void free_rt_sched_group (struct task_group * tg )
82358222{
@@ -8240,14 +8227,6 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
82408227{
82418228 return 1 ;
82428229}
8243-
8244- static inline void register_rt_sched_group (struct task_group * tg , int cpu )
8245- {
8246- }
8247-
8248- static inline void unregister_rt_sched_group (struct task_group * tg , int cpu )
8249- {
8250- }
82518230#endif /* CONFIG_RT_GROUP_SCHED */
82528231
82538232#ifdef CONFIG_CGROUP_SCHED
@@ -8263,7 +8242,6 @@ struct task_group *sched_create_group(struct task_group *parent)
82638242{
82648243 struct task_group * tg ;
82658244 unsigned long flags ;
8266- int i ;
82678245
82688246 tg = kzalloc (sizeof (* tg ), GFP_KERNEL );
82698247 if (!tg )
@@ -8276,10 +8254,6 @@ struct task_group *sched_create_group(struct task_group *parent)
82768254 goto err ;
82778255
82788256 spin_lock_irqsave (& task_group_lock , flags );
8279- for_each_possible_cpu (i ) {
8280- register_fair_sched_group (tg , i );
8281- register_rt_sched_group (tg , i );
8282- }
82838257 list_add_rcu (& tg -> list , & task_groups );
82848258
82858259 WARN_ON (!parent ); /* root should already exist */
@@ -8309,11 +8283,11 @@ void sched_destroy_group(struct task_group *tg)
83098283 unsigned long flags ;
83108284 int i ;
83118285
8312- spin_lock_irqsave ( & task_group_lock , flags );
8313- for_each_possible_cpu (i ) {
8286+ /* end participation in shares distribution */
8287+ for_each_possible_cpu (i )
83148288 unregister_fair_sched_group (tg , i );
8315- unregister_rt_sched_group ( tg , i );
8316- }
8289+
8290+ spin_lock_irqsave ( & task_group_lock , flags );
83178291 list_del_rcu (& tg -> list );
83188292 list_del_rcu (& tg -> siblings );
83198293 spin_unlock_irqrestore (& task_group_lock , flags );
@@ -8391,7 +8365,6 @@ static DEFINE_MUTEX(shares_mutex);
83918365int sched_group_set_shares (struct task_group * tg , unsigned long shares )
83928366{
83938367 int i ;
8394- unsigned long flags ;
83958368
83968369 /*
83978370 * We can't change the weight of the root cgroup.
@@ -8408,19 +8381,6 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
84088381 if (tg -> shares == shares )
84098382 goto done ;
84108383
8411- spin_lock_irqsave (& task_group_lock , flags );
8412- for_each_possible_cpu (i )
8413- unregister_fair_sched_group (tg , i );
8414- list_del_rcu (& tg -> siblings );
8415- spin_unlock_irqrestore (& task_group_lock , flags );
8416-
8417- /* wait for any ongoing reference to this group to finish */
8418- synchronize_sched ();
8419-
8420- /*
8421- * Now we are free to modify the group's share on each cpu
8422- * w/o tripping rebalance_share or load_balance_fair.
8423- */
84248384 tg -> shares = shares ;
84258385 for_each_possible_cpu (i ) {
84268386 /*
@@ -8429,15 +8389,6 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
84298389 set_se_shares (tg -> se [i ], shares );
84308390 }
84318391
8432- /*
8433- * Enable load balance activity on this group, by inserting it back on
8434- * each cpu's rq->leaf_cfs_rq_list.
8435- */
8436- spin_lock_irqsave (& task_group_lock , flags );
8437- for_each_possible_cpu (i )
8438- register_fair_sched_group (tg , i );
8439- list_add_rcu (& tg -> siblings , & tg -> parent -> children );
8440- spin_unlock_irqrestore (& task_group_lock , flags );
84418392done :
84428393 mutex_unlock (& shares_mutex );
84438394 return 0 ;
0 commit comments