diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 89b6f06abfc7f..ae7d1a30a841d 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -13,6 +13,7 @@ #[allow(non_camel_case_types)]; #[deny(warnings)]; +#[cfg(stage0)] extern mod green; extern mod extra; use std::os; diff --git a/src/libextra/comm.rs b/src/libextra/comm.rs index c3b17fe996405..52b5bedb7ea49 100644 --- a/src/libextra/comm.rs +++ b/src/libextra/comm.rs @@ -96,7 +96,6 @@ pub fn rendezvous() -> (SyncPort, SyncChan) { #[cfg(test)] mod test { use comm::{DuplexStream, rendezvous}; - use std::rt::test::run_in_uv_task; #[test] @@ -124,13 +123,11 @@ mod test { #[test] fn recv_a_lot() { // Rendezvous streams should be able to handle any number of messages being sent - do run_in_uv_task { - let (port, chan) = rendezvous(); - do spawn { - 1000000.times(|| { chan.send(()) }) - } - 1000000.times(|| { port.recv() }) + let (port, chan) = rendezvous(); + do spawn { + 1000000.times(|| { chan.send(()) }) } + 1000000.times(|| { port.recv() }) } #[test] diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 2a53775a907d0..f43329076c8b8 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -761,23 +761,21 @@ mod tests { fn test_sem_runtime_friendly_blocking() { // Force the runtime to schedule two threads on the same sched_loop. // When one blocks, it should schedule the other one. - do task::spawn_sched(task::SingleThreaded) { - let s = Semaphore::new(1); - let s2 = s.clone(); - let (p, c) = Chan::new(); - let mut child_data = Some((s2, c)); - s.access(|| { - let (s2, c) = child_data.take_unwrap(); - do task::spawn { - c.send(()); - s2.access(|| { }); - c.send(()); - } - let _ = p.recv(); // wait for child to come alive - 5.times(|| { task::deschedule(); }); // let the child contend - }); - let _ = p.recv(); // wait for child to be done - } + let s = Semaphore::new(1); + let s2 = s.clone(); + let (p, c) = Chan::new(); + let mut child_data = Some((s2, c)); + s.access(|| { + let (s2, c) = child_data.take_unwrap(); + do task::spawn { + c.send(()); + s2.access(|| { }); + c.send(()); + } + let _ = p.recv(); // wait for child to come alive + 5.times(|| { task::deschedule(); }); // let the child contend + }); + let _ = p.recv(); // wait for child to be done } /************************************************************************ * Mutex tests diff --git a/src/libextra/task_pool.rs b/src/libextra/task_pool.rs index 649a9a0664468..ba38f87628731 100644 --- a/src/libextra/task_pool.rs +++ b/src/libextra/task_pool.rs @@ -17,8 +17,6 @@ use std::task; use std::vec; -#[cfg(test)] use std::task::SingleThreaded; - enum Msg { Execute(proc(&T)), Quit diff --git a/src/libgreen/basic.rs b/src/libgreen/basic.rs index e1e489a2a2b6c..0574792c18da8 100644 --- a/src/libgreen/basic.rs +++ b/src/libgreen/basic.rs @@ -16,7 +16,7 @@ //! loop if no other one is provided (and M:N scheduling is desired). use std::cast; -use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback, PausibleIdleCallback, +use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback, PausableIdleCallback, Callback}; use std::unstable::sync::Exclusive; use std::util; diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 7318eaaf6799b..3a2e8a2b36cf5 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -18,12 +18,7 @@ //! functionality inside of 1:1 programs. #[pkgid = "green#0.9-pre"]; -#[link(name = "green", - package_id = "green", - vers = "0.9-pre", - uuid = "20c38f8c-bfea-83ed-a068-9dc05277be26", - url = "https://github.com/mozilla/rust/tree/master/src/libgreen")]; - +#[crate_id = "green#0.9-pre"]; #[license = "MIT/ASL2"]; #[crate_type = "rlib"]; #[crate_type = "dylib"]; @@ -61,16 +56,13 @@ pub mod stack; pub mod task; #[lang = "start"] +#[cfg(not(test))] pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { use std::cast; - let mut ret = None; - simple::task().run(|| { - ret = Some(do start(argc, argv) { - let main: extern "Rust" fn() = unsafe { cast::transmute(main) }; - main(); - }) - }); - ret.unwrap() + do start(argc, argv) { + let main: extern "Rust" fn() = unsafe { cast::transmute(main) }; + main(); + } } /// Set up a default runtime configuration, given compiler-supplied arguments. @@ -93,10 +85,14 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { /// error. pub fn start(argc: int, argv: **u8, main: proc()) -> int { rt::init(argc, argv); - let exit_code = run(main); + let mut main = Some(main); + let mut ret = None; + simple::task().run(|| { + ret = Some(run(main.take_unwrap())); + }); // unsafe is ok b/c we're sure that the runtime is gone unsafe { rt::cleanup() } - exit_code + ret.unwrap() } /// Execute the main function in a pool of M:N schedulers. @@ -114,6 +110,7 @@ pub fn run(main: proc()) -> int { let (port, chan) = Chan::new(); let mut opts = TaskOpts::new(); opts.notify_chan = Some(chan); + opts.name = Some(SendStrStatic("
")); pool.spawn(opts, main); // Wait for the main task to return, and set the process error code diff --git a/src/libgreen/macros.rs b/src/libgreen/macros.rs index ad0854e2b1ec6..56dc3204da86e 100644 --- a/src/libgreen/macros.rs +++ b/src/libgreen/macros.rs @@ -54,14 +54,13 @@ macro_rules! rtabort ( pub fn dumb_println(args: &fmt::Arguments) { use std::io; use std::libc; - use std::vec; struct Stderr; impl io::Writer for Stderr { fn write(&mut self, data: &[u8]) { unsafe { libc::write(libc::STDERR_FILENO, - vec::raw::to_ptr(data) as *libc::c_void, + data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } } diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index 95c4d8347d5b0..ef62f654ddf48 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -11,7 +11,7 @@ use std::cast; use std::rand::{XorShiftRng, Rng, Rand}; use std::rt::local::Local; -use std::rt::rtio::{RemoteCallback, PausibleIdleCallback, Callback, EventLoop}; +use std::rt::rtio::{RemoteCallback, PausableIdleCallback, Callback, EventLoop}; use std::rt::task::BlockedTask; use std::rt::task::Task; use std::sync::deque; @@ -779,6 +779,9 @@ impl Scheduler { /// randomness is a result of performing a round of work stealing (which /// may end up stealing from the current scheduler). pub fn yield_now(mut ~self, cur: ~GreenTask) { + // Async handles trigger the scheduler by calling yield_now on the local + // task, which eventually gets us to here. See comments in SchedRunner + // for more info on this. if cur.is_sched() { assert!(self.sched_task.is_none()); self.run_sched_once(cur); @@ -1345,7 +1348,7 @@ mod test { impl Drop for S { fn drop(&mut self) { - let _foo = @0; + let _foo = ~0; } } diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index 2277d408ee4cb..64ce9d7e3482d 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cast; use std::io; use std::libc::{pid_t, c_void, c_int}; use std::libc; @@ -17,6 +16,8 @@ use std::ptr; use std::rt::rtio; use p = std::io::process; +#[cfg(windows)] use std::cast; + use super::file; /** diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index 60ae239ee9788..e066659265149 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -15,12 +15,7 @@ //! version of I/O. #[pkgid = "native#0.9-pre"]; -#[link(name = "native", - package_id = "native", - vers = "0.9-pre", - uuid = "535344a7-890f-5a23-e1f3-e0d118805141", - url = "https://github.com/mozilla/rust/tree/master/src/native")]; - +#[crate_id = "native#0.9-pre"]; #[license = "MIT/ASL2"]; #[crate_type = "rlib"]; #[crate_type = "dylib"]; @@ -46,7 +41,7 @@ pub mod task; #[lang = "start"] pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { use std::cast; - use std::task::try; + use std::task; do start(argc, argv) { // Instead of invoking main directly on this thread, invoke it on @@ -55,7 +50,9 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { // of the main thread's stack, so for stack overflow detection to work // we must spawn the task in a subtask which we know the stack size of. let main: extern "Rust" fn() = unsafe { cast::transmute(main) }; - match do try { main() } { + let mut task = task::task(); + task.name("
"); + match do task.try { main() } { Ok(()) => { os::set_exit_status(0); } Err(..) => { os::set_exit_status(rt::DEFAULT_ERROR_CODE); } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 0cf91fbba0e88..214f60291feae 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -333,6 +333,10 @@ pub mod write { } unsafe fn configure_llvm(sess: Session) { + use std::unstable::mutex::{MUTEX_INIT, Mutex}; + static mut LOCK: Mutex = MUTEX_INIT; + static mut CONFIGURED: bool = false; + // Copy what clan does by turning on loop vectorization at O2 and // slp vectorization at O3 let vectorize_loop = !sess.no_vectorize_loops() && @@ -360,7 +364,13 @@ pub mod write { add(*arg); } - llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); + LOCK.lock(); + if !CONFIGURED { + llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, + llvm_args.as_ptr()); + CONFIGURED = true; + } + LOCK.unlock(); } unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef, diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index ecf08df5f185a..21f18eda1409d 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -487,8 +487,9 @@ fn lib_output_file_name(workspace: &Path, short_name: &str) -> Path { } fn output_file_name(workspace: &Path, short_name: ~str) -> Path { - target_build_dir(workspace).join(short_name.as_slice()).join(format!("{}{}", short_name, - os::EXE_SUFFIX)) + target_build_dir(workspace).join(short_name.as_slice()) + .join(format!("{}{}", short_name, + os::consts::EXE_SUFFIX)) } #[cfg(target_os = "linux")] @@ -1353,7 +1354,7 @@ fn test_import_rustpkg() { command_line_test([~"build", ~"foo"], workspace); debug!("workspace = {}", workspace.display()); assert!(target_build_dir(workspace).join("foo").join(format!("pkg{}", - os::EXE_SUFFIX)).exists()); + os::consts::EXE_SUFFIX)).exists()); } #[test] @@ -1366,7 +1367,7 @@ fn test_macro_pkg_script() { command_line_test([~"build", ~"foo"], workspace); debug!("workspace = {}", workspace.display()); assert!(target_build_dir(workspace).join("foo").join(format!("pkg{}", - os::EXE_SUFFIX)).exists()); + os::consts::EXE_SUFFIX)).exists()); } #[test] diff --git a/src/librustuv/file.rs b/src/librustuv/file.rs index 059bf072a1a40..82d0fd823a320 100644 --- a/src/librustuv/file.rs +++ b/src/librustuv/file.rs @@ -18,7 +18,6 @@ use std::rt::task::BlockedTask; use std::io::{FileStat, IoError}; use std::io; use std::rt::rtio; -use std::vec; use homing::{HomingIO, HomeHandle}; use super::{Loop, UvError, uv_error_to_io_error, wait_until_woken_after, wakeup}; diff --git a/src/librustuv/idle.rs b/src/librustuv/idle.rs index 44b74d050965a..80d21404e4bcb 100644 --- a/src/librustuv/idle.rs +++ b/src/librustuv/idle.rs @@ -100,7 +100,7 @@ mod test { use std::cast; use std::cell::RefCell; use std::rc::Rc; - use std::rt::rtio::{Callback, PausibleIdleCallback}; + use std::rt::rtio::{Callback, PausableIdleCallback}; use std::rt::task::{BlockedTask, Task}; use std::rt::local::Local; use super::IdleWatcher; diff --git a/src/librustuv/macros.rs b/src/librustuv/macros.rs index 61b4de5765592..6c8c16784a12b 100644 --- a/src/librustuv/macros.rs +++ b/src/librustuv/macros.rs @@ -30,14 +30,13 @@ macro_rules! uvdebug ( pub fn dumb_println(args: &fmt::Arguments) { use std::io; use std::libc; - use std::vec; struct Stderr; impl io::Writer for Stderr { fn write(&mut self, data: &[u8]) { unsafe { libc::write(libc::STDERR_FILENO, - vec::raw::to_ptr(data) as *libc::c_void, + data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } } diff --git a/src/librustuv/signal.rs b/src/librustuv/signal.rs index 0f81966b169a2..6772c6d193614 100644 --- a/src/librustuv/signal.rs +++ b/src/librustuv/signal.rs @@ -68,7 +68,7 @@ impl RtioSignal for SignalWatcher {} impl Drop for SignalWatcher { fn drop(&mut self) { let _m = self.fire_homing_missile(); - self.close_async_(); + self.close(); } } diff --git a/src/librustuv/timer.rs b/src/librustuv/timer.rs index e87090753f59c..4a0ad44d31147 100644 --- a/src/librustuv/timer.rs +++ b/src/librustuv/timer.rs @@ -169,7 +169,7 @@ impl Drop for TimerWatcher { let _action = { let _m = self.fire_homing_missile(); self.stop(); - self.close_async_(); + self.close(); self.action.take() }; } diff --git a/src/librustuv/uvio.rs b/src/librustuv/uvio.rs index 9e7343aa2da94..dbf129d0b699c 100644 --- a/src/librustuv/uvio.rs +++ b/src/librustuv/uvio.rs @@ -86,10 +86,10 @@ impl rtio::EventLoop for UvEventLoop { IdleWatcher::onetime(&mut self.uvio.loop_, f); } - fn pausible_idle_callback(&mut self, cb: ~rtio::Callback) - -> ~rtio::PausibleIdleCallback + fn pausable_idle_callback(&mut self, cb: ~rtio::Callback) + -> ~rtio::PausableIdleCallback { - IdleWatcher::new(&mut self.uvio.loop_, cb) as ~rtio::PausibleIdleCallback + IdleWatcher::new(&mut self.uvio.loop_, cb) as ~rtio::PausableIdleCallback } fn remote_callback(&mut self, f: ~rtio::Callback) -> ~rtio::RemoteCallback { diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/unix.rs index 59a6903adbf8e..01b409d43163a 100644 --- a/src/libstd/io/net/unix.rs +++ b/src/libstd/io/net/unix.rs @@ -175,7 +175,8 @@ mod tests { fn connect_error() { let mut called = false; io_error::cond.trap(|e| { - assert_eq!(e.kind, OtherIoError); + assert_eq!(e.kind, + if cfg!(windows) {OtherIoError} else {FileNotFound}); called = true; }).inside(|| { let stream = UnixStream::connect(&("path/to/nowhere")); diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 5249d331f7251..1e4fa7968dc42 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -34,7 +34,6 @@ use libc; use option::{Option, Some, None}; use result::{Ok, Err}; use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY}; -use vec; // And so begins the tale of acquiring a uv handle to a stdio stream on all // platforms in all situations. Our story begins by splitting the world into two @@ -137,7 +136,7 @@ fn with_task_stdout(f: |&mut Writer|) { fn write(&mut self, data: &[u8]) { unsafe { libc::write(libc::STDOUT_FILENO, - vec::raw::to_ptr(data) as *libc::c_void, + data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } } diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index e273aedf7cc74..4be1122796584 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -31,6 +31,7 @@ macro_rules! iotest ( use io::net::tcp::*; use io::net::ip::*; use io::net::udp::*; + #[cfg(unix)] use io::net::unix::*; use str; use util; diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs index b75f292700388..42cce272e4430 100644 --- a/src/libstd/rt/local_ptr.rs +++ b/src/libstd/rt/local_ptr.rs @@ -42,7 +42,7 @@ impl Drop for Borrowed { } let val: ~T = cast::transmute(self.val); put::(val); - assert!(exists()); + rtassert!(exists()); } } } @@ -110,7 +110,7 @@ pub mod compiled { #[inline] pub unsafe fn take() -> ~T { let ptr = RT_TLS_PTR; - assert!(!ptr.is_null()); + rtassert!(!ptr.is_null()); let ptr: ~T = cast::transmute(ptr); // can't use `as`, due to type not matching with `cfg(test)` RT_TLS_PTR = cast::transmute(0); @@ -180,7 +180,7 @@ pub mod native { } pub unsafe fn cleanup() { - assert!(INITIALIZED); + rtassert!(INITIALIZED); tls::destroy(RT_TLS_KEY); LOCK.destroy(); INITIALIZED = false; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index d0c062c1274fe..0dd6c883d5b47 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -176,6 +176,7 @@ pub fn init(argc: int, argv: **u8) { args::init(argc, argv); env::init(); logging::init(); + local_ptr::init(); } } diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 97b08cc18caf9..6b3d50a76ac8f 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -95,14 +95,16 @@ impl<'a> LocalIo<'a> { /// Returns the local I/O: either the local scheduler's I/O services or /// the native I/O services. pub fn borrow() -> Option { - // XXX: This is currently very unsafely implemented. We don't actually - // *take* the local I/O so there's a very real possibility that we - // can have two borrows at once. Currently there is not a clear way - // to actually borrow the local I/O factory safely because even if - // ownership were transferred down to the functions that the I/O - // factory implements it's just too much of a pain to know when to - // relinquish ownership back into the local task (but that would be - // the safe way of implementing this function). + // FIXME(#11053): bad + // + // This is currently very unsafely implemented. We don't actually + // *take* the local I/O so there's a very real possibility that we + // can have two borrows at once. Currently there is not a clear way + // to actually borrow the local I/O factory safely because even if + // ownership were transferred down to the functions that the I/O + // factory implements it's just too much of a pain to know when to + // relinquish ownership back into the local task (but that would be + // the safe way of implementing this function). // // In order to get around this, we just transmute a copy out of the task // in order to have what is likely a static lifetime (bad). diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 765f0b427cd54..e6ab159a76952 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -15,9 +15,10 @@ use any::AnyOwnExt; use borrow; +use cast; use cleanup; use io::Writer; -use libc::{c_char, size_t}; +use iter::{Iterator, Take}; use local_data; use ops::Drop; use option::{Option, Some, None}; @@ -488,7 +489,10 @@ mod test { #[test] #[should_fail] - fn test_begin_unwind() { begin_unwind("cause", file!(), line!()) } + fn test_begin_unwind() { + use rt::unwind::begin_unwind; + begin_unwind("cause", file!(), line!()) + } // Task blocking tests diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs index 11189282f683d..f4f4aaa276524 100644 --- a/src/libstd/rt/thread.rs +++ b/src/libstd/rt/thread.rs @@ -144,15 +144,11 @@ impl Drop for Thread { #[cfg(windows)] mod imp { - use super::DEFAULT_STACK_SIZE; - use cast; use libc; use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL, LPVOID, DWORD, LPDWORD, HANDLE}; use ptr; - use libc; - use cast; pub type rust_thread = HANDLE; pub type rust_thread_return = DWORD; diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 8248c6274ca1c..9706dbae4c61b 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -10,8 +10,9 @@ // Implementation of Rust stack unwinding // -// For background on exception handling and stack unwinding please see "Exception Handling in LLVM" -// (llvm.org/docs/ExceptionHandling.html) and documents linked from it. +// For background on exception handling and stack unwinding please see +// "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and +// documents linked from it. // These are also good reads: // http://theofilos.cs.columbia.edu/blog/2013/09/22/base_abi/ // http://monoinfinito.wordpress.com/series/exception-handling-in-c/ @@ -20,41 +21,55 @@ // ~~~ A brief summary ~~~ // Exception handling happens in two phases: a search phase and a cleanup phase. // -// In both phases the unwinder walks stack frames from top to bottom using information from -// the stack frame unwind sections of the current process's modules ("module" here refers to -// an OS module, i.e. an executable or a dynamic library). +// In both phases the unwinder walks stack frames from top to bottom using +// information from the stack frame unwind sections of the current process's +// modules ("module" here refers to an OS module, i.e. an executable or a +// dynamic library). // -// For each stack frame, it invokes the associated "personality routine", whose address is also -// stored in the unwind info section. +// For each stack frame, it invokes the associated "personality routine", whose +// address is also stored in the unwind info section. // -// In the search phase, the job of a personality routine is to examine exception object being -// thrown, and to decide whether it should be caught at that stack frame. Once the handler frame -// has been identified, cleanup phase begins. +// In the search phase, the job of a personality routine is to examine exception +// object being thrown, and to decide whether it should be caught at that stack +// frame. Once the handler frame has been identified, cleanup phase begins. // -// In the cleanup phase, personality routines invoke cleanup code associated with their -// stack frames (i.e. destructors). Once stack has been unwound down to the handler frame level, -// unwinding stops and the last personality routine transfers control to its' catch block. +// In the cleanup phase, personality routines invoke cleanup code associated +// with their stack frames (i.e. destructors). Once stack has been unwound down +// to the handler frame level, unwinding stops and the last personality routine +// transfers control to its' catch block. // // ~~~ Frame unwind info registration ~~~ -// Each module has its' own frame unwind info section (usually ".eh_frame"), and unwinder needs -// to know about all of them in order for unwinding to be able to cross module boundaries. +// Each module has its' own frame unwind info section (usually ".eh_frame"), and +// unwinder needs to know about all of them in order for unwinding to be able to +// cross module boundaries. // -// On some platforms, like Linux, this is achieved by dynamically enumerating currently loaded -// modules via the dl_iterate_phdr() API and finding all .eh_frame sections. +// On some platforms, like Linux, this is achieved by dynamically enumerating +// currently loaded modules via the dl_iterate_phdr() API and finding all +// .eh_frame sections. // -// Others, like Windows, require modules to actively register their unwind info sections by calling -// __register_frame_info() API at startup. -// In the latter case it is essential that there is only one copy of the unwinder runtime -// in the process. This is usually achieved by linking to the dynamic version of the unwind -// runtime. +// Others, like Windows, require modules to actively register their unwind info +// sections by calling __register_frame_info() API at startup. In the latter +// case it is essential that there is only one copy of the unwinder runtime in +// the process. This is usually achieved by linking to the dynamic version of +// the unwind runtime. // // Currently Rust uses unwind runtime provided by libgcc. -use prelude::*; -use cast::transmute; -use task::TaskResult; +use any::{Any, AnyRefExt}; +use c_str::CString; +use cast; +use kinds::Send; +use libc::{c_char, size_t}; use libc::{c_void, c_int}; -use self::libunwind::*; +use option::{Some, None, Option}; +use result::{Err, Ok}; +use rt::local::Local; +use rt::task::Task; +use str::Str; +use task::TaskResult; +use unstable::intrinsics; + +use uw = self::libunwind; mod libunwind { //! Unwind library interface @@ -109,34 +124,41 @@ mod libunwind { } pub struct Unwinder { - unwinding: bool, - cause: Option<~Any> + priv unwinding: bool, + priv cause: Option<~Any> } impl Unwinder { + pub fn new() -> Unwinder { + Unwinder { + unwinding: false, + cause: None, + } + } + + pub fn unwinding(&self) -> bool { + self.unwinding + } pub fn try(&mut self, f: ||) { use unstable::raw::Closure; unsafe { - let closure: Closure = transmute(f); - let code = transmute(closure.code); - let env = transmute(closure.env); - - let ep = rust_try(try_fn, code, env); + let closure: Closure = cast::transmute(f); + let ep = rust_try(try_fn, closure.code as *c_void, + closure.env as *c_void); if !ep.is_null() { rtdebug!("Caught {}", (*ep).exception_class); - _Unwind_DeleteException(ep); + uw::_Unwind_DeleteException(ep); } } extern fn try_fn(code: *c_void, env: *c_void) { unsafe { - let closure: Closure = Closure { - code: transmute(code), - env: transmute(env), - }; - let closure: || = transmute(closure); + let closure: || = cast::transmute(Closure { + code: code as *(), + env: env as *(), + }); closure(); } } @@ -144,10 +166,11 @@ impl Unwinder { extern { // Rust's try-catch // When f(...) returns normally, the return value is null. - // When f(...) throws, the return value is a pointer to the caught exception object. + // When f(...) throws, the return value is a pointer to the caught + // exception object. fn rust_try(f: extern "C" fn(*c_void, *c_void), code: *c_void, - data: *c_void) -> *_Unwind_Exception; + data: *c_void) -> *uw::_Unwind_Exception; } } @@ -158,21 +181,21 @@ impl Unwinder { self.cause = Some(cause); unsafe { - let exception = ~_Unwind_Exception { + let exception = ~uw::_Unwind_Exception { exception_class: rust_exception_class(), exception_cleanup: exception_cleanup, private_1: 0, private_2: 0 }; - let error = _Unwind_RaiseException(transmute(exception)); + let error = uw::_Unwind_RaiseException(cast::transmute(exception)); rtabort!("Could not unwind stack, error = {}", error as int) } - extern "C" fn exception_cleanup(_unwind_code: _Unwind_Reason_Code, - exception: *_Unwind_Exception) { + extern "C" fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code, + exception: *uw::_Unwind_Exception) { rtdebug!("exception_cleanup()"); unsafe { - let _: ~_Unwind_Exception = transmute(exception); + let _: ~uw::_Unwind_Exception = cast::transmute(exception); } } } @@ -188,68 +211,75 @@ impl Unwinder { // Rust's exception class identifier. This is used by personality routines to // determine whether the exception was thrown by their own runtime. -fn rust_exception_class() -> _Unwind_Exception_Class { - let bytes = bytes!("MOZ\0RUST"); // vendor, language - unsafe { - let ptr: *_Unwind_Exception_Class = transmute(bytes.as_ptr()); - *ptr - } +fn rust_exception_class() -> uw::_Unwind_Exception_Class { + // M O Z \0 R U S T -- vendor, language + 0x4d4f5a_00_52555354 } - -// We could implement our personality routine in pure Rust, however exception info decoding -// is tedious. More importantly, personality routines have to handle various platform -// quirks, which are not fun to maintain. For this reason, we attempt to reuse personality -// routine of the C language: __gcc_personality_v0. +// We could implement our personality routine in pure Rust, however exception +// info decoding is tedious. More importantly, personality routines have to +// handle various platform quirks, which are not fun to maintain. For this +// reason, we attempt to reuse personality routine of the C language: +// __gcc_personality_v0. // -// Since C does not support exception catching, __gcc_personality_v0 simply always -// returns _URC_CONTINUE_UNWIND in search phase, and always returns _URC_INSTALL_CONTEXT -// (i.e. "invoke cleanup code") in cleanup phase. +// Since C does not support exception catching, __gcc_personality_v0 simply +// always returns _URC_CONTINUE_UNWIND in search phase, and always returns +// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase. // -// This is pretty close to Rust's exception handling approach, except that Rust does have -// a single "catch-all" handler at the bottom of each task's stack. +// This is pretty close to Rust's exception handling approach, except that Rust +// does have a single "catch-all" handler at the bottom of each task's stack. // So we have two versions: -// - rust_eh_personality, used by all cleanup landing pads, which never catches, so -// the behavior of __gcc_personality_v0 is perfectly adequate there, and -// - rust_eh_personality_catch, used only by rust_try(), which always catches. This is -// achieved by overriding the return value in search phase to always say "catch!". +// - rust_eh_personality, used by all cleanup landing pads, which never catches, +// so the behavior of __gcc_personality_v0 is perfectly adequate there, and +// - rust_eh_personality_catch, used only by rust_try(), which always catches. +// This is achieved by overriding the return value in search phase to always +// say "catch!". extern "C" { fn __gcc_personality_v0(version: c_int, - actions: _Unwind_Action, - exception_class: _Unwind_Exception_Class, - ue_header: *_Unwind_Exception, - context: *_Unwind_Context) -> _Unwind_Reason_Code; + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *uw::_Unwind_Exception, + context: *uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; } #[lang="eh_personality"] #[no_mangle] // so we can reference it by name from middle/trans/base.rs #[doc(hidden)] #[cfg(not(test))] -pub extern "C" fn rust_eh_personality(version: c_int, - actions: _Unwind_Action, - exception_class: _Unwind_Exception_Class, - ue_header: *_Unwind_Exception, - context: *_Unwind_Context) -> _Unwind_Reason_Code { +pub extern "C" fn rust_eh_personality( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *uw::_Unwind_Exception, + context: *uw::_Unwind_Context +) -> uw::_Unwind_Reason_Code +{ unsafe { - __gcc_personality_v0(version, actions, exception_class, ue_header, context) + __gcc_personality_v0(version, actions, exception_class, ue_header, + context) } } #[no_mangle] // referenced from rust_try.ll #[doc(hidden)] #[cfg(not(test))] -pub extern "C" fn rust_eh_personality_catch(version: c_int, - actions: _Unwind_Action, - exception_class: _Unwind_Exception_Class, - ue_header: *_Unwind_Exception, - context: *_Unwind_Context) -> _Unwind_Reason_Code { - if (actions as c_int & _UA_SEARCH_PHASE as c_int) != 0 { // search phase - _URC_HANDLER_FOUND // catch! +pub extern "C" fn rust_eh_personality_catch( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *uw::_Unwind_Exception, + context: *uw::_Unwind_Context +) -> uw::_Unwind_Reason_Code +{ + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase + uw::_URC_HANDLER_FOUND // catch! } else { // cleanup phase unsafe { - __gcc_personality_v0(version, actions, exception_class, ue_header, context) + __gcc_personality_v0(version, actions, exception_class, ue_header, + context) } } } @@ -307,11 +337,11 @@ pub fn begin_unwind(msg: M, file: &'static str, line: uint) -> ! let n = (*task).name.as_ref() .map(|n| n.as_slice()).unwrap_or(""); - println!("task '{}' failed at '{}', {}:{}", n, msg_s, + rterrln!("task '{}' failed at '{}', {}:{}", n, msg_s, file, line); } None => { - println!("failed at '{}', {}:{}", msg_s, file, line); + rterrln!("failed at '{}', {}:{}", msg_s, file, line); intrinsics::abort(); } } diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 69c1da39abc85..730a38ce8867d 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -69,14 +69,13 @@ pub fn default_sched_threads() -> uint { pub fn dumb_println(args: &fmt::Arguments) { use io; use libc; - use vec; struct Stderr; impl io::Writer for Stderr { fn write(&mut self, data: &[u8]) { unsafe { libc::write(libc::STDERR_FILENO, - vec::raw::to_ptr(data) as *libc::c_void, + data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } } diff --git a/src/libstd/sync/arc.rs b/src/libstd/sync/arc.rs index b405104c09a25..7b94a3acc2b7d 100644 --- a/src/libstd/sync/arc.rs +++ b/src/libstd/sync/arc.rs @@ -32,7 +32,7 @@ use vec; /// An atomically reference counted pointer. /// /// Enforces no shared-memory safety. -//#[unsafe_no_drop_flag] FIXME: #9758 +#[unsafe_no_drop_flag] pub struct UnsafeArc { priv data: *mut ArcData, } diff --git a/src/libstd/unstable/stack.rs b/src/libstd/unstable/stack.rs index b8788b8c55c1e..d6cd690eaa9db 100644 --- a/src/libstd/unstable/stack.rs +++ b/src/libstd/unstable/stack.rs @@ -192,6 +192,7 @@ pub unsafe fn record_sp_limit(limit: uint) { #[cfg(target_arch = "mips")] #[cfg(target_arch = "arm")] #[inline(always)] unsafe fn target_record_sp_limit(limit: uint) { + use libc::c_void; return record_sp_limit(limit as *c_void); extern { fn record_sp_limit(limit: *c_void); @@ -265,6 +266,7 @@ pub unsafe fn get_sp_limit() -> uint { #[cfg(target_arch = "mips")] #[cfg(target_arch = "arm")] #[inline(always)] unsafe fn target_get_sp_limit() -> uint { + use libc::c_void; return get_sp_limit() as uint; extern { fn get_sp_limit() -> *c_void; diff --git a/src/test/bench/rt-messaging-ping-pong.rs b/src/test/bench/rt-messaging-ping-pong.rs index 90d81aa7c3ee6..6eef71622c5c6 100644 --- a/src/test/bench/rt-messaging-ping-pong.rs +++ b/src/test/bench/rt-messaging-ping-pong.rs @@ -1,4 +1,3 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -12,7 +11,6 @@ extern mod extra; use std::os; use std::uint; -use std::rt::test::spawntask_later; // This is a simple bench that creates M pairs of of tasks. These // tasks ping-pong back and forth over a pair of streams. This is a @@ -28,7 +26,7 @@ fn ping_pong_bench(n: uint, m: uint) { // Create a stream B->A let (pb,cb) = Chan::<()>::new(); - do spawntask_later() || { + do spawn() || { let chan = ca; let port = pb; n.times(|| { @@ -37,7 +35,7 @@ fn ping_pong_bench(n: uint, m: uint) { }) } - do spawntask_later() || { + do spawn() || { let chan = cb; let port = pa; n.times(|| { diff --git a/src/test/bench/rt-parfib.rs b/src/test/bench/rt-parfib.rs index ab607d9aebc75..6e3c42f2a4dea 100644 --- a/src/test/bench/rt-parfib.rs +++ b/src/test/bench/rt-parfib.rs @@ -12,7 +12,6 @@ extern mod extra; use std::os; use std::uint; -use std::rt::test::spawntask_later; // A simple implementation of parfib. One subtree is found in a new // task and communicated over a oneshot pipe, the other is found @@ -24,7 +23,7 @@ fn parfib(n: uint) -> uint { } let (port,chan) = Chan::new(); - do spawntask_later { + do spawn { chan.send(parfib(n-1)); }; let m2 = parfib(n-2); diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index 87cd01f9aad2e..8174347e3869e 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test arcs no longer unwrap + extern mod extra; use std::from_str::FromStr; diff --git a/src/test/compile-fail/std-uncopyable-atomics.rs b/src/test/compile-fail/std-uncopyable-atomics.rs index a46dec7830a29..57c66974fcd01 100644 --- a/src/test/compile-fail/std-uncopyable-atomics.rs +++ b/src/test/compile-fail/std-uncopyable-atomics.rs @@ -12,7 +12,7 @@ #[feature(globs)]; -use std::unstable::atomics::*; +use std::sync::atomics::*; use std::ptr; fn main() { diff --git a/src/test/run-make/bootstrap-from-c-with-uvio/Makefile b/src/test/run-make/bootstrap-from-c-with-green/Makefile similarity index 100% rename from src/test/run-make/bootstrap-from-c-with-uvio/Makefile rename to src/test/run-make/bootstrap-from-c-with-green/Makefile diff --git a/src/test/run-make/bootstrap-from-c-with-green/lib.rs b/src/test/run-make/bootstrap-from-c-with-green/lib.rs new file mode 100644 index 0000000000000..9a03c772f3a3f --- /dev/null +++ b/src/test/run-make/bootstrap-from-c-with-green/lib.rs @@ -0,0 +1,25 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[crate_id="boot#0.1"]; +#[crate_type="lib"]; +#[no_uv]; + +extern mod rustuv; +extern mod green; + +#[no_mangle] // this needs to get called from C +pub extern "C" fn foo(argc: int, argv: **u8) -> int { + do green::start(argc, argv) { + do spawn { + println!("hello"); + } + } +} diff --git a/src/test/run-make/bootstrap-from-c-with-uvio/main.c b/src/test/run-make/bootstrap-from-c-with-green/main.c similarity index 100% rename from src/test/run-make/bootstrap-from-c-with-uvio/main.c rename to src/test/run-make/bootstrap-from-c-with-green/main.c diff --git a/src/test/run-make/bootstrap-from-c-with-native/Makefile b/src/test/run-make/bootstrap-from-c-with-native/Makefile new file mode 100644 index 0000000000000..7f466573da730 --- /dev/null +++ b/src/test/run-make/bootstrap-from-c-with-native/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +all: + $(RUSTC) lib.rs -Z gen-crate-map + ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot) + $(CC) main.c -o $(call RUN,main) -lboot -Wl,-rpath,$(TMPDIR) + $(call RUN,main) + rm $(call DYLIB,boot) + $(call FAIL,main) diff --git a/src/test/run-make/bootstrap-from-c-with-uvio/lib.rs b/src/test/run-make/bootstrap-from-c-with-native/lib.rs similarity index 89% rename from src/test/run-make/bootstrap-from-c-with-uvio/lib.rs rename to src/test/run-make/bootstrap-from-c-with-native/lib.rs index 06a06c967f4fb..d0639d45fa569 100644 --- a/src/test/run-make/bootstrap-from-c-with-uvio/lib.rs +++ b/src/test/run-make/bootstrap-from-c-with-native/lib.rs @@ -10,14 +10,13 @@ #[crate_id="boot#0.1"]; #[crate_type="lib"]; +#[no_uv]; -extern mod rustuv; // pull in uvio - -use std::rt; +extern mod native; #[no_mangle] // this needs to get called from C pub extern "C" fn foo(argc: int, argv: **u8) -> int { - do rt::start(argc, argv) { + do native::start(argc, argv) { do spawn { println!("hello"); } diff --git a/src/test/run-make/bootstrap-from-c-with-native/main.c b/src/test/run-make/bootstrap-from-c-with-native/main.c new file mode 100644 index 0000000000000..1872c1ea43b11 --- /dev/null +++ b/src/test/run-make/bootstrap-from-c-with-native/main.c @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// this is the rust entry point that we're going to call. +int foo(int argc, char *argv[]); + +int main(int argc, char *argv[]) { + return foo(argc, argv); +} diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 56ce5397efb13..013487e580381 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -28,4 +28,4 @@ mod baz { } #[start] -pub fn start(_: int, _: **u8) -> int { 3 } +pub fn start(_: int, _: **u8) -> int { 0 }