diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c b/arch/arm/src/armv7-a/arm_schedulesigaction.c index 89df348ba03..c448a9a8a4d 100644 --- a/arch/arm/src/armv7-a/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c @@ -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 } } diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c b/arch/arm/src/armv7-a/arm_sigdeliver.c index be720a464c3..672648a63a5 100644 --- a/arch/arm/src/armv7-a/arm_sigdeliver.c +++ b/arch/arm/src/armv7-a/arm_sigdeliver.c @@ -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 * * 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;