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:
Tomas Hruby 2010-09-15 14:11:09 +00:00
parent e2701da5a9
commit 906a81a1c7
3 changed files with 51 additions and 5 deletions

View file

@ -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;
}

View file

@ -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));

View file

@ -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);