diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/rt/crate_map.rs | 38 | ||||
| -rw-r--r-- | src/libstd/rt/io/net/tcp.rs | 6 | ||||
| -rw-r--r-- | src/libstd/rt/mod.rs | 54 | ||||
| -rw-r--r-- | src/libstd/rt/sched.rs | 17 | ||||
| -rw-r--r-- | src/libstd/rt/test.rs | 7 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 6 | ||||
| -rw-r--r-- | src/libstd/select.rs | 4 | ||||
| -rw-r--r-- | src/libstd/std.rs | 7 | ||||
| -rw-r--r-- | src/libstd/task/mod.rs | 4 | ||||
| -rw-r--r-- | src/libstd/task/spawn.rs | 14 | ||||
| -rw-r--r-- | src/libstd/unstable/mod.rs | 2 |
11 files changed, 106 insertions, 53 deletions
diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index dd71426938d..16b41276788 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -12,6 +12,8 @@ use container::MutableSet; use hashmap::HashSet; use option::{Some, None, Option}; use vec::ImmutableVector; +#[cfg(not(stage0))] +use rt::rtio::EventLoop; // Need to tell the linker on OS X to not barf on undefined symbols // and instead look them up at runtime, which we need to resolve @@ -25,18 +27,32 @@ pub struct ModEntry<'self> { log_level: *mut u32 } +#[cfg(stage0)] pub struct CrateMap<'self> { - priv version: i32, - priv entries: &'self [ModEntry<'self>], - priv children: &'self [&'self CrateMap<'self>] + version: i32, + entries: &'self [ModEntry<'self>], + children: &'self [&'self CrateMap<'self>] +} + +#[cfg(not(stage0))] +pub struct CrateMap<'self> { + version: i32, + entries: &'self [ModEntry<'self>], + children: &'self [&'self CrateMap<'self>], + event_loop_factory: Option<extern "C" fn() -> ~EventLoop>, } #[cfg(not(windows))] pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { extern { + #[cfg(stage0)] #[weak_linkage] #[link_name = "_rust_crate_map_toplevel"] static CRATE_MAP: CrateMap<'static>; + + #[cfg(not(stage0))] + #[crate_map] + static CRATE_MAP: CrateMap<'static>; } let ptr: (*CrateMap) = &'static CRATE_MAP; @@ -108,6 +124,7 @@ pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { #[cfg(test)] mod tests { + use option::None; use rt::crate_map::{CrateMap, ModEntry, iter_crate_map}; #[test] @@ -121,13 +138,15 @@ mod tests { let child_crate = CrateMap { version: 2, entries: entries, - children: [] + children: [], + event_loop_factory: None, }; let root_crate = CrateMap { version: 2, entries: [], - children: [&child_crate, &child_crate] + children: [&child_crate, &child_crate], + event_loop_factory: None, }; let mut cnt = 0; @@ -150,7 +169,8 @@ mod tests { ModEntry { name: "c::m1", log_level: &mut level2}, ModEntry { name: "c::m2", log_level: &mut level3}, ], - children: [] + children: [], + event_loop_factory: None, }; let child_crate1 = CrateMap { @@ -158,7 +178,8 @@ mod tests { entries: [ ModEntry { name: "t::f1", log_level: &mut 1}, ], - children: [&child_crate2] + children: [&child_crate2], + event_loop_factory: None, }; let root_crate = CrateMap { @@ -166,7 +187,8 @@ mod tests { entries: [ ModEntry { name: "t::f2", log_level: &mut 0}, ], - children: [&child_crate1] + children: [&child_crate1], + event_loop_factory: None, }; let mut cnt = 0; diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs index 6314c0755a0..fb7c6766fd8 100644 --- a/src/libstd/rt/io/net/tcp.rs +++ b/src/libstd/rt/io/net/tcp.rs @@ -383,7 +383,8 @@ mod test { // on windows assert!(e.kind == ConnectionReset || e.kind == BrokenPipe || - e.kind == ConnectionAborted); + e.kind == ConnectionAborted, + "unknown error: {:?}", e); stop = true; }).inside { stream.write(buf); @@ -420,7 +421,8 @@ mod test { // on windows assert!(e.kind == ConnectionReset || e.kind == BrokenPipe || - e.kind == ConnectionAborted); + e.kind == ConnectionAborted, + "unknown error: {:?}", e); stop = true; }).inside { stream.write(buf); diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index eaaf8c43281..d8d07f14021 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -68,7 +68,6 @@ use rt::sched::{Scheduler, Shutdown}; use rt::sleeper_list::SleeperList; use rt::task::UnwindResult; use rt::task::{Task, SchedTask, GreenTask, Sched}; -use rt::uv::uvio::UvEventLoop; use unstable::atomics::{AtomicInt, AtomicBool, SeqCst}; use unstable::sync::UnsafeArc; use vec::{OwnedVector, MutableVector, ImmutableVector}; @@ -87,15 +86,13 @@ pub use self::util::set_exit_status; // method... pub use self::util::default_sched_threads; +// Re-export of the functionality in the kill module +pub use self::kill::{KillHandle, BlockedTask}; + // XXX: these probably shouldn't be public... #[doc(hidden)] pub mod shouldnt_be_public { - pub use super::sched::Scheduler; - pub use super::kill::KillHandle; - pub use super::thread::Thread; - pub use super::work_queue::WorkQueue; pub use super::select::SelectInner; - pub use super::rtio::EventLoop; pub use super::select::{SelectInner, SelectPortInner}; pub use super::local_ptr::maybe_tls_key; } @@ -116,15 +113,16 @@ pub mod task; mod kill; /// The coroutine task scheduler, built on the `io` event loop. -mod sched; +pub mod sched; /// Synchronous I/O. pub mod io; /// The EventLoop and internal synchronous I/O interface. -mod rtio; +pub mod rtio; /// libuv and default rtio implementation. +#[cfg(stage0)] pub mod uv; /// The Local trait for types that are accessible via thread-local @@ -132,10 +130,10 @@ pub mod uv; pub mod local; /// A parallel work-stealing deque. -mod work_queue; +pub mod work_queue; /// A parallel queue. -mod message_queue; +pub mod message_queue; /// A mostly lock-free multi-producer, single consumer queue. mod mpsc_queue; @@ -144,7 +142,7 @@ mod mpsc_queue; mod mpmc_bounded_queue; /// A parallel data structure for tracking sleeping schedulers. -mod sleeper_list; +pub mod sleeper_list; /// Stack segments and caching. pub mod stack; @@ -153,7 +151,7 @@ pub mod stack; mod context; /// Bindings to system threading libraries. -mod thread; +pub mod thread; /// The runtime configuration, read from environment variables. pub mod env; @@ -289,7 +287,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int { rtdebug!("inserting a regular scheduler"); // Every scheduler is driven by an I/O event loop. - let loop_ = ~UvEventLoop::new() as ~rtio::EventLoop; + let loop_ = new_event_loop(); let mut sched = ~Scheduler::new(loop_, work_queue.clone(), work_queues.clone(), @@ -313,7 +311,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int { // set. let work_queue = WorkQueue::new(); - let main_loop = ~UvEventLoop::new() as ~rtio::EventLoop; + let main_loop = new_event_loop(); let mut main_sched = ~Scheduler::new_special(main_loop, work_queue, work_queues.clone(), @@ -327,7 +325,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int { // waking up schedulers for work stealing; since this is a // non-work-stealing scheduler it should not be adding itself // to the list. - main_handle.send_shutdown(); + main_handle.send(Shutdown); Some(main_sched) } else { None @@ -464,3 +462,29 @@ pub fn in_green_task_context() -> bool { } } } + +#[cfg(stage0)] +pub fn new_event_loop() -> ~rtio::EventLoop { + use rt::uv::uvio::UvEventLoop; + ~UvEventLoop::new() as ~rtio::EventLoop +} + +#[cfg(not(stage0))] +pub fn new_event_loop() -> ~rtio::EventLoop { + #[fixed_stack_segment]; #[allow(cstack)]; + + match crate_map::get_crate_map() { + None => {} + Some(map) => { + match map.event_loop_factory { + None => {} + Some(factory) => return factory() + } + } + } + + // If the crate map didn't specify a factory to create an event loop, then + // instead just use a basic event loop missing all I/O services to at least + // get the scheduler running. + return basic::event_loop(); +} diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 93056314b14..fd4dab60ff3 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -529,7 +529,7 @@ impl Scheduler { match self.sleeper_list.casual_pop() { Some(handle) => { - let mut handle = handle; + let mut handle = handle; handle.send(Wake) } None => { (/* pass */) } @@ -800,12 +800,6 @@ impl SchedHandle { self.queue.push(msg); self.remote.fire(); } - pub fn send_task_from_friend(&mut self, friend: ~Task) { - self.send(TaskFromFriend(friend)); - } - pub fn send_shutdown(&mut self) { - self.send(Shutdown); - } } struct CleanupJob { @@ -1001,7 +995,6 @@ mod test { #[test] fn test_schedule_home_states() { - use rt::sleeper_list::SleeperList; use rt::work_queue::WorkQueue; use rt::sched::Shutdown; @@ -1248,15 +1241,15 @@ mod test { use comm::{GenericPort, GenericChan}; do run_in_mt_newsched_task { - let (end_port, end_chan) = oneshot(); + let (end_port, end_chan) = oneshot(); let n_tasks = 10; let token = 2000; - let (p, ch1) = stream(); + let (p, ch1) = stream(); let mut p = p; - ch1.send((token, end_chan)); - let mut i = 2; + ch1.send((token, end_chan)); + let mut i = 2; while i <= n_tasks { let (next_p, ch) = stream(); let imm_i = i; diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs index 5f78b9fc959..55a8db89d3c 100644 --- a/src/libstd/rt/test.rs +++ b/src/libstd/rt/test.rs @@ -24,13 +24,12 @@ use rand; use result::{Result, Ok, Err}; use rt::basic; use rt::comm::oneshot; -use rt::rtio::EventLoop; +use rt::new_event_loop; use rt::sched::Scheduler; use rt::sleeper_list::SleeperList; use rt::task::Task; use rt::task::UnwindResult; use rt::thread::Thread; -use rt::uv::uvio::UvEventLoop; use rt::work_queue::WorkQueue; use unstable::{run_in_bare_thread}; use vec::{OwnedVector, MutableVector, ImmutableVector}; @@ -40,7 +39,7 @@ pub fn new_test_uv_sched() -> Scheduler { let queue = WorkQueue::new(); let queues = ~[queue.clone()]; - let mut sched = Scheduler::new(~UvEventLoop::new() as ~EventLoop, + let mut sched = Scheduler::new(new_event_loop(), queue, queues, SleeperList::new()); @@ -237,7 +236,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) { } for i in range(0u, nthreads) { - let loop_ = ~UvEventLoop::new() as ~EventLoop; + let loop_ = new_event_loop(); let mut sched = ~Scheduler::new(loop_, work_queues[i].clone(), work_queues.clone(), diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index bd8466a7925..2d3ecbbd689 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -236,6 +236,12 @@ impl EventLoop for UvEventLoop { } } +#[cfg(not(stage0))] +#[lang = "event_loop_factory"] +pub extern "C" fn new_loop() -> ~EventLoop { + ~UvEventLoop::new() as ~EventLoop +} + pub struct UvPausibleIdleCallback { priv watcher: IdleWatcher, priv idle_flag: bool, diff --git a/src/libstd/select.rs b/src/libstd/select.rs index 75b09187f04..f5dc98c57b6 100644 --- a/src/libstd/select.rs +++ b/src/libstd/select.rs @@ -18,7 +18,9 @@ use option::*; // use either::{Either, Left, Right}; // use rt::kill::BlockedTask; use rt::local::Local; -use rt::shouldnt_be_public::{EventLoop, Scheduler, SelectInner, SelectPortInner}; +use rt::rtio::EventLoop; +use rt::sched::Scheduler; +use rt::shouldnt_be_public::{SelectInner, SelectPortInner}; use task; use unstable::finally::Finally; use vec::{OwnedVector, MutableVector}; diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 069a390f010..3a96cfb1171 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -69,8 +69,13 @@ they contained the following prologue: #[deny(non_camel_case_types)]; #[deny(missing_doc)]; +// When testing libstd, bring in libuv as the I/O backend so tests can print +// things and all of the std::rt::io tests have an I/O interface to run on top +// of +#[cfg(test)] extern mod rustuv(vers = "0.9-pre"); + // Make extra accessible for benchmarking -#[cfg(test)] extern mod extra(vers="0.9-pre"); +#[cfg(test)] extern mod extra(vers = "0.9-pre"); // Make std testable by not duplicating lang items. See #2912 #[cfg(test)] extern mod realstd(name = "std"); diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index 8efa185bbbd..023ba6f7108 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -578,7 +578,7 @@ pub fn deschedule() { //! Yield control to the task scheduler use rt::local::Local; - use rt::shouldnt_be_public::Scheduler; + use rt::sched::Scheduler; // FIXME(#7544): Optimize this, since we know we won't block. let sched: ~Scheduler = Local::take(); @@ -1094,7 +1094,7 @@ fn test_try_fail() { #[cfg(test)] fn get_sched_id() -> int { - do Local::borrow |sched: &mut ::rt::shouldnt_be_public::Scheduler| { + do Local::borrow |sched: &mut ::rt::sched::Scheduler| { sched.sched_id() as int } } diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 235e67048f6..a08bf8f3147 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -80,13 +80,14 @@ use comm::{Chan, GenericChan, oneshot}; use container::MutableMap; use hashmap::{HashSet, HashSetMoveIterator}; use local_data; -use rt::in_green_task_context; use rt::local::Local; -use rt::shouldnt_be_public::{Scheduler, KillHandle, WorkQueue, Thread, EventLoop}; +use rt::sched::{Scheduler, Shutdown, TaskFromFriend}; use rt::task::{Task, Sched}; use rt::task::{UnwindReasonLinked, UnwindReasonStr}; use rt::task::{UnwindResult, Success, Failure}; -use rt::uv::uvio::UvEventLoop; +use rt::thread::Thread; +use rt::work_queue::WorkQueue; +use rt::{in_green_task_context, new_event_loop, KillHandle}; use send_str::IntoSendStr; use task::SingleThreaded; use task::TaskOpts; @@ -617,8 +618,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { let work_queue = WorkQueue::new(); // Create a new scheduler to hold the new task - let new_loop = ~UvEventLoop::new() as ~EventLoop; - let mut new_sched = ~Scheduler::new_special(new_loop, + let mut new_sched = ~Scheduler::new_special(new_event_loop(), work_queue, (*sched).work_queues.clone(), (*sched).sleeper_list.clone(), @@ -627,7 +627,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { let mut new_sched_handle = new_sched.make_handle(); // Allow the scheduler to exit when the pinned task exits - new_sched_handle.send_shutdown(); + new_sched_handle.send(Shutdown); // Pin the new task to the new scheduler let new_task = if opts.watched { @@ -665,7 +665,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) { debug!("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); + orig_sched_handle.send(TaskFromFriend(join_task)); // NB: We can't simply send a message from here to another task // because this code isn't running in a task and message passing doesn't diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs index 835b16996b5..484ddde6d3c 100644 --- a/src/libstd/unstable/mod.rs +++ b/src/libstd/unstable/mod.rs @@ -37,7 +37,7 @@ a normal large stack. */ pub fn run_in_bare_thread(f: ~fn()) { use cell::Cell; - use rt::shouldnt_be_public::Thread; + use rt::thread::Thread; let f_cell = Cell::new(f); let (port, chan) = comm::stream(); |
