diff --git a/src/libextra/test.rs b/src/libextra/test.rs index c01c619b0c285..5cf63d958544b 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -739,7 +739,7 @@ fn get_concurrency() -> uint { } } None => { - rt::util::default_sched_threads() + rt::default_sched_threads() } } } diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index 1c9944664eee6..38925621f1200 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -123,10 +123,10 @@ pub unsafe fn annihilate() { if debug_mem() { // We do logging here w/o allocation. - rterrln!("annihilator stats:\n \ - total boxes: {}\n \ - unique boxes: {}\n \ - bytes freed: {}", - stats.n_total_boxes, stats.n_unique_boxes, stats.n_bytes_freed); + debug2!("annihilator stats:\n \ + total boxes: {}\n \ + unique boxes: {}\n \ + bytes freed: {}", + stats.n_total_boxes, stats.n_unique_boxes, stats.n_bytes_freed); } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 4de7f32248db0..e7cba0895e451 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1185,7 +1185,7 @@ pub fn last_os_error() -> ~str { */ pub fn set_exit_status(code: int) { use rt; - rt::util::set_exit_status(code); + rt::set_exit_status(code); } unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] { diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs index 6be23a983abb2..3c2000c522c4d 100644 --- a/src/libstd/rt/borrowck.rs +++ b/src/libstd/rt/borrowck.rs @@ -15,10 +15,10 @@ use option::{Option, None, Some}; use ptr::RawPtr; use rt::env; use rt::local::Local; +use rt::task; use rt::task::Task; use str::{OwnedStr, StrSlice}; use str; -use sys; use uint; use unstable::raw; use vec::ImmutableVector; @@ -64,7 +64,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) { None => { // not recording borrows let msg = "borrowed"; do msg.with_c_str |msg_p| { - sys::begin_unwind_(msg_p, file, line); + task::begin_unwind(msg_p, file, line); } } Some(borrow_list) => { // recording borrows @@ -80,7 +80,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) { } } do msg.with_c_str |msg_p| { - sys::begin_unwind_(msg_p, file, line) + task::begin_unwind(msg_p, file, line) } } } @@ -179,7 +179,7 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, if br.box != a || br.file != file || br.line != line { let err = format!("wrong borrow found, br={:?}", br); do err.with_c_str |msg_p| { - sys::begin_unwind_(msg_p, file, line) + task::begin_unwind(msg_p, file, line) } } borrow_list diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index f863ccacaf5c9..262da9f3b8e5e 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -86,6 +86,17 @@ impl Drop for LocalHeap { } } +pub unsafe fn local_malloc(td: *libc::c_char, size: libc::uintptr_t) -> *libc::c_char { + // XXX: Unsafe borrow for speed. Lame. + let task: Option<*mut Task> = Local::try_unsafe_borrow(); + match task { + Some(task) => { + (*task).heap.alloc(td as *libc::c_void, size as uint) as *libc::c_char + } + None => rtabort!("local malloc outside of task") + } +} + // A little compatibility function pub unsafe fn local_free(ptr: *libc::c_char) { // XXX: Unsafe borrow for speed. Lame. diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs index 33384594c575f..c9534413c53e4 100644 --- a/src/libstd/rt/local_ptr.rs +++ b/src/libstd/rt/local_ptr.rs @@ -178,5 +178,5 @@ pub fn maybe_tls_key() -> Option { #[inline] #[cfg(test)] pub fn maybe_tls_key() -> Option { - unsafe { ::cast::transmute(::realstd::rt::local_ptr::maybe_tls_key()) } + unsafe { ::cast::transmute(::realstd::rt::shouldnt_be_public::maybe_tls_key()) } } diff --git a/src/libstd/macros.rs b/src/libstd/rt/macros.rs similarity index 84% rename from src/libstd/macros.rs rename to src/libstd/rt/macros.rs index 17dc03d0098a8..c6ff3427c15f6 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/rt/macros.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Macros used by the runtime. +//! +//! These macros call functions which are only accessible in the `rt` module, so +//! they aren't defined anywhere outside of the `rt` module. + #[macro_escape]; -#[doc(hidden)]; macro_rules! rterrln ( ($($arg:tt)*) => ( { @@ -37,7 +41,7 @@ macro_rules! rtassert ( ) -macro_rules! rtabort( +macro_rules! rtabort ( ($($msg:tt)*) => ( { ::rt::util::abort(format!($($msg)*)); } ) diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 2db973b602ee8..78f0bb0a07ca6 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -76,6 +76,16 @@ use vec::{OwnedVector, MutableVector, ImmutableVector}; use self::thread::Thread; use self::work_queue::WorkQueue; +// the os module needs to reach into this helper, so allow general access +// through this reexport. +pub use self::util::set_exit_status; + +// this is somewhat useful when a program wants to spawn a "reasonable" number +// of workers based on the constraints of the system that it's running on. +// Perhaps this shouldn't be a `pub use` though and there should be another +// method... +pub use self::util::default_sched_threads; + // XXX: these probably shouldn't be public... #[doc(hidden)] pub mod shouldnt_be_public { @@ -86,8 +96,12 @@ pub mod shouldnt_be_public { pub use super::select::SelectInner; pub use super::rtio::EventLoop; pub use super::select::{SelectInner, SelectPortInner}; + pub use super::local_ptr::maybe_tls_key; } +// Internal macros used by the runtime. +mod macros; + /// The global (exchange) heap. pub mod global_heap; @@ -158,17 +172,14 @@ pub mod comm; mod select; -// FIXME #5248 shouldn't be pub /// The runtime needs to be able to put a pointer into thread-local storage. -pub mod local_ptr; +mod local_ptr; -// FIXME #5248: The import in `sched` doesn't resolve unless this is pub! /// Bindings to pthread/windows thread-local storage. -pub mod thread_local_storage; +mod thread_local_storage; -// FIXME #5248 shouldn't be pub /// Just stuff -pub mod util; +mod util; // Global command line argument storage pub mod args; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 71ab3b571c4c6..d5278975d8dfe 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -17,7 +17,7 @@ use borrow; use cast::transmute; use cleanup; use local_data; -use libc::{c_void, uintptr_t}; +use libc::{c_void, uintptr_t, c_char, size_t}; use prelude::*; use option::{Option, Some, None}; use rt::borrowck; @@ -465,6 +465,48 @@ impl Unwinder { } } +/// This is the entry point of unwinding for things like lang items and such. +/// The arguments are normally generated by the compiler. +pub fn begin_unwind(msg: *c_char, file: *c_char, line: size_t) -> ! { + use rt::in_green_task_context; + use rt::task::Task; + use rt::local::Local; + use rt::logging::Logger; + use str::Str; + use c_str::CString; + + unsafe { + let msg = CString::new(msg, false); + let file = CString::new(file, false); + let msg = match msg.as_str() { + Some(s) => s, None => rtabort!("message wasn't utf8?") + }; + let file = match file.as_str() { + Some(s) => s, None => rtabort!("message wasn't utf8?") + }; + + if in_green_task_context() { + // Be careful not to allocate in this block, if we're failing we may + // have been failing due to a lack of memory in the first place... + do Local::borrow |task: &mut Task| { + let n = task.name.as_ref().map(|n| n.as_slice()).unwrap_or(""); + format_args!(|args| { task.logger.log(args) }, + "task '{}' failed at '{}', {}:{}", + n, msg, file, line); + } + } else { + rterrln!("failed in non-task context at '{}', {}:{}", + msg, file, line as int); + } + + let task: *mut Task = Local::unsafe_borrow(); + if (*task).unwinder.unwinding { + rtabort!("unwinding again"); + } + (*task).unwinder.begin_unwind(); + } +} + #[cfg(test)] mod test { use rt::test::*; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 727bdb782d2c8..647d88c26f2f5 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -16,8 +16,6 @@ use option::{Some, None, Option}; use os; use str::StrSlice; use unstable::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; - -#[cfg(target_os="macos")] use unstable::running_on_valgrind; // Indicates whether we should perform expensive sanity checks, including rtassert! @@ -37,21 +35,17 @@ 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"))] +/// 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. pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { - false + (cfg!(target_os="macos")) && running_on_valgrind() } /// Get's the number of scheduler threads requested by the environment diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 53837f965938a..5a3f40f280fff 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -88,9 +88,6 @@ pub mod linkhack { } } -// Internal macros -mod macros; - /* The Prelude. */ pub mod prelude; diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index ce1be592d79c8..10c3fed1d54db 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -14,9 +14,10 @@ use c_str::ToCStr; use cast; +use libc::size_t; use libc; -use libc::{c_char, size_t}; use repr; +use rt::task; use str; use unstable::intrinsics; @@ -109,7 +110,7 @@ impl FailWithCause for ~str { fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! { do cause.with_c_str |msg_buf| { do file.with_c_str |file_buf| { - begin_unwind_(msg_buf, file_buf, line as libc::size_t) + task::begin_unwind(msg_buf, file_buf, line as libc::size_t) } } } @@ -119,47 +120,12 @@ impl FailWithCause for &'static str { fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! { do cause.with_c_str |msg_buf| { do file.with_c_str |file_buf| { - begin_unwind_(msg_buf, file_buf, line as libc::size_t) + task::begin_unwind(msg_buf, file_buf, line as libc::size_t) } } } } -// FIXME #4427: Temporary until rt::rt_fail_ goes away -pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { - use rt::in_green_task_context; - use rt::task::Task; - use rt::local::Local; - use rt::logging::Logger; - use str::Str; - - unsafe { - // XXX: Bad re-allocations. fail2! needs some refactoring - let msg = str::raw::from_c_str(msg); - let file = str::raw::from_c_str(file); - - if in_green_task_context() { - // Be careful not to allocate in this block, if we're failing we may - // have been failing due to a lack of memory in the first place... - do Local::borrow |task: &mut Task| { - let n = task.name.as_ref().map(|n| n.as_slice()).unwrap_or(""); - format_args!(|args| { task.logger.log(args) }, - "task '{}' failed at '{}', {}:{}", - n, msg.as_slice(), file.as_slice(), line); - } - } else { - rterrln!("failed in non-task context at '{}', {}:{}", - msg, file, line as int); - } - - let task: *mut Task = Local::unsafe_borrow(); - if (*task).unwinder.unwinding { - rtabort!("unwinding again"); - } - (*task).unwinder.begin_unwind(); - } -} - #[cfg(test)] mod tests { use cast; diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index d26f8eb10248e..611d2f1fdb67b 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -448,7 +448,7 @@ impl RuntimeGlue { } fn with_task_handle_and_failing(blk: &fn(&KillHandle, bool)) { - rtassert!(in_green_task_context()); + assert!(in_green_task_context()); unsafe { // Can't use safe borrow, because the taskgroup destructor needs to // access the scheduler again to send kill signals to other tasks. @@ -458,7 +458,7 @@ impl RuntimeGlue { } fn with_my_taskgroup(blk: &fn(&Taskgroup) -> U) -> U { - rtassert!(in_green_task_context()); + assert!(in_green_task_context()); unsafe { // Can't use safe borrow, because creating new hashmaps for the // tasksets requires an rng, which needs to borrow the sched. @@ -553,7 +553,7 @@ fn enlist_many(child: &KillHandle, child_arc: &TaskGroupArc, } pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { - rtassert!(in_green_task_context()); + assert!(in_green_task_context()); let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised)); let indestructible = opts.indestructible; @@ -631,7 +631,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { let (thread_port, thread_chan) = oneshot(); let thread_port_cell = Cell::new(thread_port); let join_task = do Task::build_child(None) { - rtdebug!("running join task"); + debug2!("running join task"); let thread_port = thread_port_cell.take(); let thread: Thread = thread_port.recv(); thread.join(); @@ -648,11 +648,11 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { let join_task = join_task_cell.take(); let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool, None) || { - rtdebug!("boostrapping a 1:1 scheduler"); + debug2!("boostrapping a 1:1 scheduler"); }; new_sched.bootstrap(bootstrap_task); - rtdebug!("enqueing join_task"); + debug2!("enqueing join_task"); // Now tell the original scheduler to join with this thread // by scheduling a thread-joining task on the original scheduler orig_sched_handle.send_task_from_friend(join_task); @@ -684,7 +684,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { } task.name = opts.name.take(); - rtdebug!("spawn calling run_task"); + debug2!("spawn calling run_task"); Scheduler::run_task(task); } diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index fca477763c5e6..6f2928e99fed7 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -12,16 +12,13 @@ use c_str::ToCStr; use cast::transmute; -use libc::{c_char, c_void, size_t, uintptr_t}; -use option::{Option, None, Some}; -use sys; -use rt::task::Task; -use rt::local::Local; +use libc::{c_char, size_t, uintptr_t}; +use rt::task; use rt::borrowck; #[lang="fail_"] pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! { - sys::begin_unwind_(expr, file, line); + task::begin_unwind(expr, file, line); } #[lang="fail_bounds_check"] @@ -36,14 +33,7 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, #[lang="malloc"] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { - // XXX: Unsafe borrow for speed. Lame. - let task: Option<*mut Task> = Local::try_unsafe_borrow(); - match task { - Some(task) => { - (*task).heap.alloc(td as *c_void, size as uint) as *c_char - } - None => rtabort!("local malloc outside of task") - } + ::rt::local_heap::local_malloc(td, size) } // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from