[Skiboot] [PATCH] core/cpu: parallelise global CPU register setting jobs

Nicholas Piggin npiggin at gmail.com
Tue Jul 3 19:15:14 AEST 2018


On a 176 thread system, before:

[  122.319923233,5] OPAL: Switch to big-endian OS
[  126.317897467,5] OPAL: Switch to little-endian OS

after:

[  212.439299889,5] OPAL: Switch to big-endian OS
[  212.469323643,5] OPAL: Switch to little-endian OS

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 core/cpu.c | 47 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 37 insertions(+), 10 deletions(-)

diff --git a/core/cpu.c b/core/cpu.c
index a8936fab..2f30c582 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -1304,17 +1304,30 @@ static void cpu_change_hid0(void *__req)
 static int64_t cpu_change_all_hid0(struct hid0_change_req *req)
 {
 	struct cpu_thread *cpu;
+	struct cpu_job **jobs;
+
+	jobs = zalloc(sizeof(struct cpu_job *) * cpu_max_pir + 1);
+	assert(jobs);
 
 	for_each_available_cpu(cpu) {
 		if (!cpu_is_thread0(cpu))
 			continue;
-		if (cpu == this_cpu()) {
-			cpu_change_hid0(req);
+		if (cpu == this_cpu())
 			continue;
-		}
-		cpu_wait_job(cpu_queue_job(cpu, "cpu_change_hid0",
-			cpu_change_hid0, req), true);
+		jobs[cpu->pir] = cpu_queue_job(cpu, "cpu_change_hid0",
+						cpu_change_hid0, req);
 	}
+
+	/* this cpu */
+	cpu_change_hid0(req);
+
+	for_each_available_cpu(cpu) {
+		if (jobs[cpu->pir])
+			cpu_wait_job(jobs[cpu->pir], true);
+	}
+
+	free(jobs);
+
 	return OPAL_SUCCESS;
 }
 
@@ -1342,15 +1355,29 @@ static void cpu_cleanup_one(void *param __unused)
 static int64_t cpu_cleanup_all(void)
 {
 	struct cpu_thread *cpu;
+	struct cpu_job **jobs;
+
+	jobs = zalloc(sizeof(struct cpu_job *) * cpu_max_pir + 1);
+	assert(jobs);
 
 	for_each_available_cpu(cpu) {
-		if (cpu == this_cpu()) {
-			cpu_cleanup_one(NULL);
+		if (cpu == this_cpu())
 			continue;
-		}
-		cpu_wait_job(cpu_queue_job(cpu, "cpu_cleanup",
-					   cpu_cleanup_one, NULL), true);
+		jobs[cpu->pir] = cpu_queue_job(cpu, "cpu_cleanup",
+						cpu_cleanup_one, NULL);
+	}
+
+	/* this cpu */
+	cpu_cleanup_one(NULL);
+
+	for_each_available_cpu(cpu) {
+		if (jobs[cpu->pir])
+			cpu_wait_job(jobs[cpu->pir], true);
 	}
+
+	free(jobs);
+
+
 	return OPAL_SUCCESS;
 }
 
-- 
2.17.0



More information about the Skiboot mailing list