arch: remove up_cpu_pause up_cpu_resume up_cpu_paused up_cpu_pausereq

reason:
  To remove the "sync pause" and decouple the critical section from the dependency on enabling interrupts,
  after that we need to further implement "schedlock + spinlock".
changelist
  1 Modify the implementation of critical sections to no longer involve enabling interrupts or handling synchronous pause events.
  2 GIC_SMP_CPUCALL attach to pause handler to remove arch interface up_cpu_paused_restore up_cpu_paused_save
  3 Completely remove up_cpu_pause, up_cpu_resume, up_cpu_paused, and up_cpu_pausereq
  4 change up_cpu_pause_async to up_send_cpu_sgi

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5
2024-07-29 20:47:46 +08:00
committed by Xiang Xiao
parent fc22fb8f53
commit d8cb7759b6
32 changed files with 45 additions and 4243 deletions
+3 -136
View File
@@ -75,96 +75,6 @@ volatile uint8_t g_cpu_nestcount[CONFIG_SMP_NCPUS];
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: irq_waitlock
*
* Description:
* Spin to get g_cpu_irqlock, 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
static inline_function bool irq_waitlock(int cpu)
{
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
FAR struct tcb_s *tcb = current_task(cpu);
/* Notify that we are waiting for a spinlock */
sched_note_spinlock(tcb, &g_cpu_irqlock, NOTE_SPINLOCK_LOCK);
#endif
/* Duplicate the spin_lock() logic from spinlock.c, but adding the check
* for the deadlock condition.
*/
while (!spin_trylock_wo_note(&g_cpu_irqlock))
{
/* Is a pause request pending? */
if (up_cpu_pausereq(cpu))
{
/* Yes.. some other CPU is requesting to pause this CPU!
* Abort the wait and return false.
*/
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
/* Notify that we have aborted the wait for the spinlock */
sched_note_spinlock(tcb, &g_cpu_irqlock, NOTE_SPINLOCK_ABORT);
#endif
return false;
}
}
/* We have g_cpu_irqlock! */
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
/* Notify that we have the spinlock */
sched_note_spinlock(tcb, &g_cpu_irqlock, NOTE_SPINLOCK_LOCKED);
#endif
return true;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -198,7 +108,6 @@ irqstate_t enter_critical_section(void)
* the local CPU.
*/
try_again:
ret = up_irq_save();
/* If called from an interrupt handler, then just take the spinlock.
@@ -259,8 +168,6 @@ try_again:
else
{
int paused = false;
/* Make sure that the g_cpu_irqset was not already set
* by previous logic on this CPU that was executed by the
* interrupt handler. We know that the bit in g_cpu_irqset
@@ -274,43 +181,14 @@ try_again:
* no longer blocked by the critical section).
*/
try_again_in_irq:
if (!irq_waitlock(cpu))
{
/* We are in a deadlock condition due to a pending
* pause request interrupt. Break the deadlock by
* handling the pause request now.
*/
if (!paused)
{
up_cpu_paused_save();
}
DEBUGVERIFY(up_cpu_paused(cpu));
paused = true;
DEBUGASSERT((g_cpu_irqset & (1 << cpu)) == 0);
/* NOTE: Here, this CPU does not hold g_cpu_irqlock,
* so call irq_waitlock(cpu) to acquire g_cpu_irqlock.
*/
goto try_again_in_irq;
}
cpu_irqlock_set(cpu);
spin_lock(&g_cpu_irqlock);
cpu_irqlock_set(cpu);
}
/* In any event, the nesting count is now one */
g_cpu_nestcount[cpu] = 1;
if (paused)
{
up_cpu_paused_restore();
}
DEBUGASSERT(spin_is_locked(&g_cpu_irqlock) &&
(g_cpu_irqset & (1 << cpu)) != 0);
}
@@ -354,18 +232,7 @@ try_again_in_irq:
DEBUGASSERT((g_cpu_irqset & (1 << cpu)) == 0);
if (!irq_waitlock(cpu))
{
/* We are in a deadlock condition due to a pending pause
* request interrupt. Re-enable interrupts on this CPU
* and try again. Briefly re-enabling interrupts should
* be sufficient to permit processing the pending pause
* request.
*/
up_irq_restore(ret);
goto try_again;
}
spin_lock(&g_cpu_irqlock);
/* Then set the lock count to 1.
*