Skip to content

Commit 55dda46

Browse files
author
Eric Reed
committed
Merge remote-tracking branch 'upstream/io' into io
2 parents 36c0e04 + b548c78 commit 55dda46

File tree

8 files changed

+249
-83
lines changed

8 files changed

+249
-83
lines changed

src/libstd/macros.rs

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,16 @@
1010

1111
#[macro_escape];
1212

13+
macro_rules! rterrln (
14+
($( $arg:expr),+) => ( {
15+
::rt::util::dumb_println(fmt!( $($arg),+ ));
16+
} )
17+
)
18+
1319
// Some basic logging
1420
macro_rules! rtdebug_ (
1521
($( $arg:expr),+) => ( {
16-
dumb_println(fmt!( $($arg),+ ));
17-
18-
fn dumb_println(s: &str) {
19-
use io::WriterUtil;
20-
let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
21-
dbg.write_str(s);
22-
dbg.write_str("\n");
23-
}
24-
22+
rterrln!( $($arg),+ )
2523
} )
2624
)
2725

@@ -33,24 +31,15 @@ macro_rules! rtdebug (
3331
macro_rules! rtassert (
3432
( $arg:expr ) => ( {
3533
if !$arg {
36-
abort!("assertion failed: %s", stringify!($arg));
34+
rtabort!("assertion failed: %s", stringify!($arg));
3735
}
3836
} )
3937
)
4038

4139

42-
// The do_abort function was originally inside the abort macro, but
43-
// this was ICEing the compiler so it has been moved outside. Now this
44-
// seems to work?
45-
#[allow(missing_doc)]
46-
pub fn do_abort() -> ! {
47-
unsafe { ::libc::abort(); }
48-
}
49-
50-
macro_rules! abort(
40+
macro_rules! rtabort(
5141
($( $msg:expr),+) => ( {
52-
rtdebug!($($msg),+);
53-
::macros::do_abort();
42+
::rt::util::abort(fmt!($($msg),+));
5443
} )
5544
)
5645

src/libstd/rt/global_heap.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use c_malloc = libc::malloc;
1414
use c_free = libc::free;
1515
use managed::raw::{BoxHeaderRepr, BoxRepr};
1616
use cast::transmute;
17-
use unstable::intrinsics::{atomic_xadd,atomic_xsub};
17+
use unstable::intrinsics::{atomic_xadd,atomic_xsub, atomic_load};
1818
use ptr::null;
1919
use intrinsic::TyDesc;
2020

@@ -34,8 +34,7 @@ pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
3434
box.header.prev = null();
3535
box.header.next = null();
3636

37-
let exchange_count = &mut *exchange_count_ptr();
38-
atomic_xadd(exchange_count, 1);
37+
inc_count();
3938

4039
return transmute(box);
4140
}
@@ -48,21 +47,46 @@ pub unsafe fn malloc_raw(size: uint) -> *c_void {
4847
if p.is_null() {
4948
fail!("Failure in malloc_raw: result ptr is null");
5049
}
50+
inc_count();
5151
p
5252
}
5353

5454
pub unsafe fn free(ptr: *c_void) {
55-
let exchange_count = &mut *exchange_count_ptr();
56-
atomic_xsub(exchange_count, 1);
57-
5855
assert!(ptr.is_not_null());
56+
dec_count();
5957
c_free(ptr);
6058
}
6159
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
6260
pub unsafe fn free_raw(ptr: *c_void) {
61+
assert!(ptr.is_not_null());
62+
dec_count();
6363
c_free(ptr);
6464
}
6565

66+
fn inc_count() {
67+
unsafe {
68+
let exchange_count = &mut *exchange_count_ptr();
69+
atomic_xadd(exchange_count, 1);
70+
}
71+
}
72+
73+
fn dec_count() {
74+
unsafe {
75+
let exchange_count = &mut *exchange_count_ptr();
76+
atomic_xsub(exchange_count, 1);
77+
}
78+
}
79+
80+
pub fn cleanup() {
81+
unsafe {
82+
let count_ptr = exchange_count_ptr();
83+
let allocations = atomic_load(&*count_ptr);
84+
if allocations != 0 {
85+
rtabort!("exchange heap not empty on exit - %i dangling allocations", allocations);
86+
}
87+
}
88+
}
89+
6690
fn get_box_size(body_size: uint, body_align: uint) -> uint {
6791
let header_size = size_of::<BoxHeaderRepr>();
6892
// FIXME (#2699): This alignment calculation is suspicious. Is it right?

src/libstd/rt/local.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,25 @@ impl Local for Scheduler {
3838
}
3939
match res {
4040
Some(r) => { r }
41-
None => abort!("function failed!")
41+
None => rtabort!("function failed!")
4242
}
4343
}
4444
unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() }
45-
unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { abort!("unimpl") }
45+
unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { rtabort!("unimpl") }
4646
}
4747

