]> git.proxmox.com Git - rustc.git/blobdiff - src/libstd/sys/windows/thread_local.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / libstd / sys / windows / thread_local.rs
index d371023f21880ae87d1b438676d94cc9c03854ce..5002de559884d0f52773fd9fa75f914e9a2b0e76 100644 (file)
@@ -12,9 +12,9 @@ use prelude::v1::*;
 
 use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
 
-use mem;
+use ptr;
 use rt;
-use sys_common::mutex::{MUTEX_INIT, Mutex};
+use sys_common::mutex::Mutex;
 
 pub type Key = DWORD;
 pub type Dtor = unsafe extern fn(*mut u8);
@@ -31,7 +31,7 @@ pub type Dtor = unsafe extern fn(*mut u8);
 // somewhere to run arbitrary code on thread termination. With this in place
 // we'll be able to run anything we like, including all TLS destructors!
 //
-// To accomplish this feat, we perform a number of tasks, all contained
+// To accomplish this feat, we perform a number of threads, all contained
 // within this module:
 //
 // * All TLS destructors are tracked by *us*, not the windows runtime. This
@@ -57,7 +57,7 @@ pub type Dtor = unsafe extern fn(*mut u8);
 // on poisoning and this module needs to operate at a lower level than requiring
 // the thread infrastructure to be in place (useful on the borders of
 // initialization/destruction).
-static DTOR_LOCK: Mutex = MUTEX_INIT;
+static DTOR_LOCK: Mutex = Mutex::new();
 static mut DTORS: *mut Vec<(Key, Dtor)> = 0 as *mut _;
 
 // -------------------------------------------------------------------------
@@ -132,21 +132,28 @@ unsafe fn init_dtors() {
     if !DTORS.is_null() { return }
 
     let dtors = box Vec::<(Key, Dtor)>::new();
-    DTORS = mem::transmute(dtors);
 
-    rt::at_exit(move|| {
+    let res = rt::at_exit(move|| {
         DTOR_LOCK.lock();
         let dtors = DTORS;
-        DTORS = 0 as *mut _;
-        mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
-        assert!(DTORS.is_null()); // can't re-init after destructing
+        DTORS = 1 as *mut _;
+        Box::from_raw(dtors);
+        assert!(DTORS as usize == 1); // can't re-init after destructing
         DTOR_LOCK.unlock();
     });
+    if res.is_ok() {
+        DTORS = Box::into_raw(dtors);
+    } else {
+        DTORS = 1 as *mut _;
+    }
 }
 
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
     DTOR_LOCK.lock();
     init_dtors();
+    assert!(DTORS as usize != 0);
+    assert!(DTORS as usize != 1,
+            "cannot create new TLS keys after the main thread has exited");
     (*DTORS).push((key, dtor));
     DTOR_LOCK.unlock();
 }
@@ -154,6 +161,9 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
 unsafe fn unregister_dtor(key: Key) -> bool {
     DTOR_LOCK.lock();
     init_dtors();
+    assert!(DTORS as usize != 0);
+    assert!(DTORS as usize != 1,
+            "cannot unregister destructors after the main thread has exited");
     let ret = {
         let dtors = &mut *DTORS;
         let before = dtors.len();
@@ -190,7 +200,7 @@ unsafe fn unregister_dtor(key: Key) -> bool {
 // # What's up with this callback?
 //
 // The callback specified receives a number of parameters from... someone!
-// (the kernel? the runtime? I'm not qute sure!) There are a few events that
+// (the kernel? the runtime? I'm not quite sure!) There are a few events that
 // this gets invoked for, but we're currently only interested on when a
 // thread or a process "detaches" (exits). The process part happens for the
 // last thread and the thread part happens for any normal thread.
@@ -232,14 +242,15 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID,
     }
 }
 
+#[allow(dead_code)] // actually called above
 unsafe fn run_dtors() {
     let mut any_run = true;
-    for _ in range(0, 5i) {
+    for _ in 0..5 {
         if !any_run { break }
         any_run = false;
         let dtors = {
             DTOR_LOCK.lock();
-            let ret = if DTORS.is_null() {
+            let ret = if DTORS as usize <= 1 {
                 Vec::new()
             } else {
                 (*DTORS).iter().map(|s| *s).collect()
@@ -247,10 +258,10 @@ unsafe fn run_dtors() {
             DTOR_LOCK.unlock();
             ret
         };
-        for &(key, dtor) in dtors.iter() {
+        for &(key, dtor) in &dtors {
             let ptr = TlsGetValue(key);
             if !ptr.is_null() {
-                TlsSetValue(key, 0 as *mut _);
+                TlsSetValue(key, ptr::null_mut());
                 dtor(ptr as *mut _);
                 any_run = true;
             }