core::rt: Move some TLS functions from local_sched to local_ptr
This commit is contained in:
parent
86ba457349
commit
97c2fd1a96
63
src/libcore/rt/local_ptr.rs
Normal file
63
src/libcore/rt/local_ptr.rs
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Access to a single thread-local pointer
|
||||
|
||||
use libc::c_void;
|
||||
use cast;
|
||||
use option::{Option, Some, None};
|
||||
use tls = rt::thread_local_storage;
|
||||
|
||||
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
|
||||
pub fn init_tls_key() {
|
||||
unsafe {
|
||||
rust_initialize_rt_tls_key();
|
||||
extern {
|
||||
fn rust_initialize_rt_tls_key();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tls_key() -> tls::Key {
|
||||
match maybe_tls_key() {
|
||||
Some(key) => key,
|
||||
None => abort!("runtime tls key not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_tls_key() -> Option<tls::Key> {
|
||||
unsafe {
|
||||
let key: *mut c_void = rust_get_rt_tls_key();
|
||||
let key: &mut tls::Key = cast::transmute(key);
|
||||
let key = *key;
|
||||
// Check that the key has been initialized.
|
||||
|
||||
// NB: This is a little racy because, while the key is
|
||||
// initalized under a mutex and it's assumed to be initalized
|
||||
// in the Scheduler ctor by any thread that needs to use it,
|
||||
// we are not accessing the key under a mutex. Threads that
|
||||
// are not using the new Scheduler but still *want to check*
|
||||
// whether they are running under a new Scheduler may see a 0
|
||||
// value here that is in the process of being initialized in
|
||||
// another thread. I think this is fine since the only action
|
||||
// they could take if it was initialized would be to check the
|
||||
// thread-local value and see that it's not set.
|
||||
if key != -1 {
|
||||
return Some(key);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
#[fast_ffi]
|
||||
fn rust_get_rt_tls_key() -> *mut c_void;
|
||||
}
|
@ -18,25 +18,16 @@ use cell::Cell;
|
||||
|
||||
use rt::sched::Scheduler;
|
||||
use rt::rtio::{EventLoop, IoFactoryObject};
|
||||
use tls = rt::thread_local_storage;
|
||||
use unstable::finally::Finally;
|
||||
use rt::local_ptr;
|
||||
use tls = rt::thread_local_storage;
|
||||
|
||||
#[cfg(test)] use rt::uv::uvio::UvEventLoop;
|
||||
|
||||
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
|
||||
pub fn init_tls_key() {
|
||||
unsafe {
|
||||
rust_initialize_rt_tls_key();
|
||||
extern {
|
||||
fn rust_initialize_rt_tls_key();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Give the Scheduler to thread-local storage
|
||||
pub fn put(sched: ~Scheduler) {
|
||||
unsafe {
|
||||
let key = tls_key();
|
||||
let key = local_ptr::tls_key();
|
||||
let void_sched: *mut c_void = cast::transmute(sched);
|
||||
tls::set(key, void_sched);
|
||||
}
|
||||
@ -45,7 +36,7 @@ pub fn put(sched: ~Scheduler) {
|
||||
/// Take ownership of the Scheduler from thread-local storage
|
||||
pub fn take() -> ~Scheduler {
|
||||
unsafe {
|
||||
let key = tls_key();
|
||||
let key = local_ptr::tls_key();
|
||||
let void_sched: *mut c_void = tls::get(key);
|
||||
rtassert!(void_sched.is_not_null());
|
||||
let sched: ~Scheduler = cast::transmute(void_sched);
|
||||
@ -57,7 +48,7 @@ pub fn take() -> ~Scheduler {
|
||||
/// Check whether there is a thread-local Scheduler attached to the running thread
|
||||
pub fn exists() -> bool {
|
||||
unsafe {
|
||||
match maybe_tls_key() {
|
||||
match local_ptr::maybe_tls_key() {
|
||||
Some(key) => tls::get(key).is_not_null(),
|
||||
None => false
|
||||
}
|
||||
@ -89,7 +80,7 @@ pub fn borrow(f: &fn(&mut Scheduler)) {
|
||||
/// Because this leaves the Scheduler in thread-local storage it is possible
|
||||
/// For the Scheduler pointer to be aliased
|
||||
pub unsafe fn unsafe_borrow() -> *mut Scheduler {
|
||||
let key = tls_key();
|
||||
let key = local_ptr::tls_key();
|
||||
let mut void_sched: *mut c_void = tls::get(key);
|
||||
rtassert!(void_sched.is_not_null());
|
||||
{
|
||||
@ -106,43 +97,6 @@ pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject {
|
||||
return io;
|
||||
}
|
||||
|
||||
fn tls_key() -> tls::Key {
|
||||
match maybe_tls_key() {
|
||||
Some(key) => key,
|
||||
None => abort!("runtime tls key not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_tls_key() -> Option<tls::Key> {
|
||||
unsafe {
|
||||
let key: *mut c_void = rust_get_rt_tls_key();
|
||||
let key: &mut tls::Key = cast::transmute(key);
|
||||
let key = *key;
|
||||
// Check that the key has been initialized.
|
||||
|
||||
// NB: This is a little racy because, while the key is
|
||||
// initalized under a mutex and it's assumed to be initalized
|
||||
// in the Scheduler ctor by any thread that needs to use it,
|
||||
// we are not accessing the key under a mutex. Threads that
|
||||
// are not using the new Scheduler but still *want to check*
|
||||
// whether they are running under a new Scheduler may see a 0
|
||||
// value here that is in the process of being initialized in
|
||||
// another thread. I think this is fine since the only action
|
||||
// they could take if it was initialized would be to check the
|
||||
// thread-local value and see that it's not set.
|
||||
if key != -1 {
|
||||
return Some(key);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
#[fast_ffi]
|
||||
fn rust_get_rt_tls_key() -> *mut c_void;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thread_local_scheduler_smoke_test() {
|
||||
let scheduler = ~UvEventLoop::new_scheduler();
|
||||
|
@ -85,10 +85,6 @@ pub mod uv;
|
||||
/// or task-local storage.
|
||||
pub mod local;
|
||||
|
||||
// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
|
||||
/// Bindings to pthread/windows thread-local storage.
|
||||
pub mod thread_local_storage;
|
||||
|
||||
/// A parallel work-stealing deque.
|
||||
mod work_queue;
|
||||
|
||||
@ -126,6 +122,15 @@ pub mod tube;
|
||||
/// Simple reimplementation of core::comm
|
||||
pub mod comm;
|
||||
|
||||
// FIXME #5248 shouldn't be pub
|
||||
/// The runtime needs to be able to put a pointer into thread-local storage.
|
||||
pub mod local_ptr;
|
||||
|
||||
// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
|
||||
/// Bindings to pthread/windows thread-local storage.
|
||||
pub mod thread_local_storage;
|
||||
|
||||
|
||||
/// Set up a default runtime configuration, given compiler-supplied arguments.
|
||||
///
|
||||
/// This is invoked by the `start` _language item_ (unstable::lang) to
|
||||
|
@ -11,13 +11,14 @@
|
||||
use option::*;
|
||||
use sys;
|
||||
use cast::transmute;
|
||||
use cell::Cell;
|
||||
|
||||
use super::work_queue::WorkQueue;
|
||||
use super::stack::{StackPool, StackSegment};
|
||||
use super::rtio::{EventLoop, EventLoopObject};
|
||||
use super::context::Context;
|
||||
use super::task::Task;
|
||||
use cell::Cell;
|
||||
use rt::local_ptr;
|
||||
|
||||
// A more convenient name for external callers, e.g. `local_sched::take()`
|
||||
pub mod local_sched;
|
||||
@ -64,8 +65,8 @@ pub impl Scheduler {
|
||||
|
||||
fn new(event_loop: ~EventLoopObject) -> Scheduler {
|
||||
|
||||
// Lazily initialize the scheduler TLS key
|
||||
local_sched::init_tls_key();
|
||||
// Lazily initialize the runtime TLS key
|
||||
local_ptr::init_tls_key();
|
||||
|
||||
Scheduler {
|
||||
event_loop: event_loop,
|
||||
|
Loading…
x
Reference in New Issue
Block a user