4848
impl Local for Task {
49-
fn put(_value: ~Task) { abort!("unimpl") }
50-
fn take() -> ~Task { abort!("unimpl") }
51-
fn exists() -> bool { abort!("unimpl") }
49+
fn put(_value: ~Task) { rtabort!("unimpl") }
50+
fn take() -> ~Task { rtabort!("unimpl") }
51+
fn exists() -> bool { rtabort!("unimpl") }
5252
fn borrow<T>(f: &fn(&mut Task) -> T) -> T {
5353
do Local::borrow::<Scheduler, T> |sched| {
5454
match sched.current_task {
5555
Some(~ref mut task) => {
5656
f(&mut *task.task)
5757
}
5858
None => {
59-
abort!("no scheduler")
59+
rtabort!("no scheduler")
6060
}
6161
}
6262
}
@@ -69,7 +69,7 @@ impl Local for Task {
6969
}
7070
None => {
7171
// Don't fail. Infinite recursion
72-
abort!("no scheduler")
72+
rtabort!("no scheduler")
7373
}
7474
}
7575
}
@@ -84,16 +84,16 @@ impl Local for Task {
8484

8585
// XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer
8686
impl Local for IoFactoryObject {
87-
fn put(_value: ~IoFactoryObject) { abort!("unimpl") }
88-
fn take() -> ~IoFactoryObject { abort!("unimpl") }
89-
fn exists() -> bool { abort!("unimpl") }
90-
fn borrow<T>(_f: &fn(&mut IoFactoryObject) -> T) -> T { abort!("unimpl") }
87+
fn put(_value: ~IoFactoryObject) { rtabort!("unimpl") }
88+
fn take() -> ~IoFactoryObject { rtabort!("unimpl") }
89+
fn exists() -> bool { rtabort!("unimpl") }
90+
fn borrow<T>(_f: &fn(&mut IoFactoryObject) -> T) -> T { rtabort!("unimpl") }
9191
unsafe fn unsafe_borrow() -> *mut IoFactoryObject {
9292
let sched = Local::unsafe_borrow::<Scheduler>();
9393
let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap();
9494
return io;
9595
}
96-
unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { abort!("unimpl") }
96+
unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { rtabort!("unimpl") }
9797
}
9898

9999
#[cfg(test)]

src/libstd/rt/local_ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub unsafe fn unsafe_borrow<T>() -> *mut T {
109109
fn tls_key() -> tls::Key {
110110
match maybe_tls_key() {
111111
Some(key) => key,
112-
None => abort!("runtime tls key not initialized")
112+
None => rtabort!("runtime tls key not initialized")
113113
}
114114
}
115115

src/libstd/rt/mod.rs

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,21 @@ Several modules in `core` are clients of `rt`:
6060
#[deny(unused_variable)];
6161

6262
use cell::Cell;
63+
use clone::Clone;
64+
use container::Container;
65+
use from_str::FromStr;
66+
use iterator::IteratorUtil;
67+
use option::{Some, None};
68+
use os;
6369
use ptr::RawPtr;
70+
use uint;
71+
use rt::sched::{Scheduler, Coroutine, Shutdown};
72+
use rt::sleeper_list::SleeperList;
73+
use rt::task::Task;
74+
use rt::thread::Thread;
75+
use rt::work_queue::WorkQueue;
76+
use rt::uv::uvio::UvEventLoop;
77+
use vec::{OwnedVector, MutableVector};
6478

6579
/// The global (exchange) heap.
6680
pub mod global_heap;
@@ -139,6 +153,9 @@ pub mod join_latch;
139153

140154
pub mod metrics;
141155

156+
// FIXME #5248 shouldn't be pub
157+
/// Just stuff
158+
pub mod util;
142159

143160
/// Set up a default runtime configuration, given compiler-supplied arguments.
144161
///
@@ -156,22 +173,9 @@ pub mod metrics;
156173
/// The return value is used as the process return code. 0 on success, 101 on error.
157174
pub fn start(_argc: int, _argv: **u8, crate_map: *u8, main: ~fn()) -> int {
158175

159-
use self::sched::{Scheduler, Coroutine};
160-
use self::work_queue::WorkQueue;
161-
use self::uv::uvio::UvEventLoop;
162-
use self::sleeper_list::SleeperList;
163-
164176
init(crate_map);
165-
166-
let loop_ = ~UvEventLoop::new();
167-
let work_queue = WorkQueue::new();
168-
let sleepers = SleeperList::new();
169-
let mut sched = ~Scheduler::new(loop_, work_queue, sleepers);
170-
sched.no_sleep = true;
171-
let main_task = ~Coroutine::new_root(&mut sched.stack_pool, main);
172-
173-
sched.enqueue_task(main_task);
174-
sched.run();
177+
run(main);
178+
cleanup();
175179

176180
return 0;
177181
}
@@ -182,6 +186,71 @@ pub fn init(crate_map: *u8) {
182186
logging::init(crate_map);
183187
}
184188

189+
pub fn cleanup() {
190+
global_heap::cleanup();
191+
}
192+
193+
pub fn run(main: ~fn()) {
194+
let nthreads = match os::getenv("RUST_THREADS") {
195+
Some(nstr) => FromStr::from_str(nstr).get(),
196+
None => unsafe {
197+
// Using more threads than cores in test code
198+
// to force the OS to preempt them frequently.
199+
// Assuming that this help stress test concurrent types.
200+
util::num_cpus() * 2
201+
}
202+
};
203+
204+
let sleepers = SleeperList::new();
205+
let work_queue = WorkQueue::new();
206+
207+
let mut handles = ~[];
208+
let mut scheds = ~[];
209+
210+
for uint::range(0, nthreads) |_| {
211+
let loop_ = ~UvEventLoop::new();
212+
let mut sched = ~Scheduler::new(loop_, work_queue.clone(), sleepers.clone());
213+
let handle = sched.make_handle();
214+
215+
handles.push(handle);
216+
scheds.push(sched);
217+
}
218+
219+
let main_cell = Cell::new(main);
220+
let handles = Cell::new(handles);
221+
let mut new_task = ~Task::new_root();
222+
let on_exit: ~fn(bool) = |exit_status| {
223+
224+
let mut handles = handles.take();
225+
// Tell schedulers to exit
226+
for handles.mut_iter().advance |handle| {
227+
handle.send(Shutdown);
228+
}
229+
230+
rtassert!(exit_status);
231+
};
232+
new_task.on_exit = Some(on_exit);
233+
let main_task = ~Coroutine::with_task(&mut scheds[0].stack_pool,
234+
new_task, main_cell.take());
235+
scheds[0].enqueue_task(main_task);
236+
237+
let mut threads = ~[];
238+
239+
while !scheds.is_empty() {
240+
let sched = scheds.pop();
241+
let sched_cell = Cell::new(sched);
242+
let thread = do Thread::start {
243+
let sched = sched_cell.take();
244+
sched.run();
245+
};
246+
247+
threads.push(thread);
248+
}
249+
250+
// Wait for schedulers
251+
let _threads = threads;
252+
}
253+
185254
/// Possible contexts in which Rust code may be executing.
186255
/// Different runtime services are available depending on context.
187256
/// Mostly used for determining if we're using the new scheduler

0 commit comments

Comments
 (0)