smp: add a Kconfig option to delay booting secondary CPUs
Usually Zephyr boots all secondary CPUs as a part of system boot. Some applications however need an ability to boot on the main CPU only and enable secondary CPUs selectively at run-time. Add a Kconfig option to support this behaviour. When booting CPUs on demand applications also need helpers to initialise a dummy thread and begin threaded execution on those CPUs, add two such helpers. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
parent
a871f0be49
commit
8d07b7751a
3 changed files with 33 additions and 4 deletions
|
@ -5553,6 +5553,12 @@ extern void z_init_static_threads(void);
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
extern bool z_is_thread_essential(void);
|
extern bool z_is_thread_essential(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
void z_smp_thread_init(void *arg, struct k_thread *thread);
|
||||||
|
void z_smp_thread_swap(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -785,6 +785,14 @@ config SMP
|
||||||
When true, kernel will be built with SMP support, allowing
|
When true, kernel will be built with SMP support, allowing
|
||||||
more than one CPU to schedule Zephyr tasks at a time.
|
more than one CPU to schedule Zephyr tasks at a time.
|
||||||
|
|
||||||
|
config SMP_BOOT_DELAY
|
||||||
|
bool "Delay booting secondary cores"
|
||||||
|
depends on SMP
|
||||||
|
help
|
||||||
|
By default Zephyr will boot all available CPUs during start up.
|
||||||
|
Select this option to skip this and allow architecture code boot
|
||||||
|
secondary CPUs at a later time.
|
||||||
|
|
||||||
config MP_NUM_CPUS
|
config MP_NUM_CPUS
|
||||||
int "Number of CPUs/cores"
|
int "Number of CPUs/cores"
|
||||||
default 1
|
default 1
|
||||||
|
|
23
kernel/smp.c
23
kernel/smp.c
|
@ -50,28 +50,43 @@ void z_smp_release_global_lock(struct k_thread *thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_MP_NUM_CPUS > 1
|
#if CONFIG_MP_NUM_CPUS > 1
|
||||||
static FUNC_NORETURN void smp_init_top(void *arg)
|
|
||||||
|
void z_smp_thread_init(void *arg, struct k_thread *thread)
|
||||||
{
|
{
|
||||||
atomic_t *cpu_start_flag = arg;
|
atomic_t *cpu_start_flag = arg;
|
||||||
struct k_thread dummy_thread;
|
|
||||||
|
|
||||||
/* Wait for the signal to begin scheduling */
|
/* Wait for the signal to begin scheduling */
|
||||||
while (!atomic_get(cpu_start_flag)) {
|
while (!atomic_get(cpu_start_flag)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
z_dummy_thread_init(&dummy_thread);
|
z_dummy_thread_init(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void z_smp_thread_swap(void)
|
||||||
|
{
|
||||||
|
z_swap_unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_SMP_BOOT_DELAY
|
||||||
|
static FUNC_NORETURN void smp_init_top(void *arg)
|
||||||
|
{
|
||||||
|
struct k_thread dummy_thread;
|
||||||
|
|
||||||
|
z_smp_thread_init(arg, &dummy_thread);
|
||||||
smp_timer_init();
|
smp_timer_init();
|
||||||
|
|
||||||
z_swap_unlocked();
|
z_swap_unlocked();
|
||||||
|
|
||||||
CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
|
CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
void z_smp_init(void)
|
void z_smp_init(void)
|
||||||
{
|
{
|
||||||
(void)atomic_clear(&start_flag);
|
(void)atomic_clear(&start_flag);
|
||||||
|
|
||||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 1)
|
#if CONFIG_MP_NUM_CPUS > 1 && !defined(CONFIG_SMP_BOOT_DELAY)
|
||||||
for (int i = 1; i < CONFIG_MP_NUM_CPUS; i++) {
|
for (int i = 1; i < CONFIG_MP_NUM_CPUS; i++) {
|
||||||
arch_start_cpu(i, z_interrupt_stacks[i], CONFIG_ISR_STACK_SIZE,
|
arch_start_cpu(i, z_interrupt_stacks[i], CONFIG_ISR_STACK_SIZE,
|
||||||
smp_init_top, &start_flag);
|
smp_init_top, &start_flag);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue