Merged in masayuki2009/nuttx.nuttx/fix_up_sigdeliver_for_smp (pull request #1043)
arch: armv7-m: Fix a deadlock in up_sigdeliver() in SMP mode. In previous implementation, up_disable_irq() was called before recovering local context. However, I noticed a deadlock happens in the following situation. For example, if up_sigdevliver() is in progress on CPU0 and CPU1 has called up_cpu_paused to CPU0, hence g_cpu_irqlock has been locked by CPU1, in this case, we would see a deadlock in later call of enter_critical_section() to restore irqcount. To avoid this situation, we need to call enter_critical_section() to break the deadlock. Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com> Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
parent
7715ee71d2
commit
cef90a3865
@ -138,18 +138,28 @@ void up_sigdeliver(void)
|
||||
* 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");
|
||||
|
||||
/* Call enter_critical_section() to disable local interrupts before
|
||||
* restoring local context.
|
||||
*
|
||||
* Here, we should not use up_irq_save() in SMP mode.
|
||||
* For example, if we call up_irq_save() here and another CPU might
|
||||
* have called up_cpu_pause() to this cpu, hence g_cpu_irqlock has
|
||||
* been locked by the cpu, in this case, we would see a deadlock in
|
||||
* later call of enter_critical_section() to restore irqcount.
|
||||
* To avoid this situation, we need to call enter_critical_section().
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
(void)enter_critical_section();
|
||||
#else
|
||||
(void)up_irq_save();
|
||||
#endif
|
||||
|
||||
/* Restore the saved errno value */
|
||||
|
||||
@ -182,7 +192,7 @@ void up_sigdeliver(void)
|
||||
* spinlocks.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(rtcb->irqcount == 0);
|
||||
DEBUGASSERT(rtcb->irqcount == 1);
|
||||
while (rtcb->irqcount < saved_irqcount)
|
||||
{
|
||||
(void)enter_critical_section();
|
||||
|
Loading…
Reference in New Issue
Block a user