mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
libs: Fix miscellaneous fallout of librustrt
This commit is contained in:
parent
d743b8831e
commit
75014f7b17
@ -96,6 +96,21 @@ pub mod owned;
|
||||
pub mod arc;
|
||||
pub mod rc;
|
||||
|
||||
// FIXME(#14344): When linking liballoc with libstd, this library will be linked
|
||||
// as an rlib (it only exists as an rlib). It turns out that an
|
||||
// optimized standard library doesn't actually use *any* symbols
|
||||
// from this library. Everything is inlined and optimized away.
|
||||
// This means that linkers will actually omit the object for this
|
||||
// file, even though it may be needed in the future.
|
||||
//
|
||||
// To get around this for now, we define a dummy symbol which
|
||||
// will never get inlined so the stdlib can call it. The stdlib's
|
||||
// reference to this symbol will cause this library's object file
|
||||
// to get linked in to libstd successfully (the linker won't
|
||||
// optimize it out).
|
||||
#[doc(hidden)]
|
||||
pub fn fixme_14344_be_sure_to_link_to_collections() {}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
mod std {
|
||||
|
@ -28,20 +28,3 @@ fn align_to(size: uint, align: uint) -> uint {
|
||||
assert!(align != 0);
|
||||
(size + align - 1) & !(align - 1)
|
||||
}
|
||||
|
||||
// FIXME(#14344): When linking liballoc with libstd, this library will be linked
|
||||
// as an rlib (it only exists as an rlib). It turns out that an
|
||||
// optimized standard library doesn't actually use *any* symbols
|
||||
// from this library. Everything is inlined and optimized away.
|
||||
// This means that linkers will actually omit the object for this
|
||||
// file, even though it may be needed in the future.
|
||||
//
|
||||
// To get around this for now, we define a dummy symbol which
|
||||
// will never get inlined so the stdlib can call it. The stdlib's
|
||||
// reference to this symbol will cause this library's object file
|
||||
// to get linked in to libstd successfully (the linker won't
|
||||
// optimize it out).
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
pub fn make_stdlib_link_work() {}
|
||||
|
||||
|
@ -72,6 +72,10 @@ fn expect<T>(a: core::option::Option<T>, b: &str) -> T {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#14344) this shouldn't be necessary
|
||||
#[doc(hidden)]
|
||||
pub fn fixme_14344_be_sure_to_link_to_collections() {}
|
||||
|
||||
#[cfg(not(test))]
|
||||
mod std {
|
||||
pub use core::fmt; // necessary for fail!()
|
||||
|
@ -862,7 +862,7 @@ mod tests {
|
||||
use std::prelude::*;
|
||||
use std::rand::{Rng, task_rng};
|
||||
use std::rc::Rc;
|
||||
use std::unstable;
|
||||
use std::rt;
|
||||
use slice::*;
|
||||
|
||||
use vec::Vec;
|
||||
@ -1104,9 +1104,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_swap_remove_noncopyable() {
|
||||
// Tests that we don't accidentally run destructors twice.
|
||||
let mut v = vec![unstable::sync::Exclusive::new(()),
|
||||
unstable::sync::Exclusive::new(()),
|
||||
unstable::sync::Exclusive::new(())];
|
||||
let mut v = vec![rt::exclusive::Exclusive::new(()),
|
||||
rt::exclusive::Exclusive::new(()),
|
||||
rt::exclusive::Exclusive::new(())];
|
||||
let mut _e = v.swap_remove(0);
|
||||
assert_eq!(v.len(), 2);
|
||||
_e = v.swap_remove(1);
|
||||
|
@ -20,7 +20,7 @@ use std::sync::atomics;
|
||||
use std::mem;
|
||||
use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback};
|
||||
use std::rt::rtio::{PausableIdleCallback, Callback};
|
||||
use std::unstable::sync::Exclusive;
|
||||
use std::rt::exclusive::Exclusive;
|
||||
|
||||
/// This is the only exported function from this module.
|
||||
pub fn event_loop() -> Box<EventLoop:Send> {
|
||||
@ -31,7 +31,7 @@ struct BasicLoop {
|
||||
work: Vec<proc():Send>, // pending work
|
||||
remotes: Vec<(uint, Box<Callback:Send>)>,
|
||||
next_remote: uint,
|
||||
messages: Exclusive<Vec<Message>>,
|
||||
messages: Arc<Exclusive<Vec<Message>>>,
|
||||
idle: Option<Box<Callback:Send>>,
|
||||
idle_active: Option<Arc<atomics::AtomicBool>>,
|
||||
}
|
||||
@ -46,7 +46,7 @@ impl BasicLoop {
|
||||
idle_active: None,
|
||||
next_remote: 0,
|
||||
remotes: vec![],
|
||||
messages: Exclusive::new(vec![]),
|
||||
messages: Arc::new(Exclusive::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,19 +61,10 @@ impl BasicLoop {
|
||||
|
||||
fn remote_work(&mut self) {
|
||||
let messages = unsafe {
|
||||
self.messages.with(|messages| {
|
||||
if messages.len() > 0 {
|
||||
Some(mem::replace(messages, vec![]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
mem::replace(&mut *self.messages.lock(), Vec::new())
|
||||
};
|
||||
let messages = match messages {
|
||||
Some(m) => m, None => return
|
||||
};
|
||||
for message in messages.iter() {
|
||||
self.message(*message);
|
||||
for message in messages.move_iter() {
|
||||
self.message(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,13 +116,13 @@ impl EventLoop for BasicLoop {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut messages = self.messages.lock();
|
||||
// We block here if we have no messages to process and we may
|
||||
// receive a message at a later date
|
||||
self.messages.hold_and_wait(|messages| {
|
||||
self.remotes.len() > 0 &&
|
||||
messages.len() == 0 &&
|
||||
self.work.len() == 0
|
||||
})
|
||||
if self.remotes.len() > 0 && messages.len() == 0 &&
|
||||
self.work.len() == 0 {
|
||||
messages.wait()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,33 +156,29 @@ impl EventLoop for BasicLoop {
|
||||
}
|
||||
|
||||
struct BasicRemote {
|
||||
queue: Exclusive<Vec<Message>>,
|
||||
queue: Arc<Exclusive<Vec<Message>>>,
|
||||
id: uint,
|
||||
}
|
||||
|
||||
impl BasicRemote {
|
||||
fn new(queue: Exclusive<Vec<Message>>, id: uint) -> BasicRemote {
|
||||
fn new(queue: Arc<Exclusive<Vec<Message>>>, id: uint) -> BasicRemote {
|
||||
BasicRemote { queue: queue, id: id }
|
||||
}
|
||||
}
|
||||
|
||||
impl RemoteCallback for BasicRemote {
|
||||
fn fire(&mut self) {
|
||||
unsafe {
|
||||
self.queue.hold_and_signal(|queue| {
|
||||
queue.push(RunRemote(self.id));
|
||||
})
|
||||
}
|
||||
let mut queue = unsafe { self.queue.lock() };
|
||||
queue.push(RunRemote(self.id));
|
||||
queue.signal();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BasicRemote {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.queue.hold_and_signal(|queue| {
|
||||
queue.push(RemoveRemote(self.id));
|
||||
})
|
||||
}
|
||||
let mut queue = unsafe { self.queue.lock() };
|
||||
queue.push(RemoveRemote(self.id));
|
||||
queue.signal();
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +203,7 @@ impl Drop for BasicPausable {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::task::TaskOpts;
|
||||
use std::rt::task::TaskOpts;
|
||||
|
||||
use basic;
|
||||
use PoolConfig;
|
||||
|
@ -160,7 +160,7 @@
|
||||
//! # Using a scheduler pool
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::task::TaskOpts;
|
||||
//! use std::rt::task::TaskOpts;
|
||||
//! use green::{SchedPool, PoolConfig};
|
||||
//! use green::sched::{PinnedTask, TaskFromFriend};
|
||||
//!
|
||||
@ -221,10 +221,10 @@ use std::mem::replace;
|
||||
use std::os;
|
||||
use std::rt::rtio;
|
||||
use std::rt::thread::Thread;
|
||||
use std::rt::task::TaskOpts;
|
||||
use std::rt;
|
||||
use std::sync::atomics::{SeqCst, AtomicUint, INIT_ATOMIC_UINT};
|
||||
use std::sync::deque;
|
||||
use std::task::TaskOpts;
|
||||
|
||||
use sched::{Shutdown, Scheduler, SchedHandle, TaskFromFriend, NewNeighbor};
|
||||
use sleeper_list::SleeperList;
|
||||
@ -319,7 +319,7 @@ pub fn run(event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
|
||||
let mut pool = SchedPool::new(cfg);
|
||||
let (tx, rx) = channel();
|
||||
let mut opts = TaskOpts::new();
|
||||
opts.notify_chan = Some(tx);
|
||||
opts.on_exit = Some(proc(r) tx.send(r));
|
||||
opts.name = Some("<main>".into_maybe_owned());
|
||||
pool.spawn(opts, main);
|
||||
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
use std::mem;
|
||||
use std::rt::local::Local;
|
||||
use std::rt::mutex::NativeMutex;
|
||||
use std::rt::rtio::{RemoteCallback, PausableIdleCallback, Callback, EventLoop};
|
||||
use std::rt::task::BlockedTask;
|
||||
use std::rt::task::Task;
|
||||
use std::sync::deque;
|
||||
use std::unstable::mutex::NativeMutex;
|
||||
use std::raw;
|
||||
|
||||
use std::rand::{XorShiftRng, Rng, Rand};
|
||||
@ -1022,7 +1022,7 @@ fn new_sched_rng() -> XorShiftRng {
|
||||
mod test {
|
||||
use rustuv;
|
||||
|
||||
use std::task::TaskOpts;
|
||||
use std::rt::task::TaskOpts;
|
||||
use std::rt::task::Task;
|
||||
use std::rt::local::Local;
|
||||
|
||||
@ -1475,7 +1475,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_spawn_sched_blocking() {
|
||||
use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
use std::rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||
|
||||
// Testing that a task in one scheduler can block in foreign code
|
||||
|
@ -15,10 +15,9 @@ use std::any::Any;
|
||||
use std::mem;
|
||||
use std::rt::Runtime;
|
||||
use std::rt::local::Local;
|
||||
use std::rt::mutex::NativeMutex;
|
||||
use std::rt::rtio;
|
||||
use std::rt::task::{Task, BlockedTask};
|
||||
use std::task::TaskOpts;
|
||||
use std::unstable::mutex::NativeMutex;
|
||||
use std::rt::task::{Task, BlockedTask, TaskOpts};
|
||||
|
||||
struct SimpleTask {
|
||||
lock: NativeMutex,
|
||||
|
@ -8,9 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::rt::env::max_cached_stacks;
|
||||
use std::sync::atomics;
|
||||
use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
|
||||
MapNonStandardFlags, MapVirtual};
|
||||
MapNonStandardFlags, MapVirtual, getenv};
|
||||
use libc;
|
||||
|
||||
/// A task's stack. The name "Stack" is a vestige of segmented stacks.
|
||||
@ -151,6 +151,22 @@ impl StackPool {
|
||||
}
|
||||
}
|
||||
|
||||
fn max_cached_stacks() -> uint {
|
||||
static mut AMT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
|
||||
match unsafe { AMT.load(atomics::SeqCst) } {
|
||||
0 => {}
|
||||
n => return n - 1,
|
||||
}
|
||||
let amt = getenv("RUST_MAX_CACHED_STACKS").and_then(|s| from_str(s.as_slice()));
|
||||
// This default corresponds to 20M of cache per scheduler (at the
|
||||
// default size).
|
||||
let amt = amt.unwrap_or(10);
|
||||
// 0 is our sentinel value, so ensure that we'll never see 0 after
|
||||
// initialization has run
|
||||
unsafe { AMT.store(amt + 1, atomics::SeqCst); }
|
||||
return amt;
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_valgrind_stack_register(start: *libc::uintptr_t,
|
||||
end: *libc::uintptr_t) -> libc::c_uint;
|
||||
|
@ -22,13 +22,12 @@ use std::any::Any;
|
||||
use std::mem;
|
||||
use std::raw;
|
||||
use std::rt::Runtime;
|
||||
use std::rt::env;
|
||||
use std::rt::local::Local;
|
||||
use std::rt::mutex::NativeMutex;
|
||||
use std::rt::rtio;
|
||||
use std::rt::stack;
|
||||
use std::rt::task::{Task, BlockedTask, SendMessage};
|
||||
use std::task::TaskOpts;
|
||||
use std::unstable::mutex::NativeMutex;
|
||||
use std::rt::task::{Task, BlockedTask, TaskOpts};
|
||||
use std::rt;
|
||||
|
||||
use context::Context;
|
||||
use coroutine::Coroutine;
|
||||
@ -142,7 +141,7 @@ impl GreenTask {
|
||||
let mut ops = GreenTask::new_typed(None, TypeGreen(Some(home)));
|
||||
|
||||
// Allocate a stack for us to run on
|
||||
let stack_size = stack_size.unwrap_or_else(|| env::min_stack());
|
||||
let stack_size = stack_size.unwrap_or_else(|| rt::min_stack());
|
||||
let mut stack = stack_pool.take_stack(stack_size);
|
||||
let context = Context::new(bootstrap_green_task, ops.as_uint(), start,
|
||||
&mut stack);
|
||||
@ -176,23 +175,13 @@ impl GreenTask {
|
||||
pub fn configure(pool: &mut StackPool,
|
||||
opts: TaskOpts,
|
||||
f: proc():Send) -> Box<GreenTask> {
|
||||
let TaskOpts {
|
||||
notify_chan, name, stack_size,
|
||||
stderr, stdout,
|
||||
} = opts;
|
||||
let TaskOpts { name, stack_size, on_exit } = opts;
|
||||
|
||||
let mut green = GreenTask::new(pool, stack_size, f);
|
||||
{
|
||||
let task = green.task.get_mut_ref();
|
||||
task.name = name;
|
||||
task.stderr = stderr;
|
||||
task.stdout = stdout;
|
||||
match notify_chan {
|
||||
Some(chan) => {
|
||||
task.death.on_exit = Some(SendMessage(chan));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
task.death.on_exit = on_exit;
|
||||
}
|
||||
return green;
|
||||
}
|
||||
@ -490,7 +479,7 @@ mod tests {
|
||||
use std::rt::local::Local;
|
||||
use std::rt::task::Task;
|
||||
use std::task;
|
||||
use std::task::TaskOpts;
|
||||
use std::rt::task::TaskOpts;
|
||||
|
||||
use super::super::{PoolConfig, SchedPool};
|
||||
use super::GreenTask;
|
||||
@ -529,7 +518,7 @@ mod tests {
|
||||
opts.name = Some("test".into_maybe_owned());
|
||||
opts.stack_size = Some(20 * 4096);
|
||||
let (tx, rx) = channel();
|
||||
opts.notify_chan = Some(tx);
|
||||
opts.on_exit = Some(proc(r) tx.send(r));
|
||||
spawn_opts(opts, proc() {});
|
||||
assert!(rx.recv().is_ok());
|
||||
}
|
||||
@ -538,7 +527,7 @@ mod tests {
|
||||
fn smoke_opts_fail() {
|
||||
let mut opts = TaskOpts::new();
|
||||
let (tx, rx) = channel();
|
||||
opts.notify_chan = Some(tx);
|
||||
opts.on_exit = Some(proc(r) tx.send(r));
|
||||
spawn_opts(opts, proc() { fail!() });
|
||||
assert!(rx.recv().is_err());
|
||||
}
|
||||
|
@ -172,6 +172,7 @@ pub use funcs::bsd43::{shutdown};
|
||||
#[cfg(unix)] pub use consts::os::posix88::{ENOTCONN, ECONNABORTED, EADDRNOTAVAIL, EINTR};
|
||||
#[cfg(unix)] pub use consts::os::posix88::{EADDRINUSE, ENOENT, EISDIR, EAGAIN, EWOULDBLOCK};
|
||||
#[cfg(unix)] pub use consts::os::posix88::{ECANCELED, SIGINT, EINPROGRESS};
|
||||
#[cfg(unix)] pub use consts::os::posix88::{ENOSYS, ENOTTY, ETIMEDOUT};
|
||||
#[cfg(unix)] pub use consts::os::posix88::{SIGTERM, SIGKILL, SIGPIPE, PROT_NONE};
|
||||
#[cfg(unix)] pub use consts::os::posix01::{SIG_IGN};
|
||||
#[cfg(unix)] pub use consts::os::bsd44::{AF_UNIX};
|
||||
@ -195,7 +196,7 @@ pub use funcs::bsd43::{shutdown};
|
||||
#[cfg(windows)] pub use consts::os::c95::{WSAECONNREFUSED, WSAECONNRESET, WSAEACCES};
|
||||
#[cfg(windows)] pub use consts::os::c95::{WSAEWOULDBLOCK, WSAENOTCONN, WSAECONNABORTED};
|
||||
#[cfg(windows)] pub use consts::os::c95::{WSAEADDRNOTAVAIL, WSAEADDRINUSE, WSAEINTR};
|
||||
#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS};
|
||||
#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS, WSAEINVAL};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_INSUFFICIENT_BUFFER};
|
||||
#[cfg(windows)] pub use consts::os::extra::{O_BINARY, O_NOINHERIT, PAGE_NOACCESS};
|
||||
#[cfg(windows)] pub use consts::os::extra::{PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE};
|
||||
@ -205,6 +206,9 @@ pub use funcs::bsd43::{shutdown};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_ALREADY_EXISTS, ERROR_NO_DATA};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_NAME};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_BROKEN_PIPE, ERROR_INVALID_FUNCTION};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_CALL_NOT_IMPLEMENTED};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_NOTHING_TO_TERMINATE};
|
||||
#[cfg(windows)] pub use consts::os::extra::{ERROR_INVALID_HANDLE};
|
||||
#[cfg(windows)] pub use consts::os::extra::{TRUE, FALSE, INFINITE};
|
||||
#[cfg(windows)] pub use consts::os::extra::{PROCESS_TERMINATE, PROCESS_QUERY_INFORMATION};
|
||||
#[cfg(windows)] pub use consts::os::extra::{STILL_ACTIVE, DETACHED_PROCESS};
|
||||
@ -1758,6 +1762,7 @@ pub mod consts {
|
||||
pub static ERROR_NO_DATA: c_int = 232;
|
||||
pub static ERROR_INVALID_ADDRESS : c_int = 487;
|
||||
pub static ERROR_PIPE_CONNECTED: c_int = 535;
|
||||
pub static ERROR_NOTHING_TO_TERMINATE: c_int = 758;
|
||||
pub static ERROR_OPERATION_ABORTED: c_int = 995;
|
||||
pub static ERROR_IO_PENDING: c_int = 997;
|
||||
pub static ERROR_FILE_INVALID : c_int = 1006;
|
||||
|
@ -92,8 +92,6 @@ extern "system" {
|
||||
fn freeaddrinfo(res: *mut libc::addrinfo);
|
||||
#[cfg(not(windows))]
|
||||
fn gai_strerror(errcode: c_int) -> *c_char;
|
||||
#[cfg(windows)]
|
||||
fn WSAGetLastError() -> c_int;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
@ -14,17 +14,14 @@ use alloc::arc::Arc;
|
||||
use libc::{c_int, c_void};
|
||||
use libc;
|
||||
use std::c_str::CString;
|
||||
use std::io::IoError;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
|
||||
use std::ptr;
|
||||
use std::rt::rtio;
|
||||
use std::rt::rtio::IoResult;
|
||||
use std::str;
|
||||
use std::vec;
|
||||
|
||||
use io::IoResult;
|
||||
|
||||
pub type fd_t = libc::c_int;
|
||||
|
||||
struct Inner {
|
||||
@ -52,7 +49,7 @@ impl FileDesc {
|
||||
}) }
|
||||
}
|
||||
|
||||
pub fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
|
||||
pub fn inner_read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
let mut read = 0;
|
||||
let ret = unsafe {
|
||||
libc::ReadFile(self.handle(), buf.as_ptr() as libc::LPVOID,
|
||||
@ -65,7 +62,7 @@ impl FileDesc {
|
||||
Err(super::last_error())
|
||||
}
|
||||
}
|
||||
pub fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
||||
pub fn inner_write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
let mut cur = buf.as_ptr();
|
||||
let mut remaining = buf.len();
|
||||
while remaining > 0 {
|
||||
@ -93,11 +90,11 @@ impl FileDesc {
|
||||
|
||||
// A version of seek that takes &self so that tell can call it
|
||||
// - the private seek should of course take &mut self.
|
||||
fn seek_common(&self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
|
||||
fn seek_common(&self, pos: i64, style: rtio::SeekStyle) -> IoResult<u64> {
|
||||
let whence = match style {
|
||||
io::SeekSet => libc::FILE_BEGIN,
|
||||
io::SeekEnd => libc::FILE_END,
|
||||
io::SeekCur => libc::FILE_CURRENT,
|
||||
rtio::SeekSet => libc::FILE_BEGIN,
|
||||
rtio::SeekEnd => libc::FILE_END,
|
||||
rtio::SeekCur => libc::FILE_CURRENT,
|
||||
};
|
||||
unsafe {
|
||||
let mut newpos = 0;
|
||||
@ -111,27 +108,15 @@ impl FileDesc {
|
||||
|
||||
}
|
||||
|
||||
impl io::Reader for FileDesc {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
||||
self.inner_read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Writer for FileDesc {
|
||||
fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
|
||||
self.inner_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl rtio::RtioFileStream for FileDesc {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<int> {
|
||||
self.inner_read(buf).map(|i| i as int)
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
self.inner_write(buf)
|
||||
}
|
||||
|
||||
fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
|
||||
fn pread(&mut self, buf: &mut [u8], offset: u64) -> IoResult<int> {
|
||||
let mut read = 0;
|
||||
let mut overlap: libc::OVERLAPPED = unsafe { mem::zeroed() };
|
||||
overlap.Offset = offset as libc::DWORD;
|
||||
@ -147,7 +132,7 @@ impl rtio::RtioFileStream for FileDesc {
|
||||
Err(super::last_error())
|
||||
}
|
||||
}
|
||||
fn pwrite(&mut self, buf: &[u8], mut offset: u64) -> Result<(), IoError> {
|
||||
fn pwrite(&mut self, buf: &[u8], mut offset: u64) -> IoResult<()> {
|
||||
let mut cur = buf.as_ptr();
|
||||
let mut remaining = buf.len();
|
||||
let mut overlap: libc::OVERLAPPED = unsafe { mem::zeroed() };
|
||||
@ -171,36 +156,36 @@ impl rtio::RtioFileStream for FileDesc {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn seek(&mut self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
|
||||
fn seek(&mut self, pos: i64, style: rtio::SeekStyle) -> IoResult<u64> {
|
||||
self.seek_common(pos, style)
|
||||
}
|
||||
|
||||
fn tell(&self) -> Result<u64, IoError> {
|
||||
self.seek_common(0, io::SeekCur)
|
||||
fn tell(&self) -> IoResult<u64> {
|
||||
self.seek_common(0, rtio::SeekCur)
|
||||
}
|
||||
|
||||
fn fsync(&mut self) -> Result<(), IoError> {
|
||||
fn fsync(&mut self) -> IoResult<()> {
|
||||
super::mkerr_winbool(unsafe {
|
||||
libc::FlushFileBuffers(self.handle())
|
||||
})
|
||||
}
|
||||
|
||||
fn datasync(&mut self) -> Result<(), IoError> { return self.fsync(); }
|
||||
fn datasync(&mut self) -> IoResult<()> { return self.fsync(); }
|
||||
|
||||
fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
|
||||
fn truncate(&mut self, offset: i64) -> IoResult<()> {
|
||||
let orig_pos = try!(self.tell());
|
||||
let _ = try!(self.seek(offset, io::SeekSet));
|
||||
let _ = try!(self.seek(offset, rtio::SeekSet));
|
||||
let ret = unsafe {
|
||||
match libc::SetEndOfFile(self.handle()) {
|
||||
0 => Err(super::last_error()),
|
||||
_ => Ok(())
|
||||
}
|
||||
};
|
||||
let _ = self.seek(orig_pos as i64, io::SeekSet);
|
||||
let _ = self.seek(orig_pos as i64, rtio::SeekSet);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fn fstat(&mut self) -> IoResult<io::FileStat> {
|
||||
fn fstat(&mut self) -> IoResult<rtio::FileStat> {
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
match unsafe { libc::fstat(self.fd(), &mut stat) } {
|
||||
0 => Ok(mkstat(&stat)),
|
||||
@ -210,10 +195,10 @@ impl rtio::RtioFileStream for FileDesc {
|
||||
}
|
||||
|
||||
impl rtio::RtioPipe for FileDesc {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
self.inner_read(buf)
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
self.inner_write(buf)
|
||||
}
|
||||
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
|
||||
@ -225,10 +210,10 @@ impl rtio::RtioPipe for FileDesc {
|
||||
// std::io::PipeStream. If the functionality is exposed in the future, then
|
||||
// these methods will need to be implemented.
|
||||
fn close_read(&mut self) -> IoResult<()> {
|
||||
Err(io::standard_error(io::InvalidInput))
|
||||
Err(super::unimpl())
|
||||
}
|
||||
fn close_write(&mut self) -> IoResult<()> {
|
||||
Err(io::standard_error(io::InvalidInput))
|
||||
Err(super::unimpl())
|
||||
}
|
||||
fn set_timeout(&mut self, _t: Option<u64>) {}
|
||||
fn set_read_timeout(&mut self, _t: Option<u64>) {}
|
||||
@ -236,16 +221,16 @@ impl rtio::RtioPipe for FileDesc {
|
||||
}
|
||||
|
||||
impl rtio::RtioTTY for FileDesc {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
self.inner_read(buf)
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
self.inner_write(buf)
|
||||
}
|
||||
fn set_raw(&mut self, _raw: bool) -> Result<(), IoError> {
|
||||
fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
|
||||
Err(super::unimpl())
|
||||
}
|
||||
fn get_winsize(&mut self) -> Result<(int, int), IoError> {
|
||||
fn get_winsize(&mut self) -> IoResult<(int, int)> {
|
||||
Err(super::unimpl())
|
||||
}
|
||||
fn isatty(&self) -> bool { false }
|
||||
@ -268,24 +253,24 @@ impl Drop for Inner {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
|
||||
pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
|
||||
-> IoResult<FileDesc> {
|
||||
// Flags passed to open_osfhandle
|
||||
let flags = match fm {
|
||||
io::Open => 0,
|
||||
io::Append => libc::O_APPEND,
|
||||
io::Truncate => libc::O_TRUNC,
|
||||
rtio::Open => 0,
|
||||
rtio::Append => libc::O_APPEND,
|
||||
rtio::Truncate => libc::O_TRUNC,
|
||||
};
|
||||
let flags = match fa {
|
||||
io::Read => flags | libc::O_RDONLY,
|
||||
io::Write => flags | libc::O_WRONLY | libc::O_CREAT,
|
||||
io::ReadWrite => flags | libc::O_RDWR | libc::O_CREAT,
|
||||
rtio::Read => flags | libc::O_RDONLY,
|
||||
rtio::Write => flags | libc::O_WRONLY | libc::O_CREAT,
|
||||
rtio::ReadWrite => flags | libc::O_RDWR | libc::O_CREAT,
|
||||
};
|
||||
|
||||
let mut dwDesiredAccess = match fa {
|
||||
io::Read => libc::FILE_GENERIC_READ,
|
||||
io::Write => libc::FILE_GENERIC_WRITE,
|
||||
io::ReadWrite => libc::FILE_GENERIC_READ | libc::FILE_GENERIC_WRITE
|
||||
rtio::Read => libc::FILE_GENERIC_READ,
|
||||
rtio::Write => libc::FILE_GENERIC_WRITE,
|
||||
rtio::ReadWrite => libc::FILE_GENERIC_READ | libc::FILE_GENERIC_WRITE
|
||||
};
|
||||
|
||||
// libuv has a good comment about this, but the basic idea is what we try to
|
||||
@ -295,15 +280,15 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
|
||||
libc::FILE_SHARE_DELETE;
|
||||
|
||||
let dwCreationDisposition = match (fm, fa) {
|
||||
(io::Truncate, io::Read) => libc::TRUNCATE_EXISTING,
|
||||
(io::Truncate, _) => libc::CREATE_ALWAYS,
|
||||
(io::Open, io::Read) => libc::OPEN_EXISTING,
|
||||
(io::Open, _) => libc::OPEN_ALWAYS,
|
||||
(io::Append, io::Read) => {
|
||||
(rtio::Truncate, rtio::Read) => libc::TRUNCATE_EXISTING,
|
||||
(rtio::Truncate, _) => libc::CREATE_ALWAYS,
|
||||
(rtio::Open, rtio::Read) => libc::OPEN_EXISTING,
|
||||
(rtio::Open, _) => libc::OPEN_ALWAYS,
|
||||
(rtio::Append, rtio::Read) => {
|
||||
dwDesiredAccess |= libc::FILE_APPEND_DATA;
|
||||
libc::OPEN_EXISTING
|
||||
}
|
||||
(io::Append, _) => {
|
||||
(rtio::Append, _) => {
|
||||
dwDesiredAccess &= !libc::FILE_WRITE_DATA;
|
||||
dwDesiredAccess |= libc::FILE_APPEND_DATA;
|
||||
libc::OPEN_ALWAYS
|
||||
@ -338,7 +323,7 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mkdir(p: &CString, _mode: io::FilePermission) -> IoResult<()> {
|
||||
pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
|
||||
super::mkerr_winbool(unsafe {
|
||||
// FIXME: turn mode into something useful? #2623
|
||||
as_utf16_p(p.as_str().unwrap(), |buf| {
|
||||
@ -413,9 +398,9 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
|
||||
pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
|
||||
super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
|
||||
libc::wchmod(p, mode.bits() as libc::c_int)
|
||||
libc::wchmod(p, mode as libc::c_int)
|
||||
}))
|
||||
}
|
||||
|
||||
@ -430,7 +415,7 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn readlink(p: &CString) -> IoResult<Path> {
|
||||
pub fn readlink(p: &CString) -> IoResult<CString> {
|
||||
// FIXME: I have a feeling that this reads intermediate symlinks as well.
|
||||
use io::c::compat::kernel32::GetFinalPathNameByHandleW;
|
||||
let handle = unsafe {
|
||||
@ -457,9 +442,9 @@ pub fn readlink(p: &CString) -> IoResult<Path> {
|
||||
});
|
||||
let ret = match ret {
|
||||
Some(ref s) if s.as_slice().starts_with(r"\\?\") => {
|
||||
Ok(Path::new(s.as_slice().slice_from(4)))
|
||||
Ok(Path::new(s.as_slice().slice_from(4)).to_c_str())
|
||||
}
|
||||
Some(s) => Ok(Path::new(s)),
|
||||
Some(s) => Ok(Path::new(s).to_c_str()),
|
||||
None => Err(super::last_error()),
|
||||
};
|
||||
assert!(unsafe { libc::CloseHandle(handle) } != 0);
|
||||
@ -483,39 +468,28 @@ pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
|
||||
}))
|
||||
}
|
||||
|
||||
fn mkstat(stat: &libc::stat) -> io::FileStat {
|
||||
let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
|
||||
libc::S_IFREG => io::TypeFile,
|
||||
libc::S_IFDIR => io::TypeDirectory,
|
||||
libc::S_IFIFO => io::TypeNamedPipe,
|
||||
libc::S_IFBLK => io::TypeBlockSpecial,
|
||||
libc::S_IFLNK => io::TypeSymlink,
|
||||
_ => io::TypeUnknown,
|
||||
};
|
||||
|
||||
io::FileStat {
|
||||
fn mkstat(stat: &libc::stat) -> rtio::FileStat {
|
||||
rtio::FileStat {
|
||||
size: stat.st_size as u64,
|
||||
kind: kind,
|
||||
perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
|
||||
kind: stat.st_mode as u64,
|
||||
perm: stat.st_mode as u64,
|
||||
created: stat.st_ctime as u64,
|
||||
modified: stat.st_mtime as u64,
|
||||
accessed: stat.st_atime as u64,
|
||||
unstable: io::UnstableFileStat {
|
||||
device: stat.st_dev as u64,
|
||||
inode: stat.st_ino as u64,
|
||||
rdev: stat.st_rdev as u64,
|
||||
nlink: stat.st_nlink as u64,
|
||||
uid: stat.st_uid as u64,
|
||||
gid: stat.st_gid as u64,
|
||||
blksize: 0,
|
||||
blocks: 0,
|
||||
flags: 0,
|
||||
gen: 0,
|
||||
}
|
||||
device: stat.st_dev as u64,
|
||||
inode: stat.st_ino as u64,
|
||||
rdev: stat.st_rdev as u64,
|
||||
nlink: stat.st_nlink as u64,
|
||||
uid: stat.st_uid as u64,
|
||||
gid: stat.st_gid as u64,
|
||||
blksize: 0,
|
||||
blocks: 0,
|
||||
flags: 0,
|
||||
gen: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stat(p: &CString) -> IoResult<io::FileStat> {
|
||||
pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
as_utf16_p(p.as_str().unwrap(), |up| {
|
||||
match unsafe { libc::wstat(up, &mut stat) } {
|
||||
@ -525,7 +499,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &CString) -> IoResult<io::FileStat> {
|
||||
pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
|
||||
// FIXME: implementation is missing
|
||||
Err(super::unimpl())
|
||||
}
|
||||
|
@ -135,10 +135,12 @@ pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn last_error() -> IoError {
|
||||
pub fn last_error() -> IoError {
|
||||
use std::os;
|
||||
let code = unsafe { c::WSAGetLastError() as uint };
|
||||
IoError {
|
||||
code: code,
|
||||
extra: 0,
|
||||
detail: Some(os::error_string(code)),
|
||||
}
|
||||
}
|
||||
@ -225,7 +227,7 @@ pub fn init() {}
|
||||
pub fn init() {
|
||||
|
||||
unsafe {
|
||||
use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
use std::rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
static mut INITIALIZED: bool = false;
|
||||
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||
|
||||
|
@ -87,16 +87,15 @@
|
||||
use alloc::arc::Arc;
|
||||
use libc;
|
||||
use std::c_str::CString;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::win32::as_utf16_p;
|
||||
use std::os;
|
||||
use std::ptr;
|
||||
use std::rt::rtio;
|
||||
use std::rt::rtio::{IoResult, IoError};
|
||||
use std::sync::atomics;
|
||||
use std::unstable::mutex;
|
||||
use std::rt::mutex;
|
||||
|
||||
use super::IoResult;
|
||||
use super::c;
|
||||
use super::util;
|
||||
|
||||
@ -190,6 +189,14 @@ pub fn await(handle: libc::HANDLE, deadline: u64,
|
||||
}
|
||||
}
|
||||
|
||||
fn epipe() -> IoError {
|
||||
IoError {
|
||||
code: libc::ERROR_BROKEN_PIPE as uint,
|
||||
extra: 0,
|
||||
detail: None,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Unix Streams
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -355,7 +362,7 @@ impl rtio::RtioPipe for UnixStream {
|
||||
// See comments in close_read() about why this lock is necessary.
|
||||
let guard = unsafe { self.inner.lock.lock() };
|
||||
if self.read_closed() {
|
||||
return Err(io::standard_error(io::EndOfFile))
|
||||
return Err(util::eof())
|
||||
}
|
||||
|
||||
// Issue a nonblocking requests, succeeding quickly if it happened to
|
||||
@ -403,10 +410,10 @@ impl rtio::RtioPipe for UnixStream {
|
||||
// If the reading half is now closed, then we're done. If we woke up
|
||||
// because the writing half was closed, keep trying.
|
||||
if !succeeded {
|
||||
return Err(io::standard_error(io::TimedOut))
|
||||
return Err(util::timeout("read timed out"))
|
||||
}
|
||||
if self.read_closed() {
|
||||
return Err(io::standard_error(io::EndOfFile))
|
||||
return Err(util::eof())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -431,7 +438,7 @@ impl rtio::RtioPipe for UnixStream {
|
||||
// See comments in close_read() about why this lock is necessary.
|
||||
let guard = unsafe { self.inner.lock.lock() };
|
||||
if self.write_closed() {
|
||||
return Err(io::standard_error(io::BrokenPipe))
|
||||
return Err(epipe())
|
||||
}
|
||||
let ret = unsafe {
|
||||
libc::WriteFile(self.handle(),
|
||||
@ -445,7 +452,11 @@ impl rtio::RtioPipe for UnixStream {
|
||||
|
||||
if ret == 0 {
|
||||
if err != libc::ERROR_IO_PENDING as uint {
|
||||
return Err(io::IoError::from_errno(err, true));
|
||||
return Err(IoError {
|
||||
code: err as uint,
|
||||
extra: 0,
|
||||
detail: Some(os::error_string(err as uint)),
|
||||
})
|
||||
}
|
||||
// Process a timeout if one is pending
|
||||
let succeeded = await(self.handle(), self.write_deadline,
|
||||
@ -466,17 +477,17 @@ impl rtio::RtioPipe for UnixStream {
|
||||
if !succeeded {
|
||||
let amt = offset + bytes_written as uint;
|
||||
return if amt > 0 {
|
||||
Err(io::IoError {
|
||||
kind: io::ShortWrite(amt),
|
||||
desc: "short write during write",
|
||||
detail: None,
|
||||
Err(IoError {
|
||||
code: libc::ERROR_OPERATION_ABORTED as uint,
|
||||
extra: amt,
|
||||
detail: Some("short write during write".to_str()),
|
||||
})
|
||||
} else {
|
||||
Err(util::timeout("write timed out"))
|
||||
}
|
||||
}
|
||||
if self.write_closed() {
|
||||
return Err(io::standard_error(io::BrokenPipe))
|
||||
return Err(epipe())
|
||||
}
|
||||
continue // retry
|
||||
}
|
||||
|
@ -210,23 +210,23 @@ unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
|
||||
if ret == 0 {
|
||||
Err(super::last_error())
|
||||
} else if status != libc::STILL_ACTIVE {
|
||||
Err(io::IoError {
|
||||
kind: io::OtherIoError,
|
||||
desc: "process no longer alive",
|
||||
Err(IoError {
|
||||
code: libc::ERROR_NOTHING_TO_TERMINATE as uint,
|
||||
extra: 0,
|
||||
detail: None,
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
io::process::PleaseExitSignal | io::process::MustDieSignal => {
|
||||
15 | 9 => { // sigterm or sigkill
|
||||
let ret = libc::TerminateProcess(handle, 1);
|
||||
super::mkerr_winbool(ret)
|
||||
}
|
||||
_ => Err(io::IoError {
|
||||
kind: io::OtherIoError,
|
||||
desc: "unsupported signal on windows",
|
||||
detail: None,
|
||||
_ => Err(IoError {
|
||||
code: libc::ERROR_CALL_NOT_IMPLEMENTED as uint,
|
||||
extra: 0,
|
||||
detail: Some("unsupported signal on windows".to_string()),
|
||||
})
|
||||
};
|
||||
let _ = libc::CloseHandle(handle);
|
||||
@ -266,10 +266,10 @@ fn spawn_process_os(cfg: ProcessConfig,
|
||||
use std::mem;
|
||||
|
||||
if cfg.gid.is_some() || cfg.uid.is_some() {
|
||||
return Err(io::IoError {
|
||||
kind: io::OtherIoError,
|
||||
desc: "unsupported gid/uid requested on windows",
|
||||
detail: None,
|
||||
return Err(IoError {
|
||||
code: libc::ERROR_CALL_NOT_IMPLEMENTED as uint,
|
||||
extra: 0,
|
||||
detail: Some("unsupported gid/uid requested on windows".to_str()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,10 @@
|
||||
use libc;
|
||||
use std::ptr;
|
||||
use std::rt::rtio;
|
||||
use std::rt::rtio::{IoResult, Callback};
|
||||
use std::comm;
|
||||
|
||||
use io::helper_thread::Helper;
|
||||
use io::IoResult;
|
||||
|
||||
helper_init!(static mut HELPER: Helper<Req>)
|
||||
|
||||
@ -36,7 +36,7 @@ pub struct Timer {
|
||||
}
|
||||
|
||||
pub enum Req {
|
||||
NewTimer(libc::HANDLE, Sender<()>, bool),
|
||||
NewTimer(libc::HANDLE, Box<Callback:Send>, bool),
|
||||
RemoveTimer(libc::HANDLE, Sender<()>),
|
||||
}
|
||||
|
||||
@ -79,8 +79,8 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) {
|
||||
}
|
||||
} else {
|
||||
let remove = {
|
||||
match chans.get(idx as uint - 1) {
|
||||
&(ref c, oneshot) => c.send_opt(()).is_err() || oneshot
|
||||
match chans.get_mut(idx as uint - 1) {
|
||||
&(ref mut c, oneshot) => { c.call(); oneshot }
|
||||
}
|
||||
};
|
||||
if remove {
|
||||
@ -148,9 +148,8 @@ impl rtio::RtioTimer for Timer {
|
||||
let _ = unsafe { imp::WaitForSingleObject(self.obj, libc::INFINITE) };
|
||||
}
|
||||
|
||||
fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
|
||||
fn oneshot(&mut self, msecs: u64, cb: Box<Callback:Send>) {
|
||||
self.remove();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// see above for the calculation
|
||||
let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER;
|
||||
@ -159,14 +158,12 @@ impl rtio::RtioTimer for Timer {
|
||||
ptr::mut_null(), 0)
|
||||
}, 1);
|
||||
|
||||
unsafe { HELPER.send(NewTimer(self.obj, tx, true)) }
|
||||
unsafe { HELPER.send(NewTimer(self.obj, cb, true)) }
|
||||
self.on_worker = true;
|
||||
return rx;
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64) -> Receiver<()> {
|
||||
fn period(&mut self, msecs: u64, cb: Box<Callback:Send>) {
|
||||
self.remove();
|
||||
let (tx, rx) = channel();
|
||||
|
||||
// see above for the calculation
|
||||
let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER;
|
||||
@ -175,10 +172,8 @@ impl rtio::RtioTimer for Timer {
|
||||
ptr::null(), ptr::mut_null(), 0)
|
||||
}, 1);
|
||||
|
||||
unsafe { HELPER.send(NewTimer(self.obj, tx, false)) }
|
||||
unsafe { HELPER.send(NewTimer(self.obj, cb, false)) }
|
||||
self.on_worker = true;
|
||||
|
||||
return rx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,9 +238,15 @@ impl Container for CString {
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
if self.buf.is_null() { fail!("CString is null!"); }
|
||||
let mut cur = self.buf;
|
||||
let mut len = 0;
|
||||
unsafe {
|
||||
ptr::position(self.buf, |c| *c == 0)
|
||||
while *cur != 0 {
|
||||
len += 1;
|
||||
cur = cur.offset(1);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,7 @@ pub fn init(argc: int, argv: **u8) {
|
||||
// FIXME(#14344) this shouldn't be necessary
|
||||
collections::fixme_14344_be_sure_to_link_to_collections();
|
||||
alloc::fixme_14344_be_sure_to_link_to_collections();
|
||||
libc::issue_14344_workaround();
|
||||
}
|
||||
|
||||
/// Enqueues a procedure to run when the runtime is cleaned up
|
||||
|
@ -95,8 +95,6 @@ type TLSValue = Box<LocalData:Send>;
|
||||
|
||||
// Gets the map from the runtime. Lazily initialises if not done so already.
|
||||
unsafe fn get_local_map() -> Option<&mut Map> {
|
||||
use rt::local::Local;
|
||||
|
||||
if !Local::exists(None::<Task>) { return None }
|
||||
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
|
@ -18,10 +18,11 @@ use core::prelude::*;
|
||||
use alloc::arc::Arc;
|
||||
use alloc::owned::{AnyOwnExt, Box};
|
||||
use core::any::Any;
|
||||
use core::atomics::{AtomicUint, SeqCst};
|
||||
use core::finally::Finally;
|
||||
use core::iter::Take;
|
||||
use core::mem;
|
||||
use core::finally::Finally;
|
||||
use core::atomics::{AtomicUint, SeqCst};
|
||||
use core::raw;
|
||||
|
||||
use local_data;
|
||||
use Runtime;
|
||||
@ -142,18 +143,17 @@ impl Task {
|
||||
// TLS, or possibly some destructors for those objects being
|
||||
// annihilated invoke TLS. Sadly these two operations seemed to
|
||||
// be intertwined, and miraculously work for now...
|
||||
let mut task = Local::borrow(None::<Task>);
|
||||
let storage_map = {
|
||||
drop({
|
||||
let mut task = Local::borrow(None::<Task>);
|
||||
let &LocalStorage(ref mut optmap) = &mut task.storage;
|
||||
optmap.take()
|
||||
};
|
||||
drop(task);
|
||||
drop(storage_map);
|
||||
});
|
||||
|
||||
// Destroy remaining boxes. Also may run user dtors.
|
||||
let mut task = Local::borrow(None::<Task>);
|
||||
let mut heap = mem::replace(&mut task.heap, LocalHeap::new());
|
||||
drop(task);
|
||||
let mut heap = {
|
||||
let mut task = Local::borrow(None::<Task>);
|
||||
mem::replace(&mut task.heap, LocalHeap::new())
|
||||
};
|
||||
unsafe { heap.annihilate() }
|
||||
drop(heap);
|
||||
})
|
||||
@ -202,13 +202,16 @@ impl Task {
|
||||
// crops up.
|
||||
unsafe {
|
||||
let imp = self.imp.take_unwrap();
|
||||
let &(vtable, _): &(uint, uint) = mem::transmute(&imp);
|
||||
let vtable = mem::transmute::<_, &raw::TraitObject>(&imp).vtable;
|
||||
match imp.wrap().move::<T>() {
|
||||
Ok(t) => Some(t),
|
||||
Err(t) => {
|
||||
let (_, obj): (uint, uint) = mem::transmute(t);
|
||||
let data = mem::transmute::<_, raw::TraitObject>(t).data;
|
||||
let obj: Box<Runtime:Send> =
|
||||
mem::transmute((vtable, obj));
|
||||
mem::transmute(raw::TraitObject {
|
||||
vtable: vtable,
|
||||
data: data,
|
||||
});
|
||||
self.put_runtime(obj);
|
||||
None
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ impl Unwinder {
|
||||
self.cause = unsafe { try(f) }.err();
|
||||
}
|
||||
|
||||
pub fn result(&mut self) -> TaskResult {
|
||||
pub fn result(&mut self) -> Result {
|
||||
if self.unwinding {
|
||||
Err(self.cause.take().unwrap())
|
||||
} else {
|
||||
@ -150,10 +150,7 @@ impl Unwinder {
|
||||
/// guaranteed that a rust task is in place when invoking this function.
|
||||
/// Unwinding twice can lead to resource leaks where some destructors are not
|
||||
/// run.
|
||||
pub unsafe fn try(f: ||) -> Result<(), Box<Any:Send>> {
|
||||
use raw::Closure;
|
||||
use libc::{c_void};
|
||||
|
||||
pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any:Send>> {
|
||||
let closure: Closure = mem::transmute(f);
|
||||
let ep = rust_try(try_fn, closure.code as *c_void,
|
||||
closure.env as *c_void);
|
||||
@ -300,7 +297,7 @@ pub mod eabi {
|
||||
#[cfg(target_arch = "arm", not(test))]
|
||||
#[allow(visible_private_types)]
|
||||
pub mod eabi {
|
||||
use uw = rt::libunwind;
|
||||
use uw = libunwind;
|
||||
use libc::c_int;
|
||||
|
||||
extern "C" {
|
||||
@ -432,9 +429,9 @@ fn begin_unwind_inner(msg: Box<Any:Send>,
|
||||
// Now that we've run all the necessary unwind callbacks, we actually
|
||||
// perform the unwinding. If we don't have a task, then it's time to die
|
||||
// (hopefully someone printed something about this).
|
||||
let task: Box<Task> = match Local::try_take() {
|
||||
let mut task: Box<Task> = match Local::try_take() {
|
||||
Some(task) => task,
|
||||
None => unsafe { intrinsics::abort() }
|
||||
None => rust_fail(msg),
|
||||
};
|
||||
|
||||
if task.unwinder.unwinding {
|
||||
@ -445,17 +442,13 @@ fn begin_unwind_inner(msg: Box<Any:Send>,
|
||||
rterrln!("task failed during unwinding. aborting.");
|
||||
unsafe { intrinsics::abort() }
|
||||
}
|
||||
task.unwinder.unwinding = true;
|
||||
|
||||
// Put the task back in TLS because the unwinding process may run code which
|
||||
// requires the task. We need a handle to its unwinder, however, so after
|
||||
// this we unsafely extract it and continue along.
|
||||
Local::put(task);
|
||||
unsafe {
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
(*task).unwinder.begin_unwind(msg);
|
||||
}
|
||||
task.name = name;
|
||||
Local::put(task);
|
||||
rust_fail(msg);
|
||||
}
|
||||
|
||||
/// Register a callback to be invoked when a task unwinds.
|
||||
|
@ -73,9 +73,7 @@ pub fn abort(args: &fmt::Arguments) -> ! {
|
||||
let mut w = BufWriter { buf: msg, pos: 0 };
|
||||
let _ = write!(&mut w, "{}", args);
|
||||
let msg = str::from_utf8(w.buf.slice_to(w.pos)).unwrap_or("aborted");
|
||||
let msg = if msg.is_empty() {
|
||||
"aborted"
|
||||
} else { "aborted" };
|
||||
let msg = if msg.is_empty() {"aborted"} else {msg};
|
||||
|
||||
// Give some context to the message
|
||||
let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
|
||||
|
@ -404,22 +404,23 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
|
||||
let UvError(errcode) = uverr;
|
||||
IoError {
|
||||
code: match errcode {
|
||||
uvll::EOF => io::EOF,
|
||||
uvll::EACCES => io::ERROR_ACCESS_DENIED,
|
||||
uvll::ECONNREFUSED => io::WSAECONNREFUSED,
|
||||
uvll::ECONNRESET => io::WSAECONNRESET,
|
||||
uvll::ENOTCONN => io::WSAENOTCONN,
|
||||
uvll::ENOENT => io::ERROR_NOT_FOUND,
|
||||
uvll::EPIPE => io::ERROR_BROKEN_PIPE,
|
||||
uvll::ECONNABORTED => io::WSAECONNABORTED,
|
||||
uvll::EADDRNOTAVAIL => io::WSAEADDRNOTAVAIL,
|
||||
uvll::EOF => libc::EOF,
|
||||
uvll::EACCES => libc::ERROR_ACCESS_DENIED,
|
||||
uvll::ECONNREFUSED => libc::WSAECONNREFUSED,
|
||||
uvll::ECONNRESET => libc::WSAECONNRESET,
|
||||
uvll::ENOTCONN => libc::WSAENOTCONN,
|
||||
uvll::ENOENT => libc::ERROR_FILE_NOT_FOUND,
|
||||
uvll::EPIPE => libc::ERROR_NO_DATA,
|
||||
uvll::ECONNABORTED => libc::WSAECONNABORTED,
|
||||
uvll::EADDRNOTAVAIL => libc::WSAEADDRNOTAVAIL,
|
||||
uvll::ECANCELED => libc::ERROR_OPERATION_ABORTED,
|
||||
uvll::EADDRINUSE => libc::WSAEADDRINUSE,
|
||||
err => {
|
||||
uvdebug!("uverr.code {}", err as int);
|
||||
// FIXME: Need to map remaining uv error types
|
||||
-1
|
||||
}
|
||||
},
|
||||
} as uint,
|
||||
extra: 0,
|
||||
detail: Some(uverr.desc()),
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ use std::rt::libc_heap::malloc_raw;
|
||||
use libc::uintptr_t;
|
||||
|
||||
pub use self::errors::{EACCES, ECONNREFUSED, ECONNRESET, EPIPE, ECONNABORTED,
|
||||
ECANCELED, EBADF, ENOTCONN, ENOENT, EADDRNOTAVAIL};
|
||||
ECANCELED, EBADF, ENOTCONN, ENOENT, EADDRNOTAVAIL,
|
||||
EADDRINUSE};
|
||||
|
||||
pub static OK: c_int = 0;
|
||||
pub static EOF: c_int = -4095;
|
||||
@ -61,6 +62,7 @@ pub mod errors {
|
||||
pub static ECANCELED: c_int = -4081;
|
||||
pub static EBADF: c_int = -4083;
|
||||
pub static EADDRNOTAVAIL: c_int = -4090;
|
||||
pub static EADDRINUSE: c_int = -4091;
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
pub mod errors {
|
||||
@ -77,6 +79,7 @@ pub mod errors {
|
||||
pub static ECANCELED : c_int = -libc::ECANCELED;
|
||||
pub static EBADF : c_int = -libc::EBADF;
|
||||
pub static EADDRNOTAVAIL : c_int = -libc::EADDRNOTAVAIL;
|
||||
pub static EADDRINUSE : c_int = -libc::EADDRINUSE;
|
||||
}
|
||||
|
||||
pub static PROCESS_SETUID: c_int = 1 << 0;
|
||||
|
@ -313,7 +313,8 @@ impl IoError {
|
||||
libc::ERROR_INVALID_NAME => (InvalidInput, "invalid file name"),
|
||||
libc::WSAECONNREFUSED => (ConnectionRefused, "connection refused"),
|
||||
libc::WSAECONNRESET => (ConnectionReset, "connection reset"),
|
||||
libc::WSAEACCES => (PermissionDenied, "permission denied"),
|
||||
libc::ERROR_ACCESS_DENIED | libc::WSAEACCES =>
|
||||
(PermissionDenied, "permission denied"),
|
||||
libc::WSAEWOULDBLOCK => {
|
||||
(ResourceUnavailable, "resource temporarily unavailable")
|
||||
}
|
||||
@ -327,7 +328,7 @@ impl IoError {
|
||||
libc::WSAEINVAL => (InvalidInput, "invalid argument"),
|
||||
libc::ERROR_CALL_NOT_IMPLEMENTED =>
|
||||
(IoUnavailable, "function not implemented"),
|
||||
libc::ERROR_CALL_NOT_IMPLEMENTED =>
|
||||
libc::ERROR_INVALID_HANDLE =>
|
||||
(MismatchedFileTypeForOperation,
|
||||
"invalid handle provided to function"),
|
||||
libc::ERROR_NOTHING_TO_TERMINATE =>
|
||||
|
@ -982,7 +982,8 @@ mod test {
|
||||
match TcpListener::bind(ip_str.as_slice(), port).listen() {
|
||||
Ok(..) => fail!(),
|
||||
Err(e) => {
|
||||
assert!(e.kind == ConnectionRefused || e.kind == OtherIoError);
|
||||
assert!(e.kind == ConnectionRefused || e.kind == OtherIoError,
|
||||
"unknown error: {} {}", e, e.kind);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -256,11 +256,6 @@ pub mod unstable;
|
||||
pub mod rt;
|
||||
mod failure;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn issue_14344_workaround() { // FIXME #14344 force linkage to happen correctly
|
||||
libc::issue_14344_workaround();
|
||||
}
|
||||
|
||||
// A curious inner-module that's not exported that contains the binding
|
||||
// 'std' so that macro-expanded references to std::error and such
|
||||
// can be resolved within libstd.
|
||||
|
@ -603,6 +603,7 @@ mod imp {
|
||||
mod imp {
|
||||
use c_str::CString;
|
||||
use container::Container;
|
||||
use intrinsics;
|
||||
use io::{IoResult, Writer};
|
||||
use libc;
|
||||
use mem;
|
||||
@ -610,11 +611,10 @@ mod imp {
|
||||
use option::{Some, None};
|
||||
use path::Path;
|
||||
use result::{Ok, Err};
|
||||
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
use slice::ImmutableVector;
|
||||
use str::StrSlice;
|
||||
use unstable::dynamic_lib::DynamicLibrary;
|
||||
use intrinsics;
|
||||
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
use slice::ImmutableVector;
|
||||
|
||||
#[allow(non_snake_case_functions)]
|
||||
extern "system" {
|
||||
|
@ -57,10 +57,11 @@ Several modules in `core` are clients of `rt`:
|
||||
use failure;
|
||||
use rustrt;
|
||||
|
||||
// TODO: dox
|
||||
// Reexport some of our utilities which are expected by other crates.
|
||||
pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
|
||||
|
||||
// TODO: dox
|
||||
// Reexport functionality from librustrt and other crates underneath the
|
||||
// standard library which work together to create the entire runtime.
|
||||
pub use alloc::{heap, libc_heap};
|
||||
pub use rustrt::{task, local, mutex, exclusive, stack, args, rtio};
|
||||
pub use rustrt::{Stdio, Stdout, Stderr, begin_unwind, begin_unwind_fmt};
|
||||
|
@ -182,14 +182,8 @@ impl TaskBuilder {
|
||||
};
|
||||
if stdout.is_some() || stderr.is_some() {
|
||||
t.spawn_sibling(opts, proc() {
|
||||
match stdout {
|
||||
Some(handle) => { let _ = stdio::set_stdout(handle); }
|
||||
None => {}
|
||||
}
|
||||
match stderr {
|
||||
Some(handle) => { let _ = stdio::set_stderr(handle); }
|
||||
None => {}
|
||||
}
|
||||
let _ = stdout.map(stdio::set_stdout);
|
||||
let _ = stderr.map(stdio::set_stderr);
|
||||
f();
|
||||
});
|
||||
} else {
|
||||
|
@ -64,7 +64,7 @@ use std::rt::task::{BlockedTask, Task};
|
||||
use std::rt::thread::Thread;
|
||||
use std::sync::atomics;
|
||||
use std::ty::Unsafe;
|
||||
use std::unstable::mutex;
|
||||
use std::rt::mutex;
|
||||
|
||||
use q = mpsc_intrusive;
|
||||
|
||||
|
@ -28,7 +28,7 @@ fn start(argc: int, argv: **u8) -> int {
|
||||
4 => assert!(try(|| fail!()).is_err()),
|
||||
5 => assert!(try(|| spawn(proc() {})).is_err()),
|
||||
6 => assert!(Command::new("test").spawn().is_err()),
|
||||
7 => assert!(foo.get().is_some()),
|
||||
7 => assert!(foo.get().is_none()),
|
||||
8 => assert!(try(|| { foo.replace(Some(3)); }).is_err()),
|
||||
_ => fail!()
|
||||
}
|
||||
@ -49,6 +49,8 @@ fn main() {
|
||||
pass(Command::new(me).arg(&[4u8]).output().unwrap());
|
||||
pass(Command::new(me).arg(&[5u8]).output().unwrap());
|
||||
pass(Command::new(me).arg(&[6u8]).output().unwrap());
|
||||
pass(Command::new(me).arg(&[7u8]).output().unwrap());
|
||||
pass(Command::new(me).arg(&[8u8]).output().unwrap());
|
||||
}
|
||||
|
||||
fn pass(output: ProcessOutput) {
|
||||
|
@ -61,7 +61,7 @@ fn main() {
|
||||
for _ in range(0, 1000) {
|
||||
let tx = tx.clone();
|
||||
let mut builder = TaskBuilder::new();
|
||||
builder.opts.stack_size = Some(32 * 1024);
|
||||
builder.opts.stack_size = Some(64 * 1024);
|
||||
builder.spawn(proc() {
|
||||
let host = addr.ip.to_str();
|
||||
let port = addr.port;
|
||||
|
Loading…
Reference in New Issue
Block a user