proc messages are routine instead of immediate
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 23 Mar 2010 08:24:22 +0000 (01:24 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:40 +0000 (17:35 -0700)
This should solve the races we haven't seen yet where a core is in the
kernel with interrupts enabled but in a situation where the kernel
cannot abandon its stack yet when a __death or similar message comes in.

kern/arch/i686/trap.c
kern/arch/sparc/smp.c
kern/arch/sparc/trap.c
kern/include/trap.h
kern/src/frontend.c
kern/src/process.c
kern/src/testing.c

index 515eaf5..f7b1f92 100644 (file)
@@ -406,12 +406,12 @@ uint32_t send_kernel_message(uint32_t dst, amr_t pc, TV(a0t) arg0, TV(a1t) arg1,
        k_msg->arg1 = arg1;
        k_msg->arg2 = arg2;
        switch (type) {
-               case AMSG_IMMEDIATE:
+               case KMSG_IMMEDIATE:
                        spin_lock_irqsave(&per_cpu_info[dst].immed_amsg_lock);
                        STAILQ_INSERT_TAIL(&per_cpu_info[dst].immed_amsgs, k_msg, link);
                        spin_unlock_irqsave(&per_cpu_info[dst].immed_amsg_lock);
                        break;
-               case AMSG_ROUTINE:
+               case KMSG_ROUTINE:
                        spin_lock_irqsave(&per_cpu_info[dst].routine_amsg_lock);
                        STAILQ_INSERT_TAIL(&per_cpu_info[dst].routine_amsgs, k_msg, link);
                        spin_unlock_irqsave(&per_cpu_info[dst].routine_amsg_lock);
index 8b7f949..2df8197 100644 (file)
@@ -95,12 +95,12 @@ int smp_call_function_all(isr_t handler, void* data,
                        continue;
 
                send_kernel_message(i,(amr_t)smp_call_wrapper,
-                                         handler, wrapper, data, AMSG_IMMEDIATE);
+                                         handler, wrapper, data, KMSG_IMMEDIATE);
        }
 
        // send to me
        send_kernel_message(core_id(),(amr_t)smp_call_wrapper,
-                                 handler,wrapper,data, AMSG_IMMEDIATE);
+                                 handler,wrapper,data, KMSG_IMMEDIATE);
 
        cpu_relax(); // wait to get the interrupt
 
@@ -125,7 +125,7 @@ int smp_call_function_single(uint32_t dest, isr_t handler, void* data,
        enable_irqsave(&state);
 
        send_kernel_message(dest,(amr_t)smp_call_wrapper,
-                                 handler,wrapper,data, AMSG_IMMEDIATE);
+                                 handler,wrapper,data, KMSG_IMMEDIATE);
 
        cpu_relax(); // wait to get the interrupt, if it's to this core
 
index a8222d5..24b05f7 100644 (file)
@@ -45,12 +45,12 @@ uint32_t send_kernel_message(uint32_t dst, amr_t pc,
        k_msg->arg1 = arg1;
        k_msg->arg2 = arg2;
        switch (type) {
-               case AMSG_IMMEDIATE:
+               case KMSG_IMMEDIATE:
                        spin_lock_irqsave(&per_cpu_info[dst].immed_amsg_lock);
                        STAILQ_INSERT_TAIL(&per_cpu_info[dst].immed_amsgs, k_msg, link);
                        spin_unlock_irqsave(&per_cpu_info[dst].immed_amsg_lock);
                        break;
-               case AMSG_ROUTINE:
+               case KMSG_ROUTINE:
                        spin_lock_irqsave(&per_cpu_info[dst].routine_amsg_lock);
                        STAILQ_INSERT_TAIL(&per_cpu_info[dst].routine_amsgs, k_msg, link);
                        spin_unlock_irqsave(&per_cpu_info[dst].routine_amsg_lock);
index 1ac153e..f3e92df 100644 (file)
@@ -53,8 +53,8 @@ extern void sysenter_handler();
  * messages require a unique message.  Also for now, but it might be like that
  * for a while on x86 (til we have a broadcast). */
 
-#define AMSG_IMMEDIATE                         1
-#define AMSG_ROUTINE                   2
+#define KMSG_IMMEDIATE                         1
+#define KMSG_ROUTINE                   2
 void kernel_msg_init(void);
 typedef void (*amr_t)(trapframe_t* tf, uint32_t srcid,
                       TV(a0t) a0, TV(a1t) a1, TV(a2t) a2);
index 7781399..a27b85f 100644 (file)
@@ -285,7 +285,7 @@ void appserver_die(int code)
        for(i = 0; i < num_cpus; i++)
                if(i != core_id())
                        while(send_kernel_message(i,(amr_t)&__diediedie,(void*)code,0,0,
-                                                 AMSG_IMMEDIATE));
+                                                 KMSG_IMMEDIATE));
 
        // just in case.
        __diediedie(0,0,code,0,0);
index b4c146a..3637852 100644 (file)
@@ -51,7 +51,6 @@ static uint32_t get_free_vcoreid(struct proc *SAFE p, uint32_t prev);
 static uint32_t get_busy_vcoreid(struct proc *SAFE p, uint32_t prev);
 static bool is_mapped_vcore(struct proc *p, uint32_t pcoreid);
 static uint32_t get_vcoreid(struct proc *SAFE p, uint32_t pcoreid);
-static inline void __wait_for_ipi(const char *fnname);
 
 /* PID management. */
 #define PID_MAX 32767 // goes from 0 to 32767, with 0 reserved
@@ -393,7 +392,7 @@ void proc_run(struct proc *p)
                        __seq_end_write(&p->procinfo->coremap_seqctr);
                        p->env_refcnt++; // TODO: (REF) use incref
                        p->procinfo->vcoremap[0].tf_to_run = &p->env_tf;
-                       send_kernel_message(core_id(), __startcore, p, 0, 0, AMSG_IMMEDIATE);
+                       send_kernel_message(core_id(), __startcore, p, 0, 0, KMSG_ROUTINE);
                        __proc_unlock_ipi_pending(p, TRUE);
                        break;
                case (PROC_RUNNABLE_M):
@@ -423,7 +422,7 @@ void proc_run(struct proc *p)
                                for (int i = 0; i < p->procinfo->num_vcores; i++)
                                        send_kernel_message(p->procinfo->vcoremap[i].pcoreid,
                                                            (void *)__startcore, (void *)p, 0, 0,
-                                                           AMSG_IMMEDIATE);
+                                                           KMSG_ROUTINE);
                        } else {
                                warn("Tried to proc_run() an _M with no vcores!");
                        }
