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;
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;
}
_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));
*/
#include "kernel/system.h"
+#include <assert.h>
#if USE_RUNCTL
/* 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);