sched: irq: Change irq_waitlock() from private to public

Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
This commit is contained in:
Masayuki Ishikawa 2020-11-25 09:53:03 +09:00 committed by Alin Jerpelea
parent 8d0118569c
commit a24905059e
2 changed files with 51 additions and 1 deletions

View File

@ -46,6 +46,9 @@
#ifndef __ASSEMBLY__
# include <stdint.h>
# include <assert.h>
# ifdef CONFIG_SMP
# include <stdbool.h>
# endif
#endif
/* Now include architecture-specific types */
@ -170,6 +173,53 @@ int irqchain_detach(int irq, xcpt_t isr, FAR void *arg);
# define irqchain_detach(irq, isr, arg) irq_detach(irq)
#endif
/****************************************************************************
* Name: irq_waitlock
*
* Description:
* Spin to get g_irq_waitlock, handling a known deadlock condition:
*
* A deadlock may occur if enter_critical_section is called from an
* interrupt handler. Suppose:
*
* - CPUn is in a critical section and has the g_cpu_irqlock spinlock.
* - CPUm takes an interrupt and attempts to enter the critical section.
* - It spins waiting on g_cpu_irqlock with interrupts disabled.
* - CPUn calls up_cpu_pause() to pause operation on CPUm. This will
* issue an inter-CPU interrupt to CPUm
* - But interrupts are disabled on CPUm so the up_cpu_pause() is never
* handled, causing the deadlock.
*
* This same deadlock can occur in the normal tasking case:
*
* - A task on CPUn enters a critical section and has the g_cpu_irqlock
* spinlock.
* - Another task on CPUm attempts to enter the critical section but has
* to wait, spinning to get g_cpu_irqlock with interrupts disabled.
* - The task on CPUn causes a new task to become ready-to-run and the
* scheduler selects CPUm. CPUm is requested to pause via a pause
* interrupt.
* - But the task on CPUm is also attempting to enter the critical
* section. Since it is spinning with interrupts disabled, CPUm cannot
* process the pending pause interrupt, causing the deadlock.
*
* This function detects this deadlock condition while spinning with \
* interrupts disabled.
*
* Input Parameters:
* cpu - The index of CPU that is trying to enter the critical section.
*
* Returned Value:
* True: The g_cpu_irqlock spinlock has been taken.
* False: The g_cpu_irqlock spinlock has not been taken yet, but there is
* a pending pause interrupt request.
*
****************************************************************************/
#ifdef CONFIG_SMP
bool irq_waitlock(int cpu);
#endif
/****************************************************************************
* Name: enter_critical_section
*

View File

@ -105,7 +105,7 @@ volatile uint8_t g_cpu_nestcount[CONFIG_SMP_NCPUS];
****************************************************************************/
#ifdef CONFIG_SMP
static inline bool irq_waitlock(int cpu)
bool irq_waitlock(int cpu)
{
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
FAR struct tcb_s *tcb = current_task(cpu);