[Skiboot] [PATCH 5/6] core/cpu: make cpu idle states simpler
Nicholas Piggin
npiggin at gmail.com
Tue Dec 22 03:10:41 AEDT 2020
in_idle is true for any kind of idle. This is not used anywhere
except for state assertions, but it could be used to remove the
idle_lock and global counter if that becomes a significant
cost.
in_sleep is true for sleep that requires an IPI to wake up.
in_job_sleep is true for sleep that wants an IPI sent after a job is
queued, and implies in_sleep.
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
core/cpu.c | 26 +++++++++++++++++++-------
include/cpu.h | 3 ++-
2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/core/cpu.c b/core/cpu.c
index 05901bf7f..7ccca677a 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -105,7 +105,7 @@ static void cpu_wake(struct cpu_thread *cpu)
{
/* Is it idle ? If not, no need to wake */
sync();
- if (cpu->in_idle)
+ if (cpu->in_job_sleep)
cpu_send_ipi(cpu);
}
@@ -392,7 +392,8 @@ static unsigned int cpu_idle_p8(enum cpu_wake_cause wake_on)
/* Synchronize with wakers */
if (wake_on == cpu_wake_on_job) {
/* Mark ourselves in idle so other CPUs know to send an IPI */
- cpu->in_idle = true;
+ cpu->in_sleep = true;
+ cpu->in_job_sleep = true;
sync();
/* Check for jobs again */
@@ -426,8 +427,8 @@ static unsigned int cpu_idle_p8(enum cpu_wake_cause wake_on)
skip_sleep:
/* Restore */
sync();
- cpu->in_idle = false;
cpu->in_sleep = false;
+ cpu->in_job_sleep = false;
reset_cpu_icp();
return vec;
@@ -448,7 +449,8 @@ static unsigned int cpu_idle_p9(enum cpu_wake_cause wake_on)
/* Synchronize with wakers */
if (wake_on == cpu_wake_on_job) {
/* Mark ourselves in idle so other CPUs know to send an IPI */
- cpu->in_idle = true;
+ cpu->in_sleep = true;
+ cpu->in_job_sleep = true;
sync();
/* Check for jobs again */
@@ -494,8 +496,8 @@ static unsigned int cpu_idle_p9(enum cpu_wake_cause wake_on)
skip_sleep:
/* Restore */
sync();
- cpu->in_idle = false;
cpu->in_sleep = false;
+ cpu->in_job_sleep = false;
return vec;
}
@@ -541,10 +543,15 @@ static int nr_cpus_idle = 0;
static void enter_idle(void)
{
+ struct cpu_thread *cpu = this_cpu();
+
+ assert(!cpu->in_idle);
+
for (;;) {
lock(&idle_lock);
if (!reconfigure_idle) {
nr_cpus_idle++;
+ cpu->in_idle = true;
break;
}
unlock(&idle_lock);
@@ -561,9 +568,14 @@ static void enter_idle(void)
static void exit_idle(void)
{
+ struct cpu_thread *cpu = this_cpu();
+
+ assert(cpu->in_idle);
+
lock(&idle_lock);
assert(nr_cpus_idle > 0);
nr_cpus_idle--;
+ cpu->in_idle = false;
unlock(&idle_lock);
}
@@ -594,12 +606,12 @@ static void reconfigure_idle_start(void)
/*
* Order earlier store to reconfigure_idle=true vs load from
- * cpu->in_sleep and cpu->in_idle.
+ * cpu->in_sleep.
*/
sync();
for_each_available_cpu(cpu) {
- if (cpu->in_sleep || cpu->in_idle)
+ if (cpu->in_sleep)
cpu_send_ipi(cpu);
}
diff --git a/include/cpu.h b/include/cpu.h
index b0c78ce62..1be5cb0d4 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -60,8 +60,9 @@ struct cpu_thread {
bool in_poller;
bool in_reinit;
bool in_fast_sleep;
- bool in_sleep;
bool in_idle;
+ bool in_sleep;
+ bool in_job_sleep;
uint32_t hbrt_spec_wakeup; /* primary only */
uint64_t save_l2_fir_action1;
uint64_t current_token;
--
2.23.0
More information about the Skiboot
mailing list