Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac valgrind thread fixes #8424

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/libstd/rt/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ mod test {
use rt::test::*;
use cell::Cell;
use iter::Times;
use rt::util;

#[test]
fn oneshot_single_thread_close_port_first() {
Expand Down Expand Up @@ -840,6 +841,7 @@ mod test {

#[test]
fn oneshot_multi_thread_close_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do stress_factor().times {
do run_in_newsched_task {
let (port, chan) = oneshot::<int>();
Expand All @@ -855,6 +857,7 @@ mod test {

#[test]
fn oneshot_multi_thread_send_close_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do stress_factor().times {
do run_in_newsched_task {
let (port, chan) = oneshot::<int>();
Expand All @@ -875,6 +878,7 @@ mod test {

#[test]
fn oneshot_multi_thread_recv_close_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do stress_factor().times {
do run_in_newsched_task {
let (port, chan) = oneshot::<int>();
Expand All @@ -901,6 +905,7 @@ mod test {

#[test]
fn oneshot_multi_thread_send_recv_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do stress_factor().times {
do run_in_newsched_task {
let (port, chan) = oneshot::<~int>();
Expand All @@ -920,6 +925,7 @@ mod test {

#[test]
fn stream_send_recv_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do stress_factor().times {
do run_in_mt_newsched_task {
let (port, chan) = stream::<~int>();
Expand Down Expand Up @@ -964,6 +970,7 @@ mod test {

#[test]
fn shared_chan_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do run_in_mt_newsched_task {
let (port, chan) = stream();
let chan = SharedChan::new(chan);
Expand All @@ -983,6 +990,7 @@ mod test {

#[test]
fn shared_port_stress() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
do run_in_mt_newsched_task {
// XXX: Removing these type annotations causes an ICE
let (end_port, end_chan) = stream::<()>();
Expand Down Expand Up @@ -1063,6 +1071,8 @@ mod test {
use rand;
use rand::RngUtil;

if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }

do run_in_mt_newsched_task {
let (end_port, end_chan) = stream::<()>();
let end_chan = SharedChan::new(end_chan);
Expand Down
2 changes: 2 additions & 0 deletions src/libstd/rt/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ mod test {
use cell::Cell;
use rt::thread::Thread;
use rt::task::{Task, Sched};
use rt::util;
use option::{Some};

#[test]
Expand Down Expand Up @@ -971,6 +972,7 @@ mod test {

#[test]
fn test_stress_schedule_task_states() {
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
let n = stress_factor() * 120;
for _ in range(0, n as int) {
test_schedule_home_states();
Expand Down
14 changes: 9 additions & 5 deletions src/libstd/rt/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use iterator::{Iterator, range};
use vec::{OwnedVector, MutableVector};
use super::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use rt::sched::Scheduler;
use unstable::run_in_bare_thread;
use unstable::{run_in_bare_thread};
use rt::thread::Thread;
use rt::task::Task;
use rt::uv::uvio::UvEventLoop;
Expand Down Expand Up @@ -156,10 +156,14 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
let nthreads = match os::getenv("RUST_RT_TEST_THREADS") {
Some(nstr) => FromStr::from_str(nstr).unwrap(),
None => {
// Using more threads than cores in test code
// to force the OS to preempt them frequently.
// Assuming that this help stress test concurrent types.
util::num_cpus() * 2
if util::limit_thread_creation_due_to_osx_and_valgrind() {
1
} else {
// Using more threads than cores in test code
// to force the OS to preempt them frequently.
// Assuming that this help stress test concurrent types.
util::num_cpus() * 2
}
}
};

Expand Down
26 changes: 25 additions & 1 deletion src/libstd/rt/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use libc;
use option::{Some, None};
use os;
use str::StrSlice;
use unstable::running_on_valgrind;

/// Get the number of cores available
pub fn num_cpus() -> uint {
Expand All @@ -27,12 +28,35 @@ pub fn num_cpus() -> uint {
}
}

/// Valgrind has a fixed-sized array (size around 2000) of segment descriptors wired into it; this
/// is a hard limit and requires rebuilding valgrind if you want to go beyond it. Normally this is
/// not a problem, but in some tests, we produce a lot of threads casually. Making lots of threads
/// alone might not be a problem _either_, except on OSX, the segments produced for new threads
/// _take a while_ to get reclaimed by the OS. Combined with the fact that libuv schedulers fork off
/// a separate thread for polling fsevents on OSX, we get a perfect storm of creating "too many
/// mappings" for valgrind to handle when running certain stress tests in the runtime.
#[cfg(target_os="macos")]
pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
running_on_valgrind()
}

#[cfg(not(target_os="macos"))]
pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
false
}

/// Get's the number of scheduler threads requested by the environment
/// either `RUST_THREADS` or `num_cpus`.
pub fn default_sched_threads() -> uint {
match os::getenv("RUST_THREADS") {
Some(nstr) => FromStr::from_str(nstr).unwrap(),
None => num_cpus()
None => {
if limit_thread_creation_due_to_osx_and_valgrind() {
1
} else {
num_cpus()
}
}
}
}

Expand Down
9 changes: 1 addition & 8 deletions src/libstd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ mod tests {
use path::Path;
use run;
use str;
use unstable::running_on_valgrind;

#[test]
#[cfg(windows)]
Expand Down Expand Up @@ -1331,12 +1332,4 @@ mod tests {

assert!(output.contains("RUN_TEST_NEW_ENV=123"));
}

fn running_on_valgrind() -> bool {
unsafe { rust_running_on_valgrind() != 0 }
}

extern {
fn rust_running_on_valgrind() -> uintptr_t;
}
}
14 changes: 14 additions & 0 deletions src/libstd/unstable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use comm::{GenericChan, GenericPort};
use comm;
use prelude::*;
use task;
use libc::uintptr_t;

pub mod dynamic_lib;

Expand Down Expand Up @@ -116,3 +117,16 @@ pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
fn rust_drop_change_dir_lock();
}
}


/// Dynamically inquire about whether we're running under V.
/// You should usually not use this unless your test definitely
/// can't run correctly un-altered. Valgrind is there to help
/// you notice weirdness in normal, un-doctored code paths!
pub fn running_on_valgrind() -> bool {
unsafe { rust_running_on_valgrind() != 0 }
}

extern {
fn rust_running_on_valgrind() -> uintptr_t;
}