Skip to content

Commit 5b2dc52

Browse files
committed
std::rt: Turn on multithreaded scheduling
1 parent b5fbec9 commit 5b2dc52

File tree

1 file changed

+76
-16
lines changed

1 file changed

+76
-16
lines changed

src/libstd/rt/mod.rs

Lines changed: 76 additions & 16 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;
@@ -159,23 +173,8 @@ pub mod util;
159173
/// The return value is used as the process return code. 0 on success, 101 on error.
160174
pub fn start(_argc: int, _argv: **u8, crate_map: *u8, main: ~fn()) -> int {
161175

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

181180
return 0;
@@ -191,6 +190,67 @@ pub fn cleanup() {
191190
global_heap::cleanup();
192191
}
193192

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+
194254
/// Possible contexts in which Rust code may be executing.
195255
/// Different runtime services are available depending on context.
196256
/// Mostly used for determining if we're using the new scheduler

0 commit comments

Comments
 (0)