@@ -237,9 +237,30 @@ static DEFINE_MUTEX(sched_core_mutex);
237
237
static atomic_t sched_core_count ;
238
238
static struct cpumask sched_core_mask ;
239
239
240
+ static void sched_core_lock (int cpu , unsigned long * flags )
241
+ {
242
+ const struct cpumask * smt_mask = cpu_smt_mask (cpu );
243
+ int t , i = 0 ;
244
+
245
+ local_irq_save (* flags );
246
+ for_each_cpu (t , smt_mask )
247
+ raw_spin_lock_nested (& cpu_rq (t )-> __lock , i ++ );
248
+ }
249
+
250
+ static void sched_core_unlock (int cpu , unsigned long * flags )
251
+ {
252
+ const struct cpumask * smt_mask = cpu_smt_mask (cpu );
253
+ int t ;
254
+
255
+ for_each_cpu (t , smt_mask )
256
+ raw_spin_unlock (& cpu_rq (t )-> __lock );
257
+ local_irq_restore (* flags );
258
+ }
259
+
240
260
static void __sched_core_flip (bool enabled )
241
261
{
242
- int cpu , t , i ;
262
+ unsigned long flags ;
263
+ int cpu , t ;
243
264
244
265
cpus_read_lock ();
245
266
@@ -250,19 +271,12 @@ static void __sched_core_flip(bool enabled)
250
271
for_each_cpu (cpu , & sched_core_mask ) {
251
272
const struct cpumask * smt_mask = cpu_smt_mask (cpu );
252
273
253
- i = 0 ;
254
- local_irq_disable ();
255
- for_each_cpu (t , smt_mask ) {
256
- /* supports up to SMT8 */
257
- raw_spin_lock_nested (& cpu_rq (t )-> __lock , i ++ );
258
- }
274
+ sched_core_lock (cpu , & flags );
259
275
260
276
for_each_cpu (t , smt_mask )
261
277
cpu_rq (t )-> core_enabled = enabled ;
262
278
263
- for_each_cpu (t , smt_mask )
264
- raw_spin_unlock (& cpu_rq (t )-> __lock );
265
- local_irq_enable ();
279
+ sched_core_unlock (cpu , & flags );
266
280
267
281
cpumask_andnot (& sched_core_mask , & sched_core_mask , smt_mask );
268
282
}
@@ -5736,35 +5750,109 @@ void queue_core_balance(struct rq *rq)
5736
5750
queue_balance_callback (rq , & per_cpu (core_balance_head , rq -> cpu ), sched_core_balance );
5737
5751
}
5738
5752
5739
- static inline void sched_core_cpu_starting (unsigned int cpu )
5753
+ static void sched_core_cpu_starting (unsigned int cpu )
5740
5754
{
5741
5755
const struct cpumask * smt_mask = cpu_smt_mask (cpu );
5742
- struct rq * rq , * core_rq = NULL ;
5743
- int i ;
5756
+ struct rq * rq = cpu_rq (cpu ), * core_rq = NULL ;
5757
+ unsigned long flags ;
5758
+ int t ;
5744
5759
5745
- core_rq = cpu_rq (cpu ) -> core ;
5760
+ sched_core_lock (cpu , & flags ) ;
5746
5761
5747
- if (!core_rq ) {
5748
- for_each_cpu (i , smt_mask ) {
5749
- rq = cpu_rq (i );
5750
- if (rq -> core && rq -> core == rq )
5751
- core_rq = rq ;
5762
+ WARN_ON_ONCE (rq -> core != rq );
5763
+
5764
+ /* if we're the first, we'll be our own leader */
5765
+ if (cpumask_weight (smt_mask ) == 1 )
5766
+ goto unlock ;
5767
+
5768
+ /* find the leader */
5769
+ for_each_cpu (t , smt_mask ) {
5770
+ if (t == cpu )
5771
+ continue ;
5772
+ rq = cpu_rq (t );
5773
+ if (rq -> core == rq ) {
5774
+ core_rq = rq ;
5775
+ break ;
5752
5776
}
5777
+ }
5753
5778
5754
- if (!core_rq )
5755
- core_rq = cpu_rq ( cpu ) ;
5779
+ if (WARN_ON_ONCE ( !core_rq )) /* whoopsie */
5780
+ goto unlock ;
5756
5781
5757
- for_each_cpu (i , smt_mask ) {
5758
- rq = cpu_rq (i );
5782
+ /* install and validate core_rq */
5783
+ for_each_cpu (t , smt_mask ) {
5784
+ rq = cpu_rq (t );
5759
5785
5760
- WARN_ON_ONCE ( rq -> core && rq -> core != core_rq );
5786
+ if ( t == cpu )
5761
5787
rq -> core = core_rq ;
5762
- }
5788
+
5789
+ WARN_ON_ONCE (rq -> core != core_rq );
5763
5790
}
5791
+
5792
+ unlock :
5793
+ sched_core_unlock (cpu , & flags );
5764
5794
}
5795
+
5796
+ static void sched_core_cpu_deactivate (unsigned int cpu )
5797
+ {
5798
+ const struct cpumask * smt_mask = cpu_smt_mask (cpu );
5799
+ struct rq * rq = cpu_rq (cpu ), * core_rq = NULL ;
5800
+ unsigned long flags ;
5801
+ int t ;
5802
+
5803
+ sched_core_lock (cpu , & flags );
5804
+
5805
+ /* if we're the last man standing, nothing to do */
5806
+ if (cpumask_weight (smt_mask ) == 1 ) {
5807
+ WARN_ON_ONCE (rq -> core != rq );
5808
+ goto unlock ;
5809
+ }
5810
+
5811
+ /* if we're not the leader, nothing to do */
5812
+ if (rq -> core != rq )
5813
+ goto unlock ;
5814
+
5815
+ /* find a new leader */
5816
+ for_each_cpu (t , smt_mask ) {
5817
+ if (t == cpu )
5818
+ continue ;
5819
+ core_rq = cpu_rq (t );
5820
+ break ;
5821
+ }
5822
+
5823
+ if (WARN_ON_ONCE (!core_rq )) /* impossible */
5824
+ goto unlock ;
5825
+
5826
+ /* copy the shared state to the new leader */
5827
+ core_rq -> core_task_seq = rq -> core_task_seq ;
5828
+ core_rq -> core_pick_seq = rq -> core_pick_seq ;
5829
+ core_rq -> core_cookie = rq -> core_cookie ;
5830
+ core_rq -> core_forceidle = rq -> core_forceidle ;
5831
+ core_rq -> core_forceidle_seq = rq -> core_forceidle_seq ;
5832
+
5833
+ /* install new leader */
5834
+ for_each_cpu (t , smt_mask ) {
5835
+ rq = cpu_rq (t );
5836
+ rq -> core = core_rq ;
5837
+ }
5838
+
5839
+ unlock :
5840
+ sched_core_unlock (cpu , & flags );
5841
+ }
5842
+
5843
+ static inline void sched_core_cpu_dying (unsigned int cpu )
5844
+ {
5845
+ struct rq * rq = cpu_rq (cpu );
5846
+
5847
+ if (rq -> core != rq )
5848
+ rq -> core = rq ;
5849
+ }
5850
+
5765
5851
#else /* !CONFIG_SCHED_CORE */
5766
5852
5767
5853
static inline void sched_core_cpu_starting (unsigned int cpu ) {}
5854
+ static inline void sched_core_cpu_deactivate (unsigned int cpu ) {}
5855
+ static inline void sched_core_cpu_dying (unsigned int cpu ) {}
5768
5856
5769
5857
static struct task_struct *
5770
5858
pick_next_task (struct rq * rq , struct task_struct * prev , struct rq_flags * rf )
@@ -8707,6 +8795,8 @@ int sched_cpu_deactivate(unsigned int cpu)
8707
8795
*/
8708
8796
if (cpumask_weight (cpu_smt_mask (cpu )) == 2 )
8709
8797
static_branch_dec_cpuslocked (& sched_smt_present );
8798
+
8799
+ sched_core_cpu_deactivate (cpu );
8710
8800
#endif
8711
8801
8712
8802
if (!sched_smp_initialized )
@@ -8811,6 +8901,7 @@ int sched_cpu_dying(unsigned int cpu)
8811
8901
calc_load_migrate (rq );
8812
8902
update_max_interval ();
8813
8903
hrtick_clear (rq );
8904
+ sched_core_cpu_dying (cpu );
8814
8905
return 0 ;
8815
8906
}
8816
8907
#endif
@@ -9022,7 +9113,7 @@ void __init sched_init(void)
9022
9113
atomic_set (& rq -> nr_iowait , 0 );
9023
9114
9024
9115
#ifdef CONFIG_SCHED_CORE
9025
- rq -> core = NULL ;
9116
+ rq -> core = rq ;
9026
9117
rq -> core_pick = NULL ;
9027
9118
rq -> core_enabled = 0 ;
9028
9119
rq -> core_tree = RB_ROOT ;
0 commit comments