ARMv7-A SMP: Add a little logic to signal handling.

This commit is contained in:
Gregory Nutt 2016-11-24 11:45:05 -06:00
parent eb9f8074c0
commit f77dcdf323
2 changed files with 34 additions and 3 deletions

View File

@ -153,6 +153,18 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
#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.
*/
@ -183,6 +195,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
#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

@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-a/arm_sigdeliver.c
*
* Copyright (C) 2013, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2013, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -103,18 +103,24 @@ void up_sigdeliver(void)
/* Then restore the task interrupt state */
up_irq_restore(regs[REG_CPSR]);
leave_critical_section(regs[REG_CPSR]);
/* Deliver the signals */
/* Deliver the signal */
sigdeliver(rtcb);
/* 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().
*/
sinfo("Resuming\n");
(void)up_irq_save();
rtcb->pterrno = saved_errno;