@@ -562,7 +561,7 @@ void proc_destroy(struct proc *p)
                        #endif
                        send_kernel_message(p->procinfo->vcoremap[0].pcoreid, __death,
                                           (void *SNT)0, (void *SNT)0, (void *SNT)0,
-                                          AMSG_IMMEDIATE);
+                                          KMSG_ROUTINE);
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        // TODO: might need to sort num_vcores too later (VC#)
                        /* vcore is unmapped on the receive side */
@@ -641,20 +640,6 @@ static uint32_t get_vcoreid(struct proc *SAFE p, uint32_t pcoreid)
        return p->procinfo->pcoremap[pcoreid].vcoreid;
 }
 
-/* Use this when you are waiting for an IPI that you sent yourself.  In most
- * cases, interrupts should already be on (like after a spin_unlock_irqsave from
- * process context), but aren't always, like in proc_destroy().  We might be
- * able to remove the enable_irq in the future.  Think about this (TODO).
- *
- * Note this means all non-proc management interrupt handlers must return (which
- * they need to do anyway), so that we get back to this point.  */
-static inline void __wait_for_ipi(const char *fnname)
-{
-       enable_irq();
-       udelay(1000000);
-       panic("Waiting too long on core %d for an IPI in %s()!", core_id(), fnname);
-}
-
 /* Yields the calling core.  Must be called locally (not async) for now.
  * - If RUNNING_S, you just give up your time slice and will eventually return.
  * - If RUNNING_M, you give up the current vcore (which never returns), and
@@ -797,7 +782,7 @@ bool __proc_give_cores(struct proc *SAFE p, uint32_t *pcorelist, size_t num)
                                /* should be a fresh core */
                                assert(!p->procinfo->vcoremap[i].tf_to_run);
                                send_kernel_message(pcorelist[i], __startcore, p, 0, 0,
-                                                   AMSG_IMMEDIATE);
+                                                   KMSG_ROUTINE);
                                if (pcorelist[i] == core_id())
                                        self_ipi_pending = TRUE;
                        }
