kernel/smp: Fix bitrot with the way the SMP "start flag" works

Tickless timers mean that k_busy_wait() won't work until after the
timer driver is initialized, which is very early but not as early as
SMP.  No need for it, just spin.

Also the original code used a stack variable for the start flag, which
racily presumed that _arch_start_cpu() would comes back synchronously
with the other CPU fired up and running right now.  The cleaned up smp
bringup API on x86_64 isn't so perky, so it exposed the bug.  The flag
just needs to be static.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2019-02-14 21:04:19 -08:00 committed by Anas Nashif
commit 6ed59bc442

View file

@ -12,6 +12,7 @@
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static atomic_t global_lock; static atomic_t global_lock;
static atomic_t start_flag;
unsigned int z_smp_global_lock(void) unsigned int z_smp_global_lock(void)
{ {
@ -71,9 +72,8 @@ static void smp_init_top(int key, void *arg)
atomic_t *start_flag = arg; atomic_t *start_flag = arg;
/* Wait for the signal to begin scheduling */ /* Wait for the signal to begin scheduling */
do { while (!atomic_get(start_flag)) {
k_busy_wait(100); }
} while (!atomic_get(start_flag));
/* Switch out of a dummy thread. Trick cribbed from the main /* Switch out of a dummy thread. Trick cribbed from the main
* thread init. Should probably unify implementations. * thread init. Should probably unify implementations.
@ -89,12 +89,9 @@ static void smp_init_top(int key, void *arg)
CODE_UNREACHABLE; CODE_UNREACHABLE;
} }
#endif
void smp_init(void) void smp_init(void)
{ {
atomic_t start_flag;
(void)atomic_clear(&start_flag); (void)atomic_clear(&start_flag);
#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1 #if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1
@ -114,3 +111,4 @@ void smp_init(void)
(void)atomic_set(&start_flag, 1); (void)atomic_set(&start_flag, 1);
} }
#endif