Conform to revised SMP interfaces. Improve i.MX6 SMP startup handshake.
This commit is contained in:
parent
8ad1188fe5
commit
6288e381ee
@ -55,7 +55,8 @@
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static spinlock_t g_pause_spinlock[CONFIG_SMP_NCPUS];
|
||||
static spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
|
||||
static spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -98,7 +99,8 @@ int arm_pause_handler(int irq, FAR void *context)
|
||||
|
||||
/* Wait for the spinlock to be released */
|
||||
|
||||
spin_lock(&g_pause_spinlock[cpu]);
|
||||
spin_unlock(&g_cpu_paused[cpu]);
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
|
||||
/* Restore the exception context of the tcb at the (new) head of the
|
||||
* assigned task list.
|
||||
@ -115,7 +117,7 @@ int arm_pause_handler(int irq, FAR void *context)
|
||||
*/
|
||||
|
||||
up_restorestate(tcb->xcp.regs);
|
||||
spin_unlock(&g_pause_spinlock[cpu]);
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -141,18 +143,48 @@ int arm_pause_handler(int irq, FAR void *context)
|
||||
|
||||
int up_cpu_pause(int cpu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
/* Take the spinlock. The spinlock will cause the SGI2 handler to block
|
||||
* on '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.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(!spin_islocked(&g_pause_spinlock[cpu]));
|
||||
spin_lock(&g_pause_spinlock[cpu]);
|
||||
DEBUGASSERT(!spin_islocked(&g_cpu_wait[cpu]) &&
|
||||
!spin_islocked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_lock(&g_cpu_wait[cpu]);
|
||||
spin_lock(&g_cpu_paused[cpu]);
|
||||
|
||||
/* Execute SGI2 */
|
||||
|
||||
return arm_cpu_sgi(GIC_IRQ_SGI2, (1 << cpu));
|
||||
ret = arm_cpu_sgi(GIC_IRQ_SGI2, (1 << cpu));
|
||||
if (ret < 0)
|
||||
{
|
||||
/* What happened? Unlock the g_cpu_wait spinlock */
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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
|
||||
* spinninf on g_cpu_wait and will not continue until g_cpu_resume() is
|
||||
* called. g_cpu_paused will be unlocked in any case.
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -183,8 +215,10 @@ int up_cpu_resume(int cpu)
|
||||
* established thread.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(spin_islocked(&g_pause_spinlock[cpu]));
|
||||
spin_unlock(&g_pause_spinlock[cpu]);
|
||||
DEBUGASSERT(spin_islocked(&g_cpu_wait[cpu]) &&
|
||||
!spin_islocked(&g_cpu_paused[cpu]));
|
||||
|
||||
spin_unlock(&g_cpu_wait[cpu]);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,13 @@ int arm_start_handler(int irq, FAR void *context)
|
||||
* cpu - The index of the CPU being started. This will be a numeric
|
||||
* value in the range of from one to (CONFIG_SMP_NCPUS-1). (CPU
|
||||
* 0 is already active)
|
||||
* idletask - The entry point to the IDLE task.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_start(int cpu, main_t idletask)
|
||||
int up_cpu_start(int cpu)
|
||||
{
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||
|
||||
|
@ -426,7 +426,7 @@ int arm_cpu_sgi(int sgi, unsigned int cpuset)
|
||||
|
||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);
|
||||
|
||||
#if CONFIG_SMP
|
||||
#ifdef CONFIG_SMP
|
||||
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) |
|
||||
GIC_ICDSGIR_TGTFILTER_LIST;
|
||||
#else
|
||||
|
@ -70,7 +70,7 @@ ifeq ($(CONFIG_SPINLOCK),y)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
CSRCS += up_smpsignal.c
|
||||
CSRCS += up_smpsignal.c up_smphook.c
|
||||
HOSTSRCS += up_simsmp.c
|
||||
endif
|
||||
|
||||
@ -181,7 +181,7 @@ endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
REQUIREDOBJS += up_smpsignal$(OBJEXT)
|
||||
REQUIREDOBJS += up_smpsignal$(OBJEXT) up_smphook$(OBJEXT)
|
||||
endif
|
||||
|
||||
# Determine which NuttX libraries will need to be linked in
|
||||
|
@ -228,6 +228,12 @@ void sim_cpu_pause(int cpu, FAR volatile spinlock_t *wait,
|
||||
FAR volatile unsigned char *paused);
|
||||
#endif
|
||||
|
||||
/* up_smphook.c ***********************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void sim_smp_hook(void);
|
||||
#endif
|
||||
|
||||
/* up_tickless.c **********************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
|
@ -70,7 +70,6 @@ struct sim_cpuinfo_s
|
||||
{
|
||||
int cpu; /* CPU number */
|
||||
pthread_mutex_t mutex; /* For synchronization */
|
||||
main_t idletask; /* IDLE task entry point */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -89,6 +88,7 @@ static volatile spinlock_t g_sim_cpuwait[CONFIG_SMP_NCPUS];
|
||||
void os_start(void) __attribute__ ((noreturn));
|
||||
void sim_cpu_pause(int cpu, volatile spinlock_t *wait,
|
||||
volatile unsigned char *paused);
|
||||
void sim_smp_hook(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@ -191,9 +191,12 @@ static void *sim_idle_trampoline(void *arg)
|
||||
|
||||
(void)pthread_mutex_unlock(&cpuinfo->mutex);
|
||||
|
||||
/* Give control to the IDLE task */
|
||||
/* Give control to the IDLE task via the nasty little sim_smp_hook().
|
||||
* sim_smp_hook() is logically a part of this function but needs to be
|
||||
* inserted in the path because in needs to access NuttX domain definitions.
|
||||
*/
|
||||
|
||||
(void)cpuinfo->idletask(0, (char **)0);
|
||||
sim_smp_hook();
|
||||
|
||||
/* The IDLE task will not return. This is just to keep the compiler happy */
|
||||
|
||||
@ -361,14 +364,13 @@ int up_cpu_index(void)
|
||||
* cpu - The index of the CPU being started. This will be a numeric
|
||||
* value in the range of from one to (CONFIG_SMP_NCPUS-1). (CPU
|
||||
* 0 is already active)
|
||||
* idletask - The entry point to the IDLE task.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_cpu_start(int cpu, main_t idletask)
|
||||
int up_cpu_start(int cpu)
|
||||
{
|
||||
struct sim_cpuinfo_s cpuinfo;
|
||||
int ret;
|
||||
@ -376,7 +378,6 @@ int up_cpu_start(int cpu, main_t idletask)
|
||||
/* Initialize the CPU info */
|
||||
|
||||
cpuinfo.cpu = cpu;
|
||||
cpuinfo.idletask = idletask;
|
||||
ret = pthread_mutex_init(&cpuinfo.mutex, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user