mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
sched/walt: allow checking of last halt time against threshold
Support the ability to check whether the current time is within a threshold since the last time the cpu was halted. If it's within that threshold, pass the check. Use that check to catch tasks being enqueued on halted cpus. Change-Id: I1716aefc970fc3dea7474f6321971bf00c3b76f4 Signed-off-by: Stephen Dickey <quic_dickey@quicinc.com>
This commit is contained in:
parent
2b8a21e9a4
commit
59b2ef40cb
|
|
@ -3942,6 +3942,11 @@ static void android_rvh_enqueue_task(void *unused, struct rq *rq, struct task_st
|
|||
WALT_BUG(WALT_BUG_NONCRITICAL, p, "enqueueing on rq=%d comm=%s(%d) affinity=0x%x",
|
||||
cpu_of(rq), p->comm, p->pid, (*(cpumask_bits(p->cpus_ptr))));
|
||||
|
||||
if (cpu_halted(cpu_of(rq)) && !(p->flags & PF_KTHREAD) && !walt_halt_check_last(cpu_of(rq)))
|
||||
WALT_BUG(WALT_BUG_NONCRITICAL, p,
|
||||
"Non Kthread Started on halted cpu_of(rq)=%d comm=%s(%d) affinity=0x%x\n",
|
||||
cpu_of(rq), p->comm, p->pid, (*(cpumask_bits(p->cpus_ptr))));
|
||||
|
||||
wts->prev_on_rq = 1;
|
||||
wts->prev_on_rq_cpu = cpu_of(rq);
|
||||
|
||||
|
|
|
|||
|
|
@ -905,6 +905,7 @@ struct compute_energy_output {
|
|||
unsigned int cluster_first_cpu[MAX_CLUSTERS];
|
||||
};
|
||||
|
||||
bool walt_halt_check_last(int cpu);
|
||||
extern struct cpumask __cpu_halt_mask;
|
||||
#define cpu_halt_mask ((struct cpumask *)&__cpu_halt_mask)
|
||||
#define cpu_halted(cpu) cpumask_test_cpu((cpu), cpu_halt_mask)
|
||||
|
|
|
|||
|
|
@ -15,11 +15,17 @@ struct cpumask __cpu_halt_mask;
|
|||
static DEFINE_MUTEX(halt_lock);
|
||||
|
||||
struct halt_cpu_state {
|
||||
u64 last_halt;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct halt_cpu_state, halt_state);
|
||||
|
||||
/* the amount of time allowed for enqueue operations that happen
|
||||
* just after a halt operation.
|
||||
*/
|
||||
#define WALT_HALT_CHECK_THRESHOLD_NS 400000
|
||||
|
||||
/*
|
||||
* Remove a task from the runqueue and pretend that it's migrating. This
|
||||
* should prevent migrations for the detached task and disallow further
|
||||
|
|
@ -176,6 +182,21 @@ static int cpu_drain_rq(unsigned int cpu)
|
|||
return stop_one_cpu(cpu, drain_rq_cpu_stop, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns true if last halt is within threshold
|
||||
* note: do not take halt_lock, called from atomic context
|
||||
*/
|
||||
bool walt_halt_check_last(int cpu)
|
||||
{
|
||||
u64 last_halt = per_cpu_ptr(&halt_state, cpu)->last_halt;
|
||||
|
||||
/* last_halt is valid, check it against sched_clock */
|
||||
if (last_halt != 0 && sched_clock() - last_halt > WALT_HALT_CHECK_THRESHOLD_NS)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1) add the cpus to the halt mask
|
||||
* 2) migrate tasks off the cpu
|
||||
|
|
@ -186,14 +207,22 @@ static int halt_cpus(struct cpumask *cpus)
|
|||
int cpu;
|
||||
int ret = 0;
|
||||
u64 start_time = sched_clock();
|
||||
struct halt_cpu_state *halt_cpu_state;
|
||||
|
||||
trace_halt_cpus_start(cpus, 1);
|
||||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
|
||||
halt_cpu_state = per_cpu_ptr(&halt_state, cpu);
|
||||
|
||||
/* set the cpu as halted */
|
||||
cpumask_set_cpu(cpu, cpu_halt_mask);
|
||||
|
||||
/* guarantee mask written before updating last_halt */
|
||||
wmb();
|
||||
|
||||
halt_cpu_state->last_halt = start_time;
|
||||
|
||||
/* only drain online cpus */
|
||||
if (cpu_online(cpu)) {
|
||||
/* drain the online CPU */
|
||||
|
|
@ -219,12 +248,19 @@ static int halt_cpus(struct cpumask *cpus)
|
|||
static int start_cpus(struct cpumask *cpus)
|
||||
{
|
||||
u64 start_time = sched_clock();
|
||||
struct halt_cpu_state *halt_cpu_state;
|
||||
int cpu;
|
||||
|
||||
trace_halt_cpus_start(cpus, 0);
|
||||
if (!cpumask_empty(cpus)) {
|
||||
|
||||
/* remove the cpus from the halt mask */
|
||||
cpumask_andnot(cpu_halt_mask, cpu_halt_mask, cpus);
|
||||
for_each_cpu(cpu, cpus) {
|
||||
halt_cpu_state = per_cpu_ptr(&halt_state, cpu);
|
||||
halt_cpu_state->last_halt = 0;
|
||||
|
||||
/* guarantee zero'd last_halt before clearing from the mask */
|
||||
wmb();
|
||||
|
||||
cpumask_clear_cpu(cpu, cpu_halt_mask);
|
||||
}
|
||||
|
||||
trace_halt_cpus(cpus, start_time, 0, 0);
|
||||
|
|
@ -240,9 +276,9 @@ static void update_ref_counts(struct cpumask *cpus, bool halt)
|
|||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
halt_cpu_state = per_cpu_ptr(&halt_state, cpu);
|
||||
if (halt)
|
||||
if (halt) {
|
||||
halt_cpu_state->ref_count++;
|
||||
else {
|
||||
} else {
|
||||
WARN_ON_ONCE(halt_cpu_state->ref_count == 0);
|
||||
halt_cpu_state->ref_count--;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user