diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-12-18 14:42:58 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-12-24 19:59:55 -0800 |
| commit | b47ff23673559ee9a5b91221e0212fd6a57d9802 (patch) | |
| tree | 2f9f3e7ea6791f3dcf7a6bea8c165f06a4565e20 | |
| parent | 7f483459045789d6bb44671269fd9aec73dbeb63 (diff) | |
| download | rust-b47ff23673559ee9a5b91221e0212fd6a57d9802.tar.gz rust-b47ff23673559ee9a5b91221e0212fd6a57d9802.zip | |
green: Move a scheduler test inside libgreen
This test also had a race condition in using the cvar/lock, so I fixed that up as well. The race originated from one half trying to destroy the lock when another half was using it.
| -rw-r--r-- | src/libgreen/sched.rs | 73 | ||||
| -rw-r--r-- | src/libstd/task.rs | 60 |
2 files changed, 72 insertions, 61 deletions
diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index 9e26cd41cdd..95c4d8347d5 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -957,7 +957,7 @@ mod test { use std::rt::local::Local; use basic; - use sched::TaskFromFriend; + use sched::{TaskFromFriend, PinnedTask}; use task::{GreenTask, HomeSched}; use PoolConfig; use SchedPool; @@ -1406,4 +1406,75 @@ mod test { 5.times(deschedule); } } + + #[test] + fn test_spawn_sched_blocking() { + use std::unstable::mutex::Mutex; + + // Testing that a task in one scheduler can block in foreign code + // without affecting other schedulers + for _ in range(0, 20) { + let mut pool = pool(); + let (start_po, start_ch) = Chan::new(); + let (fin_po, fin_ch) = Chan::new(); + + let lock = unsafe { Mutex::new() }; + let lock2 = unsafe { lock.clone() }; + + let mut handle = pool.spawn_sched(); + handle.send(PinnedTask(pool.task(TaskOpts::new(), proc() { + let mut lock = lock2; + unsafe { + lock.lock(); + + start_ch.send(()); + lock.wait(); // block the scheduler thread + lock.signal(); // let them know we have the lock + lock.unlock(); + } + + fin_ch.send(()); + }))); + drop(handle); + + let mut handle = pool.spawn_sched(); + handle.send(TaskFromFriend(pool.task(TaskOpts::new(), proc() { + // Wait until the other task has its lock + start_po.recv(); + + fn pingpong(po: &Port<int>, ch: &Chan<int>) { + let mut val = 20; + while val > 0 { + val = po.recv(); + ch.try_send(val - 1); + } + } + + let (setup_po, setup_ch) = Chan::new(); + let (parent_po, parent_ch) = Chan::new(); + do spawn { + let (child_po, child_ch) = Chan::new(); + setup_ch.send(child_ch); + pingpong(&child_po, &parent_ch); + }; + + let child_ch = setup_po.recv(); + child_ch.send(20); + pingpong(&parent_po, &child_ch); + unsafe { + let mut lock = lock; + lock.lock(); + lock.signal(); // wakeup waiting scheduler + lock.wait(); // wait for them to grab the lock + lock.unlock(); + lock.destroy(); // now we're guaranteed they have no locks + } + }))); + drop(handle); + + fin_po.recv(); + pool.shutdown(); + } + + } } diff --git a/src/libstd/task.rs b/src/libstd/task.rs index 836390fb416..2f0f9bf64af 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -529,66 +529,6 @@ fn test_spawn_sched_childs_on_default_sched() { po.recv(); } -#[test] -fn test_spawn_sched_blocking() { - use unstable::mutex::Mutex; - use num::Times; - - unsafe { - - // Testing that a task in one scheduler can block in foreign code - // without affecting other schedulers - 20u.times(|| { - let (start_po, start_ch) = Chan::new(); - let (fin_po, fin_ch) = Chan::new(); - - let mut lock = Mutex::new(); - let lock2 = lock.clone(); - - do spawn { - let mut lock = lock2; - lock.lock(); - - start_ch.send(()); - - // Block the scheduler thread - lock.wait(); - lock.unlock(); - - fin_ch.send(()); - }; - - // Wait until the other task has its lock - start_po.recv(); - - fn pingpong(po: &Port<int>, ch: &Chan<int>) { - let mut val = 20; - while val > 0 { - val = po.recv(); - ch.try_send(val - 1); - } - } - - let (setup_po, setup_ch) = Chan::new(); - let (parent_po, parent_ch) = Chan::new(); - do spawn { - let (child_po, child_ch) = Chan::new(); - setup_ch.send(child_ch); - pingpong(&child_po, &parent_ch); - }; - - let child_ch = setup_po.recv(); - child_ch.send(20); - pingpong(&parent_po, &child_ch); - lock.lock(); - lock.signal(); - lock.unlock(); - fin_po.recv(); - lock.destroy(); - }) - } -} - #[cfg(test)] fn avoid_copying_the_body(spawnfn: |v: proc()|) { let (p, ch) = Chan::<uint>::new(); |
