Skip to content

Commit 6502684

Browse files
committed
Use a static atomic to store a common key
1 parent da86a0e commit 6502684

1 file changed

Lines changed: 23 additions & 4 deletions

File tree

library/std/src/sys/thread_local/guard/windows.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
//! [1]: https://devblogs.microsoft.com/oldnewthing/20191011-00/?p=102989
1111
1212
use core::ffi::c_void;
13+
use core::sync::atomic::{AtomicU32, Ordering};
1314

1415
use crate::cell::Cell;
1516
use crate::ptr;
16-
use crate::sys::c;
17+
use crate::sys::c::{self, FLS_OUT_OF_INDEXES};
1718

1819
pub type Key = u32;
1920

@@ -35,15 +36,33 @@ unsafe fn set(key: Key, ptr: *const c_void) {
3536
}
3637
}
3738

39+
static KEY: AtomicU32 = AtomicU32::new(FLS_OUT_OF_INDEXES);
40+
3841
pub fn enable() {
3942
#[thread_local]
4043
static REGISTERED: Cell<bool> = Cell::new(false);
4144

4245
if !REGISTERED.replace(true) {
43-
unsafe {
44-
let key = create(Some(cleanup));
45-
set(key, ptr::dangling());
46+
let current_key = KEY.load(Ordering::Acquire);
47+
48+
// If we already allocated a key, we only need to set it to a non-null value so that the dtor is run.
49+
let key = if current_key != FLS_OUT_OF_INDEXES {
50+
current_key
51+
} else {
52+
// Otherwise, we try to allocate a key.
53+
let new_key = unsafe { create(Some(cleanup)) };
54+
55+
// Now we need to set this key to be used by everyone else.
56+
// If we won the race, our key is the right one and we can set it to non-null value.
57+
// If we lost, we'll use the winning key.
58+
// Note: we are not freeing our losing key since according to the docs
59+
// > It is expected that DLLs call [the FlsFree] function (if at all) only during DLL_PROCESS_DETACH.
60+
match KEY.compare_exchange(current_key, new_key, Ordering::Release, Ordering::Acquire) {
61+
Ok(_) => new_key,
62+
Err(other_key) => other_key,
63+
}
4664
};
65+
unsafe { set(key, ptr::without_provenance(1)) };
4766
}
4867
}
4968

0 commit comments

Comments
 (0)