arch/: Relasted to last big change to force interrupts to be disabled. In the SMP case, we still must call leave_critical_section() at least once in order to compensate for the fact that the irqcount was incremented in up_schedsigaction().

This commit is contained in:
Gregory Nutt
2018-06-06 17:03:42 -06:00
parent 5b96a26c1b
commit a581d7c2e3
7 changed files with 68 additions and 7 deletions
+6 -2
View File
@@ -121,7 +121,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
if (!CURRENT_REGS) if (!CURRENT_REGS)
{ {
/* In this case just deliver the signal now. */ /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb); sigdeliver(tcb);
} }
@@ -227,7 +229,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
if (cpu == me && !CURRENT_REGS) if (cpu == me && !CURRENT_REGS)
{ {
/* In this case just deliver the signal now. */ /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb); sigdeliver(tcb);
} }
+15
View File
@@ -101,9 +101,24 @@ void up_sigdeliver(void)
sigdeliver = rtcb->xcp.sigdeliver; sigdeliver = rtcb->xcp.sigdeliver;
rtcb->xcp.sigdeliver = NULL; rtcb->xcp.sigdeliver = NULL;
#ifdef CONFIG_SMP
/* In the SMP case, up_schedule_sigaction(0) will have incremented
* 'irqcount' in order to force us into a critical section. At a minimum,
* we must call leave_critical_section() at least once in order to
* compensate for that.
*/
leave_critical_section(regs[REG_CPSR]);
#endif /* CONFIG_SMP */
#ifndef CONFIG_SUPPRESS_INTERRUPTS #ifndef CONFIG_SUPPRESS_INTERRUPTS
/* Then make sure that interrupts are enabled. Signal handlers must always /* Then make sure that interrupts are enabled. Signal handlers must always
* run with interrupts enabled. * run with interrupts enabled.
*
* REVISIT: 'irqcount' could still be greater than zero in the SMP case.
* This would be an issue if the signal handler were to suspend because
* the critical section would be re-established when the signal handler
* resumes.
*/ */
up_irq_enable(); up_irq_enable();
+6 -2
View File
@@ -123,7 +123,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
if (!CURRENT_REGS) if (!CURRENT_REGS)
{ {
/* In this case just deliver the signal now. */ /* In this case just deliver the signal now.
* REVISIT: Signal handle will run in a critical section!
*/
sigdeliver(tcb); sigdeliver(tcb);
} }
@@ -255,7 +257,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
if (cpu == me && !CURRENT_REGS) if (cpu == me && !CURRENT_REGS)
{ {
/* In this case just deliver the signal now. */ /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb); sigdeliver(tcb);
} }
+19
View File
@@ -110,9 +110,28 @@ void up_sigdeliver(void)
sigdeliver = (sig_deliver_t)rtcb->xcp.sigdeliver; sigdeliver = (sig_deliver_t)rtcb->xcp.sigdeliver;
rtcb->xcp.sigdeliver = NULL; rtcb->xcp.sigdeliver = NULL;
#ifdef CONFIG_SMP
/* In the SMP case, up_schedule_sigaction(0) will have incremented
* 'irqcount' in order to force us into a critical section. At a minimum,
* we must call leave_critical_section() at least once in order to
* compensate for that.
*/
#ifdef CONFIG_ARMV7M_USEBASEPRI
leave_critical_section((uint8_t)regs[REG_BASEPRI]);
#else
leave_critical_section((uint16_t)regs[REG_PRIMASK]);
#endif
#endif /* CONFIG_SMP */
#ifndef CONFIG_SUPPRESS_INTERRUPTS #ifndef CONFIG_SUPPRESS_INTERRUPTS
/* Then make sure that interrupts are enabled. Signal handlers must always /* Then make sure that interrupts are enabled. Signal handlers must always
* run with interrupts enabled. * run with interrupts enabled.
*
* REVISIT: 'irqcount' could still be greater than zero in the SMP case.
* This would be an issue if the signal handler were to suspend because
* the critical section would be re-established when the signal handler
* resumes.
*/ */
up_irq_enable(); up_irq_enable();
@@ -119,7 +119,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
if (!CURRENT_REGS) if (!CURRENT_REGS)
{ {
/* In this case just deliver the signal now. */ /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb); sigdeliver(tcb);
} }
@@ -235,7 +237,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
if (cpu == me && !CURRENT_REGS) if (cpu == me && !CURRENT_REGS)
{ {
/* In this case just deliver the signal now. */ /* In this case just deliver the signal now.
* REVISIT: Signal handler will run in a critical section!
*/
sigdeliver(tcb); sigdeliver(tcb);
} }
@@ -100,9 +100,24 @@ void xtensa_sig_deliver(void)
sigdeliver = rtcb->xcp.sigdeliver; sigdeliver = rtcb->xcp.sigdeliver;
rtcb->xcp.sigdeliver = NULL; rtcb->xcp.sigdeliver = NULL;
#ifdef CONFIG_SMP
/* In the SMP case, up_schedule_sigaction(0) will have incremented
* 'irqcount' in order to force us into a critical section. At a minimum,
* we must call leave_critical_section() at least once in order to
* compensate for that.
*/
leave_critical_section((regs[REG_PS]));
#endif /* CONFIG_SMP */
#ifndef CONFIG_SUPPRESS_INTERRUPTS #ifndef CONFIG_SUPPRESS_INTERRUPTS
/* Then make sure that interrupts are enabled. Signal handlers must always /* Then make sure that interrupts are enabled. Signal handlers must always
* run with interrupts enabled. * run with interrupts enabled.
*
* REVISIT: 'irqcount' could still be greater than zero in the SMP case.
* This would be an issue if the signal handler were to suspend because
* the critical section would be re-established when the signal handler
* resumes.
*/ */
up_irq_enable(); up_irq_enable();
+1 -1
View File
@@ -615,7 +615,7 @@ struct tcb_s
uint16_t flags; /* Misc. general status flags */ uint16_t flags; /* Misc. general status flags */
int16_t lockcount; /* 0=preemptable (not-locked) */ int16_t lockcount; /* 0=preemptable (not-locked) */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
int16_t irqcount; /* 0=interrupts enabled */ int16_t irqcount; /* 0=Not in critical section */
#endif #endif
#ifdef CONFIG_CANCELLATION_POINTS #ifdef CONFIG_CANCELLATION_POINTS
int16_t cpcount; /* Nested cancellation point count */ int16_t cpcount; /* Nested cancellation point count */