Skip to content

Improve rt cleanup and rt::thread::Thread #10662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/libstd/rt/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pub unsafe fn init(argc: int, argv: **u8) { imp::init(argc, argv) }
pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) }

/// One-time global cleanup.
#[cfg(not(test))] pub fn cleanup() { imp::cleanup() }
#[cfg(test)] pub fn cleanup() { realargs::cleanup() }
#[cfg(not(test))] pub unsafe fn cleanup() { imp::cleanup() }
#[cfg(test)] pub unsafe fn cleanup() { realargs::cleanup() }

/// Take the global arguments from global storage.
#[cfg(not(test))] pub fn take() -> Option<~[~str]> { imp::take() }
Expand Down Expand Up @@ -74,14 +74,16 @@ mod imp {
use vec;

static mut global_args_ptr: uint = 0;
static mut lock: Mutex = MUTEX_INIT;

pub unsafe fn init(argc: int, argv: **u8) {
let args = load_argc_and_argv(argc, argv);
put(args);
}

pub fn cleanup() {
pub unsafe fn cleanup() {
rtassert!(take().is_some());
lock.destroy();
}

pub fn take() -> Option<~[~str]> {
Expand All @@ -108,7 +110,6 @@ mod imp {
}

fn with_lock<T>(f: || -> T) -> T {
static mut lock: Mutex = MUTEX_INIT;
(|| {
unsafe {
lock.lock();
Expand Down
38 changes: 30 additions & 8 deletions src/libstd/rt/local_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,49 @@ pub static mut RT_TLS_PTR: *mut c_void = 0 as *mut c_void;
#[cfg(stage0)]
#[cfg(windows)]
static mut RT_TLS_KEY: tls::Key = -1;
#[cfg(stage0)]
#[cfg(windows)]
static mut tls_lock: Mutex = MUTEX_INIT;
static mut tls_initialized: bool = false;

/// Initialize the TLS key. Other ops will fail if this isn't executed first.
#[inline(never)]
#[cfg(stage0)]
#[cfg(windows)]
pub fn init_tls_key() {
static mut lock: Mutex = MUTEX_INIT;
static mut initialized: bool = false;

unsafe {
lock.lock();
if !initialized {
tls_lock.lock();
if !tls_initialized {
tls::create(&mut RT_TLS_KEY);
initialized = true;
tls_initialized = true;
}
lock.unlock();
tls_lock.unlock();
}
}

#[cfg(not(stage0), not(windows))]
pub fn init_tls_key() {}
pub fn init_tls_key() {
unsafe {
tls_initialized = true;
}
}

#[cfg(windows)]
pub unsafe fn cleanup() {
// No real use to acquiring a lock around these operations. All we're
// going to do is destroy the lock anyway which races locking itself. This
// is why the whole function is labeled as 'unsafe'
assert!(tls_initialized);
tls::destroy(RT_TLS_KEY);
tls_lock.destroy();
tls_initialized = false;
}

#[cfg(not(windows))]
pub unsafe fn cleanup() {
assert!(tls_initialized);
tls_initialized = false;
}

/// Give a pointer to thread-local storage.
///
Expand Down
17 changes: 14 additions & 3 deletions src/libstd/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {

init(argc, argv);
let exit_code = run(main);
cleanup();
// unsafe is ok b/c we're sure that the runtime is gone
unsafe { cleanup(); }

return exit_code;
}
Expand All @@ -228,7 +229,8 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
pub fn start_on_main_thread(argc: int, argv: **u8, main: proc()) -> int {
init(argc, argv);
let exit_code = run_on_main_thread(main);
cleanup();
// unsafe is ok b/c we're sure that the runtime is gone
unsafe { cleanup(); }

return exit_code;
}
Expand All @@ -249,8 +251,17 @@ pub fn init(argc: int, argv: **u8) {
}

/// One-time runtime cleanup.
pub fn cleanup() {
///
/// This function is unsafe because it performs no checks to ensure that the
/// runtime has completely ceased running. It is the responsibility of the
/// caller to ensure that the runtime is entirely shut down and nothing will be
/// poking around at the internal components.
///
/// Invoking cleanup while portions of the runtime are still in use may cause
/// undefined behavior.
pub unsafe fn cleanup() {
args::cleanup();
local_ptr::cleanup();
}

/// Execute the main function in a scheduler.
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rt/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ pub fn spawntask_try(f: proc()) -> Result<(),()> {
}

/// Spawn a new task in a new scheduler and return a thread handle.
pub fn spawntask_thread(f: proc()) -> Thread {
pub fn spawntask_thread(f: proc()) -> Thread<()> {

let f = Cell::new(f);

Expand Down
Loading