From b996852f262671be049109d5bad1ea2136501295 Mon Sep 17 00:00:00 2001 From: hujun5 Date: Fri, 5 Jul 2024 20:53:49 +0800 Subject: [PATCH] arm64: g_current_regs is only used to determine if we are in irq, with other functionalities removed. Signed-off-by: hujun5 --- arch/arm64/src/common/arm64_cpupause.c | 12 +- arch/arm64/src/common/arm64_doirq.c | 10 +- arch/arm64/src/common/arm64_internal.h | 7 - .../src/common/arm64_schedulesigaction.c | 207 ++---------------- arch/arm64/src/common/arm64_switchcontext.c | 12 - 5 files changed, 31 insertions(+), 217 deletions(-) diff --git a/arch/arm64/src/common/arm64_cpupause.c b/arch/arm64/src/common/arm64_cpupause.c index 05bdf8a324c1c..870917ca152c8 100644 --- a/arch/arm64/src/common/arm64_cpupause.c +++ b/arch/arm64/src/common/arm64_cpupause.c @@ -116,11 +116,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. - */ - - arm64_savestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } @@ -210,11 +206,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. - */ - - arm64_restorestate(tcb->xcp.regs); + UNUSED(tcb); return OK; } diff --git a/arch/arm64/src/common/arm64_doirq.c b/arch/arm64/src/common/arm64_doirq.c index 5a45a40d26712..af0a5abe444c2 100644 --- a/arch/arm64/src/common/arm64_doirq.c +++ b/arch/arm64/src/common/arm64_doirq.c @@ -57,6 +57,8 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs) { + struct tcb_s *tcb = this_task(); + /* Nested interrupts are not supported */ DEBUGASSERT(up_current_regs() == NULL); @@ -66,10 +68,12 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs) */ up_set_current_regs(regs); + tcb->xcp.regs = 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 @@ -78,7 +82,7 @@ uint64_t *arm64_doirq(int irq, uint64_t * regs) * returning from the interrupt. */ - if (regs != up_current_regs()) + if (regs != tcb->xcp.regs) { /* need to do a context switch */ @@ -97,8 +101,8 @@ uint64_t *arm64_doirq(int irq, uint64_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/arm64/src/common/arm64_internal.h b/arch/arm64/src/common/arm64_internal.h index 35e51575bdb81..b123277353a62 100644 --- a/arch/arm64/src/common/arm64_internal.h +++ b/arch/arm64/src/common/arm64_internal.h @@ -84,13 +84,6 @@ # define CONFIG_ARCH_INTERRUPTSTACK 0 #endif -/* If the floating point unit is present and enabled, then save the - * floating point registers as well as normal ARM registers. - */ - -#define arm64_savestate(regs) (regs = up_current_regs()) -#define arm64_restorestate(regs) up_set_current_regs(regs) - /* This is the value used to mark the stack for subsequent stack monitoring * logic. */ diff --git a/arch/arm64/src/common/arm64_schedulesigaction.c b/arch/arm64/src/common/arm64_schedulesigaction.c index bc35117fe6335..2900b50106e85 100644 --- a/arch/arm64/src/common/arm64_schedulesigaction.c +++ b/arch/arm64/src/common/arm64_schedulesigaction.c @@ -127,9 +127,10 @@ void arm64_init_signal_process(struct tcb_s *tcb, struct regs_context *regs) * ****************************************************************************/ -#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) @@ -137,204 +138,32 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.sigdeliver = sigdeliver; /* First, handle some special cases when the signal is being delivered - * to task that is currently executing on this CPU. + * to task that is currently executing on any CPU. */ - 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. - */ - - /* create signal process context */ - - tcb->xcp.saved_reg = up_current_regs(); -#ifdef CONFIG_ARCH_FPU - tcb->xcp.saved_fpu_regs = tcb->xcp.fpu_regs; -#endif - arm64_init_signal_process(tcb, - (struct regs_context *)up_current_regs()); - - /* trigger switch to signal process */ - - up_set_current_regs(tcb->xcp.regs); - } + 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. - */ - -#ifdef CONFIG_ARCH_FPU - tcb->xcp.saved_fpu_regs = tcb->xcp.fpu_regs; -#endif - /* create signal process context */ - - tcb->xcp.saved_reg = tcb->xcp.regs; - arm64_init_signal_process(tcb, NULL); - } - } -} -#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. - */ + int cpu = tcb->cpu; + int me = this_cpu(); - if (cpu == me && !up_current_regs()) + if (cpu != me) { - /* In this case just deliver the signal now. - * REVISIT: Signal handler will run in a critical section! - */ + /* Pause the CPU */ - sigdeliver(tcb); - tcb->xcp.sigdeliver = NULL; + up_cpu_pause(cpu); } - - /* 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. - */ - -#ifdef CONFIG_ARCH_FPU - tcb->xcp.saved_fpu_regs = tcb->xcp.fpu_regs; -#endif - /* create signal process context */ - - tcb->xcp.saved_reg = tcb->xcp.regs; - arm64_init_signal_process(tcb, NULL); - } - 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. - */ - - /* create signal process context */ - - tcb->xcp.saved_reg = up_current_regs(); -#ifdef CONFIG_ARCH_FPU - tcb->xcp.saved_fpu_regs = tcb->xcp.fpu_regs; #endif - arm64_init_signal_process(tcb, - (struct regs_context *)up_current_regs()); - - /* trigger switch to signal process */ - - up_set_current_regs(tcb->xcp.regs); - } - - /* 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); - } - } - } - - /* 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. @@ -348,7 +177,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) /* create signal process context */ arm64_init_signal_process(tcb, NULL); + +#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/arm64/src/common/arm64_switchcontext.c b/arch/arm64/src/common/arm64_switchcontext.c index 78b9784e702da..b5ab2234d19c3 100644 --- a/arch/arm64/src/common/arm64_switchcontext.c +++ b/arch/arm64/src/common/arm64_switchcontext.c @@ -63,21 +63,9 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb) if (up_interrupt_context()) { - /* Yes, then we have to do things differently. - * Just copy the current_regs into the OLD rtcb. - */ - - arm64_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. - */ - - arm64_restorestate(tcb->xcp.regs); } /* No, then we will need to perform the user context switch */