mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 20:08:15 +08:00
smpcall: add nxsched_smp_call_async and nxsched_smp_call_single_async
reason: The old implementation of the SMP call, even when using the "no wait" parameter, could still result in waiting, if invoking it within a critical section may lead to deadlocks. Therefore, in order to implement a truly asynchronous SMP call strategy, we have added nxsched_smp_call_async. Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
+70
-6
@@ -232,6 +232,8 @@
|
|||||||
# define get_task_name(tcb) "<noname>"
|
# define get_task_name(tcb) "<noname>"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SMP_CALL_INITIALIZER(func, arg) {(func), (arg)}
|
||||||
|
|
||||||
/* These are macros to access the current CPU and the current task on a CPU.
|
/* These are macros to access the current CPU and the current task on a CPU.
|
||||||
* These macros are intended to support a future SMP implementation.
|
* These macros are intended to support a future SMP implementation.
|
||||||
*/
|
*/
|
||||||
@@ -833,6 +835,15 @@ typedef CODE void (*nxsched_foreach_t)(FAR struct tcb_s *tcb, FAR void *arg);
|
|||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
typedef CODE int (*nxsched_smp_call_t)(FAR void *arg);
|
typedef CODE int (*nxsched_smp_call_t)(FAR void *arg);
|
||||||
|
|
||||||
|
struct smp_call_cookie_s;
|
||||||
|
struct smp_call_data_s
|
||||||
|
{
|
||||||
|
nxsched_smp_call_t func;
|
||||||
|
FAR void *arg;
|
||||||
|
FAR struct smp_call_cookie_s *cookie;
|
||||||
|
sq_entry_t node[CONFIG_SMP_NCPUS];
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
@@ -1698,17 +1709,35 @@ void nxsched_dumponexit(void);
|
|||||||
int nxsched_smp_call_handler(int irq, FAR void *context,
|
int nxsched_smp_call_handler(int irq, FAR void *context,
|
||||||
FAR void *arg);
|
FAR void *arg);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsched_smp_call_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Init call_data
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* data - Call data
|
||||||
|
* func - Function
|
||||||
|
* arg - Function args
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Result
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nxsched_smp_call_init(FAR struct smp_call_data_s *data,
|
||||||
|
nxsched_smp_call_t func, FAR void *arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsched_smp_call_single
|
* Name: nxsched_smp_call_single
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Call function on single processor
|
* Call function on single processor, wait function callback
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cpuid - Target cpu id
|
* cpuid - Target cpu id
|
||||||
* func - Function
|
* func - Function
|
||||||
* arg - Function args
|
* arg - Function args
|
||||||
* wait - Wait function callback or not
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Result
|
* Result
|
||||||
@@ -1716,19 +1745,18 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nxsched_smp_call_single(int cpuid, nxsched_smp_call_t func,
|
int nxsched_smp_call_single(int cpuid, nxsched_smp_call_t func,
|
||||||
FAR void *arg, bool wait);
|
FAR void *arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsched_smp_call
|
* Name: nxsched_smp_call
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Call function on multi processors
|
* Call function on multi processors, wait function callback
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cpuset - Target cpuset
|
* cpuset - Target cpuset
|
||||||
* func - Function
|
* func - Function
|
||||||
* arg - Function args
|
* arg - Function args
|
||||||
* wait - Wait function callback or not
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Result
|
* Result
|
||||||
@@ -1736,7 +1764,43 @@ int nxsched_smp_call_single(int cpuid, nxsched_smp_call_t func,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func,
|
int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func,
|
||||||
FAR void *arg, bool wait);
|
FAR void *arg);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsched_smp_call_single_async
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Call function on single processor async
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* cpuset - Target cpuset
|
||||||
|
* data - Call data
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Result
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsched_smp_call_single_async(int cpuid,
|
||||||
|
FAR struct smp_call_data_s *data);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsched_smp_call_async
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Call function on multi processors async
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* cpuset - Target cpuset
|
||||||
|
* data - Call data
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Result
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsched_smp_call_async(cpu_set_t cpuset,
|
||||||
|
FAR struct smp_call_data_s *data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
|
|||||||
@@ -1879,7 +1879,7 @@ int gdb_debugpoint_add(int type, FAR void *addr, size_t size,
|
|||||||
point.callback = callback;
|
point.callback = callback;
|
||||||
point.arg = arg;
|
point.arg = arg;
|
||||||
return nxsched_smp_call((1 << CONFIG_SMP_NCPUS) - 1,
|
return nxsched_smp_call((1 << CONFIG_SMP_NCPUS) - 1,
|
||||||
gdb_smp_debugpoint_add, &point, true);
|
gdb_smp_debugpoint_add, &point);
|
||||||
#else
|
#else
|
||||||
return up_debugpoint_add(type, addr, size, callback, arg);
|
return up_debugpoint_add(type, addr, size, callback, arg);
|
||||||
#endif
|
#endif
|
||||||
@@ -1897,8 +1897,8 @@ int gdb_debugpoint_remove(int type, FAR void *addr, size_t size)
|
|||||||
point.addr = addr;
|
point.addr = addr;
|
||||||
point.size = size;
|
point.size = size;
|
||||||
|
|
||||||
return nxsched_smp_call((1 << CONFIG_SMP_NCPUS) - 1,
|
retrun nxsched_smp_call((1 << CONFIG_SMP_NCPUS) - 1,
|
||||||
gdb_smp_debugpoint_remove, &point, true);
|
gdb_smp_debugpoint_remove, &point);
|
||||||
#else
|
#else
|
||||||
return up_debugpoint_remove(type, addr, size);
|
return up_debugpoint_remove(type, addr, size);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+14
-1
@@ -98,6 +98,14 @@
|
|||||||
# define XCPTCONTEXT_ALIGN 16
|
# define XCPTCONTEXT_ALIGN 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static noreturn_function int pause_cpu_handler(FAR void *arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -124,6 +132,11 @@ static FAR const char * const g_ttypenames[4] =
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static struct smp_call_data_s g_call_data =
|
||||||
|
SMP_CALL_INITIALIZER(pause_cpu_handler, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -610,7 +623,7 @@ static void pause_all_cpu(void)
|
|||||||
int delay = CONFIG_ASSERT_PAUSE_CPU_TIMEOUT;
|
int delay = CONFIG_ASSERT_PAUSE_CPU_TIMEOUT;
|
||||||
|
|
||||||
CPU_CLR(this_cpu(), &cpus);
|
CPU_CLR(this_cpu(), &cpus);
|
||||||
nxsched_smp_call(cpus, pause_cpu_handler, NULL, false);
|
nxsched_smp_call_async(cpus, &g_call_data);
|
||||||
g_cpu_paused[this_cpu()] = true;
|
g_cpu_paused[this_cpu()] = true;
|
||||||
|
|
||||||
/* Check if all CPUs paused with timeout */
|
/* Check if all CPUs paused with timeout */
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ int sched_backtrace(pid_t tid, FAR void **buffer, int size, int skip)
|
|||||||
arg.skip = skip;
|
arg.skip = skip;
|
||||||
ret = nxsched_smp_call_single(tcb->cpu,
|
ret = nxsched_smp_call_single(tcb->cpu,
|
||||||
sched_backtrace_handler,
|
sched_backtrace_handler,
|
||||||
&arg, true);
|
&arg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -50,12 +50,21 @@ struct profinfo_s
|
|||||||
spinlock_t lock; /* Lock for this structure */
|
spinlock_t lock; /* Lock for this structure */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static int profil_timer_handler_cpu(FAR void *arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static struct profinfo_s g_prof;
|
static struct profinfo_s g_prof;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static struct smp_call_data_s g_call_data =
|
||||||
|
SMP_CALL_INITIALIZER(profil_timer_handler_cpu, &g_prof);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -89,8 +98,7 @@ static void profil_timer_handler(wdparm_t arg)
|
|||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
cpu_set_t cpus = (1 << CONFIG_SMP_NCPUS) - 1;
|
cpu_set_t cpus = (1 << CONFIG_SMP_NCPUS) - 1;
|
||||||
CPU_CLR(this_cpu(), &cpus);
|
CPU_CLR(this_cpu(), &cpus);
|
||||||
nxsched_smp_call(cpus, profil_timer_handler_cpu,
|
nxsched_smp_call_async(cpus, &g_call_data);
|
||||||
(FAR void *)arg, false);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
profil_timer_handler_cpu(prof);
|
profil_timer_handler_cpu(prof);
|
||||||
|
|||||||
@@ -40,6 +40,15 @@
|
|||||||
#if CONFIG_RR_INTERVAL > 0
|
#if CONFIG_RR_INTERVAL > 0
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static struct smp_call_data_s g_call_data;
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Type Declarations
|
* Private Type Declarations
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -55,12 +64,12 @@ struct roundrobin_arg_s
|
|||||||
|
|
||||||
static int nxsched_roundrobin_handler(FAR void *cookie)
|
static int nxsched_roundrobin_handler(FAR void *cookie)
|
||||||
{
|
{
|
||||||
FAR struct roundrobin_arg_s *arg = cookie;
|
pid_t pid = (uintptr_t)cookie;
|
||||||
FAR struct tcb_s *tcb;
|
FAR struct tcb_s *tcb;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
flags = enter_critical_section();
|
flags = enter_critical_section();
|
||||||
tcb = nxsched_get_tcb(arg->pid);
|
tcb = nxsched_get_tcb(pid);
|
||||||
|
|
||||||
if (!tcb || tcb->task_state == TSTATE_TASK_INVALID ||
|
if (!tcb || tcb->task_state == TSTATE_TASK_INVALID ||
|
||||||
(tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
|
(tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
|
||||||
@@ -185,12 +194,10 @@ uint32_t nxsched_process_roundrobin(FAR struct tcb_s *tcb, uint32_t ticks,
|
|||||||
if (tcb->task_state == TSTATE_TASK_RUNNING &&
|
if (tcb->task_state == TSTATE_TASK_RUNNING &&
|
||||||
tcb->cpu != this_cpu())
|
tcb->cpu != this_cpu())
|
||||||
{
|
{
|
||||||
struct roundrobin_arg_s arg;
|
nxsched_smp_call_init(&g_call_data,
|
||||||
|
nxsched_roundrobin_handler,
|
||||||
arg.pid = tcb->pid;
|
(FAR void *)(uintptr_t)tcb->pid);
|
||||||
nxsched_smp_call_single(tcb->cpu,
|
nxsched_smp_call_single_async(tcb->cpu, &g_call_data);
|
||||||
nxsched_roundrobin_handler,
|
|
||||||
&arg, false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -246,8 +246,7 @@ static inline void nxsched_running_setpriority(FAR struct tcb_s *tcb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
arg.sched_priority = sched_priority;
|
arg.sched_priority = sched_priority;
|
||||||
nxsched_smp_call_single(tcb->cpu, reprioritize_handler,
|
nxsched_smp_call_single(tcb->cpu, reprioritize_handler, &arg);
|
||||||
&arg, true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+134
-99
@@ -46,22 +46,11 @@ struct smp_call_cookie_s
|
|||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smp_call_data_s
|
|
||||||
{
|
|
||||||
sq_entry_t node[CONFIG_SMP_NCPUS];
|
|
||||||
nxsched_smp_call_t func;
|
|
||||||
FAR void *arg;
|
|
||||||
FAR struct smp_call_cookie_s *cookie;
|
|
||||||
spinlock_t lock;
|
|
||||||
volatile int refcount;
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static sq_queue_t g_smp_call_queue[CONFIG_SMP_NCPUS];
|
static sq_queue_t g_smp_call_queue[CONFIG_SMP_NCPUS];
|
||||||
static struct smp_call_data_s g_smp_call_data;
|
|
||||||
static spinlock_t g_smp_call_lock;
|
static spinlock_t g_smp_call_lock;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -76,7 +65,7 @@ static spinlock_t g_smp_call_lock;
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cpu - Target cpu id
|
* cpu - Target cpu id
|
||||||
* call_data - Call data
|
* data - Call data
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* None
|
||||||
@@ -84,12 +73,16 @@ static spinlock_t g_smp_call_lock;
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void nxsched_smp_call_add(int cpu,
|
static void nxsched_smp_call_add(int cpu,
|
||||||
FAR struct smp_call_data_s *call_data)
|
FAR struct smp_call_data_s *data)
|
||||||
{
|
{
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
flags = spin_lock_irqsave(&g_smp_call_lock);
|
flags = spin_lock_irqsave(&g_smp_call_lock);
|
||||||
sq_addlast(&call_data->node[cpu], &g_smp_call_queue[cpu]);
|
if (!sq_inqueue(&data->node[cpu], &g_smp_call_queue[cpu]))
|
||||||
|
{
|
||||||
|
sq_addlast(&data->node[cpu], &g_smp_call_queue[cpu]);
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&g_smp_call_lock, flags);
|
spin_unlock_irqrestore(&g_smp_call_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,33 +120,26 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
|
|||||||
|
|
||||||
sq_for_every_safe(call_queue, curr, next)
|
sq_for_every_safe(call_queue, curr, next)
|
||||||
{
|
{
|
||||||
FAR struct smp_call_data_s *call_data =
|
FAR struct smp_call_data_s *data =
|
||||||
container_of(curr, struct smp_call_data_s, node[cpu]);
|
container_of(curr, struct smp_call_data_s, node[cpu]);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sq_rem(&call_data->node[cpu], call_queue);
|
sq_rem(&data->node[cpu], call_queue);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&g_smp_call_lock, flags);
|
spin_unlock_irqrestore(&g_smp_call_lock, flags);
|
||||||
|
|
||||||
ret = call_data->func(call_data->arg);
|
ret = data->func(data->arg);
|
||||||
|
|
||||||
flags = spin_lock_irqsave(&g_smp_call_lock);
|
flags = spin_lock_irqsave(&g_smp_call_lock);
|
||||||
if (spin_is_locked(&call_data->lock))
|
|
||||||
{
|
|
||||||
if (--call_data->refcount == 0)
|
|
||||||
{
|
|
||||||
spin_unlock(&call_data->lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (call_data->cookie != NULL)
|
if (data->cookie != NULL)
|
||||||
{
|
{
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
call_data->cookie->error = ret;
|
data->cookie->error = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxsem_post(&call_data->cookie->sem);
|
nxsem_post(&data->cookie->sem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,17 +147,42 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsched_smp_call_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Init call_data
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* data - Call data
|
||||||
|
* func - Function
|
||||||
|
* arg - Function args
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Result
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nxsched_smp_call_init(FAR struct smp_call_data_s *data,
|
||||||
|
nxsched_smp_call_t func, FAR void *arg)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(data != NULL && func != NULL);
|
||||||
|
|
||||||
|
memset(data, 0, sizeof(struct smp_call_data_s));
|
||||||
|
data->func = func;
|
||||||
|
data->arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsched_smp_call_single
|
* Name: nxsched_smp_call_single
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Call function on single processor
|
* Call function on single processor, wait function callback
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cpuid - Target cpu id
|
* cpuid - Target cpu id
|
||||||
* func - Function
|
* func - Function
|
||||||
* arg - Function args
|
* arg - Function args
|
||||||
* wait - Wait function callback or not
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Result
|
* Result
|
||||||
@@ -179,26 +190,25 @@ int nxsched_smp_call_handler(int irq, FAR void *context,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nxsched_smp_call_single(int cpuid, nxsched_smp_call_t func,
|
int nxsched_smp_call_single(int cpuid, nxsched_smp_call_t func,
|
||||||
FAR void *arg, bool wait)
|
FAR void *arg)
|
||||||
{
|
{
|
||||||
cpu_set_t cpuset;
|
cpu_set_t cpuset;
|
||||||
|
|
||||||
CPU_ZERO(&cpuset);
|
CPU_ZERO(&cpuset);
|
||||||
CPU_SET(cpuid, &cpuset);
|
CPU_SET(cpuid, &cpuset);
|
||||||
return nxsched_smp_call(cpuset, func, arg, wait);
|
return nxsched_smp_call(cpuset, func, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nxsched_smp_call
|
* Name: nxsched_smp_call
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Call function on multi processors
|
* Call function on multi processors, wait function callback
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cpuset - Target cpuset
|
* cpuset - Target cpuset
|
||||||
* func - Function
|
* func - Function
|
||||||
* arg - Function args
|
* arg - Function args
|
||||||
* wait - Wait function callback or not
|
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Result
|
* Result
|
||||||
@@ -206,26 +216,96 @@ int nxsched_smp_call_single(int cpuid, nxsched_smp_call_t func,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func,
|
int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func,
|
||||||
FAR void *arg, bool wait)
|
FAR void *arg)
|
||||||
{
|
{
|
||||||
struct smp_call_data_s call_data_stack =
|
struct smp_call_data_s data;
|
||||||
{
|
struct smp_call_cookie_s cookie;
|
||||||
0
|
int cpucnt;
|
||||||
};
|
|
||||||
|
|
||||||
struct smp_call_cookie_s cookie =
|
|
||||||
{
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
FAR struct smp_call_data_s *call_data;
|
|
||||||
int remote_cpus;
|
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Cannot wait in interrupt context. */
|
/* Cannot wait in interrupt context. */
|
||||||
|
|
||||||
DEBUGASSERT(!(wait && up_interrupt_context()));
|
DEBUGASSERT(!up_interrupt_context());
|
||||||
|
nxsched_smp_call_init(&data, func, arg);
|
||||||
|
cookie.error = 0;
|
||||||
|
nxsem_init(&cookie.sem, 0, 0);
|
||||||
|
|
||||||
|
data.cookie = &cookie;
|
||||||
|
ret = nxsched_smp_call_async(cpuset, &data);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nxsem_destroy(&cookie.sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpucnt = CPU_COUNT(&cpuset);
|
||||||
|
for (i = 0; i < cpucnt; i++)
|
||||||
|
{
|
||||||
|
int rc = nxsem_wait_uninterruptible(&cookie.sem);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
ret = rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cookie.error < 0)
|
||||||
|
{
|
||||||
|
ret = cookie.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxsem_destroy(&cookie.sem);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsched_smp_call_single_async
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Call function on single processor async
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* cpuset - Target cpuset
|
||||||
|
* data - Call data
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Result
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsched_smp_call_single_async(int cpuid,
|
||||||
|
FAR struct smp_call_data_s *data)
|
||||||
|
{
|
||||||
|
cpu_set_t cpuset;
|
||||||
|
|
||||||
|
CPU_ZERO(&cpuset);
|
||||||
|
CPU_SET(cpuid, &cpuset);
|
||||||
|
return nxsched_smp_call_async(cpuset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxsched_smp_call_async
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Call function on multi processors async
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* cpuset - Target cpuset
|
||||||
|
* data - Call data
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Result
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nxsched_smp_call_async(cpu_set_t cpuset,
|
||||||
|
FAR struct smp_call_data_s *data)
|
||||||
|
{
|
||||||
|
int cpucnt;
|
||||||
|
int ret = OK;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Prevent reschedule on another processor */
|
/* Prevent reschedule on another processor */
|
||||||
|
|
||||||
@@ -234,71 +314,26 @@ int nxsched_smp_call(cpu_set_t cpuset, nxsched_smp_call_t func,
|
|||||||
sched_lock();
|
sched_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CPU_ISSET(this_cpu(), &cpuset))
|
cpucnt = CPU_COUNT(&cpuset);
|
||||||
{
|
if (cpucnt == 0)
|
||||||
ret = func(arg);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPU_CLR(this_cpu(), &cpuset);
|
|
||||||
}
|
|
||||||
|
|
||||||
remote_cpus = CPU_COUNT(&cpuset);
|
|
||||||
if (remote_cpus == 0)
|
|
||||||
{
|
{
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If waiting is necessary, initialize and wait for the cookie. */
|
|
||||||
|
|
||||||
if (wait)
|
|
||||||
{
|
|
||||||
nxsem_init(&cookie.sem, 0, 0);
|
|
||||||
|
|
||||||
call_data = &call_data_stack;
|
|
||||||
call_data->cookie = &cookie;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
call_data = &g_smp_call_data;
|
|
||||||
spin_lock(&call_data->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
call_data->func = func;
|
|
||||||
call_data->arg = arg;
|
|
||||||
call_data->refcount = remote_cpus;
|
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
|
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
|
||||||
{
|
{
|
||||||
if (CPU_ISSET(i, &cpuset))
|
if (CPU_ISSET(i, &cpuset))
|
||||||
{
|
{
|
||||||
nxsched_smp_call_add(i, call_data);
|
nxsched_smp_call_add(i, data);
|
||||||
|
if (--cpucnt == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
up_send_smp_call(cpuset);
|
up_send_smp_call(cpuset);
|
||||||
|
|
||||||
if (wait)
|
|
||||||
{
|
|
||||||
for (i = 0; i < remote_cpus; i++)
|
|
||||||
{
|
|
||||||
int wait_ret = nxsem_wait_uninterruptible(&cookie.sem);
|
|
||||||
if (wait_ret < 0)
|
|
||||||
{
|
|
||||||
ret = wait_ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cookie.error < 0)
|
|
||||||
{
|
|
||||||
ret = cookie.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
nxsem_destroy(&cookie.sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!up_interrupt_context())
|
if (!up_interrupt_context())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -166,8 +166,7 @@ void nxsched_suspend(FAR struct tcb_s *tcb)
|
|||||||
CPU_SET(tcb->cpu, &tcb->affinity);
|
CPU_SET(tcb->cpu, &tcb->affinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
nxsched_smp_call_single(tcb->cpu, nxsched_suspend_handler,
|
nxsched_smp_call_single(tcb->cpu, nxsched_suspend_handler, &arg);
|
||||||
&arg, true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -187,8 +187,7 @@ static int nxsig_queue_action(FAR struct tcb_s *stcb, siginfo_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
arg.pid = stcb->pid;
|
arg.pid = stcb->pid;
|
||||||
nxsched_smp_call_single(stcb->cpu, sig_handler, &arg,
|
nxsched_smp_call_single(stcb->cpu, sig_handler, &arg);
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ static int nxtask_restart(pid_t pid)
|
|||||||
CPU_SET(tcb->cpu, &tcb->affinity);
|
CPU_SET(tcb->cpu, &tcb->affinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
nxsched_smp_call_single(tcb->cpu, restart_handler, &arg, true);
|
nxsched_smp_call_single(tcb->cpu, restart_handler, &arg);
|
||||||
|
|
||||||
tcb = nxsched_get_tcb(pid);
|
tcb = nxsched_get_tcb(pid);
|
||||||
if (!tcb || tcb->task_state != TSTATE_TASK_INVALID ||
|
if (!tcb || tcb->task_state != TSTATE_TASK_INVALID ||
|
||||||
|
|||||||
@@ -147,8 +147,7 @@ int nxtask_terminate(pid_t pid)
|
|||||||
CPU_SET(dtcb->cpu, &dtcb->affinity);
|
CPU_SET(dtcb->cpu, &dtcb->affinity);
|
||||||
|
|
||||||
ret = nxsched_smp_call_single(dtcb->cpu, terminat_handler,
|
ret = nxsched_smp_call_single(dtcb->cpu, terminat_handler,
|
||||||
(FAR void *)(uintptr_t)pid,
|
(FAR void *)(uintptr_t)pid);
|
||||||
true);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user