diff --git a/arch/arm/src/arm/arm_doirq.c b/arch/arm/src/arm/arm_doirq.c index 9340eafb027..6cc7da46bde 100644 --- a/arch/arm/src/arm/arm_doirq.c +++ b/arch/arm/src/arm/arm_doirq.c @@ -58,6 +58,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS PANIC(); @@ -71,6 +73,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) */ up_set_current_regs(regs); + tcb->xcp.regs = regs; /* Acknowledge the interrupt */ @@ -79,6 +82,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); /* Check for a context switch. If a context switch occurred, then * current_regs will have a different value than it did on entry. If an @@ -87,7 +91,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * returning from the interrupt. */ - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -104,9 +108,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * crashes. */ - g_running_tasks[this_cpu()] = this_task(); + g_running_tasks[this_cpu()] = tcb; - regs = up_current_regs(); + regs = tcb->xcp.regs; } /* Set current_regs to NULL to indicate that we are no longer in an diff --git a/arch/arm/src/arm/arm_schedulesigaction.c b/arch/arm/src/arm/arm_schedulesigaction.c index d141a33a00a..a0a4017bf42 100644 --- a/arch/arm/src/arm/arm_schedulesigaction.c +++ b/arch/arm/src/arm/arm_schedulesigaction.c @@ -89,70 +89,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * being delivered to the currently executing task. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb == this_task()) + if (tcb == this_task() && !up_interrupt_context()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT; -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } /* Otherwise, we are (1) signaling a task is not running diff --git a/arch/arm/src/arm/arm_syscall.c b/arch/arm/src/arm/arm_syscall.c index 867d33536c9..be95d916ffe 100644 --- a/arch/arm/src/arm/arm_syscall.c +++ b/arch/arm/src/arm/arm_syscall.c @@ -54,7 +54,7 @@ uint32_t *arm_syscall(uint32_t *regs) { - struct tcb_s *tcb; + struct tcb_s *tcb = this_task(); uint32_t cmd; int cpu; @@ -66,6 +66,7 @@ uint32_t *arm_syscall(uint32_t *regs) * current_regs is also used to manage interrupt level context switches. */ + tcb->xcp.regs = regs; up_set_current_regs(regs); /* The SYSCALL command is in R0 on entry. Parameters follow in R1..R7 */ @@ -94,7 +95,7 @@ uint32_t *arm_syscall(uint32_t *regs) * set will determine the restored context. */ - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; DEBUGASSERT(up_current_regs()); } break; @@ -133,15 +134,9 @@ uint32_t *arm_syscall(uint32_t *regs) break; } -#ifdef CONFIG_ARCH_ADDRENV - /* Check for a context switch. If a context switch occurred, then - * current_regs will have a different value than it did on entry. If an - * interrupt level context switch has occurred, then establish the correct - * address environment before returning from the interrupt. - */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { +#ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, * MMU flushed) and set up the address environment for the new @@ -149,13 +144,8 @@ uint32_t *arm_syscall(uint32_t *regs) */ addrenv_switch(NULL); - } #endif - /* Restore the cpu lock */ - - if (regs != up_current_regs()) - { /* Record the new "running" task. g_running_tasks[] is only used by * assertion logic for reporting crashes. */ @@ -181,5 +171,5 @@ uint32_t *arm_syscall(uint32_t *regs) * SYS_context_switch system call. */ - return regs; + return tcb->xcp.regs; } diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c index b5a7af4e226..566d9390a00 100644 --- a/arch/arm/src/armv6-m/arm_doirq.c +++ b/arch/arm/src/armv6-m/arm_doirq.c @@ -42,6 +42,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS PANIC(); @@ -49,6 +51,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) { + tcb->xcp.regs = regs; up_set_current_regs(regs); } @@ -68,17 +71,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) { - /* Restore the cpu lock */ + tcb = this_task(); - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task when context switch occurred. * g_running_tasks[] is only used by assertion logic for reporting * crashes. */ - g_running_tasks[this_cpu()] = this_task(); - regs = up_current_regs(); + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; } /* Update the current_regs to NULL. */ diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c b/arch/arm/src/armv6-m/arm_schedulesigaction.c index 3272dd4dc75..4e5da4c5efd 100644 --- a/arch/arm/src/armv6-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c @@ -78,7 +78,6 @@ * ****************************************************************************/ -#ifndef CONFIG_SMP void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); @@ -94,158 +93,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * to the currently executing task. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb == this_task()) + if (tcb == this_task() && !up_interrupt_context()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state in - * the TCB. - */ - - else - { - /* Save the return PC, CPSR and PRIMASK - * registers (and perhaps also the LR). These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_PRIMASK] = 1; - up_current_regs()[REG_XPSR] = ARMV6M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - up_current_regs()[REG_LR] = EXC_RETURN_THREAD; - up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD; - up_current_regs()[REG_CONTROL] = getcontrol() & - ~CONTROL_NPRIV; -#endif - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling* some non-running task. - */ - else { - /* Save the return PC, CPSR and PRIMASK - * registers (and perhaps also the LR). These will be restored - * by the signal trampoline after the signal has been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_PRIMASK] = 1; - tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - } - } -} -#endif /* !CONFIG_SMP */ - -#ifdef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Refuse to handle nested signal actions */ - - if (!tcb->xcp.sigdeliver) - { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) - { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - /* CASE 2: The task that needs to receive the signal is running. * This could happen if the task is running on another CPU OR if * we are in an interrupt handler and the task is running on this @@ -254,122 +115,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * state as well as the state in the TCB. */ - else + /* If we signaling a task running on the other CPU, we have + * to PAUSE the other CPU. + */ + +#ifdef CONFIG_SMP + int cpu = tcb->cpu; + int me = this_cpu(); + + if (cpu != me) { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + /* Pause the CPU */ - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode - * to be here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_PRIMASK] = 1; - tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return PC, CPSR and either the BASEPRI or - * PRIMASK registers (and perhaps also the LR). These - * will be restored by the signal trampoline after the - * signal has been delivered. - */ - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() - + XCPTCONTEXT_REGS); - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_PRIMASK] = 1; - up_current_regs()[REG_XPSR] = ARMV6M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - up_current_regs()[REG_LR] = EXC_RETURN_THREAD; - up_current_regs()[REG_CONTROL] = getcontrol() & - ~CONTROL_NPRIV; -#endif - } - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + up_cpu_pause(cpu); } - } +#endif - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - - else - { /* Save the return PC, CPSR and either the BASEPRI or PRIMASK * registers (and perhaps also the LR). These will be restored * by the signal trampoline after the signal has been delivered. @@ -377,34 +138,43 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; /* Duplicate the register context. These will be * restored by the signal trampoline after the signal has been * delivered. */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; /* Then set up to vector to the trampoline with interrupts * disabled. We must already be in privileged thread mode to be * here. */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_PRIMASK] = 1; - tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_XPSR] = ARMV6M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; +#endif + +#ifdef CONFIG_SMP + /* RESUME the other CPU if it was PAUSED */ + + if (cpu != me) + { + up_cpu_resume(cpu); + } #endif } } } -#endif /* CONFIG_SMP */ diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c index 408a40c2495..62f57e302a4 100644 --- a/arch/arm/src/armv6-m/arm_svcall.c +++ b/arch/arm/src/armv6-m/arm_svcall.c @@ -117,6 +117,7 @@ static void dispatch_syscall(void) int arm_svcall(int irq, void *context, void *arg) { + struct tcb_s *tcb = this_task(); uint32_t *regs = (uint32_t *)context; uint32_t cmd; @@ -167,7 +168,7 @@ int arm_svcall(int irq, void *context, void *arg) case SYS_restore_context: { DEBUGASSERT(regs[REG_R1] != 0); - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; } break; @@ -192,7 +193,7 @@ int arm_svcall(int irq, void *context, void *arg) { DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); *(uint32_t **)regs[REG_R1] = regs; - up_set_current_regs((uint32_t *)regs[REG_R2]); + tcb->xcp.regs = (uint32_t *)regs[REG_R2]; } break; @@ -450,23 +451,20 @@ int arm_svcall(int irq, void *context, void *arg) # ifndef CONFIG_DEBUG_SVCALL if (cmd > SYS_switch_context) # else - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) # endif { + regs = (uint32_t *)tcb->xcp.regs; + svcinfo("SVCall Return:\n"); svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", - up_current_regs()[REG_R0], up_current_regs()[REG_R1], - up_current_regs()[REG_R2], up_current_regs()[REG_R3], - up_current_regs()[REG_R4], up_current_regs()[REG_R5], - up_current_regs()[REG_R6], up_current_regs()[REG_R7]); + regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", - up_current_regs()[REG_R8], up_current_regs()[REG_R9], - up_current_regs()[REG_R10], up_current_regs()[REG_R11], - up_current_regs()[REG_R12], up_current_regs()[REG_R13], - up_current_regs()[REG_R14], up_current_regs()[REG_R15]); - svcinfo(" PSR: %08x PRIMASK: %08x EXC_RETURN: %08x\n", - up_current_regs()[REG_XPSR], up_current_regs()[REG_PRIMASK], - up_current_regs()[REG_EXC_RETURN]); + regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); + svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n", + regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]); } # ifdef CONFIG_DEBUG_SVCALL else diff --git a/arch/arm/src/armv7-a/arm_cpupause.c b/arch/arm/src/armv7-a/arm_cpupause.c index 7077d905a31..b36c6de7aa2 100644 --- a/arch/arm/src/armv7-a/arm_cpupause.c +++ b/arch/arm/src/armv7-a/arm_cpupause.c @@ -117,11 +117,7 @@ int up_cpu_paused_save(void) sched_note_cpu_paused(tcb); #endif - /* Save the current context at current_regs into the TCB at the head - * of the assigned task list for this CPU. - */ - - arm_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -207,11 +203,7 @@ int up_cpu_paused_restore(void) nxsched_resume_scheduler(tcb); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm/src/armv7-a/arm_cpustart.c b/arch/arm/src/armv7-a/arm_cpustart.c index 6e04f872db1..e358d54b01f 100644 --- a/arch/arm/src/armv7-a/arm_cpustart.c +++ b/arch/arm/src/armv7-a/arm_cpustart.c @@ -79,18 +79,8 @@ int arm_start_handler(int irq, void *context, void *arg) nxsched_resume_scheduler(tcb); - /* Dump registers so that we can see what is going to happen on return */ + UNUSED(tcb); -#if 0 - up_dump_register(tcb->xcp.regs); -#endif - - /* Then switch contexts. This instantiates the exception context of the - * tcb at the head of the assigned task list. In this case, this should - * be the CPUs NULL task. - */ - - arm_restorestate(tcb->xcp.regs); return OK; } diff --git a/arch/arm/src/armv7-a/arm_doirq.c b/arch/arm/src/armv7-a/arm_doirq.c index cb68f8b55a4..460bb9a6c47 100644 --- a/arch/arm/src/armv7-a/arm_doirq.c +++ b/arch/arm/src/armv7-a/arm_doirq.c @@ -53,6 +53,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS PANIC(); @@ -61,6 +63,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); + /* if irq == GIC_SMP_CPUSTART + * We are initiating the multi-core jumping state to up_idle, + * and we will use this_task(). Therefore, it cannot be overridden. + */ + +#ifdef CONFIG_SMP + if (irq != GIC_SMP_CPUSTART) +#endif + { + tcb->xcp.regs = regs; + } + /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. */ @@ -70,10 +84,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); - /* Restore the cpu lock */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -90,8 +103,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * crashes. */ - g_running_tasks[this_cpu()] = this_task(); - regs = up_current_regs(); + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; } /* Set current_regs to NULL to indicate that we are no longer in an diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c b/arch/arm/src/armv7-a/arm_schedulesigaction.c index b49534c4c6c..187af9b18ba 100644 --- a/arch/arm/src/armv7-a/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c @@ -77,7 +77,6 @@ * ****************************************************************************/ -#ifndef CONFIG_SMP void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); @@ -92,157 +91,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * to task that is currently executing on this CPU. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb == this_task()) + if (tcb == this_task() && !up_interrupt_context()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state - * in the TCB. - * - * Hmmm... there looks like a latent bug here: The following logic - * would fail in the strange case where we are in an interrupt - * handler, the thread is signaling itself, but a context switch - * to another task has occurred so that current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - else { - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - } - } -} -#endif /* !CONFIG_SMP */ - -#ifdef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Refuse to handle nested signal actions */ - - if (!tcb->xcp.sigdeliver) - { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) - { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - /* CASE 2: The task that needs to receive the signal is running. * This could happen if the task is running on another CPU OR if * we are in an interrupt handler and the task is running on this @@ -251,118 +113,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * state as well as the state in the TCB. */ - else + /* If we signaling a task running on the other CPU, we have + * to PAUSE the other CPU. + */ + +#ifdef CONFIG_SMP + int cpu = tcb->cpu; + int me = this_cpu(); + + if (cpu != me) { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + /* Pause the CPU */ - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return PC, CPSR and either the BASEPRI or - * PRIMASK registers (and perhaps also the LR). These will - * be restored by the signal trampoline after the signal - * has been delivered. - */ - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() - + XCPTCONTEXT_REGS); - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - } - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + up_cpu_pause(cpu); } - } +#endif - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - - else - { /* Save the return lr and cpsr and one scratch register. These * will be restored by the signal trampoline after the signals * have been delivered. @@ -394,7 +160,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #ifdef CONFIG_ARM_THUMB tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif + +#ifdef CONFIG_SMP + /* RESUME the other CPU if it was PAUSED */ + + if (cpu != me) + { + up_cpu_resume(cpu); + } +#endif } } } -#endif /* CONFIG_SMP */ diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c index feca24da09f..9a8df57bdd8 100644 --- a/arch/arm/src/armv7-a/arm_syscall.c +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -160,7 +160,7 @@ static void dispatch_syscall(void) uint32_t *arm_syscall(uint32_t *regs) { - struct tcb_s *tcb; + struct tcb_s *tcb = this_task(); uint32_t cmd; int cpu; #ifdef CONFIG_BUILD_KERNEL @@ -171,6 +171,8 @@ uint32_t *arm_syscall(uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); + tcb->xcp.regs = regs; + /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. */ @@ -272,7 +274,7 @@ uint32_t *arm_syscall(uint32_t *regs) * set will determine the restored context. */ - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; DEBUGASSERT(up_current_regs()); } break; @@ -298,7 +300,7 @@ uint32_t *arm_syscall(uint32_t *regs) { DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); *(uint32_t **)regs[REG_R1] = regs; - up_set_current_regs((uint32_t *)regs[REG_R2]); + tcb->xcp.regs = (uint32_t *)regs[REG_R2]; } break; @@ -565,15 +567,9 @@ uint32_t *arm_syscall(uint32_t *regs) break; } -#ifdef CONFIG_ARCH_ADDRENV - /* Check for a context switch. If a context switch occurred, then - * current_regs will have a different value than it did on entry. If an - * interrupt level context switch has occurred, then establish the correct - * address environment before returning from the interrupt. - */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { +#ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, * MMU flushed) and set up the address environment for the new @@ -581,13 +577,8 @@ uint32_t *arm_syscall(uint32_t *regs) */ addrenv_switch(NULL); - } #endif - /* Restore the cpu lock */ - - if (regs != up_current_regs()) - { /* Record the new "running" task. g_running_tasks[] is only used by * assertion logic for reporting crashes. */ @@ -599,7 +590,7 @@ uint32_t *arm_syscall(uint32_t *regs) /* Restore the cpu lock */ restore_critical_section(tcb, cpu); - regs = up_current_regs(); + regs = tcb->xcp.regs; } /* Report what happened */ diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c index 66af948ef34..c1370659c9e 100644 --- a/arch/arm/src/armv7-m/arm_doirq.c +++ b/arch/arm/src/armv7-m/arm_doirq.c @@ -42,6 +42,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS PANIC(); @@ -49,6 +51,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) { + tcb->xcp.regs = regs; up_set_current_regs(regs); } @@ -68,17 +71,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE) { - /* Restore the cpu lock */ + tcb = this_task(); - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task when context switch occurred. * g_running_tasks[] is only used by assertion logic for reporting * crashes. */ - g_running_tasks[this_cpu()] = this_task(); - regs = up_current_regs(); + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; } /* Update the current_regs to NULL. */ diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c b/arch/arm/src/armv7-m/arm_schedulesigaction.c index 1aea1dd908e..531e295bbd8 100644 --- a/arch/arm/src/armv7-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c @@ -79,7 +79,6 @@ * ****************************************************************************/ -#ifndef CONFIG_SMP void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); @@ -95,167 +94,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * to the currently executing task. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb == this_task()) + if (tcb == this_task() && !up_interrupt_context()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state in - * the TCB. - */ - - else - { - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV7M_USEBASEPRI - up_current_regs()[REG_BASEPRI] = - NVIC_SYSH_DISABLE_PRIORITY; -#else - up_current_regs()[REG_PRIMASK] = 1; -#endif - up_current_regs()[REG_XPSR] = ARMV7M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - up_current_regs()[REG_LR] = EXC_RETURN_THREAD; - up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD; - up_current_regs()[REG_CONTROL] = getcontrol() & - ~CONTROL_NPRIV; -#endif - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling* some non-running task. - */ - else { - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be restored - * by the signal trampoline after the signal has been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV7M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; -#else - tcb->xcp.regs[REG_PRIMASK] = 1; -#endif - tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - } - } -} -#endif /* !CONFIG_SMP */ - -#ifdef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Refuse to handle nested signal actions */ - - if (!tcb->xcp.sigdeliver) - { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) - { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - /* CASE 2: The task that needs to receive the signal is running. * This could happen if the task is running on another CPU OR if * we are in an interrupt handler and the task is running on this @@ -264,131 +116,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * state as well as the state in the TCB. */ - else + /* If we signaling a task running on the other CPU, we have + * to PAUSE the other CPU. + */ + +#ifdef CONFIG_SMP + int cpu = tcb->cpu; + int me = this_cpu(); + + if (cpu != me) { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + /* Pause the CPU */ - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode - * to be here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV7M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; -#else - tcb->xcp.regs[REG_PRIMASK] = 1; -#endif - tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return PC, CPSR and either the BASEPRI or - * PRIMASK registers (and perhaps also the LR). These - * will be restored by the signal trampoline after the - * signal has been delivered. - */ - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() - + XCPTCONTEXT_REGS); - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV7M_USEBASEPRI - up_current_regs()[REG_BASEPRI] = - NVIC_SYSH_DISABLE_PRIORITY; -#else - up_current_regs()[REG_PRIMASK] = 1; -#endif - up_current_regs()[REG_XPSR] = ARMV7M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - up_current_regs()[REG_LR] = EXC_RETURN_THREAD; - up_current_regs()[REG_CONTROL] = getcontrol() & - ~CONTROL_NPRIV; -#endif - } - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + up_cpu_pause(cpu); } - } +#endif - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - - else - { /* Save the return PC, CPSR and either the BASEPRI or PRIMASK * registers (and perhaps also the LR). These will be restored * by the signal trampoline after the signal has been delivered. @@ -396,38 +139,47 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; /* Duplicate the register context. These will be * restored by the signal trampoline after the signal has been * delivered. */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; /* Then set up to vector to the trampoline with interrupts * disabled. We must already be in privileged thread mode to be * here. */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; #ifdef CONFIG_ARMV7M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; + tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; #else - tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_PRIMASK] = 1; #endif - tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; + tcb->xcp.regs[REG_XPSR] = ARMV7M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; +#endif + +#ifdef CONFIG_SMP + /* RESUME the other CPU if it was PAUSED */ + + if (cpu != me) + { + up_cpu_resume(cpu); + } #endif } } } -#endif /* CONFIG_SMP */ diff --git a/arch/arm/src/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c index a025681c532..6c6f507aeca 100644 --- a/arch/arm/src/armv7-m/arm_svcall.c +++ b/arch/arm/src/armv7-m/arm_svcall.c @@ -125,6 +125,7 @@ static void dispatch_syscall(void) int arm_svcall(int irq, void *context, void *arg) { + struct tcb_s *tcb = this_task(); uint32_t *regs = (uint32_t *)context; uint32_t cmd; @@ -176,7 +177,7 @@ int arm_svcall(int irq, void *context, void *arg) case SYS_restore_context: { DEBUGASSERT(regs[REG_R1] != 0); - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; } break; @@ -201,7 +202,7 @@ int arm_svcall(int irq, void *context, void *arg) { DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); *(uint32_t **)regs[REG_R1] = regs; - up_set_current_regs((uint32_t *)regs[REG_R2]); + tcb->xcp.regs = (uint32_t *)regs[REG_R2]; } break; @@ -459,24 +460,20 @@ int arm_svcall(int irq, void *context, void *arg) # ifndef CONFIG_DEBUG_SVCALL if (cmd > SYS_switch_context) # else - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) # endif { + regs = (uint32_t *)tcb->xcp.regs; + svcinfo("SVCall Return:\n"); svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", - up_current_regs()[REG_R0], up_current_regs()[REG_R1], - up_current_regs()[REG_R2], up_current_regs()[REG_R3], - up_current_regs()[REG_R4], up_current_regs()[REG_R5], - up_current_regs()[REG_R6], up_current_regs()[REG_R7]); + regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", - up_current_regs()[REG_R8], up_current_regs()[REG_R9], - up_current_regs()[REG_R10], up_current_regs()[REG_R11], - up_current_regs()[REG_R12], up_current_regs()[REG_R13], - up_current_regs()[REG_R14], up_current_regs()[REG_R15]); - svcinfo(" PSR: %08x EXC_RETURN: %08x, CONTROL: %08x\n", - up_current_regs()[REG_XPSR], - up_current_regs()[REG_EXC_RETURN], - up_current_regs()[REG_CONTROL]); + regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); + svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n", + regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]); } # ifdef CONFIG_DEBUG_SVCALL else diff --git a/arch/arm/src/armv7-r/arm_cpupause.c b/arch/arm/src/armv7-r/arm_cpupause.c index b51b98e5390..a466d963eba 100644 --- a/arch/arm/src/armv7-r/arm_cpupause.c +++ b/arch/arm/src/armv7-r/arm_cpupause.c @@ -117,11 +117,7 @@ int up_cpu_paused_save(void) sched_note_cpu_paused(tcb); #endif - /* Save the current context at current_regs into the TCB at the head - * of the assigned task list for this CPU. - */ - - arm_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -207,11 +203,7 @@ int up_cpu_paused_restore(void) nxsched_resume_scheduler(tcb); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm/src/armv7-r/arm_cpustart.c b/arch/arm/src/armv7-r/arm_cpustart.c index fe93836e5b5..15d0ec1ac0a 100644 --- a/arch/arm/src/armv7-r/arm_cpustart.c +++ b/arch/arm/src/armv7-r/arm_cpustart.c @@ -79,12 +79,8 @@ int arm_start_handler(int irq, void *context, void *arg) nxsched_resume_scheduler(tcb); - /* Then switch contexts. This instantiates the exception context of the - * tcb at the head of the assigned task list. In this case, this should - * be the CPUs NULL task. - */ + UNUSED(tcb); - arm_restorestate(tcb->xcp.regs); return OK; } diff --git a/arch/arm/src/armv7-r/arm_doirq.c b/arch/arm/src/armv7-r/arm_doirq.c index 61adb183b66..7b08a7dd563 100644 --- a/arch/arm/src/armv7-r/arm_doirq.c +++ b/arch/arm/src/armv7-r/arm_doirq.c @@ -41,6 +41,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS @@ -50,6 +52,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); + /* if irq == GIC_SMP_CPUSTART + * We are initiating the multi-core jumping state to up_idle, + * and we will use this_task(). Therefore, it cannot be overridden. + */ + +#ifdef CONFIG_SMP + if (irq != GIC_SMP_CPUSTART) +#endif + { + tcb->xcp.regs = regs; + } + /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. */ @@ -59,18 +73,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); - /* Restore the cpu lock */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task when context switch occurred. * g_running_tasks[] is only used by assertion logic for reporting * crashes. */ - g_running_tasks[this_cpu()] = this_task(); - regs = up_current_regs(); + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; } /* Set current_regs to NULL to indicate that we are no longer in an diff --git a/arch/arm/src/armv7-r/arm_schedulesigaction.c b/arch/arm/src/armv7-r/arm_schedulesigaction.c index e24fc8de3bd..b21a0c9188d 100644 --- a/arch/arm/src/armv7-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c @@ -75,147 +75,12 @@ * ****************************************************************************/ -#ifndef CONFIG_SMP void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); /* Refuse to handle nested signal actions */ - if (!tcb->xcp.sigdeliver) - { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) - { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state - * in the TCB. - * - * Hmmm... there looks like a latent bug here: The following logic - * would fail in the strange case where we are in an interrupt - * handler, the thread is signalling itself, but a context switch - * to another task has occurred so that current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_ENDIAN_BIG - up_current_regs()[REG_CPSR] |= PSR_E_BIT; -#endif - } - } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signalling some non-running task. - */ - - else - { - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_ENDIAN_BIG - tcb->xcp.regs[REG_CPSR] |= PSR_E_BIT; -#endif - } - } -} -#else -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Refuse to handle nested signal actions */ - if (!tcb->xcp.sigdeliver) { tcb->xcp.sigdeliver = sigdeliver; @@ -224,147 +89,36 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * to task that is currently executing on any CPU. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb->task_state == TSTATE_TASK_RUNNING) + if (tcb == this_task() && !up_interrupt_context()) { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return PC, CPSR and either the BASEPRI or - * PRIMASK registers (and perhaps also the LR). These will - * be restored by the signal trampoline after the signal - * has been delivered. - */ - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() - + XCPTCONTEXT_REGS); - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - } - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - else { + /* If we signaling a task running on the other CPU, we have + * to PAUSE the other CPU. + */ + +#ifdef CONFIG_SMP + int cpu = tcb->cpu; + int me = this_cpu(); + + if (cpu != me) + { + /* Pause the CPU */ + + up_cpu_pause(cpu); + } +#endif + /* Save the return lr and cpsr and one scratch register. These * will be restored by the signal trampoline after the signals * have been delivered. @@ -396,7 +150,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #ifdef CONFIG_ARM_THUMB tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif + +#ifdef CONFIG_SMP + /* RESUME the other CPU if it was PAUSED */ + + if (cpu != me) + { + up_cpu_resume(cpu); + } +#endif } } } -#endif diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c index f1e149e7494..66d21816184 100644 --- a/arch/arm/src/armv7-r/arm_syscall.c +++ b/arch/arm/src/armv7-r/arm_syscall.c @@ -156,7 +156,8 @@ static void dispatch_syscall(void) uint32_t *arm_syscall(uint32_t *regs) { - struct tcb_s *tcb; + struct tcb_s *tcb = this_task(); + uint32_t cmd; int cpu; #ifdef CONFIG_BUILD_PROTECTED @@ -167,6 +168,8 @@ uint32_t *arm_syscall(uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); + tcb->xcp.regs = regs; + /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. */ @@ -268,7 +271,7 @@ uint32_t *arm_syscall(uint32_t *regs) * set will determine the restored context. */ - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; DEBUGASSERT(up_current_regs()); } break; @@ -294,7 +297,7 @@ uint32_t *arm_syscall(uint32_t *regs) { DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); *(uint32_t **)regs[REG_R1] = regs; - up_set_current_regs((uint32_t *)regs[REG_R2]); + tcb->xcp.regs = (uint32_t *)regs[REG_R2]; } break; @@ -561,22 +564,19 @@ uint32_t *arm_syscall(uint32_t *regs) break; } - /* Restore the cpu lock */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task. g_running_tasks[] is only used by * assertion logic for reporting crashes. */ cpu = this_cpu(); - tcb = current_task(cpu); g_running_tasks[cpu] = tcb; /* Restore the cpu lock */ restore_critical_section(tcb, cpu); - regs = up_current_regs(); + regs = tcb->xcp.regs; } /* Report what happened */ diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c index 198261961d0..e35cbb0eef8 100644 --- a/arch/arm/src/armv8-m/arm_doirq.c +++ b/arch/arm/src/armv8-m/arm_doirq.c @@ -91,6 +91,8 @@ static inline bool arm_from_thread(uint32_t excret) uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS PANIC(); @@ -98,6 +100,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (arm_from_thread(regs[REG_EXC_RETURN])) { + tcb->xcp.regs = regs; up_set_current_regs(regs); } @@ -117,17 +120,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (arm_from_thread(regs[REG_EXC_RETURN])) { - /* Restore the cpu lock */ + tcb = this_task(); - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task when context switch occurred. * g_running_tasks[] is only used by assertion logic for reporting * crashes. */ - g_running_tasks[this_cpu()] = this_task(); - regs = up_current_regs(); + g_running_tasks[this_cpu()] = tcb; + regs = tcb->xcp.regs; } /* Update the current_regs to NULL. */ diff --git a/arch/arm/src/armv8-m/arm_schedulesigaction.c b/arch/arm/src/armv8-m/arm_schedulesigaction.c index f96309538e8..42b0ccfb064 100644 --- a/arch/arm/src/armv8-m/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c @@ -79,7 +79,6 @@ * ****************************************************************************/ -#ifndef CONFIG_SMP void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); @@ -95,167 +94,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * to the currently executing task. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb == this_task()) + if (tcb == this_task() && !up_interrupt_context()) { - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handle will run in a critical section! */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handle will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state in - * the TCB. - */ - - else - { - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV8M_USEBASEPRI - up_current_regs()[REG_BASEPRI] = - NVIC_SYSH_DISABLE_PRIORITY; -#else - up_current_regs()[REG_PRIMASK] = 1; -#endif - up_current_regs()[REG_XPSR] = ARMV8M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - up_current_regs()[REG_LR] = EXC_RETURN_THREAD; - up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD; - up_current_regs()[REG_CONTROL] = getcontrol() & - ~CONTROL_NPRIV; -#endif - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling* some non-running task. - */ - else { - /* Save the return PC, CPSR and either the BASEPRI or PRIMASK - * registers (and perhaps also the LR). These will be restored - * by the signal trampoline after the signal has been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode to be - * here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV8M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; -#else - tcb->xcp.regs[REG_PRIMASK] = 1; -#endif - tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - } - } -} -#endif /* !CONFIG_SMP */ - -#ifdef CONFIG_SMP -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Refuse to handle nested signal actions */ - - if (!tcb->xcp.sigdeliver) - { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on any CPU. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb->task_state == TSTATE_TASK_RUNNING) - { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. - */ - - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - /* CASE 2: The task that needs to receive the signal is running. * This could happen if the task is running on another CPU OR if * we are in an interrupt handler and the task is running on this @@ -264,124 +116,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * state as well as the state in the TCB. */ - else + /* If we signaling a task running on the other CPU, we have + * to PAUSE the other CPU. + */ + +#ifdef CONFIG_SMP + int cpu = tcb->cpu; + int me = this_cpu(); + + if (cpu != me) { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ + /* Pause the CPU */ - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up vector to the trampoline with interrupts - * disabled. We must already be in privileged thread mode - * to be here. - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV8M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; -#else - tcb->xcp.regs[REG_PRIMASK] = 1; -#endif - tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; -#endif - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return PC, CPSR and either the BASEPRI or - * PRIMASK registers (and perhaps also the LR). These - * will be restored by the signal trampoline after the - * signal has been delivered. - */ - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() - + XCPTCONTEXT_REGS); - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; -#ifdef CONFIG_ARMV8M_USEBASEPRI - up_current_regs()[REG_BASEPRI] = - NVIC_SYSH_DISABLE_PRIORITY; -#else - up_current_regs()[REG_PRIMASK] = 1; -#endif - up_current_regs()[REG_XPSR] = ARMV8M_XPSR_T; -#ifdef CONFIG_BUILD_PROTECTED - up_current_regs()[REG_LR] = EXC_RETURN_THREAD; - up_current_regs()[REG_CONTROL] = getcontrol() & - ~CONTROL_NPRIV; -#endif - } - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } + up_cpu_pause(cpu); } - } +#endif - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - - else - { /* Save the return PC, CPSR and either the BASEPRI or PRIMASK * registers (and perhaps also the LR). These will be restored * by the signal trampoline after the signal has been delivered. @@ -389,38 +139,47 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) /* Save the current register context location */ - tcb->xcp.saved_regs = tcb->xcp.regs; + tcb->xcp.saved_regs = tcb->xcp.regs; /* Duplicate the register context. These will be * restored by the signal trampoline after the signal has been * delivered. */ - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); + tcb->xcp.regs = (void *) + ((uint32_t)tcb->xcp.regs - + XCPTCONTEXT_SIZE); memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + + XCPTCONTEXT_SIZE; /* Then set up to vector to the trampoline with interrupts * disabled. We must already be in privileged thread mode to be * here. */ - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; + tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; #ifdef CONFIG_ARMV8M_USEBASEPRI - tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; + tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY; #else - tcb->xcp.regs[REG_PRIMASK] = 1; + tcb->xcp.regs[REG_PRIMASK] = 1; #endif - tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; + tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T; #ifdef CONFIG_BUILD_PROTECTED - tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; - tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; + tcb->xcp.regs[REG_LR] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD; + tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV; +#endif + +#ifdef CONFIG_SMP + /* RESUME the other CPU if it was PAUSED */ + + if (cpu != me) + { + up_cpu_resume(cpu); + } #endif } } } -#endif /* CONFIG_SMP */ diff --git a/arch/arm/src/armv8-m/arm_svcall.c b/arch/arm/src/armv8-m/arm_svcall.c index 9df396b6c4e..aeb427322c0 100644 --- a/arch/arm/src/armv8-m/arm_svcall.c +++ b/arch/arm/src/armv8-m/arm_svcall.c @@ -124,6 +124,7 @@ static void dispatch_syscall(void) int arm_svcall(int irq, void *context, void *arg) { + struct tcb_s *tcb = this_task(); uint32_t *regs = (uint32_t *)context; uint32_t cmd; @@ -175,7 +176,7 @@ int arm_svcall(int irq, void *context, void *arg) case SYS_restore_context: { DEBUGASSERT(regs[REG_R1] != 0); - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; } break; @@ -200,7 +201,7 @@ int arm_svcall(int irq, void *context, void *arg) { DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); *(uint32_t **)regs[REG_R1] = regs; - up_set_current_regs((uint32_t *)regs[REG_R2]); + tcb->xcp.regs = (uint32_t *)regs[REG_R2]; } break; @@ -460,24 +461,20 @@ int arm_svcall(int irq, void *context, void *arg) # ifndef CONFIG_DEBUG_SVCALL if (cmd > SYS_switch_context) # else - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) # endif { + regs = (uint32_t *)tcb->xcp.regs; + svcinfo("SVCall Return:\n"); svcinfo(" R0: %08x %08x %08x %08x %08x %08x %08x %08x\n", - up_current_regs()[REG_R0], up_current_regs()[REG_R1], - up_current_regs()[REG_R2], up_current_regs()[REG_R3], - up_current_regs()[REG_R4], up_current_regs()[REG_R5], - up_current_regs()[REG_R6], up_current_regs()[REG_R7]); + regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]); svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n", - up_current_regs()[REG_R8], up_current_regs()[REG_R9], - up_current_regs()[REG_R10], up_current_regs()[REG_R11], - up_current_regs()[REG_R12], up_current_regs()[REG_R13], - up_current_regs()[REG_R14], up_current_regs()[REG_R15]); + regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]); svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n", - up_current_regs()[REG_XPSR], - up_current_regs()[REG_EXC_RETURN], - up_current_regs()[REG_CONTROL]); + regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]); } # ifdef CONFIG_DEBUG_SVCALL else diff --git a/arch/arm/src/armv8-r/arm_doirq.c b/arch/arm/src/armv8-r/arm_doirq.c index 982795fe139..2863292052b 100644 --- a/arch/arm/src/armv8-r/arm_doirq.c +++ b/arch/arm/src/armv8-r/arm_doirq.c @@ -42,6 +42,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS @@ -51,6 +53,16 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); + /* if irq == GIC_SMP_CPUSTART + * We are initiating the multi-core jumping state to up_idle, + * and we will use this_task(). Therefore, it cannot be overridden. + */ + + if (irq != GIC_SMP_CPUSTART) + { + tcb->xcp.regs = regs; + } + /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. */ @@ -60,10 +72,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); - /* Restore the cpu lock */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task when context switch occurred. * g_running_tasks[] is only used by assertion logic for reporting @@ -71,7 +82,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) */ g_running_tasks[this_cpu()] = this_task(); - regs = up_current_regs(); + regs = tcb->xcp.regs; } /* Set current_regs to NULL to indicate that we are no longer in an diff --git a/arch/arm/src/armv8-r/arm_schedulesigaction.c b/arch/arm/src/armv8-r/arm_schedulesigaction.c index 400dbc339d2..1ceba997f7f 100644 --- a/arch/arm/src/armv8-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv8-r/arm_schedulesigaction.c @@ -75,147 +75,12 @@ * ****************************************************************************/ -#ifndef CONFIG_SMP void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); /* Refuse to handle nested signal actions */ - if (!tcb->xcp.sigdeliver) - { - tcb->xcp.sigdeliver = sigdeliver; - - /* First, handle some special cases when the signal is being delivered - * to the currently executing task. - */ - - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); - - if (tcb == this_task()) - { - /* CASE 1: We are not in an interrupt handler and a task is - * signalling itself for some reason. - */ - - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the interrupted - * task is the same as the one that must receive the signal, then - * we will have to modify the return state as well as the state - * in the TCB. - * - * Hmmm... there looks like a latent bug here: The following logic - * would fail in the strange case where we are in an interrupt - * handler, the thread is signalling itself, but a context switch - * to another task has occurred so that current_regs does not - * refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* And make sure that the saved context in the TCB is the same - * as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_ENDIAN_BIG - up_current_regs()[REG_CPSR] |= PSR_E_BIT; -#endif - } - } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signalling some non-running task. - */ - - else - { - /* Save the return lr and cpsr and one scratch register. These - * will be restored by the signal trampoline after the signals - * have been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - -#ifdef CONFIG_ENDIAN_BIG - tcb->xcp.regs[REG_CPSR] |= PSR_E_BIT; -#endif - } - } -} -#else -void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) -{ - int cpu; - int me; - - sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - - /* Refuse to handle nested signal actions */ - if (!tcb->xcp.sigdeliver) { tcb->xcp.sigdeliver = sigdeliver; @@ -224,154 +89,36 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * to task that is currently executing on any CPU. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb->task_state == TSTATE_TASK_RUNNING) + if (tcb == this_task() && !up_interrupt_context()) { - me = this_cpu(); - cpu = tcb->cpu; - - /* CASE 1: We are not in an interrupt handler and a task is - * signaling itself for some reason. + /* In this case just deliver the signal now. + * REVISIT: Signal handler will run in a critical section! */ - if (cpu == me && !up_current_regs()) - { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: The task that needs to receive the signal is running. - * This could happen if the task is running on another CPU OR if - * we are in an interrupt handler and the task is running on this - * CPU. In the former case, we will have to PAUSE the other CPU - * first. But in either case, we will have to modify the return - * state as well as the state in the TCB. - */ - - else - { - /* If we signaling a task running on the other CPU, we have - * to PAUSE the other CPU. - */ - - if (cpu != me) - { - /* Pause the CPU */ - - up_cpu_pause(cpu); - - /* Now tcb on the other CPU can be accessed safely */ - - /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - /* Save the current register context location */ - - tcb->xcp.saved_regs = tcb->xcp.regs; - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - tcb->xcp.regs = (void *) - ((uint32_t)tcb->xcp.regs - - XCPTCONTEXT_SIZE); - memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + - XCPTCONTEXT_SIZE; - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver; - tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; -#endif - } - else - { - /* tcb is running on the same CPU */ - - /* Save the return PC, CPSR and either the BASEPRI or - * PRIMASK registers (and perhaps also the LR). These will - * be restored by the signal trampoline after the signal - * has been delivered. - */ - - /* And make sure that the saved context in the TCB is the - * same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has - * been delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() - + XCPTCONTEXT_REGS); - - /* Then set up vector to the trampoline with interrupts - * disabled. The kernel-space trampoline must run in - * privileged thread mode. - */ - - up_current_regs()[REG_PC] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | - PSR_F_BIT); -#ifdef CONFIG_ARM_THUMB - up_current_regs()[REG_CPSR] |= PSR_T_BIT; -#endif - } - - /* Increment the IRQ lock count so that when the task is - * restarted, it will hold the IRQ spinlock. - */ - - DEBUGASSERT(tcb->irqcount < INT16_MAX); - tcb->irqcount++; - - /* NOTE: If the task runs on another CPU(cpu), adjusting - * global IRQ controls will be done in the pause handler - * on the CPU(cpu) by taking a critical section. - * If the task is scheduled on this CPU(me), do nothing - * because this CPU already took a critical section - */ - - /* RESUME the other CPU if it was PAUSED */ - - if (cpu != me) - { - up_cpu_resume(cpu); - } - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } - - /* Otherwise, we are (1) signaling a task is not running from an - * interrupt handler or (2) we are not in an interrupt handler and the - * running task is signaling some other non-running task. - */ - else { + /* If we signaling a task running on the other CPU, we have + * to PAUSE the other CPU. + */ + +#ifdef CONFIG_SMP + int cpu = tcb->cpu; + int me = this_cpu(); + + if (cpu != me) + { + /* Pause the CPU */ + + up_cpu_pause(cpu); + } +#endif + /* Save the return lr and cpsr and one scratch register. These * will be restored by the signal trampoline after the signals * have been delivered. @@ -394,13 +141,6 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs + XCPTCONTEXT_SIZE; - /* Increment the IRQ lock count so that when the task is restarted, - * it will hold the IRQ spinlock. - */ - - DEBUGASSERT(tcb->irqcount < INT16_MAX); - tcb->irqcount++; - /* Then set up to vector to the trampoline with interrupts * disabled */ @@ -410,7 +150,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) #ifdef CONFIG_ARM_THUMB tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT; #endif + +#ifdef CONFIG_SMP + /* RESUME the other CPU if it was PAUSED */ + + if (cpu != me) + { + up_cpu_resume(cpu); + } +#endif } } } -#endif diff --git a/arch/arm/src/armv8-r/arm_syscall.c b/arch/arm/src/armv8-r/arm_syscall.c index ffc57ee1f22..1f82dc20e7b 100644 --- a/arch/arm/src/armv8-r/arm_syscall.c +++ b/arch/arm/src/armv8-r/arm_syscall.c @@ -156,7 +156,7 @@ static void dispatch_syscall(void) uint32_t *arm_syscall(uint32_t *regs) { - struct tcb_s *tcb; + struct tcb_s *tcb = this_task(); uint32_t cmd; int cpu; #ifdef CONFIG_BUILD_PROTECTED @@ -167,6 +167,8 @@ uint32_t *arm_syscall(uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); + tcb->xcp.regs = regs; + /* Current regs non-zero indicates that we are processing an interrupt; * current_regs is also used to manage interrupt level context switches. */ @@ -268,7 +270,7 @@ uint32_t *arm_syscall(uint32_t *regs) * set will determine the restored context. */ - up_set_current_regs((uint32_t *)regs[REG_R1]); + tcb->xcp.regs = (uint32_t *)regs[REG_R1]; DEBUGASSERT(up_current_regs()); } break; @@ -294,7 +296,7 @@ uint32_t *arm_syscall(uint32_t *regs) { DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0); *(uint32_t **)regs[REG_R1] = regs; - up_set_current_regs((uint32_t *)regs[REG_R2]); + tcb->xcp.regs = (uint32_t *)regs[REG_R2]; } break; @@ -561,22 +563,19 @@ uint32_t *arm_syscall(uint32_t *regs) break; } - /* Restore the cpu lock */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Record the new "running" task. g_running_tasks[] is only used by * assertion logic for reporting crashes. */ cpu = this_cpu(); - tcb = current_task(cpu); g_running_tasks[cpu] = tcb; /* Restore the cpu lock */ restore_critical_section(tcb, cpu); - regs = up_current_regs(); + regs = tcb->xcp.regs; } /* Report what happened */ diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h index c5c02a89277..e7ace0d52ed 100644 --- a/arch/arm/src/common/arm_internal.h +++ b/arch/arm/src/common/arm_internal.h @@ -96,11 +96,6 @@ #define INTSTACK_SIZE (CONFIG_ARCH_INTERRUPTSTACK & ~STACK_ALIGN_MASK) -/* Macros to handle saving and restoring interrupt state. */ - -#define arm_savestate(regs) (regs = up_current_regs()) -#define arm_restorestate(regs) up_set_current_regs(regs) - /* Toolchain dependent, linker defined section addresses */ #if defined(__ICCARM__) diff --git a/arch/arm/src/common/arm_switchcontext.c b/arch/arm/src/common/arm_switchcontext.c index 51fe498e0c1..f342da9ebc7 100644 --- a/arch/arm/src/common/arm_switchcontext.c +++ b/arch/arm/src/common/arm_switchcontext.c @@ -63,21 +63,9 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb) if (up_current_regs()) { - /* Yes, then we have to do things differently. - * Just copy the current_regs into the OLD rtcb. - */ - - arm_savestate(rtcb->xcp.regs); - /* Update scheduler parameters */ nxsched_resume_scheduler(tcb); - - /* Then switch contexts. Any necessary address environment - * changes will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); } /* No, then we will need to perform the user context switch */ diff --git a/arch/arm/src/cxd56xx/cxd56_cpupause.c b/arch/arm/src/cxd56xx/cxd56_cpupause.c index d02a51b8a2d..3857728f450 100644 --- a/arch/arm/src/cxd56xx/cxd56_cpupause.c +++ b/arch/arm/src/cxd56xx/cxd56_cpupause.c @@ -199,11 +199,7 @@ int up_cpu_paused_save(void) sched_note_cpu_paused(tcb); #endif - /* Save the current context at current_regs into the TCB at the head - * of the assigned task list for this CPU. - */ - - arm_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -290,11 +286,7 @@ int up_cpu_paused_restore(void) nxsched_resume_scheduler(tcb); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm/src/dm320/dm320_decodeirq.c b/arch/arm/src/dm320/dm320_decodeirq.c index 0fc6b0b39df..3cdec04c059 100644 --- a/arch/arm/src/dm320/dm320_decodeirq.c +++ b/arch/arm/src/dm320/dm320_decodeirq.c @@ -34,6 +34,7 @@ #include "chip.h" #include "arm_internal.h" +#include "sched/sched.h" /**************************************************************************** * Public Functions @@ -41,6 +42,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) { + struct tcb_s *tcb = this_task(); + #ifdef CONFIG_SUPPRESS_INTERRUPTS up_set_current_regs(regs); err("ERROR: Unexpected IRQ\n"); @@ -78,11 +81,13 @@ uint32_t *arm_decodeirq(uint32_t *regs) */ DEBUGASSERT(up_current_regs() == NULL); + tcb->xcp.regs = regs; up_set_current_regs(regs); /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); #ifdef CONFIG_ARCH_ADDRENV /* Check for a context switch. If a context switch occurred, then @@ -92,7 +97,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) * from the interrupt. */ - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, diff --git a/arch/arm/src/imx1/imx_decodeirq.c b/arch/arm/src/imx1/imx_decodeirq.c index b164e5adbe1..43f7c8e1ed4 100644 --- a/arch/arm/src/imx1/imx_decodeirq.c +++ b/arch/arm/src/imx1/imx_decodeirq.c @@ -57,6 +57,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) { + struct tcb_s *tcb = this_task(); + #ifdef CONFIG_SUPPRESS_INTERRUPTS up_set_current_regs(regs); err("ERROR: Unexpected IRQ\n"); @@ -74,6 +76,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); up_set_current_regs(regs); + tcb->xcp.regs = regs; /* Loop while there are pending interrupts to be processed */ @@ -99,6 +102,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); #ifdef CONFIG_ARCH_ADDRENV /* Check for a context switch. If a context switch occurred, then @@ -108,7 +112,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) * from the interrupt. */ - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, diff --git a/arch/arm/src/lc823450/lc823450_cpupause.c b/arch/arm/src/lc823450/lc823450_cpupause.c index 31957f8ad2c..c75abbae17b 100644 --- a/arch/arm/src/lc823450/lc823450_cpupause.c +++ b/arch/arm/src/lc823450/lc823450_cpupause.c @@ -127,11 +127,7 @@ int up_cpu_paused_save(void) sched_note_cpu_paused(tcb); #endif - /* Save the current context at current_regs into the TCB at the head - * of the assigned task list for this CPU. - */ - - arm_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -211,11 +207,7 @@ int up_cpu_paused_restore(void) nxsched_resume_scheduler(tcb); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm/src/lpc214x/lpc214x_decodeirq.c b/arch/arm/src/lpc214x/lpc214x_decodeirq.c index ecf0294b257..08662be3b5a 100644 --- a/arch/arm/src/lpc214x/lpc214x_decodeirq.c +++ b/arch/arm/src/lpc214x/lpc214x_decodeirq.c @@ -33,6 +33,7 @@ #include "chip.h" #include "arm_internal.h" #include "lpc214x_vic.h" +#include "sched/sched.h" /**************************************************************************** * Private Data @@ -81,6 +82,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) static uint32_t *lpc214x_decodeirq(uint32_t *regs) #endif { + struct tcb_s *tcb = this_task(); + #ifdef CONFIG_SUPPRESS_INTERRUPTS up_set_current_regs(regs); err("ERROR: Unexpected IRQ\n"); @@ -125,6 +128,7 @@ static uint32_t *lpc214x_decodeirq(uint32_t *regs) savestate = up_current_regs(); up_set_current_regs(regs); + tcb->xcp.regs = regs; /* Deliver the IRQ */ diff --git a/arch/arm/src/lpc2378/lpc23xx_decodeirq.c b/arch/arm/src/lpc2378/lpc23xx_decodeirq.c index 0affc82ebaf..9a2d253dea8 100644 --- a/arch/arm/src/lpc2378/lpc23xx_decodeirq.c +++ b/arch/arm/src/lpc2378/lpc23xx_decodeirq.c @@ -56,6 +56,7 @@ #include "arm_internal.h" #include "lpc2378.h" #include "lpc23xx_vic.h" +#include "sched/sched.h" /**************************************************************************** * Public Functions @@ -91,6 +92,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) static uint32_t *lpc23xx_decodeirq(uint32_t *regs) #endif { + struct tcb_s *tcb = this_task(); + #ifdef CONFIG_SUPPRESS_INTERRUPTS err("ERROR: Unexpected IRQ\n"); up_set_current_regs(regs); @@ -124,6 +127,7 @@ static uint32_t *lpc23xx_decodeirq(uint32_t *regs) savestate = up_current_regs(); up_set_current_regs(regs); + tcb->xcp.regs = regs; /* Acknowledge the interrupt */ diff --git a/arch/arm/src/lpc31xx/lpc31_decodeirq.c b/arch/arm/src/lpc31xx/lpc31_decodeirq.c index 517761d9ceb..64e603ce301 100644 --- a/arch/arm/src/lpc31xx/lpc31_decodeirq.c +++ b/arch/arm/src/lpc31xx/lpc31_decodeirq.c @@ -34,7 +34,7 @@ #include "chip.h" #include "arm_internal.h" - +#include "sched/sched.h" #include "lpc31_intc.h" /**************************************************************************** @@ -43,6 +43,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) { + struct tcb_s *tcb = this_task(); + #ifdef CONFIG_SUPPRESS_INTERRUPTS up_set_current_regs(regs); err("ERROR: Unexpected IRQ\n"); @@ -84,10 +86,12 @@ uint32_t *arm_decodeirq(uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); up_set_current_regs(regs); + tcb->xcp.regs = regs; /* Deliver the IRQ */ irq_dispatch(irq, regs); + tcb = this_task(); #ifdef CONFIG_ARCH_ADDRENV /* Check for a context switch. If a context switch occurred, then @@ -97,7 +101,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) * from the interrupt. */ - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump, diff --git a/arch/arm/src/moxart/moxart_irq.c b/arch/arm/src/moxart/moxart_irq.c index 0fcb8c4348d..029582c0e01 100644 --- a/arch/arm/src/moxart/moxart_irq.c +++ b/arch/arm/src/moxart/moxart_irq.c @@ -260,6 +260,7 @@ void arm_ack_irq(int irq) uint32_t *arm_decodeirq(uint32_t *regs) { + struct tcb_s *tcb = this_task(); uint32_t num; uint32_t status; @@ -278,6 +279,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) DEBUGASSERT(up_current_regs() == NULL); up_set_current_regs(regs); + tcb->xcp.regs = regs; irq_dispatch(num, regs); up_set_current_regs(NULL); diff --git a/arch/arm/src/rp2040/rp2040_cpupause.c b/arch/arm/src/rp2040/rp2040_cpupause.c index 06edbadef23..b5a4e8f8201 100644 --- a/arch/arm/src/rp2040/rp2040_cpupause.c +++ b/arch/arm/src/rp2040/rp2040_cpupause.c @@ -167,11 +167,7 @@ int up_cpu_paused_save(void) sched_note_cpu_paused(tcb); #endif - /* Save the current context at current_regs into the TCB at the head - * of the assigned task list for this CPU. - */ - - arm_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -251,11 +247,7 @@ int up_cpu_paused_restore(void) nxsched_resume_scheduler(tcb); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm/src/sam34/sam4cm_cpupause.c b/arch/arm/src/sam34/sam4cm_cpupause.c index 5ad0adb4106..4abd9068de7 100644 --- a/arch/arm/src/sam34/sam4cm_cpupause.c +++ b/arch/arm/src/sam34/sam4cm_cpupause.c @@ -129,11 +129,7 @@ int up_cpu_paused_save(void) sched_note_cpu_paused(tcb); #endif - /* Save the current context at current_regs into the TCB at the head - * of the assigned task list for this CPU. - */ - - arm_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -213,11 +209,7 @@ int up_cpu_paused_restore(void) nxsched_resume_scheduler(tcb); - /* Then switch contexts. Any necessary address environment changes - * will be made when the interrupt returns. - */ - - arm_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm/src/str71x/str71x_decodeirq.c b/arch/arm/src/str71x/str71x_decodeirq.c index 44e8fe94784..f3098e76b89 100644 --- a/arch/arm/src/str71x/str71x_decodeirq.c +++ b/arch/arm/src/str71x/str71x_decodeirq.c @@ -35,6 +35,7 @@ #include "chip.h" #include "arm_internal.h" +#include "sched/sched.h" /**************************************************************************** * Public Functions @@ -53,6 +54,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) { + struct tcb_s *tcb = this_task(); + #ifdef CONFIG_SUPPRESS_INTERRUPTS board_autoled_on(LED_INIRQ); up_set_current_regs(regs); @@ -82,6 +85,7 @@ uint32_t *arm_decodeirq(uint32_t *regs) savestate = up_current_regs(); up_set_current_regs(regs); + tcb->xcp.regs = regs; /* Acknowledge the interrupt */ diff --git a/arch/arm/src/tlsr82/tc32/tc32_doirq.c b/arch/arm/src/tlsr82/tc32/tc32_doirq.c index 82fcd63710b..aa301a36698 100644 --- a/arch/arm/src/tlsr82/tc32/tc32_doirq.c +++ b/arch/arm/src/tlsr82/tc32/tc32_doirq.c @@ -36,7 +36,7 @@ #include #include "arm_internal.h" - +#include "sched/sched.h" #include "hardware/tlsr82_irq.h" /**************************************************************************** @@ -57,6 +57,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) { + struct tcb_s *tcb = this_task(); + board_autoled_on(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS PANIC(); @@ -78,6 +80,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) regs = NULL; } + tcb->xcp.regs = regs; + /* Acknowledge the interrupt */ arm_ack_irq(irq); @@ -85,6 +89,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) /* Deliver the IRQ */ irq_dispatch(irq, up_current_regs()); + tcb = this_task(); /* If a context switch occurred while processing the interrupt then * current_regs may have change value. If we return any value different @@ -94,11 +99,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) if (regs == NULL) { - /* Restore the cpu lock */ - - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { - regs = up_current_regs(); + regs = tcb->xcp.regs; } /* Update the current_regs to NULL. */ diff --git a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c index 73fd3322789..4e90afee3a8 100644 --- a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c +++ b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c @@ -89,67 +89,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * being delivered to the currently executing task. */ - sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs()); + sinfo("rtcb=%p current_regs=%p\n", this_task(), + this_task()->xcp.regs); - if (tcb == this_task()) + if (tcb == this_task() && !up_interrupt_context()) { - /* CASE 1: We are not in an interrupt handler and - * a task is signalling itself for some reason. - */ + /* In this case just deliver the signal now. */ - if (!up_current_regs()) - { - /* In this case just deliver the signal now. */ - - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; - } - - /* CASE 2: We are in an interrupt handler AND the - * interrupted task is the same as the one that - * must receive the signal, then we will have to modify - * the return state as well as the state in the TCB. - * - * Hmmm... there looks like a latent bug here: The following - * logic would fail in the strange case where we are in an - * interrupt handler, the thread is signalling itself, but - * a context switch to another task has occurred so that - * current_regs does not refer to the thread of this_task()! - */ - - else - { - /* Save the return lr and cpsr and one scratch register - * These will be restored by the signal trampoline after - * the signals have been delivered. - */ - - /* And make sure that the saved context in the TCB - * is the same as the interrupt return context. - */ - - arm_savestate(tcb->xcp.saved_regs); - - /* Duplicate the register context. These will be - * restored by the signal trampoline after the signal has been - * delivered. - */ - - up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS); - memcpy(up_current_regs(), tcb->xcp.saved_regs, - XCPTCONTEXT_SIZE); - - up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() + - XCPTCONTEXT_REGS); - - /* Then set up to vector to the trampoline with interrupts - * disabled - */ - - up_current_regs()[REG_LR] = (uint32_t)arm_sigdeliver; - up_current_regs()[REG_CPSR] = PSR_MODE_SVC | PSR_I_BIT; - up_current_regs()[REG_IRQ_EN] = 0; - } + sigdeliver(tcb); + tcb->xcp.sigdeliver = NULL; } /* Otherwise, we are (1) signaling a task is not running