ARMv7-M SMP: Applied the latest changes for ARMv7A-SMP

This commit is contained in:
Masayuki Ishikawa 2016-12-04 06:49:49 -06:00 committed by Gregory Nutt
parent 9c65b0321d
commit 84900298b7
3 changed files with 50 additions and 2 deletions

View File

@ -53,6 +53,7 @@
#include "up_arch.h"
#include "sched/sched.h"
#include "irq/irq.h"
#include "up_internal.h"
/****************************************************************************
@ -319,6 +320,12 @@ static void up_dumpstate(void)
#endif
#ifdef CONFIG_SMP
/* Show the CPU number */
_alert("CPU%d:\n", up_cpu_index());
#endif
/* Then dump the registers (if available) */
up_registerdump();
@ -351,6 +358,12 @@ static void _up_assert(int errorcode)
(void)up_irq_save();
for (; ; )
{
#ifdef CONFIG_SMP
/* Try (again) to stop activity on other CPUs */
(void)spin_trylock(&g_cpu_irqlock);
#endif
#ifdef CONFIG_ARCH_LEDS
board_autoled_on(LED_PANIC);
up_mdelay(250);

View File

@ -165,6 +165,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
#ifdef CONFIG_BUILD_PROTECTED
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
#endif
#ifdef CONFIG_SMP
/* In an SMP configuration, the interrupt disable logic also
* involves spinlocks that are configured per the TCB irqcount
* field. This is logically equivalent to enter_critical_section().
* The matching call to leave_critical_section() will be
* performed in up_sigdeliver().
*/
DEBUGASSERT(tcb->irqcount < INT16_MAX);
tcb->irqcount++;
#endif
/* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
@ -211,6 +224,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
#endif
#ifdef CONFIG_SMP
/* In an SMP configuration, the interrupt disable logic also
* involves spinlocks that are configured per the TCB irqcount
* field. This is logically equivalent to enter_critical_section();
* The matching leave_critical_section will be performed in
* The matching call to leave_critical_section() will be performed
* in up_sigdeliver().
*/
DEBUGASSERT(tcb->irqcount < INT16_MAX);
tcb->irqcount++;
#endif
}
}

View File

@ -124,9 +124,9 @@ void up_sigdeliver(void)
/* Then restore the task interrupt state */
#ifdef CONFIG_ARMV7M_USEBASEPRI
up_irq_restore((uint8_t)regs[REG_BASEPRI]);
leave_critical_section((uint8_t)regs[REG_BASEPRI]);
#else
up_irq_restore((uint16_t)regs[REG_PRIMASK]);
leave_critical_section((uint16_t)regs[REG_PRIMASK]);
#endif
/* Deliver the signal */
@ -136,9 +136,18 @@ void up_sigdeliver(void)
/* Output any debug messages BEFORE restoring errno (because they may
* alter errno), then disable interrupts again and restore the original
* errno that is needed by the user logic (it is probably EINTR).
*
* REVISIT: In SMP mode up_irq_save() probably only disables interrupts
* on the local CPU. We do not want to call enter_critical_section()
* here, however, because we don't want this state to stick after the
* call to up_fullcontextrestore().
*
* I would prefer that all interrupts are disabled when
* up_fullcontextrestore() is called, but that may not be necessary.
*/
sinfo("Resuming\n");
(void)up_irq_save();
rtcb->pterrno = saved_errno;