diff options
Diffstat (limited to 'kernel/sched/psi.c')
| -rw-r--r-- | kernel/sched/psi.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index fe24de3fbc93..c3484785b179 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c | |||
| @@ -124,6 +124,7 @@ | |||
| 124 | * sampling of the aggregate task states would be. | 124 | * sampling of the aggregate task states would be. |
| 125 | */ | 125 | */ |
| 126 | 126 | ||
| 127 | #include "../workqueue_internal.h" | ||
| 127 | #include <linux/sched/loadavg.h> | 128 | #include <linux/sched/loadavg.h> |
| 128 | #include <linux/seq_file.h> | 129 | #include <linux/seq_file.h> |
| 129 | #include <linux/proc_fs.h> | 130 | #include <linux/proc_fs.h> |
| @@ -480,9 +481,6 @@ static void psi_group_change(struct psi_group *group, int cpu, | |||
| 480 | groupc->tasks[t]++; | 481 | groupc->tasks[t]++; |
| 481 | 482 | ||
| 482 | write_seqcount_end(&groupc->seq); | 483 | write_seqcount_end(&groupc->seq); |
| 483 | |||
| 484 | if (!delayed_work_pending(&group->clock_work)) | ||
| 485 | schedule_delayed_work(&group->clock_work, PSI_FREQ); | ||
| 486 | } | 484 | } |
| 487 | 485 | ||
| 488 | static struct psi_group *iterate_groups(struct task_struct *task, void **iter) | 486 | static struct psi_group *iterate_groups(struct task_struct *task, void **iter) |
| @@ -513,6 +511,7 @@ void psi_task_change(struct task_struct *task, int clear, int set) | |||
| 513 | { | 511 | { |
| 514 | int cpu = task_cpu(task); | 512 | int cpu = task_cpu(task); |
| 515 | struct psi_group *group; | 513 | struct psi_group *group; |
| 514 | bool wake_clock = true; | ||
| 516 | void *iter = NULL; | 515 | void *iter = NULL; |
| 517 | 516 | ||
| 518 | if (!task->pid) | 517 | if (!task->pid) |
| @@ -530,8 +529,22 @@ void psi_task_change(struct task_struct *task, int clear, int set) | |||
| 530 | task->psi_flags &= ~clear; | 529 | task->psi_flags &= ~clear; |
| 531 | task->psi_flags |= set; | 530 | task->psi_flags |= set; |
| 532 | 531 | ||
| 533 | while ((group = iterate_groups(task, &iter))) | 532 | /* |
| 533 | * Periodic aggregation shuts off if there is a period of no | ||
| 534 | * task changes, so we wake it back up if necessary. However, | ||
| 535 | * don't do this if the task change is the aggregation worker | ||
| 536 | * itself going to sleep, or we'll ping-pong forever. | ||
| 537 | */ | ||
| 538 | if (unlikely((clear & TSK_RUNNING) && | ||
| 539 | (task->flags & PF_WQ_WORKER) && | ||
| 540 | wq_worker_last_func(task) == psi_update_work)) | ||
| 541 | wake_clock = false; | ||
| 542 | |||
| 543 | while ((group = iterate_groups(task, &iter))) { | ||
| 534 | psi_group_change(group, cpu, clear, set); | 544 | psi_group_change(group, cpu, clear, set); |
| 545 | if (wake_clock && !delayed_work_pending(&group->clock_work)) | ||
| 546 | schedule_delayed_work(&group->clock_work, PSI_FREQ); | ||
| 547 | } | ||
| 535 | } | 548 | } |
| 536 | 549 | ||
| 537 | void psi_memstall_tick(struct task_struct *task, int cpu) | 550 | void psi_memstall_tick(struct task_struct *task, int cpu) |
