diff --git a/sched/sched/sched_smp.c b/sched/sched/sched_smp.c index 94aab39130..af6c88a4e5 100644 --- a/sched/sched/sched_smp.c +++ b/sched/sched/sched_smp.c @@ -26,6 +26,7 @@ #include +#include #include #include #include @@ -61,6 +62,7 @@ struct smp_call_data_s static sq_queue_t g_smp_call_queue[CONFIG_SMP_NCPUS]; static struct smp_call_data_s g_smp_call_data; +static spinlock_t g_smp_call_lock; /**************************************************************************** * Private Functions @@ -86,9 +88,9 @@ static void nxsched_smp_call_add(int cpu, { irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_smp_call_lock); sq_addlast(&call_data->node[cpu], &g_smp_call_queue[cpu]); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_smp_call_lock, flags); } /**************************************************************************** @@ -119,7 +121,7 @@ int nxsched_smp_call_handler(int irq, FAR void *context, FAR sq_entry_t *next; int cpu = this_cpu(); - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&g_smp_call_lock); call_queue = &g_smp_call_queue[cpu]; @@ -132,11 +134,11 @@ int nxsched_smp_call_handler(int irq, FAR void *context, sq_rem(&call_data->node[cpu], call_queue); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_smp_call_lock, flags); ret = call_data->func(call_data->arg); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_smp_call_lock); if (spin_is_locked(&call_data->lock)) { if (--call_data->refcount == 0) @@ -157,7 +159,7 @@ int nxsched_smp_call_handler(int irq, FAR void *context, } up_cpu_paused_restore(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_smp_call_lock, flags); return OK; } @@ -219,13 +221,20 @@ int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func, }; FAR struct smp_call_data_s *call_data; - int remote_cpus = 0; + int remote_cpus; int ret = OK; int i; + /* Cannot wait in interrupt context. */ + + DEBUGASSERT(!(wait && up_interrupt_context())); + /* Prevent reschedule on another processor */ - sched_lock(); + if (!up_interrupt_context()) + { + sched_lock(); + } if (CPU_ISSET(this_cpu(), &cpuset)) { @@ -293,6 +302,10 @@ int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func, } out: - sched_unlock(); + if (!up_interrupt_context()) + { + sched_unlock(); + } + return ret; }