mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 19:36:35 +08:00
arch/tricore: optimize task switching process
g_current_regs is only used to determine if we are in irq, with other functionalities removed. Signed-off-by: zhangyu117 <zhangyu117@xiaomi.com>
This commit is contained in:
@@ -79,6 +79,8 @@ IFX_INTERRUPT_INTERNAL(tricore_doirq, 0, 255)
|
|||||||
|
|
||||||
irq_dispatch(icr.B.CCPN, regs);
|
irq_dispatch(icr.B.CCPN, regs);
|
||||||
|
|
||||||
|
tcb = this_task();
|
||||||
|
|
||||||
/* Check for a context switch. If a context switch occurred, then
|
/* Check for a context switch. If a context switch occurred, then
|
||||||
* g_current_regs will have a different value than it did on entry. If an
|
* g_current_regs will have a different value than it did on entry. If an
|
||||||
* interrupt level context switch has occurred, then restore the floating
|
* interrupt level context switch has occurred, then restore the floating
|
||||||
@@ -86,10 +88,8 @@ IFX_INTERRUPT_INTERNAL(tricore_doirq, 0, 255)
|
|||||||
* returning from the interrupt.
|
* returning from the interrupt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (regs != up_current_regs())
|
if (regs != tcb->xcp.regs)
|
||||||
{
|
{
|
||||||
tcb = this_task();
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_ADDRENV
|
#ifdef CONFIG_ARCH_ADDRENV
|
||||||
/* Make sure that the address environment for the previously
|
/* Make sure that the address environment for the previously
|
||||||
* running task is closed down gracefully (data caches dump,
|
* running task is closed down gracefully (data caches dump,
|
||||||
@@ -112,7 +112,7 @@ IFX_INTERRUPT_INTERNAL(tricore_doirq, 0, 255)
|
|||||||
running_task = tcb;
|
running_task = tcb;
|
||||||
g_running_tasks[this_cpu()] = running_task;
|
g_running_tasks[this_cpu()] = running_task;
|
||||||
|
|
||||||
__mtcr(CPU_PCXI, tricore_addr2csa(up_current_regs()));
|
__mtcr(CPU_PCXI, tricore_addr2csa(tcb->xcp.regs));
|
||||||
__isync();
|
__isync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -204,11 +204,6 @@ extern uintptr_t __A0_MEM[]; /* End+1 of .data */
|
|||||||
* Inline Functions
|
* Inline Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Macros to handle saving and restoring interrupt state. */
|
|
||||||
|
|
||||||
#define tricore_savestate(regs) (regs = up_current_regs())
|
|
||||||
#define tricore_restorestate(regs) (up_set_current_regs(regs))
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -117,16 +117,16 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
* been delivered.
|
* been delivered.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tricore_savestate(tcb->xcp.saved_regs);
|
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||||
|
|
||||||
/* Create a new CSA for signal delivery. The new context
|
/* Create a new CSA for signal delivery. The new context
|
||||||
* will borrow the process stack of the current tcb.
|
* will borrow the process stack of the current tcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
up_set_current_regs(tricore_alloc_csa((uintptr_t)
|
tcb->xcp.regs =
|
||||||
tricore_sigdeliver,
|
tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
|
||||||
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
|
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
|
||||||
PSW_IO_SUPERVISOR | PSW_CDE, true));
|
PSW_IO_SUPERVISOR | PSW_CDE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +151,9 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||||||
* will borrow the process stack of the current tcb.
|
* will borrow the process stack of the current tcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tcb->xcp.regs = tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
|
tcb->xcp.regs =
|
||||||
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
|
tricore_alloc_csa((uintptr_t)tricore_sigdeliver,
|
||||||
PSW_IO_SUPERVISOR | PSW_CDE, true);
|
STACK_ALIGN_DOWN(up_getusrsp(tcb->xcp.regs)),
|
||||||
|
PSW_IO_SUPERVISOR | PSW_CDE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,14 +58,12 @@ void tricore_svcall(volatile void *trap)
|
|||||||
{
|
{
|
||||||
struct tcb_s *running_task;
|
struct tcb_s *running_task;
|
||||||
struct tcb_s *tcb;
|
struct tcb_s *tcb;
|
||||||
int cpu = this_cpu();
|
|
||||||
|
|
||||||
uintptr_t *regs;
|
uintptr_t *regs;
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
|
|
||||||
regs = (uintptr_t *)__mfcr(CPU_PCXI);
|
regs = (uintptr_t *)__mfcr(CPU_PCXI);
|
||||||
|
|
||||||
running_task = g_running_tasks[cpu];
|
running_task = g_running_tasks[this_cpu()];
|
||||||
tcb = this_task();
|
tcb = this_task();
|
||||||
|
|
||||||
/* DSYNC instruction should be executed immediately prior to the MTCR */
|
/* DSYNC instruction should be executed immediately prior to the MTCR */
|
||||||
@@ -102,14 +100,14 @@ void tricore_svcall(volatile void *trap)
|
|||||||
case SYS_restore_context:
|
case SYS_restore_context:
|
||||||
{
|
{
|
||||||
tricore_reclaim_csa(regs[REG_UPCXI]);
|
tricore_reclaim_csa(regs[REG_UPCXI]);
|
||||||
up_set_current_regs((uintptr_t *)regs[REG_D9]);
|
tcb->xcp.regs = (uintptr_t *)regs[REG_D9];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYS_switch_context:
|
case SYS_switch_context:
|
||||||
{
|
{
|
||||||
*(uintptr_t **)regs[REG_D9] = tricore_csa2addr(regs[REG_UPCXI]);
|
*(uintptr_t **)regs[REG_D9] = tricore_csa2addr(regs[REG_UPCXI]);
|
||||||
up_set_current_regs((uintptr_t *)regs[REG_D10]);
|
tcb->xcp.regs = (uintptr_t *)regs[REG_D10];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -120,7 +118,7 @@ void tricore_svcall(volatile void *trap)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regs != up_current_regs())
|
if (regs != tcb->xcp.regs)
|
||||||
{
|
{
|
||||||
/* Update scheduler parameters */
|
/* Update scheduler parameters */
|
||||||
|
|
||||||
@@ -131,9 +129,9 @@ void tricore_svcall(volatile void *trap)
|
|||||||
* crashes.
|
* crashes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g_running_tasks[cpu] = this_task();
|
g_running_tasks[this_cpu()] = this_task();
|
||||||
|
|
||||||
regs[REG_UPCXI] = tricore_addr2csa(up_current_regs());
|
regs[REG_UPCXI] = tricore_addr2csa(tcb->xcp.regs);
|
||||||
|
|
||||||
__isync();
|
__isync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,35 +59,10 @@
|
|||||||
|
|
||||||
void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
|
||||||
{
|
{
|
||||||
/* Are we in an interrupt handler? */
|
if (!up_current_regs())
|
||||||
|
|
||||||
if (up_current_regs())
|
|
||||||
{
|
|
||||||
/* Yes, then we have to do things differently.
|
|
||||||
* Just copy the g_current_regs into the OLD rtcb.
|
|
||||||
*/
|
|
||||||
|
|
||||||
tricore_savestate(rtcb->xcp.regs);
|
|
||||||
|
|
||||||
/* Then switch contexts. Any necessary address environment
|
|
||||||
* changes will be made when the interrupt returns.
|
|
||||||
*/
|
|
||||||
|
|
||||||
tricore_restorestate(tcb->xcp.regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No, then we will need to perform the user context switch */
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Then switch contexts */
|
/* Then switch contexts */
|
||||||
|
|
||||||
tricore_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
|
tricore_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
|
||||||
|
|
||||||
/* tricore_switchcontext forces a context switch to the task at the
|
|
||||||
* head of the ready-to-run list. It does not 'return' in the
|
|
||||||
* normal sense. When it does return, it is because the blocked
|
|
||||||
* task is again ready to run and has execution priority.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user