[Skiboot] [PATCH v3 1/5] cpu: add cpu_queue_job_on_node()
Stewart Smith
stewart at linux.ibm.com
Tue Jul 17 14:58:25 AEST 2018
From: Nicholas Piggin <npiggin at gmail.com>
Add a job scheduling API which will run the job on the requested
chip_id (or return failure).
Includes test harness fixes from Stewart.
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Signed-off-by: Stewart Smith <stewart at linux.ibm.com>
---
core/cpu.c | 84 +++++++++++++++----
core/test/dummy-cpu.h | 40 +++++++++
core/test/run-malloc-speed.c | 7 +-
core/test/run-malloc.c | 7 +-
core/test/run-mem_range_is_reserved.c | 8 +-
core/test/run-mem_region.c | 10 +--
core/test/run-mem_region_init.c | 8 +-
core/test/run-mem_region_next.c | 8 +-
core/test/run-mem_region_release_unused.c | 8 +-
.../run-mem_region_release_unused_noalloc.c | 8 +-
core/test/run-mem_region_reservations.c | 8 +-
core/test/stubs.c | 44 ++++++++++
hdata/test/hdata_to_dt.c | 9 ++
hdata/test/stubs.c | 47 +++++++++++
include/cpu.h | 4 +
15 files changed, 230 insertions(+), 70 deletions(-)
create mode 100644 core/test/dummy-cpu.h
diff --git a/core/cpu.c b/core/cpu.c
index 15eb1324bb31..8c55178a40c3 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -106,7 +106,11 @@ static void cpu_wake(struct cpu_thread *cpu)
}
}
-static struct cpu_thread *cpu_find_job_target(void)
+/*
+ * If chip_id is >= 0, schedule the job on that node.
+ * Otherwise schedule the job anywhere.
+ */
+static struct cpu_thread *cpu_find_job_target(int32_t chip_id)
{
struct cpu_thread *cpu, *best, *me = this_cpu();
uint32_t best_count;
@@ -124,6 +128,8 @@ static struct cpu_thread *cpu_find_job_target(void)
/* First we scan all available primary threads
*/
for_each_available_cpu(cpu) {
+ if (chip_id >= 0 && cpu->chip_id != chip_id)
+ continue;
if (cpu == me || !cpu_is_thread0(cpu) || cpu->job_has_no_return)
continue;
if (cpu->job_count)
@@ -143,6 +149,8 @@ static struct cpu_thread *cpu_find_job_target(void)
best = NULL;
best_count = -1u;
for_each_available_cpu(cpu) {
+ if (chip_id >= 0 && cpu->chip_id != chip_id)
+ continue;
if (cpu == me || cpu->job_has_no_return)
continue;
if (!best || cpu->job_count < best_count) {
@@ -167,6 +175,26 @@ static struct cpu_thread *cpu_find_job_target(void)
return NULL;
}
+/* job_lock is held, returns with it released */
+static void queue_job_on_cpu(struct cpu_thread *cpu, struct cpu_job *job)
+{
+ /* That's bad, the job will never run */
+ if (cpu->job_has_no_return) {
+ prlog(PR_WARNING, "WARNING ! Job %s scheduled on CPU 0x%x"
+ " which has a no-return job on its queue !\n",
+ job->name, cpu->pir);
+ backtrace();
+ }
+ list_add_tail(&cpu->job_queue, &job->link);
+ if (job->no_return)
+ cpu->job_has_no_return = true;
+ else
+ cpu->job_count++;
+ if (pm_enabled)
+ cpu_wake(cpu);
+ unlock(&cpu->job_lock);
+}
+
struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
const char *name,
void (*func)(void *data), void *data,
@@ -196,7 +224,7 @@ struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
/* Pick a candidate. Returns with target queue locked */
if (cpu == NULL)
- cpu = cpu_find_job_target();
+ cpu = cpu_find_job_target(-1);
else if (cpu != this_cpu())
lock(&cpu->job_lock);
else
@@ -211,21 +239,45 @@ struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
return job;
}
- /* That's bad, the job will never run */
- if (cpu->job_has_no_return) {
- prlog(PR_WARNING, "WARNING ! Job %s scheduled on CPU 0x%x"
- " which has a no-return job on its queue !\n",
- job->name, cpu->pir);
- backtrace();
+ queue_job_on_cpu(cpu, job);
+
+ return job;
+}
+
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data)
+{
+ struct cpu_thread *cpu;
+ struct cpu_job *job;
+
+ job = zalloc(sizeof(struct cpu_job));
+ if (!job)
+ return NULL;
+ job->func = func;
+ job->data = data;
+ job->name = name;
+ job->complete = false;
+ job->no_return = false;
+
+ /* Pick a candidate. Returns with target queue locked */
+ cpu = cpu_find_job_target(chip_id);
+
+ /* Can't be scheduled... */
+ if (cpu == NULL) {
+ cpu = this_cpu();
+ if (cpu->chip_id == chip_id) {
+ /* Run it now if we're the right node. */
+ func(data);
+ job->complete = true;
+ return job;
+ }
+ /* Otherwise fail. */
+ free(job);
+ return NULL;
}
- list_add_tail(&cpu->job_queue, &job->link);
- if (no_return)
- cpu->job_has_no_return = true;
- else
- cpu->job_count++;
- if (pm_enabled)
- cpu_wake(cpu);
- unlock(&cpu->job_lock);
+
+ queue_job_on_cpu(cpu, job);
return job;
}
diff --git a/core/test/dummy-cpu.h b/core/test/dummy-cpu.h
new file mode 100644
index 000000000000..46f180cde1e8
--- /dev/null
+++ b/core/test/dummy-cpu.h
@@ -0,0 +1,40 @@
+/* Copyright 2013-2018 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* A dummy cpu.h for tests.
+ * We don't want to include the real skiboot cpu.h, it's PPC-specific
+ */
+
+#ifndef __CPU_H
+#define __CPU_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+static unsigned int cpu_max_pir = 1;
+struct cpu_thread {
+ unsigned int chip_id;
+};
+struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ const char *name,
+ void (*func)(void *data), void *data,
+ bool no_return);
+void cpu_wait_job(struct cpu_job *job, bool free_it);
+void cpu_process_local_jobs(void);
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data);
+#endif /* __CPU_H */
diff --git a/core/test/run-malloc-speed.c b/core/test/run-malloc-speed.c
index d842bd6432c4..8ecef3a09f24 100644
--- a/core/test/run-malloc-speed.c
+++ b/core/test/run-malloc-speed.c
@@ -17,12 +17,7 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/run-malloc.c b/core/test/run-malloc.c
index 2feaacb95974..0204e77d6326 100644
--- a/core/test/run-malloc.c
+++ b/core/test/run-malloc.c
@@ -18,12 +18,7 @@
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/run-mem_range_is_reserved.c b/core/test/run-mem_range_is_reserved.c
index 37f7db3f744c..f44f1c2db6fd 100644
--- a/core/test/run-mem_range_is_reserved.c
+++ b/core/test/run-mem_range_is_reserved.c
@@ -17,12 +17,8 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/run-mem_region.c b/core/test/run-mem_region.c
index f2506d65f19a..1fd20937e12f 100644
--- a/core/test/run-mem_region.c
+++ b/core/test/run-mem_region.c
@@ -15,14 +15,12 @@
*/
#include <config.h>
+#include <stdbool.h>
+#include <stdint.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
#include <string.h>
diff --git a/core/test/run-mem_region_init.c b/core/test/run-mem_region_init.c
index f1028da32703..f70d70f85280 100644
--- a/core/test/run-mem_region_init.c
+++ b/core/test/run-mem_region_init.c
@@ -17,12 +17,8 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/run-mem_region_next.c b/core/test/run-mem_region_next.c
index 72d02a981a6e..fec5df8f7c13 100644
--- a/core/test/run-mem_region_next.c
+++ b/core/test/run-mem_region_next.c
@@ -17,12 +17,8 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
#include <string.h>
diff --git a/core/test/run-mem_region_release_unused.c b/core/test/run-mem_region_release_unused.c
index fdd273a7f55b..4fe62ca5dc39 100644
--- a/core/test/run-mem_region_release_unused.c
+++ b/core/test/run-mem_region_release_unused.c
@@ -17,12 +17,8 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/run-mem_region_release_unused_noalloc.c b/core/test/run-mem_region_release_unused_noalloc.c
index 6ae79591f08e..fe571350d957 100644
--- a/core/test/run-mem_region_release_unused_noalloc.c
+++ b/core/test/run-mem_region_release_unused_noalloc.c
@@ -17,12 +17,8 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/run-mem_region_reservations.c b/core/test/run-mem_region_reservations.c
index ae885829645f..b0e484740ff0 100644
--- a/core/test/run-mem_region_reservations.c
+++ b/core/test/run-mem_region_reservations.c
@@ -17,12 +17,8 @@
#include <config.h>
#define BITS_PER_LONG (sizeof(long) * 8)
-/* Don't include this, it's PPC-specific */
-#define __CPU_H
-static unsigned int cpu_max_pir = 1;
-struct cpu_thread {
- unsigned int chip_id;
-};
+
+#include "dummy-cpu.h"
#include <stdlib.h>
diff --git a/core/test/stubs.c b/core/test/stubs.c
index 39ff18d8f103..939e3dc7950b 100644
--- a/core/test/stubs.c
+++ b/core/test/stubs.c
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <stdint.h>
#include "../../ccan/list/list.c"
@@ -41,6 +42,49 @@ static void stub_function(void)
abort();
}
+struct cpu_thread;
+
+struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ const char *name,
+ void (*func)(void *data), void *data,
+ bool no_return);
+void cpu_wait_job(struct cpu_job *job, bool free_it);
+void cpu_process_local_jobs(void);
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data);
+
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data)
+{
+ (void)chip_id;
+ return __cpu_queue_job(NULL, name, func, data, false);
+}
+
+struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ const char *name,
+ void (*func)(void *data), void *data,
+ bool no_return)
+{
+ (void)cpu;
+ (void)name;
+ (func)(data);
+ (void)no_return;
+ return NULL;
+}
+
+void cpu_wait_job(struct cpu_job *job, bool free_it)
+{
+ (void)job;
+ (void)free_it;
+ return;
+}
+
+void cpu_process_local_jobs(void)
+{
+}
+
#define STUB(fnname) \
void fnname(void) __attribute__((weak, alias ("stub_function")))
diff --git a/hdata/test/hdata_to_dt.c b/hdata/test/hdata_to_dt.c
index 8c61b4f62a48..bd11fb0b40e7 100644
--- a/hdata/test/hdata_to_dt.c
+++ b/hdata/test/hdata_to_dt.c
@@ -83,6 +83,15 @@ struct cpu_thread {
uint32_t pir;
uint32_t chip_id;
};
+struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ const char *name,
+ void (*func)(void *data), void *data,
+ bool no_return);
+void cpu_wait_job(struct cpu_job *job, bool free_it);
+void cpu_process_local_jobs(void);
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data);
struct cpu_thread __boot_cpu, *boot_cpu = &__boot_cpu;
static unsigned long fake_pvr = PVR_P7;
diff --git a/hdata/test/stubs.c b/hdata/test/stubs.c
index 592257051bd2..f7b1da105e0e 100644
--- a/hdata/test/stubs.c
+++ b/hdata/test/stubs.c
@@ -18,6 +18,7 @@
#include <stdarg.h>
#include <string.h>
#include <malloc.h>
+#include <stdint.h>
#include <compiler.h>
@@ -84,6 +85,52 @@ void *__zalloc(size_t bytes, const char *location)
return p;
}
+struct cpu_thread;
+
+struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ const char *name,
+ void (*func)(void *data), void *data,
+ bool no_return);
+
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data);
+
+struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data)
+{
+ (void)chip_id;
+ return __cpu_queue_job(NULL, name, func, data, false);
+}
+
+struct cpu_job *__cpu_queue_job(struct cpu_thread *cpu,
+ const char *name,
+ void (*func)(void *data), void *data,
+ bool no_return)
+{
+ (void)cpu;
+ (void)name;
+ (func)(data);
+ (void)no_return;
+ return NULL;
+}
+
+void cpu_wait_job(struct cpu_job *job, bool free_it);
+
+void cpu_wait_job(struct cpu_job *job, bool free_it)
+{
+ (void)job;
+ (void)free_it;
+ return;
+}
+
+void cpu_process_local_jobs(void);
+
+void cpu_process_local_jobs(void)
+{
+}
+
/* Add any stub functions required for linking here. */
static void stub_function(void)
{
diff --git a/include/cpu.h b/include/cpu.h
index 2ca59b9648fa..ae3185723673 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -280,6 +280,10 @@ static inline struct cpu_job *cpu_queue_job(struct cpu_thread *cpu,
return __cpu_queue_job(cpu, name, func, data, false);
}
+extern struct cpu_job *cpu_queue_job_on_node(uint32_t chip_id,
+ const char *name,
+ void (*func)(void *data), void *data);
+
/* Poll job status, returns true if completed */
extern bool cpu_poll_job(struct cpu_job *job);
--
2.17.1
More information about the Skiboot
mailing list