]> xenbits.xensource.com Git - xen.git/commitdiff
[Mini-OS] Make sure schedule() is called safely
authorKeir Fraser <keir.fraser@citrix.com>
Sat, 24 Nov 2007 13:29:20 +0000 (13:29 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Sat, 24 Nov 2007 13:29:20 +0000 (13:29 +0000)
If a thread tries to sleep from a callback or with callbacks disabled,
Mini-OS will completely lock, so make sure this never happens.

Signed-off-by: Samuel Thibault <samuel.thibault@citrix.com>
extras/mini-os/hypervisor.c
extras/mini-os/include/hypervisor.h
extras/mini-os/sched.c

index ed87845195163a66a9c7a1bb11d4a45b4859ceec..e84d34ccaf005974fe30fd5d76c2ba03753a77cc 100644 (file)
@@ -33,6 +33,8 @@
     ((sh)->evtchn_pending[idx] &                \
      ~(sh)->evtchn_mask[idx])
 
+int in_callback;
+
 void do_hypervisor_callback(struct pt_regs *regs)
 {
     unsigned long  l1, l2, l1i, l2i;
@@ -41,6 +43,7 @@ void do_hypervisor_callback(struct pt_regs *regs)
     shared_info_t *s = HYPERVISOR_shared_info;
     vcpu_info_t   *vcpu_info = &s->vcpu_info[cpu];
 
+    in_callback = 1;
    
     vcpu_info->evtchn_upcall_pending = 0;
     /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
@@ -59,6 +62,8 @@ void do_hypervisor_callback(struct pt_regs *regs)
                        do_event(port, regs);
         }
     }
+
+    in_callback = 0;
 }
 
 
index 1b7ea72ac3402823649c3f202e02d7e8e0e198fa..e06f54bdefb849164325042821eabb5ed4d19729 100644 (file)
@@ -42,4 +42,6 @@ void mask_evtchn(u32 port);
 void unmask_evtchn(u32 port);
 void clear_evtchn(u32 port);
 
+extern int in_callback;
+
 #endif /* __HYPERVISOR_H__ */
index 69f398ed13f8233a380e2d3dc9f78d032f5606ad..fbcffd463e15fa118f710d874f3794db0e91bd10 100644 (file)
@@ -125,6 +125,14 @@ void schedule(void)
     unsigned long flags;
     prev = current;
     local_irq_save(flags); 
+    if (in_callback) {
+        printk("Must not call schedule() from a callback\n");
+        BUG();
+    }
+    if (flags) {
+        printk("Must not call schedule() with IRQs disabled\n");
+        BUG();
+    }
     list_for_each(iterator, &exited_threads)
     {
         thread = list_entry(iterator, struct thread, thread_list);