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
|
* 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
|
* Public Functions
|
||||||
@ -98,7 +99,8 @@ int arm_pause_handler(int irq, FAR void *context)
|
|||||||
|
|
||||||
/* Wait for the spinlock to be released */
|
/* 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
|
/* Restore the exception context of the tcb at the (new) head of the
|
||||||
* assigned task list.
|
* assigned task list.
|
||||||
@ -115,7 +117,7 @@ int arm_pause_handler(int irq, FAR void *context)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
up_restorestate(tcb->xcp.regs);
|
up_restorestate(tcb->xcp.regs);
|
||||||
spin_unlock(&g_pause_spinlock[cpu]);
|
spin_unlock(&g_cpu_wait[cpu]);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,18 +143,48 @@ int arm_pause_handler(int irq, FAR void *context)
|
|||||||
|
|
||||||
int up_cpu_pause(int cpu)
|
int up_cpu_pause(int cpu)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
|
||||||
|
|
||||||
/* Take the spinlock. The spinlock will cause the SGI2 handler to block
|
/* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
|
||||||
* on 'cpu'.
|
* 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]));
|
DEBUGASSERT(!spin_islocked(&g_cpu_wait[cpu]) &&
|
||||||
spin_lock(&g_pause_spinlock[cpu]);
|
!spin_islocked(&g_cpu_paused[cpu]));
|
||||||
|
|
||||||
|
spin_lock(&g_cpu_wait[cpu]);
|
||||||
|
spin_lock(&g_cpu_paused[cpu]);
|
||||||
|
|
||||||
/* Execute SGI2 */
|
/* 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.
|
* established thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(spin_islocked(&g_pause_spinlock[cpu]));
|
DEBUGASSERT(spin_islocked(&g_cpu_wait[cpu]) &&
|
||||||
spin_unlock(&g_pause_spinlock[cpu]);
|
!spin_islocked(&g_cpu_paused[cpu]));
|
||||||
|
|
||||||
|
spin_unlock(&g_cpu_wait[cpu]);
|
||||||
return OK;
|
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
|
* 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
|
* value in the range of from one to (CONFIG_SMP_NCPUS-1). (CPU
|
||||||
* 0 is already active)
|
* 0 is already active)
|
||||||
* idletask - The entry point to the IDLE task.
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero on success; a negated errno value on failure.
|
* 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());
|
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);
|
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);
|
||||||
|
|
||||||
#if CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) |
|
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) |
|
||||||
GIC_ICDSGIR_TGTFILTER_LIST;
|
GIC_ICDSGIR_TGTFILTER_LIST;
|
||||||
#else
|
#else
|
||||||
|
@ -70,7 +70,7 @@ ifeq ($(CONFIG_SPINLOCK),y)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SMP),y)
|
ifeq ($(CONFIG_SMP),y)
|
||||||
CSRCS += up_smpsignal.c
|
CSRCS += up_smpsignal.c up_smphook.c
|
||||||
HOSTSRCS += up_simsmp.c
|
HOSTSRCS += up_simsmp.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SMP),y)
|
ifeq ($(CONFIG_SMP),y)
|
||||||
REQUIREDOBJS += up_smpsignal$(OBJEXT)
|
REQUIREDOBJS += up_smpsignal$(OBJEXT) up_smphook$(OBJEXT)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Determine which NuttX libraries will need to be linked in
|
# 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);
|
FAR volatile unsigned char *paused);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* up_smphook.c ***********************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
void sim_smp_hook(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* up_tickless.c **********************************************************/
|
/* up_tickless.c **********************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_TICKLESS
|
#ifdef CONFIG_SCHED_TICKLESS
|
||||||
|
@ -70,7 +70,6 @@ struct sim_cpuinfo_s
|
|||||||
{
|
{
|
||||||
int cpu; /* CPU number */
|
int cpu; /* CPU number */
|
||||||
pthread_mutex_t mutex; /* For synchronization */
|
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 os_start(void) __attribute__ ((noreturn));
|
||||||
void sim_cpu_pause(int cpu, volatile spinlock_t *wait,
|
void sim_cpu_pause(int cpu, volatile spinlock_t *wait,
|
||||||
volatile unsigned char *paused);
|
volatile unsigned char *paused);
|
||||||
|
void sim_smp_hook(void);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -191,9 +191,12 @@ static void *sim_idle_trampoline(void *arg)
|
|||||||
|
|
||||||
(void)pthread_mutex_unlock(&cpuinfo->mutex);
|
(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 */
|
/* 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
|
* 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
|
* value in the range of from one to (CONFIG_SMP_NCPUS-1). (CPU
|
||||||
* 0 is already active)
|
* 0 is already active)
|
||||||
* idletask - The entry point to the IDLE task.
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero on success; a negated errno value on failure.
|
* 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;
|
struct sim_cpuinfo_s cpuinfo;
|
||||||
int ret;
|
int ret;
|
||||||
@ -376,7 +378,6 @@ int up_cpu_start(int cpu, main_t idletask)
|
|||||||
/* Initialize the CPU info */
|
/* Initialize the CPU info */
|
||||||
|
|
||||||
cpuinfo.cpu = cpu;
|
cpuinfo.cpu = cpu;
|
||||||
cpuinfo.idletask = idletask;
|
|
||||||
ret = pthread_mutex_init(&cpuinfo.mutex, NULL);
|
ret = pthread_mutex_init(&cpuinfo.mutex, NULL);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user