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)]
mod test {
use option::None;
use unstable::run_in_bare_thread;
use rt::test::*;
use super::*;
@ -137,7 +138,7 @@ mod test {
do run_in_bare_thread {
local_ptr::init_tls_key();
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);
let task: ~Task = Local::take();
cleanup_task(task);
@ -149,11 +150,11 @@ mod test {
do run_in_bare_thread {
local_ptr::init_tls_key();
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);
let task: ~Task = Local::take();
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);
let task: ~Task = Local::take();
cleanup_task(task);
@ -166,7 +167,7 @@ mod test {
do run_in_bare_thread {
local_ptr::init_tls_key();
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);
unsafe {
@ -182,7 +183,7 @@ mod test {
do run_in_bare_thread {
local_ptr::init_tls_key();
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);
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
// run the main task in one of our threads.
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
main.take());
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, None, main.take());
main_task.death.on_exit = Some(on_exit.take());
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 thread = do Thread::start {
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");
};
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 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());
main_task.death.on_exit = Some(on_exit.take());
rtdebug!("boostrapping main_task");

View file

@ -833,7 +833,7 @@ mod test {
let mut sched = ~new_test_uv_sched();
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)) {
unsafe { *task_ran_ptr = true };
assert!(Task::on_appropriate_sched());
@ -893,21 +893,21 @@ mod test {
// 3) task not homed, sched requeues
// 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)) || {
rtassert!(Task::on_appropriate_sched());
};
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());
};
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());
};
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)) {
rtassert!(Task::on_appropriate_sched());
};
@ -923,7 +923,7 @@ mod test {
let port = Cell::new(port);
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*");
Scheduler::run_task(task2.take());
rtdebug!("*about to submit task4*");
@ -938,7 +938,7 @@ mod test {
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*");
Scheduler::run_task(task1.take());
rtdebug!("*about to submit task3*");

View file

@ -86,12 +86,13 @@ impl Task {
// A helper to build a new task using the dynamically found
// 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 home = Cell::new(home);
do Local::borrow::<Task, ~Task> |running_task| {
let mut sched = running_task.sched.take_unwrap();
let new_task = ~running_task.new_child_homed(&mut sched.stack_pool,
stack_size,
home.take(),
f.take());
running_task.sched = Some(sched);
@ -99,25 +100,26 @@ impl Task {
}
}
pub fn build_child(f: ~fn()) -> ~Task {
Task::build_homed_child(f, AnySched)
pub fn build_child(stack_size: Option<uint>, f: ~fn()) -> ~Task {
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 home = Cell::new(home);
do Local::borrow::<Task, ~Task> |running_task| {
let mut sched = running_task.sched.take_unwrap();
let new_task = ~Task::new_root_homed(&mut sched.stack_pool,
home.take(),
f.take());
stack_size,
home.take(),
f.take());
running_task.sched = Some(sched);
new_task
}
}
pub fn build_root(f: ~fn()) -> ~Task {
Task::build_homed_root(f, AnySched)
pub fn build_root(stack_size: Option<uint>, f: ~fn()) -> ~Task {
Task::build_homed_root(stack_size, f, AnySched)
}
pub fn new_sched_task() -> Task {
@ -138,17 +140,20 @@ impl Task {
}
pub fn new_root(stack_pool: &mut StackPool,
stack_size: Option<uint>,
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,
stack_pool: &mut StackPool,
stack_size: Option<uint>,
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,
stack_size: Option<uint>,
home: SchedHome,
start: ~fn()) -> Task {
Task {
@ -161,7 +166,7 @@ impl Task {
death: Death::new(),
destroyed: false,
name: None,
coroutine: Some(Coroutine::new(stack_pool, start)),
coroutine: Some(Coroutine::new(stack_pool, stack_size, start)),
sched: None,
task_type: GreenTask(Some(~home))
}
@ -169,6 +174,7 @@ impl Task {
pub fn new_child_homed(&mut self,
stack_pool: &mut StackPool,
stack_size: Option<uint>,
home: SchedHome,
start: ~fn()) -> Task {
Task {
@ -182,7 +188,7 @@ impl Task {
death: self.death.new_child(),
destroyed: false,
name: None,
coroutine: Some(Coroutine::new(stack_pool, start)),
coroutine: Some(Coroutine::new(stack_pool, stack_size, start)),
sched: None,
task_type: GreenTask(Some(~home))
}
@ -326,8 +332,11 @@ impl Drop for Task {
impl Coroutine {
pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine {
let stack_size = env::min_stack();
pub fn new(stack_pool: &mut StackPool, stack_size: Option<uint>, start: ~fn()) -> Coroutine {
let stack_size = match stack_size {
Some(size) => size,
None => env::min_stack()
};
let start = Coroutine::build_start_wrapper(start);
let mut stack = stack_pool.take_segment(stack_size);
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);
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);
sched.bootstrap(task);
@ -190,8 +190,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
rtassert!(exit_status);
};
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
f.take());
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, None, f.take());
main_task.death.on_exit = Some(on_exit);
let mut threads = ~[];
@ -209,7 +208,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
while !scheds.is_empty() {
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");
};
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
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
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()) {
@ -259,7 +258,7 @@ pub fn spawntask_try(f: ~fn()) -> Result<(),()> {
let chan = Cell::new(chan);
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);
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) {
do run_in_bare_thread {
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);
}
}

View file

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

View file

@ -713,9 +713,9 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
let mut task = unsafe {
if opts.sched.mode != SingleThreaded {
if opts.watched {
Task::build_child(child_wrapper)
Task::build_child(opts.stack_size, child_wrapper)
} else {
Task::build_root(child_wrapper)
Task::build_root(opts.stack_size, child_wrapper)
}
} else {
// 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
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 {
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
// thread when it is ready to terminate
let (thread_port, thread_chan) = oneshot();
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");
let thread_port = thread_port_cell.take();
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 join_task = join_task_cell.take();
let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool) || {
rtdebug!("bootstrapping a 1:1 scheduler");
let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool, None) || {
rtdebug!("boostrapping a 1:1 scheduler");
};
new_sched.bootstrap(bootstrap_task);