smp: fix a race when starting / resuming multiple CPUs

cpu_start_fn is global, it's used by the initiator CPU to start or
resume secondary CPUs. However it's possible, that the initiator CPU
goes ahead and starts a second secondary CPU before the first one has
finished using the object. Fix this by creating a local copy of the
global object.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
Guennadi Liakhovetski 2024-01-29 18:13:54 +01:00 committed by Henrik Brix Andersen
parent f3d591815f
commit 09cf3e0910

View file

@ -109,7 +109,7 @@ static void wait_for_start_signal(atomic_t *start_flag)
static inline void smp_init_top(void *arg)
{
struct k_thread dummy_thread;
struct cpu_start_cb *csc = arg;
struct cpu_start_cb csc = arg ? *(struct cpu_start_cb *)arg : (struct cpu_start_cb){0};
/* Let start_cpu() know that this CPU has powered up. */
(void)atomic_set(&ready_flag, 1);
@ -119,7 +119,7 @@ static inline void smp_init_top(void *arg)
*/
wait_for_start_signal(&cpu_start_flag);
if ((csc == NULL) || csc->invoke_sched) {
if ((arg == NULL) || csc.invoke_sched) {
/* Initialize the dummy thread struct so that
* the scheduler can schedule actual threads to run.
*/
@ -127,17 +127,17 @@ static inline void smp_init_top(void *arg)
}
#ifdef CONFIG_SYS_CLOCK_EXISTS
if ((csc == NULL) || csc->reinit_timer) {
if ((arg == NULL) || csc.reinit_timer) {
smp_timer_init();
}
#endif
/* Do additional initialization steps if needed. */
if ((csc != NULL) && (csc->fn != NULL)) {
csc->fn(csc->arg);
if (csc.fn != NULL) {
csc.fn(csc.arg);
}
if ((csc != NULL) && !csc->invoke_sched) {
if ((arg != NULL) && !csc.invoke_sched) {
/* Don't invoke scheduler. */
return;
}