Loading include/linux/psi_types.h +6 −3 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ enum psi_task_count { NR_IOWAIT, NR_MEMSTALL, NR_RUNNING, NR_PSI_TASK_COUNTS, NR_PSI_TASK_COUNTS = 3, }; /* Task state bitmasks */ Loading @@ -24,7 +24,7 @@ enum psi_res { PSI_IO, PSI_MEM, PSI_CPU, NR_PSI_RESOURCES, NR_PSI_RESOURCES = 3, }; /* Loading @@ -41,7 +41,7 @@ enum psi_states { PSI_CPU_SOME, /* Only per-CPU, to weigh the CPU in the global average: */ PSI_NONIDLE, NR_PSI_STATES, NR_PSI_STATES = 6, }; struct psi_group_cpu { Loading @@ -53,6 +53,9 @@ struct psi_group_cpu { /* States of the tasks belonging to this group */ unsigned int tasks[NR_PSI_TASK_COUNTS]; /* Aggregate pressure state derived from the tasks */ u32 state_mask; /* Period time sampling buckets for each state of interest (ns) */ u32 times[NR_PSI_STATES]; Loading kernel/sched/psi.c +19 −10 Original line number Diff line number Diff line Loading @@ -213,17 +213,17 @@ static bool test_state(unsigned int *tasks, enum psi_states state) static void get_recent_times(struct psi_group *group, int cpu, u32 *times) { struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu); unsigned int tasks[NR_PSI_TASK_COUNTS]; u64 now, state_start; enum psi_states s; unsigned int seq; int s; u32 state_mask; /* Snapshot a coherent view of the CPU state */ do { seq = read_seqcount_begin(&groupc->seq); now = cpu_clock(cpu); memcpy(times, groupc->times, sizeof(groupc->times)); memcpy(tasks, groupc->tasks, sizeof(groupc->tasks)); state_mask = groupc->state_mask; state_start = groupc->state_start; } while (read_seqcount_retry(&groupc->seq, seq)); Loading @@ -239,7 +239,7 @@ static void get_recent_times(struct psi_group *group, int cpu, u32 *times) * (u32) and our reported pressure close to what's * actually happening. */ if (test_state(tasks, s)) if (state_mask & (1 << s)) times[s] += now - state_start; delta = times[s] - groupc->times_prev[s]; Loading Loading @@ -407,15 +407,15 @@ static void record_times(struct psi_group_cpu *groupc, int cpu, delta = now - groupc->state_start; groupc->state_start = now; if (test_state(groupc->tasks, PSI_IO_SOME)) { if (groupc->state_mask & (1 << PSI_IO_SOME)) { groupc->times[PSI_IO_SOME] += delta; if (test_state(groupc->tasks, PSI_IO_FULL)) if (groupc->state_mask & (1 << PSI_IO_FULL)) groupc->times[PSI_IO_FULL] += delta; } if (test_state(groupc->tasks, PSI_MEM_SOME)) { if (groupc->state_mask & (1 << PSI_MEM_SOME)) { groupc->times[PSI_MEM_SOME] += delta; if (test_state(groupc->tasks, PSI_MEM_FULL)) if (groupc->state_mask & (1 << PSI_MEM_FULL)) groupc->times[PSI_MEM_FULL] += delta; else if (memstall_tick) { u32 sample; Loading @@ -436,10 +436,10 @@ static void record_times(struct psi_group_cpu *groupc, int cpu, } } if (test_state(groupc->tasks, PSI_CPU_SOME)) if (groupc->state_mask & (1 << PSI_CPU_SOME)) groupc->times[PSI_CPU_SOME] += delta; if (test_state(groupc->tasks, PSI_NONIDLE)) if (groupc->state_mask & (1 << PSI_NONIDLE)) groupc->times[PSI_NONIDLE] += delta; } Loading @@ -448,6 +448,8 @@ static void psi_group_change(struct psi_group *group, int cpu, { struct psi_group_cpu *groupc; unsigned int t, m; enum psi_states s; u32 state_mask = 0; groupc = per_cpu_ptr(group->pcpu, cpu); Loading Loading @@ -480,6 +482,13 @@ static void psi_group_change(struct psi_group *group, int cpu, if (set & (1 << t)) groupc->tasks[t]++; /* Calculate state mask representing active states */ for (s = 0; s < NR_PSI_STATES; s++) { if (test_state(groupc->tasks, s)) state_mask |= (1 << s); } groupc->state_mask = state_mask; write_seqcount_end(&groupc->seq); } Loading kernel/workqueue.c +10 −0 Original line number Diff line number Diff line Loading @@ -920,6 +920,16 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task) * CONTEXT: * spin_lock_irq(rq->lock) * * This function is called during schedule() when a kworker is going * to sleep. It's used by psi to identify aggregation workers during * dequeuing, to allow periodic aggregation to shut-off when that * worker is the last task in the system or cgroup to go to sleep. * * As this function doesn't involve any workqueue-related locking, it * only returns stable values when called from inside the scheduler's * queuing and dequeuing paths, when @task, which must be a kworker, * is guaranteed to not be processing any works. * * Return: * The last work function %current executed as a worker, NULL if it * hasn't executed any work yet. Loading Loading
include/linux/psi_types.h +6 −3 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ enum psi_task_count { NR_IOWAIT, NR_MEMSTALL, NR_RUNNING, NR_PSI_TASK_COUNTS, NR_PSI_TASK_COUNTS = 3, }; /* Task state bitmasks */ Loading @@ -24,7 +24,7 @@ enum psi_res { PSI_IO, PSI_MEM, PSI_CPU, NR_PSI_RESOURCES, NR_PSI_RESOURCES = 3, }; /* Loading @@ -41,7 +41,7 @@ enum psi_states { PSI_CPU_SOME, /* Only per-CPU, to weigh the CPU in the global average: */ PSI_NONIDLE, NR_PSI_STATES, NR_PSI_STATES = 6, }; struct psi_group_cpu { Loading @@ -53,6 +53,9 @@ struct psi_group_cpu { /* States of the tasks belonging to this group */ unsigned int tasks[NR_PSI_TASK_COUNTS]; /* Aggregate pressure state derived from the tasks */ u32 state_mask; /* Period time sampling buckets for each state of interest (ns) */ u32 times[NR_PSI_STATES]; Loading
kernel/sched/psi.c +19 −10 Original line number Diff line number Diff line Loading @@ -213,17 +213,17 @@ static bool test_state(unsigned int *tasks, enum psi_states state) static void get_recent_times(struct psi_group *group, int cpu, u32 *times) { struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu); unsigned int tasks[NR_PSI_TASK_COUNTS]; u64 now, state_start; enum psi_states s; unsigned int seq; int s; u32 state_mask; /* Snapshot a coherent view of the CPU state */ do { seq = read_seqcount_begin(&groupc->seq); now = cpu_clock(cpu); memcpy(times, groupc->times, sizeof(groupc->times)); memcpy(tasks, groupc->tasks, sizeof(groupc->tasks)); state_mask = groupc->state_mask; state_start = groupc->state_start; } while (read_seqcount_retry(&groupc->seq, seq)); Loading @@ -239,7 +239,7 @@ static void get_recent_times(struct psi_group *group, int cpu, u32 *times) * (u32) and our reported pressure close to what's * actually happening. */ if (test_state(tasks, s)) if (state_mask & (1 << s)) times[s] += now - state_start; delta = times[s] - groupc->times_prev[s]; Loading Loading @@ -407,15 +407,15 @@ static void record_times(struct psi_group_cpu *groupc, int cpu, delta = now - groupc->state_start; groupc->state_start = now; if (test_state(groupc->tasks, PSI_IO_SOME)) { if (groupc->state_mask & (1 << PSI_IO_SOME)) { groupc->times[PSI_IO_SOME] += delta; if (test_state(groupc->tasks, PSI_IO_FULL)) if (groupc->state_mask & (1 << PSI_IO_FULL)) groupc->times[PSI_IO_FULL] += delta; } if (test_state(groupc->tasks, PSI_MEM_SOME)) { if (groupc->state_mask & (1 << PSI_MEM_SOME)) { groupc->times[PSI_MEM_SOME] += delta; if (test_state(groupc->tasks, PSI_MEM_FULL)) if (groupc->state_mask & (1 << PSI_MEM_FULL)) groupc->times[PSI_MEM_FULL] += delta; else if (memstall_tick) { u32 sample; Loading @@ -436,10 +436,10 @@ static void record_times(struct psi_group_cpu *groupc, int cpu, } } if (test_state(groupc->tasks, PSI_CPU_SOME)) if (groupc->state_mask & (1 << PSI_CPU_SOME)) groupc->times[PSI_CPU_SOME] += delta; if (test_state(groupc->tasks, PSI_NONIDLE)) if (groupc->state_mask & (1 << PSI_NONIDLE)) groupc->times[PSI_NONIDLE] += delta; } Loading @@ -448,6 +448,8 @@ static void psi_group_change(struct psi_group *group, int cpu, { struct psi_group_cpu *groupc; unsigned int t, m; enum psi_states s; u32 state_mask = 0; groupc = per_cpu_ptr(group->pcpu, cpu); Loading Loading @@ -480,6 +482,13 @@ static void psi_group_change(struct psi_group *group, int cpu, if (set & (1 << t)) groupc->tasks[t]++; /* Calculate state mask representing active states */ for (s = 0; s < NR_PSI_STATES; s++) { if (test_state(groupc->tasks, s)) state_mask |= (1 << s); } groupc->state_mask = state_mask; write_seqcount_end(&groupc->seq); } Loading
kernel/workqueue.c +10 −0 Original line number Diff line number Diff line Loading @@ -920,6 +920,16 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task) * CONTEXT: * spin_lock_irq(rq->lock) * * This function is called during schedule() when a kworker is going * to sleep. It's used by psi to identify aggregation workers during * dequeuing, to allow periodic aggregation to shut-off when that * worker is the last task in the system or cgroup to go to sleep. * * As this function doesn't involve any workqueue-related locking, it * only returns stable values when called from inside the scheduler's * queuing and dequeuing paths, when @task, which must be a kworker, * is guaranteed to not be processing any works. * * Return: * The last work function %current executed as a worker, NULL if it * hasn't executed any work yet. Loading