SMP - runctl() can stop across cpus
- if stopping a process that runs on a different CPU we tell the remote cpu to do that
This commit is contained in:
parent
e2701da5a9
commit
906a81a1c7
3 changed files with 51 additions and 5 deletions
44
kernel/smp.c
44
kernel/smp.c
|
@ -5,7 +5,17 @@ unsigned ncpus;
|
|||
unsigned ht_per_core;
|
||||
unsigned bsp_cpu_id;
|
||||
|
||||
struct cpu cpus[CONFIG_MAX_CPUS];
|
||||
PUBLIC struct cpu cpus[CONFIG_MAX_CPUS];
|
||||
|
||||
/* flags passed to another cpu along with a sched ipi */
|
||||
struct sched_ipi_data {
|
||||
volatile u32_t flags;
|
||||
volatile u32_t data;
|
||||
};
|
||||
|
||||
PRIVATE struct sched_ipi_data sched_ipi_data[CONFIG_MAX_CPUS];
|
||||
|
||||
#define SCHED_IPI_STOP_PROC 1
|
||||
|
||||
static volatile unsigned ap_cpus_booted;
|
||||
|
||||
|
@ -36,18 +46,44 @@ PUBLIC void smp_ipi_halt_handler(void)
|
|||
|
||||
PUBLIC void smp_schedule(unsigned cpu)
|
||||
{
|
||||
/*
|
||||
* check if the cpu is processing some other ipi already. If yes, no
|
||||
* need to wake it up
|
||||
*/
|
||||
if ((volatile unsigned)sched_ipi_data[cpu].flags != 0)
|
||||
return;
|
||||
arch_send_smp_schedule_ipi(cpu);
|
||||
}
|
||||
|
||||
PUBLIC void smp_schedule_stop_proc(struct proc * p)
|
||||
{
|
||||
unsigned cpu = p->p_cpu;
|
||||
|
||||
sched_ipi_data[cpu].flags |= SCHED_IPI_STOP_PROC;
|
||||
sched_ipi_data[cpu].data = (u32_t) p;
|
||||
arch_send_smp_schedule_ipi(cpu);
|
||||
BKL_UNLOCK();
|
||||
while ((volatile unsigned)sched_ipi_data[cpu].flags != 0);
|
||||
BKL_LOCK();
|
||||
}
|
||||
|
||||
PUBLIC void smp_ipi_sched_handler(void)
|
||||
{
|
||||
struct proc * p;
|
||||
unsigned mycpu = cpuid;
|
||||
unsigned flgs;
|
||||
|
||||
ipi_ack();
|
||||
|
||||
p = get_cpulocal_var(proc_ptr);
|
||||
p = get_cpu_var(mycpu, proc_ptr);
|
||||
flgs = sched_ipi_data[mycpu].flags;
|
||||
|
||||
if (p->p_endpoint != IDLE)
|
||||
RTS_SET(p, RTS_PREEMPTED); /* calls dequeue() */
|
||||
if (flgs & SCHED_IPI_STOP_PROC) {
|
||||
RTS_SET((struct proc *)sched_ipi_data[mycpu].data, RTS_PROC_STOP);
|
||||
}
|
||||
else if (p->p_endpoint != IDLE) {
|
||||
RTS_SET(p, RTS_PREEMPTED);
|
||||
}
|
||||
sched_ipi_data[cpuid].flags = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ _PROTOTYPE(void smp_ipi_halt_handler, (void));
|
|||
_PROTOTYPE(void smp_ipi_sched_handler, (void));
|
||||
|
||||
_PROTOTYPE(void smp_schedule, (unsigned cpu));
|
||||
_PROTOTYPE(void smp_schedule_stop_proc, (struct proc * p));
|
||||
|
||||
_PROTOTYPE(void arch_send_smp_schedule_ipi, (unsigned cpu));
|
||||
_PROTOTYPE(void arch_smp_halt_cpu, (void));
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include "kernel/system.h"
|
||||
#include <assert.h>
|
||||
|
||||
#if USE_RUNCTL
|
||||
|
||||
|
@ -51,7 +52,15 @@ PUBLIC int do_runctl(struct proc * caller, message * m_ptr)
|
|||
/* Either set or clear the stop flag. */
|
||||
switch (action) {
|
||||
case RC_STOP:
|
||||
RTS_SET(rp, RTS_PROC_STOP);
|
||||
#if CONFIG_SMP
|
||||
/* check if we must stop a process on a different CPU */
|
||||
if (rp->p_cpu != cpuid) {
|
||||
smp_schedule_stop_proc(rp);
|
||||
assert(RTS_ISSET(rp, RTS_PROC_STOP));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
RTS_SET(rp, RTS_PROC_STOP);
|
||||
break;
|
||||
case RC_RESUME:
|
||||
RTS_UNSET(rp, RTS_PROC_STOP);
|
||||
|
|
Loading…
Reference in a new issue