sched: handle sched lock in interrupt

Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
xuxingliang 2024-07-16 14:59:15 +08:00 committed by Xiang Xiao
parent 755bef6c56
commit 5e2d205e1b

View File

@ -26,6 +26,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <assert.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/nuttx.h> #include <nuttx/nuttx.h>
#include <nuttx/queue.h> #include <nuttx/queue.h>
@ -61,6 +62,7 @@ struct smp_call_data_s
static sq_queue_t g_smp_call_queue[CONFIG_SMP_NCPUS]; static sq_queue_t g_smp_call_queue[CONFIG_SMP_NCPUS];
static struct smp_call_data_s g_smp_call_data; static struct smp_call_data_s g_smp_call_data;
static spinlock_t g_smp_call_lock;
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@ -86,9 +88,9 @@ static void nxsched_smp_call_add(int cpu,
{ {
irqstate_t flags; 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]); 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; FAR sq_entry_t *next;
int cpu = this_cpu(); 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]; 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); 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); 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 (spin_is_locked(&call_data->lock))
{ {
if (--call_data->refcount == 0) if (--call_data->refcount == 0)
@ -157,7 +159,7 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
} }
up_cpu_paused_restore(); up_cpu_paused_restore();
leave_critical_section(flags); spin_unlock_irqrestore(&g_smp_call_lock, flags);
return OK; 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; FAR struct smp_call_data_s *call_data;
int remote_cpus = 0; int remote_cpus;
int ret = OK; int ret = OK;
int i; int i;
/* Cannot wait in interrupt context. */
DEBUGASSERT(!(wait && up_interrupt_context()));
/* Prevent reschedule on another processor */ /* Prevent reschedule on another processor */
if (!up_interrupt_context())
{
sched_lock(); sched_lock();
}
if (CPU_ISSET(this_cpu(), &cpuset)) if (CPU_ISSET(this_cpu(), &cpuset))
{ {
@ -293,6 +302,10 @@ int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func,
} }
out: out:
if (!up_interrupt_context())
{
sched_unlock(); sched_unlock();
}
return ret; return ret;
} }