std: Allow spawners to specify stack size

This commit is contained in:
Brian Anderson 2013-08-05 13:10:08 -07:00
parent f82da818a7
commit ae1ed4fd78
7 changed files with 61 additions and 49 deletions

View file

@ -126,6 +126,7 @@ impl Local for IoFactoryObject {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use option::None;
use unstable::run_in_bare_thread; use unstable::run_in_bare_thread;
use rt::test::*; use rt::test::*;
use super::*; use super::*;
@ -137,7 +138,7 @@ mod test {
do run_in_bare_thread { do run_in_bare_thread {
local_ptr::init_tls_key(); local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched(); let mut sched = ~new_test_uv_sched();
let task = ~Task::new_root(&mut sched.stack_pool, || {}); let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task); Local::put(task);
let task: ~Task = Local::take(); let task: ~Task = Local::take();
cleanup_task(task); cleanup_task(task);
@ -149,11 +150,11 @@ mod test {
do run_in_bare_thread { do run_in_bare_thread {
local_ptr::init_tls_key(); local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched(); let mut sched = ~new_test_uv_sched();
let task = ~Task::new_root(&mut sched.stack_pool, || {}); let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task); Local::put(task);
let task: ~Task = Local::take(); let task: ~Task = Local::take();
cleanup_task(task); cleanup_task(task);
let task = ~Task::new_root(&mut sched.stack_pool, || {}); let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task); Local::put(task);
let task: ~Task = Local::take(); let task: ~Task = Local::take();
cleanup_task(task); cleanup_task(task);
@ -166,7 +167,7 @@ mod test {
do run_in_bare_thread { do run_in_bare_thread {
local_ptr::init_tls_key(); local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched(); let mut sched = ~new_test_uv_sched();
let task = ~Task::new_root(&mut sched.stack_pool, || {}); let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task); Local::put(task);
unsafe { unsafe {
@ -182,7 +183,7 @@ mod test {
do run_in_bare_thread { do run_in_bare_thread {
local_ptr::init_tls_key(); local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched(); let mut sched = ~new_test_uv_sched();
let task = ~Task::new_root(&mut sched.stack_pool, || {}); let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task); Local::put(task);
let res = do Local::borrow::<Task,bool> |_task| { let res = do Local::borrow::<Task,bool> |_task| {

View file

@ -331,8 +331,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
// In the case where we do not use a main_thread scheduler we // In the case where we do not use a main_thread scheduler we
// run the main task in one of our threads. // run the main task in one of our threads.
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, None, main.take());
main.take());
main_task.death.on_exit = Some(on_exit.take()); main_task.death.on_exit = Some(on_exit.take());
let main_task_cell = Cell::new(main_task); let main_task_cell = Cell::new(main_task);
@ -352,7 +351,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
let sched_cell = Cell::new(sched); let sched_cell = Cell::new(sched);
let thread = do Thread::start { let thread = do Thread::start {
let mut sched = sched_cell.take(); let mut sched = sched_cell.take();
let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool) || { let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool, None) || {
rtdebug!("boostraping a non-primary scheduler"); rtdebug!("boostraping a non-primary scheduler");
}; };
sched.bootstrap(bootstrap_task); sched.bootstrap(bootstrap_task);
@ -369,7 +368,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
let mut main_sched = main_sched.unwrap(); let mut main_sched = main_sched.unwrap();
let home = Sched(main_sched.make_handle()); let home = Sched(main_sched.make_handle());
let mut main_task = ~Task::new_root_homed(&mut main_sched.stack_pool, let mut main_task = ~Task::new_root_homed(&mut main_sched.stack_pool, None,
home, main.take()); home, main.take());
main_task.death.on_exit = Some(on_exit.take()); main_task.death.on_exit = Some(on_exit.take());
rtdebug!("boostrapping main_task"); rtdebug!("boostrapping main_task");

View file

@ -833,7 +833,7 @@ mod test {
let mut sched = ~new_test_uv_sched(); let mut sched = ~new_test_uv_sched();
let sched_handle = sched.make_handle(); let sched_handle = sched.make_handle();
let mut task = ~do Task::new_root_homed(&mut sched.stack_pool, let mut task = ~do Task::new_root_homed(&mut sched.stack_pool, None,
Sched(sched_handle)) { Sched(sched_handle)) {
unsafe { *task_ran_ptr = true }; unsafe { *task_ran_ptr = true };
assert!(Task::on_appropriate_sched()); assert!(Task::on_appropriate_sched());
@ -893,21 +893,21 @@ mod test {
// 3) task not homed, sched requeues // 3) task not homed, sched requeues
// 4) task not home, send home // 4) task not home, send home
let task1 = ~do Task::new_root_homed(&mut special_sched.stack_pool, let task1 = ~do Task::new_root_homed(&mut special_sched.stack_pool, None,
Sched(t1_handle)) || { Sched(t1_handle)) || {
rtassert!(Task::on_appropriate_sched()); rtassert!(Task::on_appropriate_sched());
}; };
rtdebug!("task1 id: **%u**", borrow::to_uint(task1)); rtdebug!("task1 id: **%u**", borrow::to_uint(task1));
let task2 = ~do Task::new_root(&mut normal_sched.stack_pool) { let task2 = ~do Task::new_root(&mut normal_sched.stack_pool, None) {
rtassert!(Task::on_appropriate_sched()); rtassert!(Task::on_appropriate_sched());
}; };
let task3 = ~do Task::new_root(&mut normal_sched.stack_pool) { let task3 = ~do Task::new_root(&mut normal_sched.stack_pool, None) {
rtassert!(Task::on_appropriate_sched()); rtassert!(Task::on_appropriate_sched());
}; };
let task4 = ~do Task::new_root_homed(&mut special_sched.stack_pool, let task4 = ~do Task::new_root_homed(&mut special_sched.stack_pool, None,
Sched(t4_handle)) { Sched(t4_handle)) {
rtassert!(Task::on_appropriate_sched()); rtassert!(Task::on_appropriate_sched());
}; };
@ -923,7 +923,7 @@ mod test {
let port = Cell::new(port); let port = Cell::new(port);
let chan = Cell::new(chan); let chan = Cell::new(chan);
let normal_task = ~do Task::new_root(&mut normal_sched.stack_pool) { let normal_task = ~do Task::new_root(&mut normal_sched.stack_pool, None) {
rtdebug!("*about to submit task2*"); rtdebug!("*about to submit task2*");
Scheduler::run_task(task2.take()); Scheduler::run_task(task2.take());
rtdebug!("*about to submit task4*"); rtdebug!("*about to submit task4*");
@ -938,7 +938,7 @@ mod test {
rtdebug!("normal task: %u", borrow::to_uint(normal_task)); rtdebug!("normal task: %u", borrow::to_uint(normal_task));
let special_task = ~do Task::new_root(&mut special_sched.stack_pool) { let special_task = ~do Task::new_root(&mut special_sched.stack_pool, None) {
rtdebug!("*about to submit task1*"); rtdebug!("*about to submit task1*");
Scheduler::run_task(task1.take()); Scheduler::run_task(task1.take());
rtdebug!("*about to submit task3*"); rtdebug!("*about to submit task3*");

View file

@ -86,12 +86,13 @@ impl Task {
// A helper to build a new task using the dynamically found // A helper to build a new task using the dynamically found
// scheduler and task. Only works in GreenTask context. // scheduler and task. Only works in GreenTask context.
pub fn build_homed_child(f: ~fn(), home: SchedHome) -> ~Task { pub fn build_homed_child(stack_size: Option<uint>, f: ~fn(), home: SchedHome) -> ~Task {
let f = Cell::new(f); let f = Cell::new(f);
let home = Cell::new(home); let home = Cell::new(home);
do Local::borrow::<Task, ~Task> |running_task| { do Local::borrow::<Task, ~Task> |running_task| {
let mut sched = running_task.sched.take_unwrap(); let mut sched = running_task.sched.take_unwrap();
let new_task = ~running_task.new_child_homed(&mut sched.stack_pool, let new_task = ~running_task.new_child_homed(&mut sched.stack_pool,
stack_size,
home.take(), home.take(),
f.take()); f.take());
running_task.sched = Some(sched); running_task.sched = Some(sched);
@ -99,25 +100,26 @@ impl Task {
} }
} }
pub fn build_child(f: ~fn()) -> ~Task { pub fn build_child(stack_size: Option<uint>, f: ~fn()) -> ~Task {
Task::build_homed_child(f, AnySched) Task::build_homed_child(stack_size, f, AnySched)
} }
pub fn build_homed_root(f: ~fn(), home: SchedHome) -> ~Task { pub fn build_homed_root(stack_size: Option<uint>, f: ~fn(), home: SchedHome) -> ~Task {
let f = Cell::new(f); let f = Cell::new(f);
let home = Cell::new(home); let home = Cell::new(home);
do Local::borrow::<Task, ~Task> |running_task| { do Local::borrow::<Task, ~Task> |running_task| {
let mut sched = running_task.sched.take_unwrap(); let mut sched = running_task.sched.take_unwrap();
let new_task = ~Task::new_root_homed(&mut sched.stack_pool, let new_task = ~Task::new_root_homed(&mut sched.stack_pool,
home.take(), stack_size,
f.take()); home.take(),
f.take());
running_task.sched = Some(sched); running_task.sched = Some(sched);
new_task new_task
} }
} }
pub fn build_root(f: ~fn()) -> ~Task { pub fn build_root(stack_size: Option<uint>, f: ~fn()) -> ~Task {
Task::build_homed_root(f, AnySched) Task::build_homed_root(stack_size, f, AnySched)
} }
pub fn new_sched_task() -> Task { pub fn new_sched_task() -> Task {
@ -138,17 +140,20 @@ impl Task {
} }
pub fn new_root(stack_pool: &mut StackPool, pub fn new_root(stack_pool: &mut StackPool,
stack_size: Option<uint>,
start: ~fn()) -> Task { start: ~fn()) -> Task {
Task::new_root_homed(stack_pool, AnySched, start) Task::new_root_homed(stack_pool, stack_size, AnySched, start)
} }
pub fn new_child(&mut self, pub fn new_child(&mut self,
stack_pool: &mut StackPool, stack_pool: &mut StackPool,
stack_size: Option<uint>,
start: ~fn()) -> Task { start: ~fn()) -> Task {
self.new_child_homed(stack_pool, AnySched, start) self.new_child_homed(stack_pool, stack_size, AnySched, start)
} }
pub fn new_root_homed(stack_pool: &mut StackPool, pub fn new_root_homed(stack_pool: &mut StackPool,
stack_size: Option<uint>,
home: SchedHome, home: SchedHome,
start: ~fn()) -> Task { start: ~fn()) -> Task {
Task { Task {
@ -161,7 +166,7 @@ impl Task {
death: Death::new(), death: Death::new(),
destroyed: false, destroyed: false,
name: None, name: None,
coroutine: Some(Coroutine::new(stack_pool, start)), coroutine: Some(Coroutine::new(stack_pool, stack_size, start)),
sched: None, sched: None,
task_type: GreenTask(Some(~home)) task_type: GreenTask(Some(~home))
} }
@ -169,6 +174,7 @@ impl Task {
pub fn new_child_homed(&mut self, pub fn new_child_homed(&mut self,
stack_pool: &mut StackPool, stack_pool: &mut StackPool,
stack_size: Option<uint>,
home: SchedHome, home: SchedHome,
start: ~fn()) -> Task { start: ~fn()) -> Task {
Task { Task {
@ -182,7 +188,7 @@ impl Task {
death: self.death.new_child(), death: self.death.new_child(),
destroyed: false, destroyed: false,
name: None, name: None,
coroutine: Some(Coroutine::new(stack_pool, start)), coroutine: Some(Coroutine::new(stack_pool, stack_size, start)),
sched: None, sched: None,
task_type: GreenTask(Some(~home)) task_type: GreenTask(Some(~home))
} }
@ -326,8 +332,11 @@ impl Drop for Task {
impl Coroutine { impl Coroutine {
pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine { pub fn new(stack_pool: &mut StackPool, stack_size: Option<uint>, start: ~fn()) -> Coroutine {
let stack_size = env::min_stack(); let stack_size = match stack_size {
Some(size) => size,
None => env::min_stack()
};
let start = Coroutine::build_start_wrapper(start); let start = Coroutine::build_start_wrapper(start);
let mut stack = stack_pool.take_segment(stack_size); let mut stack = stack_pool.take_segment(stack_size);
let initial_context = Context::new(start, &mut stack); let initial_context = Context::new(start, &mut stack);

View file

@ -57,7 +57,7 @@ pub fn run_in_newsched_task_core(f: ~fn()) {
exit_handle.take().send(Shutdown); exit_handle.take().send(Shutdown);
rtassert!(exit_status); rtassert!(exit_status);
}; };
let mut task = ~Task::new_root(&mut sched.stack_pool, f); let mut task = ~Task::new_root(&mut sched.stack_pool, None, f);
task.death.on_exit = Some(on_exit); task.death.on_exit = Some(on_exit);
sched.bootstrap(task); sched.bootstrap(task);
@ -190,8 +190,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
rtassert!(exit_status); rtassert!(exit_status);
}; };
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, None, f.take());
f.take());
main_task.death.on_exit = Some(on_exit); main_task.death.on_exit = Some(on_exit);
let mut threads = ~[]; let mut threads = ~[];
@ -209,7 +208,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
while !scheds.is_empty() { while !scheds.is_empty() {
let mut sched = scheds.pop(); let mut sched = scheds.pop();
let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool) || { let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool, None) || {
rtdebug!("bootstrapping non-primary scheduler"); rtdebug!("bootstrapping non-primary scheduler");
}; };
let bootstrap_task_cell = Cell::new(bootstrap_task); let bootstrap_task_cell = Cell::new(bootstrap_task);
@ -232,12 +231,12 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
/// Test tasks will abort on failure instead of unwinding /// Test tasks will abort on failure instead of unwinding
pub fn spawntask(f: ~fn()) { pub fn spawntask(f: ~fn()) {
Scheduler::run_task(Task::build_child(f)); Scheduler::run_task(Task::build_child(None, f));
} }
/// Create a new task and run it right now. Aborts on failure /// Create a new task and run it right now. Aborts on failure
pub fn spawntask_later(f: ~fn()) { pub fn spawntask_later(f: ~fn()) {
Scheduler::run_task_later(Task::build_child(f)); Scheduler::run_task_later(Task::build_child(None, f));
} }
pub fn spawntask_random(f: ~fn()) { pub fn spawntask_random(f: ~fn()) {
@ -259,7 +258,7 @@ pub fn spawntask_try(f: ~fn()) -> Result<(),()> {
let chan = Cell::new(chan); let chan = Cell::new(chan);
let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status); let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status);
let mut new_task = Task::build_root(f); let mut new_task = Task::build_root(None, f);
new_task.death.on_exit = Some(on_exit); new_task.death.on_exit = Some(on_exit);
Scheduler::run_task(new_task); Scheduler::run_task(new_task);
@ -285,7 +284,7 @@ pub fn spawntask_thread(f: ~fn()) -> Thread {
pub fn with_test_task(blk: ~fn(~Task) -> ~Task) { pub fn with_test_task(blk: ~fn(~Task) -> ~Task) {
do run_in_bare_thread { do run_in_bare_thread {
let mut sched = ~new_test_uv_sched(); let mut sched = ~new_test_uv_sched();
let task = blk(~Task::new_root(&mut sched.stack_pool, ||{})); let task = blk(~Task::new_root(&mut sched.stack_pool, None, ||{}));
cleanup_task(task); cleanup_task(task);
} }
} }

View file

@ -142,7 +142,8 @@ pub struct TaskOpts {
indestructible: bool, indestructible: bool,
notify_chan: Option<Chan<TaskResult>>, notify_chan: Option<Chan<TaskResult>>,
name: Option<~str>, name: Option<~str>,
sched: SchedOpts sched: SchedOpts,
stack_size: Option<uint>
} }
/** /**
@ -197,7 +198,8 @@ impl TaskBuilder {
indestructible: self.opts.indestructible, indestructible: self.opts.indestructible,
notify_chan: notify_chan, notify_chan: notify_chan,
name: name, name: name,
sched: self.opts.sched sched: self.opts.sched,
stack_size: self.opts.stack_size
}, },
gen_body: gen_body, gen_body: gen_body,
can_not_copy: None, can_not_copy: None,
@ -351,7 +353,8 @@ impl TaskBuilder {
indestructible: x.opts.indestructible, indestructible: x.opts.indestructible,
notify_chan: notify_chan, notify_chan: notify_chan,
name: name, name: name,
sched: x.opts.sched sched: x.opts.sched,
stack_size: x.opts.stack_size
}; };
let f = match gen_body { let f = match gen_body {
Some(gen) => { Some(gen) => {
@ -422,7 +425,8 @@ pub fn default_task_opts() -> TaskOpts {
name: None, name: None,
sched: SchedOpts { sched: SchedOpts {
mode: DefaultScheduler, mode: DefaultScheduler,
} },
stack_size: None
} }
} }

View file

@ -713,9 +713,9 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
let mut task = unsafe { let mut task = unsafe {
if opts.sched.mode != SingleThreaded { if opts.sched.mode != SingleThreaded {
if opts.watched { if opts.watched {
Task::build_child(child_wrapper) Task::build_child(opts.stack_size, child_wrapper)
} else { } else {
Task::build_root(child_wrapper) Task::build_root(opts.stack_size, child_wrapper)
} }
} else { } else {
// Creating a 1:1 task:thread ... // Creating a 1:1 task:thread ...
@ -736,16 +736,16 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
// Pin the new task to the new scheduler // Pin the new task to the new scheduler
let new_task = if opts.watched { let new_task = if opts.watched {
Task::build_homed_child(child_wrapper, Sched(new_sched_handle)) Task::build_homed_child(opts.stack_size, child_wrapper, Sched(new_sched_handle))
} else { } else {
Task::build_homed_root(child_wrapper, Sched(new_sched_handle)) Task::build_homed_root(opts.stack_size, child_wrapper, Sched(new_sched_handle))
}; };
// Create a task that will later be used to join with the new scheduler // Create a task that will later be used to join with the new scheduler
// thread when it is ready to terminate // thread when it is ready to terminate
let (thread_port, thread_chan) = oneshot(); let (thread_port, thread_chan) = oneshot();
let thread_port_cell = Cell::new(thread_port); let thread_port_cell = Cell::new(thread_port);
let join_task = do Task::build_child() { let join_task = do Task::build_child(None) {
rtdebug!("running join task"); rtdebug!("running join task");
let thread_port = thread_port_cell.take(); let thread_port = thread_port_cell.take();
let thread: Thread = thread_port.recv(); let thread: Thread = thread_port.recv();
@ -762,8 +762,8 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
let mut orig_sched_handle = orig_sched_handle_cell.take(); let mut orig_sched_handle = orig_sched_handle_cell.take();
let join_task = join_task_cell.take(); let join_task = join_task_cell.take();
let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool) || { let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool, None) || {
rtdebug!("bootstrapping a 1:1 scheduler"); rtdebug!("boostrapping a 1:1 scheduler");
}; };
new_sched.bootstrap(bootstrap_task); new_sched.bootstrap(bootstrap_task);