Skip to content

Commit

Permalink
arm64: g_current_regs is only used to determine if we are in irq,
Browse files Browse the repository at this point in the history
with other functionalities removed.

Signed-off-by: hujun5 <[email protected]>
  • Loading branch information
hujun260 committed Sep 19, 2024
1 parent 1b52a96 commit 33662c6
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 217 deletions.
12 changes: 2 additions & 10 deletions arch/arm64/src/common/arm64_cpupause.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
10 changes: 7 additions & 3 deletions arch/arm64/src/common/arm64_doirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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 */

Expand All @@ -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
Expand Down
7 changes: 0 additions & 7 deletions arch/arm64/src/common/arm64_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
207 changes: 22 additions & 185 deletions arch/arm64/src/common/arm64_schedulesigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,214 +126,43 @@ 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)
{
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.
Expand All @@ -347,7 +176,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 */
12 changes: 0 additions & 12 deletions arch/arm64/src/common/arm64_switchcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 33662c6

Please sign in to comment.