]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - runctl() can stop across cpus
authorTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:11:09 +0000 (14:11 +0000)
committerTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:11:09 +0000 (14:11 +0000)
- if stopping a process that runs on a different CPU we tell the
  remote cpu to do that

kernel/smp.c
kernel/smp.h
kernel/system/do_runctl.c

index b11e0738c7716895ff6554ab9437fa3ae087dcdf..77b6cede8e22e925cec3a40aca1d645672fed6ba 100644 (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;
 }
 
index 0cb209d2e04ebd798f68bfc84d01eb3a66562a3f..408f166bb4c7ca3e444fc0888095cf408d8566d6 100644 (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));
index a724d01b42d5ba9a74dacc294307ebafd6b5a3c5..3500f28f26e7b33e31bc83f7d86f0ca699b8f50b 100644 (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);