summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-05-30 00:18:49 -0700
committerBrian Anderson <banderson@mozilla.com>2013-05-30 00:18:49 -0700
commit053b38e7e1cba8f7bb649a5fc8d82b0448d33c55 (patch)
tree139cb953e1aedd723324a33149279750917c6b34 /src/libstd/rt
parent8eb358bb00f161f9e289de6cad8cfecc4c6eb681 (diff)
downloadrust-053b38e7e1cba8f7bb649a5fc8d82b0448d33c55.tar.gz
rust-053b38e7e1cba8f7bb649a5fc8d82b0448d33c55.zip
core::rt: Fix two multithreading bugs and add a threadring test
This properly distributes the load now
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/sched.rs66
-rw-r--r--src/libstd/rt/test.rs2
2 files changed, 66 insertions, 2 deletions
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index b5b8bb732e7..a57a87ffba7 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -131,6 +131,11 @@ pub impl Scheduler {
 
         let mut self_sched = self;
 
+        // Always run through the scheduler loop at least once so that
+        // we enter the sleep state and can then be woken up by other
+        // schedulers.
+        self_sched.event_loop.callback(Scheduler::run_sched_once);
+
         unsafe {
             let event_loop: *mut ~EventLoopObject = {
                 let event_loop: *mut ~EventLoopObject = &mut self_sched.event_loop;
@@ -258,7 +263,7 @@ pub impl Scheduler {
                                 let mut handle = handle;
                                 handle.send(Wake);
                             }
-                            None => (/* pass */)
+                            None => break
                         }
                     }
                 }
@@ -781,4 +786,63 @@ mod test {
             }
         }
     }
+
+    #[test]
+    fn thread_ring() {
+        use rt::comm::*;
+        use iter::Times;
+        use vec::OwnedVector;
+        use container::Container;
+        use comm::{GenericPort, GenericChan};
+
+        do run_in_mt_newsched_task {
+            let (end_port, end_chan) = oneshot();
+
+            let n_tasks = 10;
+            let token = 2000;
+
+            let mut (p, ch1) = stream();
+            ch1.send((token, end_chan));
+            let mut i = 2;
+            while i <= n_tasks {
+                let (next_p, ch) = stream();
+                let imm_i = i;
+                let imm_p = p;
+                do spawntask_random {
+                    roundtrip(imm_i, n_tasks, &imm_p, &ch);
+                };
+                p = next_p;
+                i += 1;
+            }
+            let imm_p = p;
+            let imm_ch = ch1;
+            do spawntask_random {
+                roundtrip(1, n_tasks, &imm_p, &imm_ch);
+            }
+
+            end_port.recv();
+        }
+
+        fn roundtrip(id: int, n_tasks: int,
+                     p: &Port<(int, ChanOne<()>)>, ch: &Chan<(int, ChanOne<()>)>) {
+            while (true) {
+                match p.recv() {
+                    (1, end_chan) => {
+                        debug!("%d\n", id);
+                        end_chan.send(());
+                        return;
+                    }
+                    (token, end_chan) => {
+                        debug!("thread: %d   got token: %d", id, token);
+                        ch.send((token - 1, end_chan));
+                        if token <= n_tasks {
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+
 }
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
index 16b0aef5e26..e05e2004e0b 100644
--- a/src/libstd/rt/test.rs
+++ b/src/libstd/rt/test.rs
@@ -66,7 +66,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
     let f_cell = Cell(f);
 
     do run_in_bare_thread {
-        static N: uint = 2;
+        static N: uint = 4;
 
         let sleepers = SleeperList::new();
         let work_queue = WorkQueue::new();