arm64: g_current_regs is only used to determine if we are in irq, with other functionalities removed.
Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
d573952790
commit
8cd52bee2e
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -126,99 +126,8 @@ 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)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
@ -231,109 +140,29 @@ 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());
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
#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.
|
||||
@ -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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user