@@ -864,7 +849,7 @@ bool __proc_take_cores(struct proc *SAFE p, uint32_t *pcorelist,
                        if (pcoreid == core_id())
                                self_ipi_pending = TRUE;
                        send_kernel_message(pcoreid, message, arg0, arg1, arg2,
-                                           AMSG_IMMEDIATE);
+                                           KMSG_ROUTINE);
                } else {
                        /* if there was a msg, the vcore is unmapped on the receive side.
                         * o/w, we need to do it here. */
@@ -913,7 +898,7 @@ bool __proc_take_allcores(struct proc *SAFE p, amr_t message,
                        if (pcoreid == core_id())
                                self_ipi_pending = TRUE;
                        send_kernel_message(pcoreid, message, arg0, arg1, arg2,
-                                           AMSG_IMMEDIATE);
+                                           KMSG_ROUTINE);
                } else {
                        /* if there was a msg, the vcore is unmapped on the receive side.
                         * o/w, we need to do it here. */
@@ -930,14 +915,20 @@ bool __proc_take_allcores(struct proc *SAFE p, amr_t message,
 }
 
 /* Helper, to be used when unlocking after calling the above functions that
- * might cause an IPI to be sent.  TODO inline this, so the __FUNCTION__ works.
- * Will require an overhaul of core_request (break it up, etc) */
+ * might cause an IPI to be sent.  There should already be a kmsg waiting for
+ * us, since when we checked state to see a message was coming, the message had
+ * already been sent before unlocking.  Note we do not need interrupts enabled
+ * for this to work (you can receive a message before its IPI by polling).
+ *
+ * TODO: consider inlining this, so __FUNCTION__ works (will require effort in
+ * core_request(). */
 void __proc_unlock_ipi_pending(struct proc *p, bool ipi_pending)
 {
        if (ipi_pending) {
                p->env_refcnt--; // TODO: (REF) (atomics)
                spin_unlock_irqsave(&p->proc_lock);
-               __wait_for_ipi(__FUNCTION__);
+               process_routine_kmsg();
+               panic("stack-killing kmsg not found in %s!!!", __FUNCTION__);
        } else {
                spin_unlock_irqsave(&p->proc_lock);
        }
index ff03780..1b8992b 100644 (file)
@@ -687,27 +687,27 @@ void test_kernel_messages(void)
        printk("sending 5 IMMED to core 1, sending (#,deadbeef,0)\n");
        for (int i = 0; i < 5; i++)
                send_kernel_message(1, test_km_handler, (void*)i, (void*)0xdeadbeef,
-                                   (void*)0, AMSG_IMMEDIATE);
+                                   (void*)0, KMSG_IMMEDIATE);
        udelay(5000000);
        printk("sending 5 routine to core 1, sending (#,cafebabe,0)\n");
        for (int i = 0; i < 5; i++)
                send_kernel_message(1, test_km_handler, (void*)i, (void*)0xcafebabe,
-                                   (void*)0, AMSG_ROUTINE);
+                                   (void*)0, KMSG_ROUTINE);
        udelay(5000000);
        printk("sending 10 routine and 3 immediate to core 2\n");
        for (int i = 0; i < 10; i++)
                send_kernel_message(2, test_km_handler, (void*)i, (void*)0xcafebabe,
-                                   (void*)0, AMSG_ROUTINE);
+                                   (void*)0, KMSG_ROUTINE);
        for (int i = 0; i < 3; i++)
                send_kernel_message(2, test_km_handler, (void*)i, (void*)0xdeadbeef,
-                                   (void*)0, AMSG_IMMEDIATE);
+                                   (void*)0, KMSG_IMMEDIATE);
        udelay(5000000);
        printk("sending 5 ea alternating to core 2\n");
        for (int i = 0; i < 5; i++) {
                send_kernel_message(2, test_km_handler, (void*)i, (void*)0xdeadbeef,
-                                   (void*)0, AMSG_IMMEDIATE);
+                                   (void*)0, KMSG_IMMEDIATE);
                send_kernel_message(2, test_km_handler, (void*)i, (void*)0xcafebabe,
-                                   (void*)0, AMSG_ROUTINE);
+                                   (void*)0, KMSG_ROUTINE);
        }
        udelay(5000000);
        return;