FROMLIST: psi: introduce state_mask to represent stalled psi states
The psi monitoring patches will need to determine the same states as record_times(). To avoid calculating them twice, maintain a state mask that can be consulted cheaply. Do this in a separate patch to keep the churn in the main feature patch at a minimum. This adds 4-byte state_mask member into psi_group_cpu struct which results in its first cacheline-aligned part becoming 52 bytes long. Add explicit values to enumeration element counters that affect psi_group_cpu struct size. Link: http://lkml.kernel.org/r/20190124211518.244221-4-surenb@google.com Signed-off-by: Suren Baghdasaryan <surenb@google.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Dennis Zhou <dennis@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Li Zefan <lizefan@huawei.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> (not upstream yet, latest version published at: https://lore.kernel.org/patchwork/patch/1052414/) Bug: 127712811 Bug: 129157727 Test: lmkd in PSI mode Change-Id: I38a1ca3d5c9e6cc3ba39e88c6a9af29ecdc0df5b Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
@@ -11,7 +11,7 @@ enum psi_task_count {
|
|||||||
NR_IOWAIT,
|
NR_IOWAIT,
|
||||||
NR_MEMSTALL,
|
NR_MEMSTALL,
|
||||||
NR_RUNNING,
|
NR_RUNNING,
|
||||||
NR_PSI_TASK_COUNTS,
|
NR_PSI_TASK_COUNTS = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Task state bitmasks */
|
/* Task state bitmasks */
|
||||||
@@ -24,7 +24,7 @@ enum psi_res {
|
|||||||
PSI_IO,
|
PSI_IO,
|
||||||
PSI_MEM,
|
PSI_MEM,
|
||||||
PSI_CPU,
|
PSI_CPU,
|
||||||
NR_PSI_RESOURCES,
|
NR_PSI_RESOURCES = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -41,7 +41,7 @@ enum psi_states {
|
|||||||
PSI_CPU_SOME,
|
PSI_CPU_SOME,
|
||||||
/* Only per-CPU, to weigh the CPU in the global average: */
|
/* Only per-CPU, to weigh the CPU in the global average: */
|
||||||
PSI_NONIDLE,
|
PSI_NONIDLE,
|
||||||
NR_PSI_STATES,
|
NR_PSI_STATES = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct psi_group_cpu {
|
struct psi_group_cpu {
|
||||||
@@ -53,6 +53,9 @@ struct psi_group_cpu {
|
|||||||
/* States of the tasks belonging to this group */
|
/* States of the tasks belonging to this group */
|
||||||
unsigned int tasks[NR_PSI_TASK_COUNTS];
|
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) */
|
/* Period time sampling buckets for each state of interest (ns) */
|
||||||
u32 times[NR_PSI_STATES];
|
u32 times[NR_PSI_STATES];
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
static void get_recent_times(struct psi_group *group, int cpu, u32 *times)
|
||||||
{
|
{
|
||||||
struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu);
|
struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu);
|
||||||
unsigned int tasks[NR_PSI_TASK_COUNTS];
|
|
||||||
u64 now, state_start;
|
u64 now, state_start;
|
||||||
|
enum psi_states s;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
int s;
|
u32 state_mask;
|
||||||
|
|
||||||
/* Snapshot a coherent view of the CPU state */
|
/* Snapshot a coherent view of the CPU state */
|
||||||
do {
|
do {
|
||||||
seq = read_seqcount_begin(&groupc->seq);
|
seq = read_seqcount_begin(&groupc->seq);
|
||||||
now = cpu_clock(cpu);
|
now = cpu_clock(cpu);
|
||||||
memcpy(times, groupc->times, sizeof(groupc->times));
|
memcpy(times, groupc->times, sizeof(groupc->times));
|
||||||
memcpy(tasks, groupc->tasks, sizeof(groupc->tasks));
|
state_mask = groupc->state_mask;
|
||||||
state_start = groupc->state_start;
|
state_start = groupc->state_start;
|
||||||
} while (read_seqcount_retry(&groupc->seq, seq));
|
} while (read_seqcount_retry(&groupc->seq, seq));
|
||||||
|
|
||||||
@@ -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
|
* (u32) and our reported pressure close to what's
|
||||||
* actually happening.
|
* actually happening.
|
||||||
*/
|
*/
|
||||||
if (test_state(tasks, s))
|
if (state_mask & (1 << s))
|
||||||
times[s] += now - state_start;
|
times[s] += now - state_start;
|
||||||
|
|
||||||
delta = times[s] - groupc->times_prev[s];
|
delta = times[s] - groupc->times_prev[s];
|
||||||
@@ -407,15 +407,15 @@ static void record_times(struct psi_group_cpu *groupc, int cpu,
|
|||||||
delta = now - groupc->state_start;
|
delta = now - groupc->state_start;
|
||||||
groupc->state_start = now;
|
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;
|
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;
|
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;
|
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;
|
groupc->times[PSI_MEM_FULL] += delta;
|
||||||
else if (memstall_tick) {
|
else if (memstall_tick) {
|
||||||
u32 sample;
|
u32 sample;
|
||||||
@@ -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;
|
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;
|
groupc->times[PSI_NONIDLE] += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,6 +448,8 @@ static void psi_group_change(struct psi_group *group, int cpu,
|
|||||||
{
|
{
|
||||||
struct psi_group_cpu *groupc;
|
struct psi_group_cpu *groupc;
|
||||||
unsigned int t, m;
|
unsigned int t, m;
|
||||||
|
enum psi_states s;
|
||||||
|
u32 state_mask = 0;
|
||||||
|
|
||||||
groupc = per_cpu_ptr(group->pcpu, cpu);
|
groupc = per_cpu_ptr(group->pcpu, cpu);
|
||||||
|
|
||||||
@@ -480,6 +482,13 @@ static void psi_group_change(struct psi_group *group, int cpu,
|
|||||||
if (set & (1 << t))
|
if (set & (1 << t))
|
||||||
groupc->tasks[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);
|
write_seqcount_end(&groupc->seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user