diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-12-15 00:42:21 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-12-24 19:59:54 -0800 |
| commit | 51c03c1f35f6b076928a1e5b94ec81e6d00c3ac2 (patch) | |
| tree | 5503ef16e6be59f8a0c8948fe347d48be9267a47 /src/libnative | |
| parent | 282f3d99a5ad85acbc58c03b5dfcdabf649c0c85 (diff) | |
| download | rust-51c03c1f35f6b076928a1e5b94ec81e6d00c3ac2.tar.gz rust-51c03c1f35f6b076928a1e5b94ec81e6d00c3ac2.zip | |
green: Properly wait for main before shutdown
There was a race in the code previously where schedulers would *immediately* shut down after spawning the main task (because the global task count would still be 0). This fixes the logic by blocking the sched pool task in receving on a port instead of spawning a task into the pool to receive on a port. The modifications necessary were to have a "simple task" running by the time the code is executing, but this is a simple enough thing to implement and I forsee this being necessary to have implemented in the future anyway.
Diffstat (limited to 'src/libnative')
| -rw-r--r-- | src/libnative/lib.rs | 25 | ||||
| -rw-r--r-- | src/libnative/task.rs | 10 |
2 files changed, 17 insertions, 18 deletions
diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index 44b66a7804d..60ae239ee97 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -33,15 +33,16 @@ // answer is that you don't need them) use std::os; +use std::rt::local::Local; +use std::rt::task::Task; use std::rt; -use stdtask = std::rt::task; pub mod io; pub mod task; // XXX: this should not exist here -#[cfg(stage0, notready)] +#[cfg(stage0)] #[lang = "start"] pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { use std::cast; @@ -72,9 +73,13 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { /// exited. pub fn start(argc: int, argv: **u8, main: proc()) -> int { rt::init(argc, argv); - let exit_code = run(main); + let mut exit_code = None; + let mut main = Some(main); + task::new().run(|| { + exit_code = Some(run(main.take_unwrap())); + }); unsafe { rt::cleanup(); } - return exit_code; + return exit_code.unwrap(); } /// Executes a procedure on the current thread in a Rust task context. @@ -82,11 +87,11 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int { /// This function has all of the same details as `start` except for a different /// number of arguments. pub fn run(main: proc()) -> int { - // Create a task, run the procedure in it, and then wait for everything. - task::run(task::new(), main); - - // Block this OS task waiting for everything to finish. - unsafe { stdtask::wait_for_completion() } - + // Run the main procedure and then wait for everything to finish + main(); + unsafe { + let mut task = Local::borrow(None::<Task>); + task.get().wait_for_other_tasks(); + } os::get_exit_status() } diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 48768def067..0d5e08979ca 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -77,17 +77,11 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) { stack::record_stack_bounds(my_stack - stack + 1024, my_stack); } - run(task, f); + let mut f = Some(f); + task.run(|| { f.take_unwrap()() }); }) } -/// Runs a task once, consuming the task. The given procedure is run inside of -/// the task. -pub fn run(t: ~Task, f: proc()) { - let mut f = Some(f); - t.run(|| { f.take_unwrap()(); }); -} - // This structure is the glue between channels and the 1:1 scheduling mode. This // structure is allocated once per task. struct Ops { |
