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 ht_per_core;
|
||||||
unsigned bsp_cpu_id;
|
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;
|
static volatile unsigned ap_cpus_booted;
|
||||||
|
|
||||||
|
@ -36,18 +46,44 @@ PUBLIC void smp_ipi_halt_handler(void)
|
||||||
|
|
||||||
PUBLIC void smp_schedule(unsigned cpu)
|
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);
|
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)
|
PUBLIC void smp_ipi_sched_handler(void)
|
||||||
{
|
{
|
||||||
struct proc * p;
|
struct proc * p;
|
||||||
|
unsigned mycpu = cpuid;
|
||||||
|
unsigned flgs;
|
||||||
|
|
||||||
ipi_ack();
|
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)
|
if (flgs & SCHED_IPI_STOP_PROC) {
|
||||||
RTS_SET(p, RTS_PREEMPTED); /* calls dequeue() */
|
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_ipi_sched_handler, (void));
|
||||||
|
|
||||||
_PROTOTYPE(void smp_schedule, (unsigned cpu));
|
_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_send_smp_schedule_ipi, (unsigned cpu));
|
||||||
_PROTOTYPE(void arch_smp_halt_cpu, (void));
|
_PROTOTYPE(void arch_smp_halt_cpu, (void));
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kernel/system.h"
|
#include "kernel/system.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#if USE_RUNCTL
|
#if USE_RUNCTL
|
||||||
|
|
||||||
|
@ -51,7 +52,15 @@ PUBLIC int do_runctl(struct proc * caller, message * m_ptr)
|
||||||
/* Either set or clear the stop flag. */
|
/* Either set or clear the stop flag. */
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case RC_STOP:
|
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;
|
break;
|
||||||
case RC_RESUME:
|
case RC_RESUME:
|
||||||
RTS_UNSET(rp, RTS_PROC_STOP);
|
RTS_UNSET(rp, RTS_PROC_STOP);
|
||||||
|
|
Loading…
Reference in a new issue