Skip to content

Commit

Permalink
arch: We can use an independent SIG interrupt to handle async pause,
Browse files Browse the repository at this point in the history
       which can save processing time.

Signed-off-by: hujun5 <hujun5@xiaomi.com>
  • Loading branch information
hujun260 committed Sep 27, 2024
1 parent 0ce3fe5 commit 26ef816
Show file tree
Hide file tree
Showing 15 changed files with 223 additions and 16 deletions.
34 changes: 30 additions & 4 deletions arch/arm/src/armv7-a/arm_cpupause.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,34 @@ int up_cpu_paused_restore(void)
return OK;
}

/****************************************************************************
* Name: arm_pause_async_handler
*
* Description:
* This is the handler for async pause.
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It porcess g_delivertasks
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* Standard interrupt handling
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/

int arm_pause_async_handler(int irq, void *context, void *arg)
{
int cpu = this_cpu();

nxsched_process_delivered(cpu);
return OK;
}

/****************************************************************************
* Name: arm_pause_handler
*
Expand Down Expand Up @@ -256,8 +284,6 @@ int arm_pause_handler(int irq, void *context, void *arg)
leave_critical_section(flags);
}

nxsched_process_delivered(cpu);

return OK;
}

Expand All @@ -282,7 +308,7 @@ int arm_pause_handler(int irq, void *context, void *arg)

inline_function int up_cpu_pause_async(int cpu)
{
arm_cpu_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));
arm_cpu_sgi(GIC_SMP_CPUPAUSE_ASYNC, (1 << cpu));

return OK;
}
Expand Down Expand Up @@ -331,7 +357,7 @@ int up_cpu_pause(int cpu)
spin_lock(&g_cpu_wait[cpu]);
spin_lock(&g_cpu_paused[cpu]);

up_cpu_pause_async(cpu);
arm_cpu_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));

/* Wait for the other CPU to unlock g_cpu_paused meaning that
* it is fully paused and ready for up_cpu_resume();
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/src/armv7-a/arm_gicv2.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ void arm_gic0_initialize(void)

DEBUGVERIFY(irq_attach(GIC_SMP_CPUSTART, arm_start_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm_pause_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE_ASYNC,
arm_pause_async_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
nxsched_smp_call_handler, NULL));
#endif
Expand Down
25 changes: 25 additions & 0 deletions arch/arm/src/armv7-a/gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,10 +619,12 @@
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI12
#else
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI4
#endif

/****************************************************************************
Expand Down Expand Up @@ -839,6 +841,29 @@ int arm_start_handler(int irq, void *context, void *arg);
int arm_pause_handler(int irq, void *context, void *arg);
#endif

/****************************************************************************
* Name: arm_pause_async_handler
*
* Description:
* This is the handler for async pause.
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It porcess g_delivertasks
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* Standard interrupt handling
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/

#ifdef CONFIG_SMP
int arm_pause_async_handler(int irq, void *context, void *arg);
#endif
/****************************************************************************
* Name: arm_gic_dump
*
Expand Down
34 changes: 29 additions & 5 deletions arch/arm/src/armv7-r/arm_cpupause.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,6 @@ int up_cpu_paused_restore(void)

int arm_pause_handler(int irq, void *context, void *arg)
{
int cpu = this_cpu();

/* Check for false alarms. Such false could occur as a consequence of
* some deadlock breaking logic that might have already serviced the SG2
* interrupt by calling up_cpu_paused(). If the pause event has already
Expand All @@ -256,8 +254,34 @@ int arm_pause_handler(int irq, void *context, void *arg)
leave_critical_section(flags);
}

nxsched_process_delivered(cpu);
return OK;
}

/****************************************************************************
* Name: arm_pause_async_handler
*
* Description:
* This is the handler for async pause.
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It porcess g_delivertasks
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* Standard interrupt handling
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/

int arm_pause_async_handler(int irq, void *context, void *arg)
{
int cpu = this_cpu();

nxsched_process_delivered(cpu);
return OK;
}

Expand All @@ -282,7 +306,7 @@ int arm_pause_handler(int irq, void *context, void *arg)

inline_function int up_cpu_pause_async(int cpu)
{
arm_cpu_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));
arm_cpu_sgi(GIC_SMP_CPUPAUSE_ASYNC, (1 << cpu));

return OK;
}
Expand Down Expand Up @@ -331,7 +355,7 @@ int up_cpu_pause(int cpu)
spin_lock(&g_cpu_wait[cpu]);
spin_lock(&g_cpu_paused[cpu]);

up_cpu_pause_async(cpu);
arm_cpu_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));

/* Wait for the other CPU to unlock g_cpu_paused meaning that
* it is fully paused and ready for up_cpu_resume();
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/src/armv7-r/arm_gicv2.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ void arm_gic0_initialize(void)

DEBUGVERIFY(irq_attach(GIC_SMP_CPUSTART, arm_start_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm_pause_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE_ASYNC,
arm_pause_async_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
nxsched_smp_call_handler, NULL));
#endif
Expand Down
26 changes: 26 additions & 0 deletions arch/arm/src/armv7-r/gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,12 @@
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI12
#else
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI4
#endif

/****************************************************************************
Expand Down Expand Up @@ -827,6 +829,30 @@ int arm_start_handler(int irq, void *context, void *arg);
int arm_pause_handler(int irq, void *context, void *arg);
#endif

/****************************************************************************
* Name: arm_pause_async_handler
*
* Description:
* This is the handler for async pause.
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It porcess g_delivertasks
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* Standard interrupt handling
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/

#ifdef CONFIG_SMP
int arm_pause_async_handler(int irq, void *context, void *arg);
#endif

/****************************************************************************
* Name: arm_gic_dump
*
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/src/armv8-r/arm_gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,12 @@
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI12
#else
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI4
#endif

/****************************************************************************
Expand Down Expand Up @@ -355,6 +357,10 @@ int arm_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);

int arm_pause_handler(int irq, void *context, void *arg);

#ifdef CONFIG_SMP
int arm_pause_async_handler(int irq, void *context, void *arg);
#endif

void arm_gic_secondary_init(void);

#endif
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/src/armv8-r/arm_gicv3.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ static void gicv3_dist_init(void)
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */

DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm64_pause_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE_ASYNC,
arm64_pause_async_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
nxsched_smp_call_handler, NULL));
#endif
Expand Down Expand Up @@ -814,6 +816,7 @@ static void arm_gic_init(void)

#ifdef CONFIG_SMP
up_enable_irq(GIC_SMP_CPUPAUSE);
up_enable_irq(GIC_SMP_CPUPAUSE_ASYNC);
#endif
}

Expand Down
35 changes: 31 additions & 4 deletions arch/arm64/src/common/arm64_cpupause.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,35 @@ int up_cpu_paused_restore(void)
return OK;
}

/****************************************************************************
* Name: arm64_pause_async_handler
*
* Description:
* This is the handler for async pause.
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It porcess g_delivertasks
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* Standard interrupt handling
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/

int arm64_pause_async_handler(int irq, void *context, void *arg)
{
int cpu = this_cpu();

nxsched_process_delivered(cpu);

return OK;
}

/****************************************************************************
* Name: arm64_pause_handler
*
Expand Down Expand Up @@ -259,8 +288,6 @@ int arm64_pause_handler(int irq, void *context, void *arg)
leave_critical_section(flags);
}

nxsched_process_delivered(cpu);

return OK;
}

Expand All @@ -287,7 +314,7 @@ inline_function int up_cpu_pause_async(int cpu)
{
/* Execute SGI2 */

arm64_gic_raise_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));
arm64_gic_raise_sgi(GIC_SMP_CPUPAUSE_ASYNC, (1 << cpu));

return OK;
}
Expand Down Expand Up @@ -336,7 +363,7 @@ int up_cpu_pause(int cpu)
spin_lock(&g_cpu_wait[cpu]);
spin_lock(&g_cpu_paused[cpu]);

up_cpu_pause_async(cpu);
arm64_gic_raise_sgi(GIC_SMP_CPUPAUSE, (1 << cpu));

/* Wait for the other CPU to unlock g_cpu_paused meaning that
* it is fully paused and ready for up_cpu_resume();
Expand Down
24 changes: 24 additions & 0 deletions arch/arm64/src/common/arm64_gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,12 @@
#define GIC_IRQ_SGI15 15

#ifdef CONFIG_ARCH_TRUSTZONE_SECURE
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI8
# define GIC_SMP_CPUSTART GIC_IRQ_SGI9
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI10
# define GIC_SMP_CPUCALL GIC_IRQ_SGI11
#else
# define GIC_SMP_CPUPAUSE_ASYNC GIC_IRQ_SGI0
# define GIC_SMP_CPUSTART GIC_IRQ_SGI1
# define GIC_SMP_CPUPAUSE GIC_IRQ_SGI2
# define GIC_SMP_CPUCALL GIC_IRQ_SGI3
Expand Down Expand Up @@ -343,6 +345,28 @@ void arm64_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);

int arm64_pause_handler(int irq, void *context, void *arg);

/****************************************************************************
* Name: arm64_pause_async_handler
*
* Description:
* This is the handler for async pause.
*
* 1. It saves the current task state at the head of the current assigned
* task list.
* 2. It porcess g_delivertasks
* 3. Returns from interrupt, restoring the state of the new task at the
* head of the ready to run list.
*
* Input Parameters:
* Standard interrupt handling
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
****************************************************************************/

int arm64_pause_async_handler(int irq, void *context, void *arg);

void arm64_gic_secondary_init(void);

#endif
Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/src/common/arm64_gicv2.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,8 @@ static void arm_gic0_initialize(void)
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */

DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE, arm64_pause_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUPAUSE_ASYNC,
arm64_pause_async_handler, NULL));
DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL,
nxsched_smp_call_handler, NULL));
#endif
Expand Down
Loading

0 comments on commit 26ef816

Please sign in to comment.