diff options
Diffstat (limited to 'src/libstd/rt/mod.rs')
| -rw-r--r-- | src/libstd/rt/mod.rs | 110 |
1 files changed, 51 insertions, 59 deletions
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 3bcf6787824..268d402adf5 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -67,9 +67,10 @@ use iter::Times; use iterator::{Iterator, IteratorUtil}; use option::{Some, None}; use ptr::RawPtr; +use rt::local::Local; use rt::sched::{Scheduler, Shutdown}; use rt::sleeper_list::SleeperList; -use rt::task::{Task, Sched}; +use rt::task::{Task, SchedTask, GreenTask}; use rt::thread::Thread; use rt::work_queue::WorkQueue; use rt::uv::uvio::UvEventLoop; @@ -309,44 +310,53 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int { } }; - // Build the main task and queue it up - match main_sched { - None => { - // The default case where we don't need a scheduler on the main thread. - // Just put an unpinned task onto one of the default schedulers. - let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, main); - main_task.death.on_exit = Some(on_exit); - main_task.name = Some(~"main"); - scheds[0].enqueue_task(main_task); - } - Some(ref mut main_sched) => { - let home = Sched(main_sched.make_handle()); - let mut main_task = ~Task::new_root_homed(&mut scheds[0].stack_pool, home, main); - main_task.death.on_exit = Some(on_exit); - main_task.name = Some(~"main"); - main_sched.enqueue_task(main_task); - } - }; - - // Run each scheduler in a thread. let mut threads = ~[]; - while !scheds.is_empty() { + + if !use_main_sched { + + // In the case where we do not use a main_thread scheduler we + // run the main task in one of our threads. + + let main_cell = Cell::new(main); + let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, + main_cell.take()); + main_task.death.on_exit = Some(on_exit); + let main_task_cell = Cell::new(main_task); + let sched = scheds.pop(); let sched_cell = Cell::new(sched); let thread = do Thread::start { let sched = sched_cell.take(); - sched.run(); + sched.bootstrap(main_task_cell.take()); }; - threads.push(thread); } - // Run the main-thread scheduler - match main_sched { - Some(sched) => { let _ = sched.run(); }, - None => () + // Run each remaining scheduler in a thread. + while !scheds.is_empty() { + let sched = scheds.pop(); + 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) || { + rtdebug!("boostraping a non-primary scheduler"); + }; + sched.bootstrap(bootstrap_task); + }; + threads.push(thread); } + // If we do have a main thread scheduler, run it now. + + if use_main_sched { + let home = Sched(main_sched.make_handle()); + let mut main_task = ~Task::new_root_homed(&mut scheds[0].stack_pool, + home, main); + main_task.death.on_exit = Some(on_exit); + let main_task_cell = Cell::new(main_task); + sched.bootstrap(main_task); + } + // Wait for schedulers foreach thread in threads.consume_iter() { thread.join(); @@ -378,27 +388,23 @@ pub enum RuntimeContext { pub fn context() -> RuntimeContext { use task::rt::rust_task; - use self::local::Local; - use self::sched::Scheduler; - // XXX: Hitting TLS twice to check if the scheduler exists - // then to check for the task is not good for perf if unsafe { rust_try_get_task().is_not_null() } { return OldTaskContext; - } else { - if Local::exists::<Scheduler>() { - let context = Cell::new_empty(); - do Local::borrow::<Scheduler, ()> |sched| { - if sched.in_task_context() { - context.put_back(TaskContext); - } else { - context.put_back(SchedulerContext); - } + } else if Local::exists::<Task>() { + rtdebug!("either task or scheduler context in newrt"); + // In this case we know it is a new runtime context, but we + // need to check which one. Going to try borrowing task to + // check. Task should always be in TLS, so hopefully this + // doesn't conflict with other ops that borrow. + return do Local::borrow::<Task,RuntimeContext> |task| { + match task.task_type { + SchedTask => SchedulerContext, + GreenTask(_) => TaskContext } - return context.take(); - } else { - return GlobalContext; - } + }; + } else { + return GlobalContext; } extern { @@ -410,23 +416,9 @@ pub fn context() -> RuntimeContext { #[test] fn test_context() { use unstable::run_in_bare_thread; - use self::sched::{Scheduler}; - use rt::local::Local; - use rt::test::new_test_uv_sched; assert_eq!(context(), OldTaskContext); do run_in_bare_thread { assert_eq!(context(), GlobalContext); - let mut sched = ~new_test_uv_sched(); - let task = ~do Task::new_root(&mut sched.stack_pool) { - assert_eq!(context(), TaskContext); - let sched = Local::take::<Scheduler>(); - do sched.deschedule_running_task_and_then() |sched, task| { - assert_eq!(context(), SchedulerContext); - sched.enqueue_blocked_task(task); - } - }; - sched.enqueue_task(task); - sched.run(); } } |
