@@ -212,7 +212,7 @@ void __init psi_init(void)
212
212
group_init (& psi_system );
213
213
}
214
214
215
- static bool test_state (unsigned int * tasks , enum psi_states state )
215
+ static bool test_state (unsigned int * tasks , enum psi_states state , bool oncpu )
216
216
{
217
217
switch (state ) {
218
218
case PSI_IO_SOME :
@@ -225,9 +225,9 @@ static bool test_state(unsigned int *tasks, enum psi_states state)
225
225
return unlikely (tasks [NR_MEMSTALL ] &&
226
226
tasks [NR_RUNNING ] == tasks [NR_MEMSTALL_RUNNING ]);
227
227
case PSI_CPU_SOME :
228
- return unlikely (tasks [NR_RUNNING ] > tasks [ NR_ONCPU ] );
228
+ return unlikely (tasks [NR_RUNNING ] > oncpu );
229
229
case PSI_CPU_FULL :
230
- return unlikely (tasks [NR_RUNNING ] && !tasks [ NR_ONCPU ] );
230
+ return unlikely (tasks [NR_RUNNING ] && !oncpu );
231
231
case PSI_NONIDLE :
232
232
return tasks [NR_IOWAIT ] || tasks [NR_MEMSTALL ] ||
233
233
tasks [NR_RUNNING ];
@@ -689,9 +689,9 @@ static void psi_group_change(struct psi_group *group, int cpu,
689
689
bool wake_clock )
690
690
{
691
691
struct psi_group_cpu * groupc ;
692
- u32 state_mask = 0 ;
693
692
unsigned int t , m ;
694
693
enum psi_states s ;
694
+ u32 state_mask ;
695
695
696
696
groupc = per_cpu_ptr (group -> pcpu , cpu );
697
697
@@ -707,17 +707,36 @@ static void psi_group_change(struct psi_group *group, int cpu,
707
707
708
708
record_times (groupc , now );
709
709
710
+ /*
711
+ * Start with TSK_ONCPU, which doesn't have a corresponding
712
+ * task count - it's just a boolean flag directly encoded in
713
+ * the state mask. Clear, set, or carry the current state if
714
+ * no changes are requested.
715
+ */
716
+ if (unlikely (clear & TSK_ONCPU )) {
717
+ state_mask = 0 ;
718
+ clear &= ~TSK_ONCPU ;
719
+ } else if (unlikely (set & TSK_ONCPU )) {
720
+ state_mask = PSI_ONCPU ;
721
+ set &= ~TSK_ONCPU ;
722
+ } else {
723
+ state_mask = groupc -> state_mask & PSI_ONCPU ;
724
+ }
725
+
726
+ /*
727
+ * The rest of the state mask is calculated based on the task
728
+ * counts. Update those first, then construct the mask.
729
+ */
710
730
for (t = 0 , m = clear ; m ; m &= ~(1 << t ), t ++ ) {
711
731
if (!(m & (1 << t )))
712
732
continue ;
713
733
if (groupc -> tasks [t ]) {
714
734
groupc -> tasks [t ]-- ;
715
735
} else if (!psi_bug ) {
716
- printk_deferred (KERN_ERR "psi: task underflow! cpu=%d t=%d tasks=[%u %u %u %u %u ] clear=%x set=%x\n" ,
736
+ printk_deferred (KERN_ERR "psi: task underflow! cpu=%d t=%d tasks=[%u %u %u %u] clear=%x set=%x\n" ,
717
737
cpu , t , groupc -> tasks [0 ],
718
738
groupc -> tasks [1 ], groupc -> tasks [2 ],
719
- groupc -> tasks [3 ], groupc -> tasks [4 ],
720
- clear , set );
739
+ groupc -> tasks [3 ], clear , set );
721
740
psi_bug = 1 ;
722
741
}
723
742
}
@@ -726,9 +745,8 @@ static void psi_group_change(struct psi_group *group, int cpu,
726
745
if (set & (1 << t ))
727
746
groupc -> tasks [t ]++ ;
728
747
729
- /* Calculate state mask representing active states */
730
748
for (s = 0 ; s < NR_PSI_STATES ; s ++ ) {
731
- if (test_state (groupc -> tasks , s ))
749
+ if (test_state (groupc -> tasks , s , state_mask & PSI_ONCPU ))
732
750
state_mask |= (1 << s );
733
751
}
734
752
@@ -740,7 +758,7 @@ static void psi_group_change(struct psi_group *group, int cpu,
740
758
* task in a cgroup is in_memstall, the corresponding groupc
741
759
* on that cpu is in PSI_MEM_FULL state.
742
760
*/
743
- if (unlikely (groupc -> tasks [ NR_ONCPU ] && cpu_curr (cpu )-> in_memstall ))
761
+ if (unlikely (( state_mask & PSI_ONCPU ) && cpu_curr (cpu )-> in_memstall ))
744
762
state_mask |= (1 << PSI_MEM_FULL );
745
763
746
764
groupc -> state_mask = state_mask ;
@@ -828,7 +846,8 @@ void psi_task_switch(struct task_struct *prev, struct task_struct *next,
828
846
*/
829
847
iter = NULL ;
830
848
while ((group = iterate_groups (next , & iter ))) {
831
- if (per_cpu_ptr (group -> pcpu , cpu )-> tasks [NR_ONCPU ]) {
849
+ if (per_cpu_ptr (group -> pcpu , cpu )-> state_mask &
850
+ PSI_ONCPU ) {
832
851
common = group ;
833
852
break ;
834
853
}
0 commit comments