You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/10/10 17:31:19 UTC
(nuttx) 21/28: arch: remove up_cpu_pause up_cpu_resume up_cpu_paused up_cpu_pausereq
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch releases/12.7
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d54bc8a9f86329203e32d38fc2a70da4c9ef1e87
Author: hujun5 <hu...@xiaomi.com>
AuthorDate: Mon Jul 29 20:47:46 2024 +0800
arch: remove up_cpu_pause up_cpu_resume up_cpu_paused up_cpu_pausereq
reason:
To remove the "sync pause" and decouple the critical section from the dependency on enabling interrupts,
after that we need to further implement "schedlock + spinlock".
changelist
1 Modify the implementation of critical sections to no longer involve enabling interrupts or handling synchronous pause events.
2 GIC_SMP_CPUCALL attach to pause handler to remove arch interface up_cpu_paused_restore up_cpu_paused_save
3 Completely remove up_cpu_pause, up_cpu_resume, up_cpu_paused, and up_cpu_pausereq
4 change up_cpu_pause_async to up_send_cpu_sgi
Signed-off-by: hujun5 <hu...@xiaomi.com>
---
arch/arm/src/armv7-a/arm_cpupause.c | 322 ---------------------------
arch/arm/src/armv7-a/arm_gicv2.c | 4 +-
arch/arm/src/armv7-a/gic.h | 24 --
arch/arm/src/armv7-r/arm_cpupause.c | 320 --------------------------
arch/arm/src/armv7-r/arm_gicv2.c | 4 +-
arch/arm/src/armv7-r/gic.h | 24 --
arch/arm/src/armv8-r/arm_gic.h | 25 ---
arch/arm/src/armv8-r/arm_gicv3.c | 3 +-
arch/arm/src/cxd56xx/cxd56_cpupause.c | 345 +----------------------------
arch/arm/src/lc823450/lc823450_cpupause.c | 295 ------------------------
arch/arm/src/lc823450/lc823450_cpustart.c | 2 +-
arch/arm/src/rp2040/rp2040_cpupause.c | 331 ---------------------------
arch/arm/src/sam34/sam4cm_cpupause.c | 283 -----------------------
arch/arm64/src/common/arm64_cpupause.c | 327 ---------------------------
arch/arm64/src/common/arm64_gic.h | 22 --
arch/arm64/src/common/arm64_gicv2.c | 1 -
arch/arm64/src/common/arm64_gicv3.c | 2 -
arch/risc-v/src/common/riscv_cpupause.c | 302 -------------------------
arch/sim/src/sim/sim_smpsignal.c | 316 ++------------------------
arch/sparc/src/s698pm/s698pm_cpupause.c | 306 +------------------------
arch/x86_64/src/intel64/intel64_cpupause.c | 318 +-------------------------
arch/xtensa/src/common/xtensa_cpupause.c | 281 +----------------------
include/nuttx/arch.h | 148 -------------
include/nuttx/irq.h | 1 +
sched/irq/irq_csection.c | 139 +-----------
sched/sched/CMakeLists.txt | 1 -
sched/sched/Make.defs | 2 +-
sched/sched/sched.h | 2 -
sched/sched/sched_cpupause.c | 106 ---------
sched/sched/sched_process_delivered.c | 8 +-
sched/sched/sched_removereadytorun.c | 16 +-
sched/sched/sched_smp.c | 2 -
32 files changed, 42 insertions(+), 4240 deletions(-)
diff --git a/arch/arm/src/armv7-a/arm_cpupause.c b/arch/arm/src/armv7-a/arm_cpupause.c
index 81dc1a534e..271ead55b7 100644
--- a/arch/arm/src/armv7-a/arm_cpupause.c
+++ b/arch/arm/src/armv7-a/arm_cpupause.c
@@ -42,172 +42,10 @@
* Private Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Release the g_cpu_paused spinlock to synchronize with the
- * requesting CPU.
- */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- /* Wait for the spinlock to be released. The requesting CPU will release
- * the spinlock when the CPU is resumed.
- */
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: arm_pause_async_handler
*
@@ -236,57 +74,6 @@ int arm_pause_async_handler(int irq, void *context, void *arg)
return OK;
}
-/****************************************************************************
- * Name: arm_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_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
- * been processed then g_cpu_paused[cpu] will not be locked.
- */
-
- if (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
- return OK;
-}
-
/****************************************************************************
* Name: up_cpu_pause_async
*
@@ -313,113 +100,4 @@ inline_function int up_cpu_pause_async(int cpu)
return OK;
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[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();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/armv7-a/arm_gicv2.c b/arch/arm/src/armv7-a/arm_gicv2.c
index bb4dba3717..78f189e2c9 100644
--- a/arch/arm/src/armv7-a/arm_gicv2.c
+++ b/arch/arm/src/armv7-a/arm_gicv2.c
@@ -219,11 +219,9 @@ void arm_gic0_initialize(void)
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
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));
+ DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL, nxsched_smp_call_handler, NULL));
#endif
arm_gic_dump("Exit arm_gic0_initialize", true, 0);
diff --git a/arch/arm/src/armv7-a/gic.h b/arch/arm/src/armv7-a/gic.h
index ce7cbd0ec6..34d53db92c 100644
--- a/arch/arm/src/armv7-a/gic.h
+++ b/arch/arm/src/armv7-a/gic.h
@@ -835,30 +835,6 @@ uint32_t *arm_decodefiq(uint32_t *regs);
int arm_start_handler(int irq, void *context, void *arg);
#endif
-/****************************************************************************
- * Name: arm_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_handler(int irq, void *context, void *arg);
-#endif
-
/****************************************************************************
* Name: arm_pause_async_handler
*
diff --git a/arch/arm/src/armv7-r/arm_cpupause.c b/arch/arm/src/armv7-r/arm_cpupause.c
index c7d1ebe38e..51a9af8dc0 100644
--- a/arch/arm/src/armv7-r/arm_cpupause.c
+++ b/arch/arm/src/armv7-r/arm_cpupause.c
@@ -42,221 +42,10 @@
* Private Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Release the g_cpu_paused spinlock to synchronize with the
- * requesting CPU.
- */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- /* Wait for the spinlock to be released. The requesting CPU will release
- * the spinlock when the CPU is resumed.
- */
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: arm_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_handler(int irq, void *context, void *arg)
-{
- /* 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
- * been processed then g_cpu_paused[cpu] will not be locked.
- */
-
- if (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
- return OK;
-}
-
/****************************************************************************
* Name: arm_pause_async_handler
*
@@ -311,113 +100,4 @@ inline_function int up_cpu_pause_async(int cpu)
return OK;
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[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();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/armv7-r/arm_gicv2.c b/arch/arm/src/armv7-r/arm_gicv2.c
index 431ace37a4..7851e6fcd7 100644
--- a/arch/arm/src/armv7-r/arm_gicv2.c
+++ b/arch/arm/src/armv7-r/arm_gicv2.c
@@ -160,11 +160,9 @@ void arm_gic0_initialize(void)
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
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));
+ DEBUGVERIFY(irq_attach(GIC_SMP_CPUCALL, nxsched_smp_call_handler, NULL));
#endif
arm_gic_dump("Exit arm_gic0_initialize", true, 0);
diff --git a/arch/arm/src/armv7-r/gic.h b/arch/arm/src/armv7-r/gic.h
index d863233056..5a0a284e52 100644
--- a/arch/arm/src/armv7-r/gic.h
+++ b/arch/arm/src/armv7-r/gic.h
@@ -805,30 +805,6 @@ uint32_t *arm_decodeirq(uint32_t *regs);
int arm_start_handler(int irq, void *context, void *arg);
#endif
-/****************************************************************************
- * Name: arm_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_handler(int irq, void *context, void *arg);
-#endif
-
/****************************************************************************
* Name: arm_pause_async_handler
*
diff --git a/arch/arm/src/armv8-r/arm_gic.h b/arch/arm/src/armv8-r/arm_gic.h
index 717e3660d2..b8b9b588d9 100644
--- a/arch/arm/src/armv8-r/arm_gic.h
+++ b/arch/arm/src/armv8-r/arm_gic.h
@@ -335,32 +335,7 @@ int arm_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);
#ifdef CONFIG_SMP
-/****************************************************************************
- * Name: arm_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_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
diff --git a/arch/arm/src/armv8-r/arm_gicv3.c b/arch/arm/src/armv8-r/arm_gicv3.c
index d32db05ac7..d7dfe2b47f 100644
--- a/arch/arm/src/armv8-r/arm_gicv3.c
+++ b/arch/arm/src/armv8-r/arm_gicv3.c
@@ -567,7 +567,6 @@ static void gicv3_dist_init(void)
#ifdef CONFIG_SMP
/* 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,
@@ -815,7 +814,7 @@ static void arm_gic_init(void)
gicv3_cpuif_init();
#ifdef CONFIG_SMP
- up_enable_irq(GIC_SMP_CPUPAUSE);
+ up_enable_irq(GIC_SMP_CPUCALL);
up_enable_irq(GIC_SMP_CPUPAUSE_ASYNC);
#endif
}
diff --git a/arch/arm/src/cxd56xx/cxd56_cpupause.c b/arch/arm/src/cxd56xx/cxd56_cpupause.c
index 42807545bf..fe655bff7f 100644
--- a/arch/arm/src/cxd56xx/cxd56_cpupause.c
+++ b/arch/arm/src/cxd56xx/cxd56_cpupause.c
@@ -56,24 +56,6 @@
* Private Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
static volatile int g_irq_to_handle[CONFIG_SMP_NCPUS][2];
/****************************************************************************
@@ -109,14 +91,6 @@ static bool handle_irqreq(int cpu)
if (irqreq)
{
- /* Unlock the spinlock first */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Then wait for the spinlock to be released */
-
- spin_lock(&g_cpu_wait[cpu]);
-
/* Clear g_irq_to_handle[cpu][i] */
g_irq_to_handle[cpu][i] = 0;
@@ -130,9 +104,6 @@ static bool handle_irqreq(int cpu)
up_disable_irq(irqreq);
}
- /* Finally unlock the spinlock */
-
- spin_unlock(&g_cpu_wait[cpu]);
handled = true;
break;
@@ -146,151 +117,6 @@ static bool handle_irqreq(int cpu)
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Fistly, check if this IPI is to enable/disable IRQ */
-
- if (handle_irqreq(cpu))
- {
- return OK;
- }
-
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: arm_pause_handler
*
@@ -310,6 +136,8 @@ int arm_pause_handler(int irq, void *c, void *arg)
int cpu = this_cpu();
int ret = OK;
+ handle_irqreq(cpu);
+
nxsched_smp_call_handler(irq, c, arg);
DPRINTF("cpu%d will be paused\n", cpu);
@@ -318,41 +146,6 @@ int arm_pause_handler(int irq, void *c, void *arg)
putreg32(0, CXD56_CPU_P2_INT + (4 * 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 (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() would call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: Normally, we do not call up_cpu_paused() here because
- * the above enter_critical_setion() would call up_cpu_paused()
- * inside because the caller holds a crtical section.
- * However, cxd56's remote IRQ control logic also uses this handler
- * and a caller might not take a critical section to avoid a deadlock
- * during up_enable_irq() and up_disable_irq(). This is allowed
- * because IRQ control logic does not interact wtih the scheduler.
- * This means that if the request was not handled above, we need
- * to call up_cpu_paused() here again.
- */
-
- if (up_cpu_pausereq(cpu))
- {
- ret = up_cpu_paused(cpu);
- }
-
- leave_critical_section(flags);
- }
-
nxsched_process_delivered(cpu);
return ret;
@@ -411,120 +204,6 @@ void up_send_smp_call(cpu_set_t cpuset)
}
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- /* Generate IRQ for CPU(cpu) */
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
- return OK;
-}
-
/****************************************************************************
* Name: up_send_irqreq()
*
@@ -546,11 +225,6 @@ void up_send_irqreq(int idx, int irq, int cpu)
{
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
- /* Wait for the spinlocks to be released */
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
/* Set irq for the cpu */
g_irq_to_handle[cpu][idx] = irq;
@@ -558,21 +232,6 @@ void up_send_irqreq(int idx, int irq, int cpu)
/* Generate IRQ for CPU(cpu) */
putreg32(1, CXD56_CPU_P2_INT + (4 * cpu));
-
- /* Wait for the handler is executed on cpu */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Finally unlock the spinlock to proceed the handler */
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
}
#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/lc823450/lc823450_cpupause.c b/arch/arm/src/lc823450/lc823450_cpupause.c
index b4249b36d9..162e79da8b 100644
--- a/arch/arm/src/lc823450/lc823450_cpupause.c
+++ b/arch/arm/src/lc823450/lc823450_cpupause.c
@@ -52,166 +52,10 @@
* Public Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: lc823450_pause_handler
*
@@ -245,29 +89,6 @@ int lc823450_pause_handler(int irq, void *c, void *arg)
putreg32(IPICLR_INTISR1_CLR_1, IPICLR);
}
- /* 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 (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
nxsched_process_delivered(cpu);
return OK;
@@ -332,119 +153,3 @@ void up_send_smp_call(cpu_set_t cpuset)
up_cpu_pause_async(cpu);
}
}
-
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- /* Execute Pause IRQ to CPU(cpu) */
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
diff --git a/arch/arm/src/lc823450/lc823450_cpustart.c b/arch/arm/src/lc823450/lc823450_cpustart.c
index 8611eea093..34936eee19 100644
--- a/arch/arm/src/lc823450/lc823450_cpustart.c
+++ b/arch/arm/src/lc823450/lc823450_cpustart.c
@@ -63,7 +63,7 @@
* Public Data
****************************************************************************/
-extern volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
+static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
/****************************************************************************
* Private Functions
diff --git a/arch/arm/src/rp2040/rp2040_cpupause.c b/arch/arm/src/rp2040/rp2040_cpupause.c
index d71a3c5f65..434bdd4fef 100644
--- a/arch/arm/src/rp2040/rp2040_cpupause.c
+++ b/arch/arm/src/rp2040/rp2040_cpupause.c
@@ -50,28 +50,6 @@
#define DPRINTF(fmt, args...) do {} while (0)
#endif
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Name: rp2040_handle_irqreq
*
@@ -88,14 +66,6 @@ static void rp2040_handle_irqreq(int irqreq)
{
DEBUGASSERT(this_cpu() == 0);
- /* Unlock the spinlock first */
-
- spin_unlock(&g_cpu_paused[0]);
-
- /* Then wait for the spinlock to be released */
-
- spin_lock(&g_cpu_wait[0]);
-
if (irqreq > 0)
{
up_enable_irq(irqreq);
@@ -104,154 +74,12 @@ static void rp2040_handle_irqreq(int irqreq)
{
up_disable_irq(-irqreq);
}
-
- /* Finally unlock the spinlock */
-
- spin_unlock(&g_cpu_wait[0]);
}
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: arm_pause_handler
*
@@ -301,29 +129,6 @@ int arm_pause_handler(int irq, void *c, void *arg)
DPRINTF("cpu%d will be paused\n", 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 (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
nxsched_process_delivered(cpu);
return OK;
@@ -384,122 +189,6 @@ void up_send_smp_call(cpu_set_t cpuset)
}
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- DEBUGASSERT(cpu != this_cpu());
-
- /* Generate IRQ for CPU(cpu) */
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
- return OK;
-}
-
/****************************************************************************
* Name: rp2040_send_irqreq()
*
@@ -517,31 +206,11 @@ int up_cpu_resume(int cpu)
void rp2040_send_irqreq(int irqreq)
{
- /* Wait for the spinlocks to be released */
-
- spin_lock(&g_cpu_wait[0]);
- spin_lock(&g_cpu_paused[0]);
-
/* Send IRQ number to Core #0 */
while (!(getreg32(RP2040_SIO_FIFO_ST) & RP2040_SIO_FIFO_ST_RDY))
;
putreg32(irqreq, RP2040_SIO_FIFO_WR);
-
- /* Wait for the handler is executed on cpu */
-
- spin_lock(&g_cpu_paused[0]);
- spin_unlock(&g_cpu_paused[0]);
-
- /* Finally unlock the spinlock to proceed the handler */
-
- spin_unlock(&g_cpu_wait[0]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[0]);
-
- spin_unlock(&g_cpu_resumed[0]);
}
#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/sam34/sam4cm_cpupause.c b/arch/arm/src/sam34/sam4cm_cpupause.c
index 2ebc5ea2d9..aba110580a 100644
--- a/arch/arm/src/sam34/sam4cm_cpupause.c
+++ b/arch/arm/src/sam34/sam4cm_cpupause.c
@@ -54,166 +54,10 @@
* Private Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: arm_pause_handler
*
@@ -249,16 +93,6 @@ int arm_pause_handler(int irq, void *c, void *arg)
putreg32(0x1, SAM_IPC0_ICCR);
}
- /* 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 (spin_is_locked(&g_cpu_paused[cpu]))
- {
- return up_cpu_paused(cpu);
- }
-
nxsched_process_delivered(cpu);
return OK;
@@ -326,121 +160,4 @@ void up_send_smp_call(cpu_set_t cpuset)
}
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the
- * interrupt handler from returning until up_cpu_resume() is called;
- * g_cpu_paused is a handshake that will prefent this function from
- * returning until the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- /* Execute Pause IRQ to CPU(cpu) */
-
- /* Set IPC Interrupt (IRQ0) (write-only) */
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DPRINTF("cpu=%d\n", cpu);
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
#endif /* CONFIG_SMP */
diff --git a/arch/arm64/src/common/arm64_cpupause.c b/arch/arm64/src/common/arm64_cpupause.c
index da81259d8d..4c893bfad0 100644
--- a/arch/arm64/src/common/arm64_cpupause.c
+++ b/arch/arm64/src/common/arm64_cpupause.c
@@ -41,176 +41,10 @@
* Private Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Release the g_cpu_paused spinlock to synchronize with the
- * requesting CPU.
- */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- /* Wait for the spinlock to be released. The requesting CPU will release
- * the spinlock when the CPU is resumed.
- */
-
- spin_lock(&g_cpu_wait[cpu]);
-
- /* This CPU has been resumed. Restore the exception context of the TCB at
- * the (new) head of the assigned task list.
- */
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: arm64_pause_async_handler
*
@@ -240,57 +74,6 @@ int arm64_pause_async_handler(int irq, void *context, void *arg)
return OK;
}
-/****************************************************************************
- * Name: arm64_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_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
- * been processed then g_cpu_paused[cpu] will not be locked.
- */
-
- if (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
- return OK;
-}
-
/****************************************************************************
* Name: up_cpu_pause_async
*
@@ -318,113 +101,3 @@ inline_function int up_cpu_pause_async(int cpu)
return OK;
}
-
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[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();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
diff --git a/arch/arm64/src/common/arm64_gic.h b/arch/arm64/src/common/arm64_gic.h
index 191e40aa7c..20ae8d8e57 100644
--- a/arch/arm64/src/common/arm64_gic.h
+++ b/arch/arm64/src/common/arm64_gic.h
@@ -328,28 +328,6 @@ int arm64_gic_v2m_initialize(void);
#ifdef CONFIG_SMP
-/****************************************************************************
- * Name: arm64_pause_handler
- *
- * Description:
- * This is the handler for SGI2. It performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 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_handler(int irq, void *context, void *arg);
-
/****************************************************************************
* Name: arm64_pause_async_handler
*
diff --git a/arch/arm64/src/common/arm64_gicv2.c b/arch/arm64/src/common/arm64_gicv2.c
index a69c881305..bdeccde1ee 100644
--- a/arch/arm64/src/common/arm64_gicv2.c
+++ b/arch/arm64/src/common/arm64_gicv2.c
@@ -864,7 +864,6 @@ static void arm_gic0_initialize(void)
#ifdef CONFIG_SMP
/* 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,
diff --git a/arch/arm64/src/common/arm64_gicv3.c b/arch/arm64/src/common/arm64_gicv3.c
index 81fe66bb49..d501a76786 100644
--- a/arch/arm64/src/common/arm64_gicv3.c
+++ b/arch/arm64/src/common/arm64_gicv3.c
@@ -653,7 +653,6 @@ static void gicv3_dist_init(void)
#ifdef CONFIG_SMP
/* 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,
@@ -953,7 +952,6 @@ static void arm64_gic_init(void)
gicv3_cpuif_init();
#ifdef CONFIG_SMP
- up_enable_irq(GIC_SMP_CPUPAUSE);
up_enable_irq(GIC_SMP_CPUPAUSE_ASYNC);
up_enable_irq(GIC_SMP_CPUCALL);
#endif
diff --git a/arch/risc-v/src/common/riscv_cpupause.c b/arch/risc-v/src/common/riscv_cpupause.c
index 148706ca44..87f0be026d 100644
--- a/arch/risc-v/src/common/riscv_cpupause.c
+++ b/arch/risc-v/src/common/riscv_cpupause.c
@@ -43,174 +43,10 @@
* Public Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- 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.
- */
-
- riscv_savecontext(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- /* Then switch contexts. Any necessary address environment changes
- * will be made when the interrupt returns.
- */
-
- riscv_restorecontext(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: riscv_pause_handler
*
@@ -236,29 +72,6 @@ int riscv_pause_handler(int irq, void *c, void *arg)
riscv_ipi_clear(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 (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
tcb = current_task(cpu);
riscv_savecontext(tcb);
nxsched_process_delivered(cpu);
@@ -321,118 +134,3 @@ void up_send_smp_call(cpu_set_t cpuset)
}
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- sinfo("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- /* Execute Pause IRQ to CPU(cpu) */
-
- riscv_ipi_send(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- sinfo("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
diff --git a/arch/sim/src/sim/sim_smpsignal.c b/arch/sim/src/sim/sim_smpsignal.c
index 140ea6f879..6ca2953fcf 100644
--- a/arch/sim/src/sim/sim_smpsignal.c
+++ b/arch/sim/src/sim/sim_smpsignal.c
@@ -33,77 +33,26 @@
#include "sched/sched.h"
#include "sim_internal.h"
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
- * Name: sim_cpupause_handler
+ * Name: sim_smp_call_handler
*
* Description:
- * This is the SIGUSR signal handler. It implements the core logic of
- * up_cpu_pause() on the thread of execution the simulated CPU.
- *
- * Input Parameters:
- * irq - the interrupt number
- * context - not used
- * arg - not used
- *
- * Returned Value:
- * In case of success OK (0) is returned otherwise a negative value.
+ * This is the handler for SMP_CALL.
*
****************************************************************************/
-static int sim_cpupause_handler(int irq, void *context, void *arg)
+static int sim_smp_call_handler(int irq, void *context, void *arg)
{
struct tcb_s *tcb;
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
- * been processed then g_cpu_paused[cpu] will not be locked.
- */
-
- if (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
tcb = current_task(cpu);
sim_savestate(tcb->xcp.regs);
- nxsched_process_delivered(cpu);
+ nxsched_smp_call_handler(irq, context, arg);
tcb = current_task(cpu);
sim_restorestate(tcb->xcp.regs);
@@ -111,155 +60,40 @@ static int sim_cpupause_handler(int irq, void *context, void *arg)
}
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
+ * Name: sim_cpupause_handler
*
* Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
+ * This is the SIGUSR signal handler. It implements the core logic of
+ * up_cpu_pause() on the thread of execution the simulated CPU.
*
* Input Parameters:
- * None
+ * irq - the interrupt number
+ * context - not used
+ * arg - not used
*
* Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
+ * In case of success OK (0) is returned otherwise a negative value.
*
****************************************************************************/
-int up_cpu_paused_save(void)
+static int sim_cpupause_handler(int irq, void *context, void *arg)
{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- 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.
- */
+ struct tcb_s *tcb;
+ int cpu = this_cpu();
+ tcb = current_task(cpu);
sim_savestate(tcb->xcp.regs);
+ nxsched_process_delivered(cpu);
+ tcb = current_task(cpu);
+ sim_restorestate(tcb->xcp.regs);
return OK;
}
/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
+ * Public Functions
****************************************************************************/
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- /* Then switch contexts. Any necessary address environment changes
- * will be made when the interrupt returns.
- */
-
- sim_restorestate(tcb->xcp.regs);
-
- return OK;
-}
-
/****************************************************************************
* Name: host_cpu_started
*
@@ -370,115 +204,6 @@ inline_function int up_cpu_pause_async(int cpu)
return OK;
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-#ifdef CONFIG_SMP
-
/****************************************************************************
* Name: sim_init_func_call_ipi
*
@@ -495,7 +220,7 @@ int up_cpu_resume(int cpu)
int sim_init_func_call_ipi(int irq)
{
up_enable_irq(irq);
- return irq_attach(irq, nxsched_smp_call_handler, NULL);
+ return irq_attach(irq, sim_smp_call_handler, NULL);
}
/****************************************************************************
@@ -516,4 +241,3 @@ void up_send_smp_call(cpu_set_t cpuset)
host_send_func_call_ipi(cpu);
}
}
-#endif
diff --git a/arch/sparc/src/s698pm/s698pm_cpupause.c b/arch/sparc/src/s698pm/s698pm_cpupause.c
index 225ef9ec24..a9b9b570f6 100644
--- a/arch/sparc/src/s698pm/s698pm_cpupause.c
+++ b/arch/sparc/src/s698pm/s698pm_cpupause.c
@@ -42,174 +42,10 @@
* Public Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- 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.
- */
-
- sparc_savestate(tcb->xcp.regs);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- /* Then switch contexts. Any necessary address environment changes
- * will be made when the interrupt returns.
- */
-
- sparc_restorestate(tcb->xcp.regs);
-
- return OK;
-}
-
/****************************************************************************
* Name: s698pm_pause_handler
*
@@ -229,37 +65,13 @@ int s698pm_pause_handler(int irq, void *c, void *arg)
struct tcb_s *tcb;
int cpu = this_cpu();
- nxsched_smp_call_handler(irq, c, arg);
-
/* Clear IPI (Inter-Processor-Interrupt) */
putreg32(1 << S698PM_IPI_VECTOR, S698PM_IRQREG_ICLEAR);
- /* 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 (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
tcb = current_task(cpu);
sparc_savestate(tcb->xcp.regs);
+ nxsched_smp_call_handler(irq, c, arg);
nxsched_process_delivered(cpu);
tcb = current_task(cpu);
sparc_restorestate(tcb->xcp.regs);
@@ -322,119 +134,3 @@ void up_send_smp_call(cpu_set_t cpuset)
up_cpu_pause_async(cpu);
}
}
-
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- sinfo("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- /* Execute Pause IRQ to CPU(cpu) */
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- sinfo("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
diff --git a/arch/x86_64/src/intel64/intel64_cpupause.c b/arch/x86_64/src/intel64/intel64_cpupause.c
index 9d95e8f08d..a1932e615b 100644
--- a/arch/x86_64/src/intel64/intel64_cpupause.c
+++ b/arch/x86_64/src/intel64/intel64_cpupause.c
@@ -44,180 +44,10 @@
* Public Data
****************************************************************************/
-/* These spinlocks are used in the SMP configuration in order to implement
- * up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
- *
- * 1. The up_cpu_pause() implementation on CPUn locks both g_cpu_wait[m]
- * and g_cpu_paused[m]. CPUn then waits spinning on g_cpu_paused[m].
- * 2. CPUm receives the interrupt it (1) unlocks g_cpu_paused[m] and
- * (2) locks g_cpu_wait[m]. The first unblocks CPUn and the second
- * blocks CPUm in the interrupt handler.
- *
- * When CPUm resumes, CPUn unlocks g_cpu_wait[m] and the interrupt handler
- * on CPUm continues. CPUm must, of course, also then unlock g_cpu_wait[m]
- * so that it will be ready for the next pause operation.
- */
-
-volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-volatile spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- 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.
- */
-
- x86_64_savestate(tcb->xcp.regs);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Release the g_cpu_paused spinlock to synchronize with the
- * requesting CPU.
- */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- /* Wait for the spinlock to be released. The requesting CPU will release
- * the spinlock when the CPU is resumed.
- */
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- /* Then switch contexts. Any necessary address environment changes
- * will be made when the interrupt returns.
- */
-
- x86_64_restorestate(tcb->xcp.regs);
-
- return OK;
-}
-
/****************************************************************************
* Name: up_pause_handler
*
@@ -234,32 +64,14 @@ int up_cpu_paused_restore(void)
int up_pause_handler(int irq, void *c, void *arg)
{
+ struct tcb_s *tcb;
int cpu = this_cpu();
+ tcb = current_task(cpu);
+ x86_64_savestate(tcb->xcp.regs);
nxsched_smp_call_handler(irq, c, arg);
-
- /* 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 (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
+ tcb = current_task(cpu);
+ x86_64_restorestate(tcb->xcp.regs);
return OK;
}
@@ -349,123 +161,3 @@ void up_send_smp_call(cpu_set_t cpuset)
{
up_trigger_irq(SMP_IPI_IRQ, cpuset);
}
-
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped/
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
- cpu_set_t cpuset;
- sinfo("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prefent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- /* Execute Pause IRQ to CPU(cpu) */
-
- CPU_ZERO(&cpuset);
- CPU_SET(cpu, &cpuset);
-
- up_trigger_irq(SMP_IPI_IRQ, cpuset);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return 0;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
- sinfo("cpu=%d\n", cpu);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Release the spinlock. Releasing the spinlock will cause the SGI2
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return 0;
-}
diff --git a/arch/xtensa/src/common/xtensa_cpupause.c b/arch/xtensa/src/common/xtensa_cpupause.c
index 9fdca0d5c3..287b93b568 100644
--- a/arch/xtensa/src/common/xtensa_cpupause.c
+++ b/arch/xtensa/src/common/xtensa_cpupause.c
@@ -41,152 +41,10 @@
* Private Data
****************************************************************************/
-static spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
-static spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
-static spinlock_t g_cpu_resumed[CONFIG_SMP_NCPUS];
-
/****************************************************************************
* Public Functions
****************************************************************************/
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-bool up_cpu_pausereq(int cpu)
-{
- return spin_is_locked(&g_cpu_paused[cpu]);
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_save(void)
-{
- struct tcb_s *tcb = this_task();
-
- /* Update scheduler parameters */
-
- nxsched_suspend_scheduler(tcb);
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we are paused */
-
- sched_note_cpu_paused(tcb);
-#endif
-
- UNUSED(tcb);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending pause
- * operation in other contexts where the interrupt cannot be taken in
- * order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused(int cpu)
-{
- /* Wait for the spinlock to be released */
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_lock(&g_cpu_wait[cpu]);
-
- spin_unlock(&g_cpu_wait[cpu]);
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-int up_cpu_paused_restore(void)
-{
- struct tcb_s *tcb = this_task();
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify that we have resumed */
-
- sched_note_cpu_resumed(tcb);
-#endif
-
- /* Reset scheduler parameters */
-
- nxsched_resume_scheduler(tcb);
-
- UNUSED(tcb);
-
- return OK;
-}
-
/****************************************************************************
* Name: xtensa_pause_handler
*
@@ -210,35 +68,8 @@ int up_cpu_paused_restore(void)
void xtensa_pause_handler(int irq, void *context, void *arg)
{
- struct tcb_s *tcb;
- int cpu = this_cpu();
-
nxsched_smp_call_handler(irq, context, arg);
-
- /* Check for false alarms. Such false could occur as a consequence of
- * some deadlock breaking logic that might have already serviced the
- * interrupt by calling up_cpu_paused.
- */
-
- if (up_cpu_pausereq(cpu))
- {
- /* NOTE: The following enter_critical_section() will call
- * up_cpu_paused() to process a pause request to break a deadlock
- * because the caller held a critical section. Once up_cpu_paused()
- * finished, the caller will proceed and release the g_cpu_irqlock.
- * Then this CPU will acquire g_cpu_irqlock in the function.
- */
-
- irqstate_t flags = enter_critical_section();
-
- /* NOTE: the pause request should not exist here */
-
- DEBUGVERIFY(!up_cpu_pausereq(cpu));
-
- leave_critical_section(flags);
- }
-
- nxsched_process_delivered(cpu);
+ nxsched_process_delivered(this_cpu());
}
/****************************************************************************
@@ -294,114 +125,4 @@ void up_send_smp_call(cpu_set_t cpuset)
}
}
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be stopped.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_pause(int cpu)
-{
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the pause event */
-
- sched_note_cpu_pause(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Take both spinlocks. The g_cpu_wait spinlock will prevent the interrupt
- * handler from returning until up_cpu_resume() is called; g_cpu_paused
- * is a handshake that will prevent this function from returning until
- * the CPU is actually paused.
- * Note that we might spin before getting g_cpu_wait, this just means that
- * the other CPU still hasn't finished responding to the previous resume
- * request.
- */
-
- DEBUGASSERT(!spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_lock(&g_cpu_wait[cpu]);
- spin_lock(&g_cpu_paused[cpu]);
-
- up_cpu_pause_async(cpu);
-
- /* Wait for the other CPU to unlock g_cpu_paused meaning that
- * it is fully paused and ready for up_cpu_resume();
- */
-
- spin_lock(&g_cpu_paused[cpu]);
-
- spin_unlock(&g_cpu_paused[cpu]);
-
- /* On successful return g_cpu_wait will be locked, the other CPU will be
- * spinning on g_cpu_wait and will not continue until g_cpu_resume() is
- * called. g_cpu_paused will be unlocked in any case.
- */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order resume operation of
- * the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being re-started.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int up_cpu_resume(int cpu)
-{
-#ifdef CONFIG_SCHED_INSTRUMENTATION
- /* Notify of the resume event */
-
- sched_note_cpu_resume(this_task(), cpu);
-#endif
-
- DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
-
- /* Release the spinlock. Releasing the spinlock will cause the interrupt
- * handler on 'cpu' to continue and return from interrupt to the newly
- * established thread.
- */
-
- DEBUGASSERT(spin_is_locked(&g_cpu_wait[cpu]) &&
- !spin_is_locked(&g_cpu_paused[cpu]));
-
- spin_unlock(&g_cpu_wait[cpu]);
-
- /* Ensure the CPU has been resumed to avoid causing a deadlock */
-
- spin_lock(&g_cpu_resumed[cpu]);
-
- spin_unlock(&g_cpu_resumed[cpu]);
-
- return OK;
-}
-
#endif /* CONFIG_SMP */
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index f149d8a36d..4edd69ce04 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -2288,34 +2288,6 @@ int up_cpu_idlestack(int cpu, FAR struct tcb_s *tcb, size_t stack_size);
int up_cpu_start(int cpu);
#endif
-/****************************************************************************
- * Name: up_cpu_pause
- *
- * Description:
- * Save the state of the current task at the head of the
- * g_assignedtasks[cpu] task list and then pause task execution on the
- * CPU.
- *
- * This function is called by the OS when the logic executing on one CPU
- * needs to modify the state of the g_assignedtasks[cpu] list for another
- * CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- * Assumptions:
- * Called from within a critical section; up_cpu_resume() must be called
- * later while still within the same critical section.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-int up_cpu_pause(int cpu);
-#endif
-
/****************************************************************************
* Name: up_cpu_pause_async
*
@@ -2339,126 +2311,6 @@ int up_cpu_pause(int cpu);
int up_cpu_pause_async(int cpu);
#endif
-/****************************************************************************
- * Name: up_cpu_pausereq
- *
- * Description:
- * Return true if a pause request is pending for this CPU.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be queried
- *
- * Returned Value:
- * true = a pause request is pending.
- * false = no pasue request is pending.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-bool up_cpu_pausereq(int cpu);
-#endif
-
-/****************************************************************************
- * Name: up_cpu_paused_save
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending
- * pause operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-int up_cpu_paused_save(void);
-#endif
-
-/****************************************************************************
- * Name: up_cpu_paused
- *
- * Description:
- * Handle a pause request from another CPU. Normally, this logic is
- * executed from interrupt handling logic within the architecture-specific
- * However, it is sometimes necessary to perform the pending pause
- * operation in other contexts where the interrupt cannot be taken
- * in order to avoid deadlocks.
- *
- * This function performs the following operations:
- *
- * 1. It saves the current task state at the head of the current assigned
- * task list.
- * 2. It waits on a spinlock, then
- * 3. Returns from interrupt, restoring the state of the new task at the
- * head of the ready to run list.
- *
- * Input Parameters:
- * cpu - The index of the CPU to be paused
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-int up_cpu_paused(int cpu);
-#endif
-
-/****************************************************************************
- * Name: up_cpu_paused_restore
- *
- * Description:
- * Restore the state of the CPU after it was paused via up_cpu_pause(),
- * and resume normal tasking.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * On success, OK is returned. Otherwise, a negated errno value indicating
- * the nature of the failure is returned.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-int up_cpu_paused_restore(void);
-#endif
-
-/****************************************************************************
- * Name: up_cpu_resume
- *
- * Description:
- * Restart the cpu after it was paused via up_cpu_pause(), restoring the
- * state of the task at the head of the g_assignedtasks[cpu] list, and
- * resume normal tasking.
- *
- * This function is called after up_cpu_pause in order to resume operation
- * of the CPU after modifying its g_assignedtasks[cpu] list.
- *
- * Input Parameters:
- * cpu - The index of the CPU being resumed.
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- * Assumptions:
- * Called from within a critical section; up_cpu_pause() must have
- * previously been called within the same critical section.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-int up_cpu_resume(int cpu);
-#endif
-
/****************************************************************************
* Name: up_romgetc
*
diff --git a/include/nuttx/irq.h b/include/nuttx/irq.h
index 2177440c98..3d0373f030 100644
--- a/include/nuttx/irq.h
+++ b/include/nuttx/irq.h
@@ -81,6 +81,7 @@
SP_DMB(); \
g_cpu_irqlock = SP_UNLOCKED; \
SP_DSB(); \
+ SP_SEV(); \
} \
while (0)
#endif
diff --git a/sched/irq/irq_csection.c b/sched/irq/irq_csection.c
index 3397741a76..a0432f7fe9 100644
--- a/sched/irq/irq_csection.c
+++ b/sched/irq/irq_csection.c
@@ -75,96 +75,6 @@ volatile uint8_t g_cpu_nestcount[CONFIG_SMP_NCPUS];
* Private Functions
****************************************************************************/
-/****************************************************************************
- * Name: irq_waitlock
- *
- * Description:
- * Spin to get g_cpu_irqlock, handling a known deadlock condition:
- *
- * A deadlock may occur if enter_critical_section is called from an
- * interrupt handler. Suppose:
- *
- * - CPUn is in a critical section and has the g_cpu_irqlock spinlock.
- * - CPUm takes an interrupt and attempts to enter the critical section.
- * - It spins waiting on g_cpu_irqlock with interrupts disabled.
- * - CPUn calls up_cpu_pause() to pause operation on CPUm. This will
- * issue an inter-CPU interrupt to CPUm
- * - But interrupts are disabled on CPUm so the up_cpu_pause() is never
- * handled, causing the deadlock.
- *
- * This same deadlock can occur in the normal tasking case:
- *
- * - A task on CPUn enters a critical section and has the g_cpu_irqlock
- * spinlock.
- * - Another task on CPUm attempts to enter the critical section but has
- * to wait, spinning to get g_cpu_irqlock with interrupts disabled.
- * - The task on CPUn causes a new task to become ready-to-run and the
- * scheduler selects CPUm. CPUm is requested to pause via a pause
- * interrupt.
- * - But the task on CPUm is also attempting to enter the critical
- * section. Since it is spinning with interrupts disabled, CPUm cannot
- * process the pending pause interrupt, causing the deadlock.
- *
- * This function detects this deadlock condition while spinning with
- * interrupts disabled.
- *
- * Input Parameters:
- * cpu - The index of CPU that is trying to enter the critical section.
- *
- * Returned Value:
- * True: The g_cpu_irqlock spinlock has been taken.
- * False: The g_cpu_irqlock spinlock has not been taken yet, but there is
- * a pending pause interrupt request.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SMP
-static inline_function bool irq_waitlock(int cpu)
-{
-#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
- FAR struct tcb_s *tcb = current_task(cpu);
-
- /* Notify that we are waiting for a spinlock */
-
- sched_note_spinlock(tcb, &g_cpu_irqlock, NOTE_SPINLOCK_LOCK);
-#endif
-
- /* Duplicate the spin_lock() logic from spinlock.c, but adding the check
- * for the deadlock condition.
- */
-
- while (!spin_trylock_wo_note(&g_cpu_irqlock))
- {
- /* Is a pause request pending? */
-
- if (up_cpu_pausereq(cpu))
- {
- /* Yes.. some other CPU is requesting to pause this CPU!
- * Abort the wait and return false.
- */
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
- /* Notify that we have aborted the wait for the spinlock */
-
- sched_note_spinlock(tcb, &g_cpu_irqlock, NOTE_SPINLOCK_ABORT);
-#endif
-
- return false;
- }
- }
-
- /* We have g_cpu_irqlock! */
-
-#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
- /* Notify that we have the spinlock */
-
- sched_note_spinlock(tcb, &g_cpu_irqlock, NOTE_SPINLOCK_LOCKED);
-#endif
-
- return true;
-}
-#endif
-
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -198,7 +108,6 @@ irqstate_t enter_critical_section(void)
* the local CPU.
*/
-try_again:
ret = up_irq_save();
/* If called from an interrupt handler, then just take the spinlock.
@@ -259,8 +168,6 @@ try_again:
else
{
- int paused = false;
-
/* Make sure that the g_cpu_irqset was not already set
* by previous logic on this CPU that was executed by the
* interrupt handler. We know that the bit in g_cpu_irqset
@@ -274,43 +181,14 @@ try_again:
* no longer blocked by the critical section).
*/
-try_again_in_irq:
- if (!irq_waitlock(cpu))
- {
- /* We are in a deadlock condition due to a pending
- * pause request interrupt. Break the deadlock by
- * handling the pause request now.
- */
-
- if (!paused)
- {
- up_cpu_paused_save();
- }
-
- DEBUGVERIFY(up_cpu_paused(cpu));
- paused = true;
-
- DEBUGASSERT((g_cpu_irqset & (1 << cpu)) == 0);
-
- /* NOTE: Here, this CPU does not hold g_cpu_irqlock,
- * so call irq_waitlock(cpu) to acquire g_cpu_irqlock.
- */
-
- goto try_again_in_irq;
- }
-
- cpu_irqlock_set(cpu);
+ spin_lock(&g_cpu_irqlock);
+ cpu_irqlock_set(cpu);
}
/* In any event, the nesting count is now one */
g_cpu_nestcount[cpu] = 1;
- if (paused)
- {
- up_cpu_paused_restore();
- }
-
DEBUGASSERT(spin_is_locked(&g_cpu_irqlock) &&
(g_cpu_irqset & (1 << cpu)) != 0);
}
@@ -354,18 +232,7 @@ try_again_in_irq:
DEBUGASSERT((g_cpu_irqset & (1 << cpu)) == 0);
- if (!irq_waitlock(cpu))
- {
- /* We are in a deadlock condition due to a pending pause
- * request interrupt. Re-enable interrupts on this CPU
- * and try again. Briefly re-enabling interrupts should
- * be sufficient to permit processing the pending pause
- * request.
- */
-
- up_irq_restore(ret);
- goto try_again;
- }
+ spin_lock(&g_cpu_irqlock);
/* Then set the lock count to 1.
*
diff --git a/sched/sched/CMakeLists.txt b/sched/sched/CMakeLists.txt
index 29bf9c1f59..6f18fb7cfb 100644
--- a/sched/sched/CMakeLists.txt
+++ b/sched/sched/CMakeLists.txt
@@ -59,7 +59,6 @@ if(CONFIG_SMP)
APPEND
SRCS
sched_cpuselect.c
- sched_cpupause.c
sched_getcpu.c
sched_getaffinity.c
sched_setaffinity.c
diff --git a/sched/sched/Make.defs b/sched/sched/Make.defs
index b6ca4a7131..2ce6fe813a 100644
--- a/sched/sched/Make.defs
+++ b/sched/sched/Make.defs
@@ -37,7 +37,7 @@ CSRCS += sched_reprioritize.c
endif
ifeq ($(CONFIG_SMP),y)
-CSRCS += sched_cpuselect.c sched_cpupause.c sched_getcpu.c sched_process_delivered.c
+CSRCS += sched_cpuselect.c sched_getcpu.c sched_process_delivered.c
CSRCS += sched_getaffinity.c sched_setaffinity.c
endif
diff --git a/sched/sched/sched.h b/sched/sched/sched.h
index 47ea3b448b..6f1e758605 100644
--- a/sched/sched/sched.h
+++ b/sched/sched/sched.h
@@ -401,11 +401,9 @@ static inline_function FAR struct tcb_s *this_task(void)
}
int nxsched_select_cpu(cpu_set_t affinity);
-int nxsched_pause_cpu(FAR struct tcb_s *tcb);
void nxsched_process_delivered(int cpu);
#else
# define nxsched_select_cpu(a) (0)
-# define nxsched_pause_cpu(t) (-38) /* -ENOSYS */
#endif
#define nxsched_islocked_tcb(tcb) ((tcb)->lockcount > 0)
diff --git a/sched/sched/sched_cpupause.c b/sched/sched/sched_cpupause.c
deleted file mode 100644
index 571c1a928b..0000000000
--- a/sched/sched/sched_cpupause.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
- * sched/sched/sched_cpupause.c
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <sys/types.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <nuttx/arch.h>
-#include <nuttx/sched_note.h>
-
-#include "sched/sched.h"
-
-#ifdef CONFIG_SMP
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: nxsched_pause_cpu
- *
- * Description:
- * Check if task associated with 'tcb' is running on a different CPU. If
- * so then pause that CPU and return its CPU index.
- *
- * Input Parameters:
- * tcb - The TCB of the task to be conditionally paused.
- *
- * Returned Value:
- * If a CPU is pauses its non-negative CPU index is returned. This index
- * may then be used to resume the CPU. If the task is not running at all
- * (or if an error occurs), then a negated errno value is returned. -ESRCH
- * is returned in the case where the task is not running on any CPU.
- *
- * Assumptions:
- * This function was called in a critical section. In that case, no tasks
- * may started or may exit until the we leave the critical section. This
- * critical section should extend until up_cpu_resume() is called in the
- * typical case.
- *
- ****************************************************************************/
-
-int nxsched_pause_cpu(FAR struct tcb_s *tcb)
-{
- int cpu;
- int ret;
-
- DEBUGASSERT(tcb != NULL);
-
- /* If the task is not running at all then our job is easy */
-
- cpu = tcb->cpu;
- if (tcb->task_state != TSTATE_TASK_RUNNING)
- {
- return -ESRCH;
- }
-
- /* Check the CPU that the task is running on */
-
- DEBUGASSERT(cpu != this_cpu() && (unsigned int)cpu < CONFIG_SMP_NCPUS);
- if (cpu == this_cpu())
- {
- /* We can't pause ourself */
-
- return -EACCES;
- }
-
- /* Pause the CPU that the task is running on */
-
- ret = up_cpu_pause(cpu);
- if (ret < 0)
- {
- return ret;
- }
-
- /* Return the CPU that the task is running on */
-
- return cpu;
-}
-
-#endif /* CONFIG_SMP */
diff --git a/sched/sched/sched_process_delivered.c b/sched/sched/sched_process_delivered.c
index bb90b0cf0e..b039435443 100644
--- a/sched/sched/sched_process_delivered.c
+++ b/sched/sched/sched_process_delivered.c
@@ -73,13 +73,7 @@ void nxsched_process_delivered(int cpu)
if ((g_cpu_irqset & (1 << cpu)) == 0)
{
- while (!spin_trylock_wo_note(&g_cpu_irqlock))
- {
- if (up_cpu_pausereq(cpu))
- {
- up_cpu_paused(cpu);
- }
- }
+ spin_lock_wo_note(&g_cpu_irqlock);
g_cpu_irqset |= (1 << cpu);
}
diff --git a/sched/sched/sched_removereadytorun.c b/sched/sched/sched_removereadytorun.c
index 5ff83b31ce..e54c69d7b9 100644
--- a/sched/sched/sched_removereadytorun.c
+++ b/sched/sched/sched_removereadytorun.c
@@ -290,19 +290,9 @@ bool nxsched_remove_readytorun(FAR struct tcb_s *tcb, bool merge)
if (tcb->task_state == TSTATE_TASK_RUNNING)
{
- int me = this_cpu();
- int cpu = tcb->cpu;
- if (cpu != me)
- {
- up_cpu_pause(tcb->cpu);
- nxsched_remove_running(tcb);
- up_cpu_resume(tcb->cpu);
- }
- else
- {
- nxsched_remove_running(tcb);
- doswitch = true;
- }
+ DEBUGASSERT(tcb->cpu == this_cpu());
+ nxsched_remove_running(tcb);
+ return true;
}
else
{
diff --git a/sched/sched/sched_smp.c b/sched/sched/sched_smp.c
index af6c88a4e5..ff2607964e 100644
--- a/sched/sched/sched_smp.c
+++ b/sched/sched/sched_smp.c
@@ -125,7 +125,6 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
call_queue = &g_smp_call_queue[cpu];
- up_cpu_paused_save();
sq_for_every_safe(call_queue, curr, next)
{
FAR struct smp_call_data_s *call_data =
@@ -158,7 +157,6 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
}
}
- up_cpu_paused_restore();
spin_unlock_irqrestore(&g_smp_call_lock, flags);
return OK;
}