Skip to content

Commit

Permalink
green: Move a scheduler test inside libgreen
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Dec 25, 2013
1 parent 7f48345 commit b47ff23
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 61 deletions.
73 changes: 72 additions & 1 deletion src/libgreen/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}

}
}
60 changes: 0 additions & 60 deletions src/libstd/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit b47ff23

Please sign in to comment.